OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [lib/] [source/] [neorv32_rte.c] - Blame information for rev 61

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 zero_gravi
// #################################################################################################
2
// # << NEORV32: neorv32_rte.c - NEORV32 Runtime Environment >>                                    #
3
// # ********************************************************************************************* #
4
// # BSD 3-Clause License                                                                          #
5
// #                                                                                               #
6 42 zero_gravi
// # Copyright (c) 2021, Stephan Nolting. All rights reserved.                                     #
7 2 zero_gravi
// #                                                                                               #
8
// # Redistribution and use in source and binary forms, with or without modification, are          #
9
// # permitted provided that the following conditions are met:                                     #
10
// #                                                                                               #
11
// # 1. Redistributions of source code must retain the above copyright notice, this list of        #
12
// #    conditions and the following disclaimer.                                                   #
13
// #                                                                                               #
14
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
15
// #    conditions and the following disclaimer in the documentation and/or other materials        #
16
// #    provided with the distribution.                                                            #
17
// #                                                                                               #
18
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
19
// #    endorse or promote products derived from this software without specific prior written      #
20
// #    permission.                                                                                #
21
// #                                                                                               #
22
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
23
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
24
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
25
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
26
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
27
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
28
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
29
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
30
// # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
31
// # ********************************************************************************************* #
32
// # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
33
// #################################################################################################
34
 
35
 
36
/**********************************************************************//**
37
 * @file neorv32_rte.c
38
 * @author Stephan Nolting
39
 * @brief NEORV32 Runtime Environment.
40
 **************************************************************************/
41
 
42
#include "neorv32.h"
43
#include "neorv32_rte.h"
44
 
45 14 zero_gravi
/**********************************************************************//**
46
 * The >private< trap vector look-up table of the NEORV32 RTE.
47
 **************************************************************************/
48 58 zero_gravi
static uint32_t __neorv32_rte_vector_lut[NEORV32_RTE_NUM_TRAPS] __attribute__((unused)); // trap handler vector table
49 14 zero_gravi
 
50
// private functions
51
static void __attribute__((__interrupt__)) __neorv32_rte_core(void) __attribute__((aligned(16))) __attribute__((unused));
52 6 zero_gravi
static void __neorv32_rte_debug_exc_handler(void)     __attribute__((unused));
53
static void __neorv32_rte_print_true_false(int state) __attribute__((unused));
54 33 zero_gravi
static void __neorv32_rte_print_hex_word(uint32_t num);
55 2 zero_gravi
 
56
 
57
/**********************************************************************//**
58 14 zero_gravi
 * Setup NEORV32 runtime environment.
59 2 zero_gravi
 *
60
 * @note This function installs a debug handler for ALL exception and interrupt sources, which
61 14 zero_gravi
 * gives detailed information about the exception/interrupt. Actual handler can be installed afterwards
62
 * via neorv32_rte_exception_install(uint8_t id, void (*handler)(void)).
63 2 zero_gravi
 **************************************************************************/
64 14 zero_gravi
void neorv32_rte_setup(void) {
65 2 zero_gravi
 
66 14 zero_gravi
  // configure trap handler base address
67
  uint32_t mtvec_base = (uint32_t)(&__neorv32_rte_core);
68
  neorv32_cpu_csr_write(CSR_MTVEC, mtvec_base);
69 2 zero_gravi
 
70
  // install debug handler for all sources
71 14 zero_gravi
  uint8_t id;
72
  for (id = 0; id < (sizeof(__neorv32_rte_vector_lut)/sizeof(__neorv32_rte_vector_lut[0])); id++) {
73
    neorv32_rte_exception_uninstall(id); // this will configure the debug handler
74 2 zero_gravi
  }
75
}
76
 
77
 
78
/**********************************************************************//**
79
 * Install exception handler function to NEORV32 runtime environment.
80
 *
81 17 zero_gravi
 * @note Interrupt sources have to be explicitly enabled by the user via the CSR.mie bits via neorv32_cpu_irq_enable(uint8_t irq_sel)
82
 * and the global interrupt enable bit mstatus.mie via neorv32_cpu_eint(void).
83 2 zero_gravi
 *
84 14 zero_gravi
 * @param[in] id Identifier (type) of the targeted exception. See #NEORV32_RTE_TRAP_enum.
85
 * @param[in] handler The actual handler function for the specified exception (function MUST be of type "void function(void);").
86 18 zero_gravi
 * @return 0 if success, 1 if error (invalid id or targeted exception not supported).
87 2 zero_gravi
 **************************************************************************/
88 14 zero_gravi
int neorv32_rte_exception_install(uint8_t id, void (*handler)(void)) {
89 2 zero_gravi
 
90
  // id valid?
91 48 zero_gravi
  if ((id >= RTE_TRAP_I_MISALIGNED) && (id <= CSR_MIE_FIRQ15E)) {
92 24 zero_gravi
    __neorv32_rte_vector_lut[id] = (uint32_t)handler; // install handler
93 2 zero_gravi
    return 0;
94
  }
95
  return 1;
96
}
97
 
98
 
99
/**********************************************************************//**
100
 * Uninstall exception handler function from NEORV32 runtime environment, which was
101 14 zero_gravi
 * previously installed via neorv32_rte_exception_install(uint8_t id, void (*handler)(void)).
102 2 zero_gravi
 *
103 17 zero_gravi
 * @note Interrupt sources have to be explicitly disabled by the user via the CSR.mie bits via neorv32_cpu_irq_disable(uint8_t irq_sel)
104
 * and/or the global interrupt enable bit mstatus.mie via neorv32_cpu_dint(void).
105 2 zero_gravi
 *
106 14 zero_gravi
 * @param[in] id Identifier (type) of the targeted exception. See #NEORV32_RTE_TRAP_enum.
107 18 zero_gravi
 * @return 0 if success, 1 if error (invalid id or targeted exception not supported).
108 2 zero_gravi
 **************************************************************************/
109 14 zero_gravi
int neorv32_rte_exception_uninstall(uint8_t id) {
110 2 zero_gravi
 
111
  // id valid?
112 48 zero_gravi
  if ((id >= RTE_TRAP_I_MISALIGNED) && (id <= CSR_MIE_FIRQ15E)) {
113 14 zero_gravi
    __neorv32_rte_vector_lut[id] = (uint32_t)(&__neorv32_rte_debug_exc_handler); // use dummy handler in case the exception is accidently triggered
114 2 zero_gravi
    return 0;
115
  }
116
  return 1;
117
}
118
 
119
 
120
/**********************************************************************//**
121 14 zero_gravi
 * This is the core of the NEORV32 RTE.
122
 *
123
 * @note This function must no be explicitly used by the user.
124 33 zero_gravi
 * @note The RTE core uses mscratch CSR to store the trap-causing mepc for further (user-defined) processing.
125
 *
126 14 zero_gravi
 * @warning When using the the RTE, this function is the ONLY function that can use the 'interrupt' attribute!
127 2 zero_gravi
 **************************************************************************/
128 14 zero_gravi
static void __attribute__((__interrupt__)) __attribute__((aligned(16)))  __neorv32_rte_core(void) {
129 2 zero_gravi
 
130 33 zero_gravi
  register uint32_t rte_mepc = neorv32_cpu_csr_read(CSR_MEPC);
131
  neorv32_cpu_csr_write(CSR_MSCRATCH, rte_mepc); // store for later
132 14 zero_gravi
  register uint32_t rte_mcause = neorv32_cpu_csr_read(CSR_MCAUSE);
133
 
134
  // compute return address
135 61 zero_gravi
  if (((int32_t)rte_mcause) >= 0) { // modify pc only if exception (MSB cleared)
136 14 zero_gravi
 
137
    // get low half word of faulting instruction
138
    register uint32_t rte_trap_inst;
139
    asm volatile ("lh %[result], 0(%[input_i])" : [result] "=r" (rte_trap_inst) : [input_i] "r" (rte_mepc));
140
 
141
    if ((rte_trap_inst & 3) == 3) { // faulting instruction is uncompressed instruction
142
      rte_mepc += 4;
143
    }
144
    else { // faulting instruction is compressed instruction
145
      rte_mepc += 2;
146
    }
147
 
148
    // store new return address
149
    neorv32_cpu_csr_write(CSR_MEPC, rte_mepc);
150
  }
151
 
152
  // find according trap handler
153
  register uint32_t rte_handler = (uint32_t)(&__neorv32_rte_debug_exc_handler);
154
  switch (rte_mcause) {
155
    case TRAP_CODE_I_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_MISALIGNED]; break;
156
    case TRAP_CODE_I_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ACCESS]; break;
157
    case TRAP_CODE_I_ILLEGAL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ILLEGAL]; break;
158
    case TRAP_CODE_BREAKPOINT:   rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_BREAKPOINT]; break;
159
    case TRAP_CODE_L_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_L_MISALIGNED]; break;
160
    case TRAP_CODE_L_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_L_ACCESS]; break;
161
    case TRAP_CODE_S_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_S_MISALIGNED]; break;
162
    case TRAP_CODE_S_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_S_ACCESS]; break;
163 40 zero_gravi
    case TRAP_CODE_UENV_CALL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_UENV_CALL]; break;
164 14 zero_gravi
    case TRAP_CODE_MENV_CALL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MENV_CALL]; break;
165 58 zero_gravi
    case TRAP_CODE_NMI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_NMI]; break;
166 14 zero_gravi
    case TRAP_CODE_MSI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MSI]; break;
167
    case TRAP_CODE_MTI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MTI]; break;
168
    case TRAP_CODE_MEI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MEI]; break;
169
    case TRAP_CODE_FIRQ_0:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_0]; break;
170
    case TRAP_CODE_FIRQ_1:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_1]; break;
171
    case TRAP_CODE_FIRQ_2:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_2]; break;
172
    case TRAP_CODE_FIRQ_3:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_3]; break;
173 47 zero_gravi
    case TRAP_CODE_FIRQ_4:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_4]; break;
174
    case TRAP_CODE_FIRQ_5:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_5]; break;
175
    case TRAP_CODE_FIRQ_6:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_6]; break;
176
    case TRAP_CODE_FIRQ_7:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_7]; break;
177 48 zero_gravi
    case TRAP_CODE_FIRQ_8:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_8]; break;
178
    case TRAP_CODE_FIRQ_9:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_9]; break;
179
    case TRAP_CODE_FIRQ_10:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_10]; break;
180
    case TRAP_CODE_FIRQ_11:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_11]; break;
181
    case TRAP_CODE_FIRQ_12:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_12]; break;
182
    case TRAP_CODE_FIRQ_13:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_13]; break;
183
    case TRAP_CODE_FIRQ_14:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_14]; break;
184
    case TRAP_CODE_FIRQ_15:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_15]; break;
185 14 zero_gravi
    default: break;
186
  }
187
 
188
  // execute handler
189
  void (*handler_pnt)(void);
190
  handler_pnt = (void*)rte_handler;
191
  (*handler_pnt)();
192 2 zero_gravi
}
193
 
194
 
195
/**********************************************************************//**
196
 * NEORV32 runtime environment: Debug exception handler, printing various exception/interrupt information via UART.
197 14 zero_gravi
 * @note This function is used by neorv32_rte_exception_uninstall(void) only.
198 2 zero_gravi
 **************************************************************************/
199
static void __neorv32_rte_debug_exc_handler(void) {
200
 
201 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
202
    return; // handler cannot output anything if UART0 is not implemented
203
  }
204
 
205 48 zero_gravi
  char tmp;
206
 
207 15 zero_gravi
  // intro
208 33 zero_gravi
  neorv32_uart_print("<RTE> ");
209 2 zero_gravi
 
210 15 zero_gravi
  // cause
211 7 zero_gravi
  register uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
212 48 zero_gravi
  tmp = (char)(trap_cause & 0xf);
213
  if (tmp >= 10) {
214
    tmp = 'a' + (tmp - 10);
215
  }
216
  else {
217
    tmp = '0' + tmp;
218
  }
219 7 zero_gravi
  switch (trap_cause) {
220 33 zero_gravi
    case TRAP_CODE_I_MISALIGNED: neorv32_uart_print("Instruction address misaligned"); break;
221
    case TRAP_CODE_I_ACCESS:     neorv32_uart_print("Instruction access fault"); break;
222
    case TRAP_CODE_I_ILLEGAL:    neorv32_uart_print("Illegal instruction"); break;
223
    case TRAP_CODE_BREAKPOINT:   neorv32_uart_print("Breakpoint"); break;
224
    case TRAP_CODE_L_MISALIGNED: neorv32_uart_print("Load address misaligned"); break;
225
    case TRAP_CODE_L_ACCESS:     neorv32_uart_print("Load access fault"); break;
226
    case TRAP_CODE_S_MISALIGNED: neorv32_uart_print("Store address misaligned"); break;
227
    case TRAP_CODE_S_ACCESS:     neorv32_uart_print("Store access fault"); break;
228 40 zero_gravi
    case TRAP_CODE_UENV_CALL:    neorv32_uart_print("Environment call from U-mode"); break;
229
    case TRAP_CODE_MENV_CALL:    neorv32_uart_print("Environment call from M-mode"); break;
230 33 zero_gravi
    case TRAP_CODE_MSI:          neorv32_uart_print("Machine software interrupt"); break;
231
    case TRAP_CODE_MTI:          neorv32_uart_print("Machine timer interrupt"); break;
232
    case TRAP_CODE_MEI:          neorv32_uart_print("Machine external interrupt"); break;
233 47 zero_gravi
    case TRAP_CODE_FIRQ_0:
234
    case TRAP_CODE_FIRQ_1:
235
    case TRAP_CODE_FIRQ_2:
236
    case TRAP_CODE_FIRQ_3:
237
    case TRAP_CODE_FIRQ_4:
238
    case TRAP_CODE_FIRQ_5:
239
    case TRAP_CODE_FIRQ_6:
240 48 zero_gravi
    case TRAP_CODE_FIRQ_7:
241
    case TRAP_CODE_FIRQ_8:
242
    case TRAP_CODE_FIRQ_9:
243
    case TRAP_CODE_FIRQ_10:
244
    case TRAP_CODE_FIRQ_11:
245
    case TRAP_CODE_FIRQ_12:
246
    case TRAP_CODE_FIRQ_13:
247
    case TRAP_CODE_FIRQ_14:
248
    case TRAP_CODE_FIRQ_15:      neorv32_uart_print("Fast interrupt "); neorv32_uart_putc(tmp); break;
249 33 zero_gravi
    default:                     neorv32_uart_print("Unknown trap cause: "); __neorv32_rte_print_hex_word(trap_cause); break;
250 2 zero_gravi
  }
251
 
252 33 zero_gravi
  // instruction address
253 35 zero_gravi
  neorv32_uart_print(" @ PC=");
254 33 zero_gravi
  __neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MSCRATCH)); // rte core stores actual mepc to mscratch
255 15 zero_gravi
 
256 33 zero_gravi
  // additional info
257
  neorv32_uart_print(", MTVAL=");
258
  __neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MTVAL));
259
  neorv32_uart_print(" </RTE>");
260 6 zero_gravi
}
261
 
262
 
263
/**********************************************************************//**
264
 * NEORV32 runtime environment: Print hardware configuration information via UART
265
 **************************************************************************/
266
void neorv32_rte_print_hw_config(void) {
267
 
268 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
269
    return; // cannot output anything if UART0 is not implemented
270
  }
271
 
272 6 zero_gravi
  uint32_t tmp;
273
  int i;
274
  char c;
275
 
276 49 zero_gravi
  neorv32_uart_printf("\n\n<<< Processor Configuration Overview >>>\n");
277 6 zero_gravi
 
278 49 zero_gravi
  // Processor - general stuff
279 61 zero_gravi
  neorv32_uart0_printf("\n=== << General >> ===\n"
280
                       "Clock:         %u Hz\n"
281
                       "User ID:       0x%x\n", SYSINFO_CLK, SYSINFO_USER_CODE);
282
  neorv32_uart0_printf("Full HW reset: "); __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_HW_RESET));
283
  neorv32_uart0_printf("Boot Config.:  Boot ");
284
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_BOOTLOADER)) {
285
    neorv32_uart0_printf("via Bootloader\n");
286
  }
287
  else {
288
    neorv32_uart0_printf("from memory (@ 0x%x)\n", SYSINFO_ISPACE_BASE);
289
  }
290
  neorv32_uart0_printf("On-chip debug: "); __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_OCD));
291 49 zero_gravi
 
292
 
293 6 zero_gravi
  // CPU configuration
294 61 zero_gravi
  neorv32_uart0_printf("\n=== << CPU >> ===\n");
295 6 zero_gravi
 
296 23 zero_gravi
  // ID
297 61 zero_gravi
  neorv32_uart0_printf("Hart ID:           0x%x\n"
298
                       "Vendor ID:         0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID), neorv32_cpu_csr_read(CSR_MVENDORID));
299 12 zero_gravi
 
300 23 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MARCHID);
301 61 zero_gravi
  neorv32_uart0_printf("Architecture ID:   0x%x", tmp);
302 32 zero_gravi
  if (tmp == NEORV32_ARCHID) {
303 61 zero_gravi
    neorv32_uart0_printf(" (NEORV32)");
304 32 zero_gravi
  }
305 23 zero_gravi
 
306 49 zero_gravi
  // hardware version
307 61 zero_gravi
  neorv32_uart0_printf("\nImplementation ID: 0x%x (", neorv32_cpu_csr_read(CSR_MIMPID));
308 12 zero_gravi
  neorv32_rte_print_hw_version();
309 61 zero_gravi
  neorv32_uart0_putc(')');
310 6 zero_gravi
 
311 60 zero_gravi
  // CPU architecture and endianness
312 61 zero_gravi
  neorv32_uart0_printf("\nArchitecture:      ");
313 6 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MISA);
314
  tmp = (tmp >> 30) & 0x03;
315
  if (tmp == 1) {
316 61 zero_gravi
    neorv32_uart0_printf("rv32-little");
317 6 zero_gravi
  }
318 40 zero_gravi
  else {
319 61 zero_gravi
    neorv32_uart0_printf("unknown");
320 40 zero_gravi
  }
321
 
322
  // CPU extensions
323 61 zero_gravi
  neorv32_uart0_printf("\nISA extensions:    ");
324 6 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MISA);
325
  for (i=0; i<26; i++) {
326
    if (tmp & (1 << i)) {
327
      c = (char)('A' + i);
328 61 zero_gravi
      neorv32_uart0_putc(c);
329
      neorv32_uart0_putc(' ');
330 6 zero_gravi
    }
331
  }
332 22 zero_gravi
 
333 40 zero_gravi
  // Z* CPU extensions (from custom "mzext" CSR)
334 22 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MZEXT);
335 42 zero_gravi
  if (tmp & (1<<CSR_MZEXT_ZICSR)) {
336 61 zero_gravi
    neorv32_uart0_printf("Zicsr ");
337 22 zero_gravi
  }
338 42 zero_gravi
  if (tmp & (1<<CSR_MZEXT_ZIFENCEI)) {
339 61 zero_gravi
    neorv32_uart0_printf("Zifencei ");
340 22 zero_gravi
  }
341 61 zero_gravi
  if (tmp & (1<<CSR_MZEXT_ZMMUL)) {
342
    neorv32_uart0_printf("Zmmul ");
343
  }
344 60 zero_gravi
 
345 53 zero_gravi
  if (tmp & (1<<CSR_MZEXT_ZFINX)) {
346 61 zero_gravi
    neorv32_uart0_printf("Zfinx ");
347 53 zero_gravi
  }
348 56 zero_gravi
  if (tmp & (1<<CSR_MZEXT_ZXNOCNT)) {
349 61 zero_gravi
    neorv32_uart0_printf("Zxnocnt(!) ");
350 56 zero_gravi
  }
351
  if (tmp & (1<<CSR_MZEXT_ZXSCNT)) {
352 61 zero_gravi
    neorv32_uart0_printf("Zxscnt(!) ");
353 56 zero_gravi
  }
354 59 zero_gravi
  if (tmp & (1<<CSR_MZEXT_DEBUGMODE)) {
355 61 zero_gravi
    neorv32_uart0_printf("Debug-Mode ");
356 59 zero_gravi
  }
357 6 zero_gravi
 
358 34 zero_gravi
  // check physical memory protection
359 61 zero_gravi
  neorv32_uart0_printf("\nPMP:               ");
360 42 zero_gravi
  uint32_t pmp_num_regions = neorv32_cpu_pmp_get_num_regions();
361
  if (pmp_num_regions != 0)  {
362 61 zero_gravi
    neorv32_uart0_printf("%u regions, %u bytes minimal granularity\n", pmp_num_regions, neorv32_cpu_pmp_get_granularity());
363 34 zero_gravi
  }
364
  else {
365 61 zero_gravi
    neorv32_uart0_printf("not implemented\n");
366 34 zero_gravi
  }
367
 
368 43 zero_gravi
  // check hardware performance monitors
369 61 zero_gravi
  neorv32_uart0_printf("HPM Counters:      %u counters, %u-bit wide\n", neorv32_cpu_hpm_get_counters(), neorv32_cpu_hpm_get_size());
370 34 zero_gravi
 
371 42 zero_gravi
 
372 6 zero_gravi
  // Memory configuration
373 61 zero_gravi
  neorv32_uart0_printf("\n=== << Memory Configuration >> ===\n");
374 6 zero_gravi
 
375 61 zero_gravi
  neorv32_uart0_printf("Instr. base address:  0x%x\n", SYSINFO_ISPACE_BASE);
376 56 zero_gravi
 
377
  // IMEM
378 61 zero_gravi
  neorv32_uart0_printf("Internal IMEM:        ");
379 56 zero_gravi
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM)) {
380 61 zero_gravi
    neorv32_uart0_printf("yes, %u bytes\n", SYSINFO_IMEM_SIZE);
381 56 zero_gravi
  }
382
  else {
383 61 zero_gravi
    neorv32_uart0_printf("no\n");
384 56 zero_gravi
  }
385 6 zero_gravi
 
386 56 zero_gravi
  // DMEM
387 61 zero_gravi
  neorv32_uart0_printf("Data base address:    0x%x\n", SYSINFO_DSPACE_BASE);
388
  neorv32_uart0_printf("Internal DMEM:        ");
389
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_DMEM)) { neorv32_uart0_printf("yes, %u bytes\n", SYSINFO_DMEM_SIZE); }
390
  else {  neorv32_uart0_printf("no\n"); }
391 6 zero_gravi
 
392 56 zero_gravi
  // i-cache
393 61 zero_gravi
  neorv32_uart0_printf("Internal i-cache:     ");
394 41 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE));
395
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE)) {
396 61 zero_gravi
    neorv32_uart0_printf("- ");
397 41 zero_gravi
 
398
    uint32_t ic_block_size = (SYSINFO_CACHE >> SYSINFO_CACHE_IC_BLOCK_SIZE_0) & 0x0F;
399
    if (ic_block_size) {
400
      ic_block_size = 1 << ic_block_size;
401
    }
402
    else {
403
      ic_block_size = 0;
404
    }
405
 
406
    uint32_t ic_num_blocks = (SYSINFO_CACHE >> SYSINFO_CACHE_IC_NUM_BLOCKS_0) & 0x0F;
407
    if (ic_num_blocks) {
408
      ic_num_blocks = 1 << ic_num_blocks;
409
    }
410
    else {
411
      ic_num_blocks = 0;
412
    }
413
 
414
    uint32_t ic_associativity = (SYSINFO_CACHE >> SYSINFO_CACHE_IC_ASSOCIATIVITY_0) & 0x0F;
415
    ic_associativity = 1 << ic_associativity;
416
 
417 61 zero_gravi
    neorv32_uart0_printf("%u bytes: %u set(s), %u block(s) per set, %u bytes per block", ic_associativity*ic_num_blocks*ic_block_size, ic_associativity, ic_num_blocks, ic_block_size);
418 45 zero_gravi
    if (ic_associativity == 1) {
419 61 zero_gravi
      neorv32_uart0_printf(" (direct-mapped)\n");
420 41 zero_gravi
    }
421 45 zero_gravi
    else if (((SYSINFO_CACHE >> SYSINFO_CACHE_IC_REPLACEMENT_0) & 0x0F) == 1) {
422 61 zero_gravi
      neorv32_uart0_printf(" (LRU replacement policy)\n");
423 41 zero_gravi
    }
424
    else {
425 61 zero_gravi
      neorv32_uart0_printf("\n");
426 41 zero_gravi
    }
427
  }
428
 
429 61 zero_gravi
  neorv32_uart0_printf("Ext. bus interface:   ");
430 12 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT));
431 61 zero_gravi
  neorv32_uart0_printf("Ext. bus Endianness:  ");
432 40 zero_gravi
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT_ENDIAN)) {
433 61 zero_gravi
    neorv32_uart0_printf("big\n");
434 40 zero_gravi
  }
435
  else {
436 61 zero_gravi
    neorv32_uart0_printf("little\n");
437 40 zero_gravi
  }
438 6 zero_gravi
 
439
  // peripherals
440 61 zero_gravi
  neorv32_uart0_printf("\n=== << Peripherals >> ===\n");
441 15 zero_gravi
 
442 12 zero_gravi
  tmp = SYSINFO_FEATURES;
443 61 zero_gravi
  neorv32_uart0_printf("GPIO   - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_GPIO));
444
  neorv32_uart0_printf("MTIME  - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_MTIME));
445
  neorv32_uart0_printf("UART0  - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_UART0));
446
  neorv32_uart0_printf("UART1  - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_UART1));
447
  neorv32_uart0_printf("SPI    - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_SPI));
448
  neorv32_uart0_printf("TWI    - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TWI));
449
  neorv32_uart0_printf("PWM    - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_PWM));
450
  neorv32_uart0_printf("WDT    - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_WDT));
451
  neorv32_uart0_printf("TRNG   - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TRNG));
452
  neorv32_uart0_printf("CFS    - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_CFS));
453
  neorv32_uart0_printf("SLINK  - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_SLINK));
454
  neorv32_uart0_printf("NEOLED - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_NEOLED));
455
  neorv32_uart0_printf("XIRQ   - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_XIRQ));
456 6 zero_gravi
}
457
 
458
 
459
/**********************************************************************//**
460 50 zero_gravi
 * NEORV32 runtime environment: Private function to print yes or no.
461 6 zero_gravi
 * @note This function is used by neorv32_rte_print_hw_config(void) only.
462
 *
463 50 zero_gravi
 * @param[in] state Print 'yes' when !=0, print '0' when 0
464 6 zero_gravi
 **************************************************************************/
465
static void __neorv32_rte_print_true_false(int state) {
466
 
467
  if (state) {
468 61 zero_gravi
    neorv32_uart0_print("yes\n");
469 6 zero_gravi
  }
470 2 zero_gravi
  else {
471 61 zero_gravi
    neorv32_uart0_print("no\n");
472 2 zero_gravi
  }
473 6 zero_gravi
}
474 2 zero_gravi
 
475
 
476 6 zero_gravi
/**********************************************************************//**
477 33 zero_gravi
 * NEORV32 runtime environment: Private function to print 32-bit number
478
 * as 8-digit hexadecimal value (with "0x" suffix).
479
 *
480
 * @param[in] num Number to print as hexadecimal.
481
 **************************************************************************/
482
void __neorv32_rte_print_hex_word(uint32_t num) {
483
 
484
  static const char hex_symbols[16] = "0123456789ABCDEF";
485
 
486 61 zero_gravi
  neorv32_uart0_print("0x");
487 33 zero_gravi
 
488
  int i;
489
  for (i=0; i<8; i++) {
490
    uint32_t index = (num >> (28 - 4*i)) & 0xF;
491 61 zero_gravi
    neorv32_uart0_putc(hex_symbols[index]);
492 33 zero_gravi
  }
493
}
494
 
495
 
496 47 zero_gravi
/**********************************************************************//**
497 41 zero_gravi
 * NEORV32 runtime environment: Print the processor version in human-readable format.
498 6 zero_gravi
 **************************************************************************/
499 12 zero_gravi
void neorv32_rte_print_hw_version(void) {
500 6 zero_gravi
 
501
  uint32_t i;
502
  char tmp, cnt;
503
 
504 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
505
    return; // cannot output anything if UART0 is not implemented
506
  }
507
 
508 6 zero_gravi
  for (i=0; i<4; i++) {
509
 
510 33 zero_gravi
    tmp = (char)(neorv32_cpu_csr_read(CSR_MIMPID) >> (24 - 8*i));
511 6 zero_gravi
 
512
    // serial division
513
    cnt = 0;
514 35 zero_gravi
    while (tmp >= 16) {
515
      tmp = tmp - 16;
516 6 zero_gravi
      cnt++;
517
    }
518
 
519
    if (cnt) {
520 61 zero_gravi
      neorv32_uart0_putc('0' + cnt);
521 6 zero_gravi
    }
522 61 zero_gravi
    neorv32_uart0_putc('0' + tmp);
523 6 zero_gravi
    if (i < 3) {
524 61 zero_gravi
      neorv32_uart0_putc('.');
525 6 zero_gravi
    }
526
  }
527 2 zero_gravi
}
528 11 zero_gravi
 
529
 
530
/**********************************************************************//**
531
 * NEORV32 runtime environment: Print project credits
532
 **************************************************************************/
533
void neorv32_rte_print_credits(void) {
534
 
535 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
536
    return; // cannot output anything if UART0 is not implemented
537
  }
538
 
539
  neorv32_uart0_print("The NEORV32 RISC-V Processor\n"
540
                      "(c) Stephan Nolting\n"
541
                      "BSD 3-Clause License\n"
542
                      "https://github.com/stnolting/neorv32\n\n");
543 11 zero_gravi
}
544
 
545 22 zero_gravi
 
546
/**********************************************************************//**
547 41 zero_gravi
 * NEORV32 runtime environment: Print project logo
548 37 zero_gravi
 **************************************************************************/
549
void neorv32_rte_print_logo(void) {
550
 
551 40 zero_gravi
  const uint32_t logo_data_c[11][4] =
552
  {
553
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000},
554
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
555
    {0b01100000110001111111110001111111,0b10000111111110001100000011000111,0b11111000011111111000000110000000,0b11111111111111110000000000000000},
556
    {0b11110000110011000000000011000000,0b11001100000011001100000011001100,0b00001100110000001100000110000011,0b11000000000000111100000000000000},
557
    {0b11011000110011000000000011000000,0b11001100000011001100000011000000,0b00001100000000011000000110000000,0b11000111111000110000000000000000},
558
    {0b11001100110011111111100011000000,0b11001111111110001100000011000000,0b11111000000001100000000110000011,0b11000111111000111100000000000000},
559
    {0b11000110110011000000000011000000,0b11001100001100000110000110000000,0b00001100000110000000000110000000,0b11000111111000110000000000000000},
560
    {0b11000011110011000000000011000000,0b11001100000110000011001100001100,0b00001100011000000000000110000011,0b11000000000000111100000000000000},
561
    {0b11000001100001111111110001111111,0b10001100000011000000110000000111,0b11111000111111111100000110000000,0b11111111111111110000000000000000},
562
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
563
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000}
564
  };
565
 
566
  int u,v,w;
567
  uint32_t tmp;
568
 
569 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
570
    return; // cannot output anything if UART0 is not implemented
571
  }
572
 
573 40 zero_gravi
  for (u=0; u<11; u++) {
574 61 zero_gravi
    neorv32_uart0_print("\n");
575 40 zero_gravi
    for (v=0; v<4; v++) {
576
      tmp = logo_data_c[u][v];
577
      for (w=0; w<32; w++){
578 61 zero_gravi
        if (((int32_t)tmp) < 0) { // check MSB
579
          neorv32_uart0_putc('#');
580 40 zero_gravi
        }
581
        else {
582 61 zero_gravi
          neorv32_uart0_putc(' ');
583 40 zero_gravi
        }
584 47 zero_gravi
        tmp <<= 1;
585 40 zero_gravi
      }
586
    }
587
  }
588 61 zero_gravi
  neorv32_uart0_print("\n");
589 37 zero_gravi
}
590
 
591
 
592
/**********************************************************************//**
593 22 zero_gravi
 * NEORV32 runtime environment: Print project license
594
 **************************************************************************/
595
void neorv32_rte_print_license(void) {
596
 
597 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
598
    return; // cannot output anything if UART0 is not implemented
599
  }
600
 
601 22 zero_gravi
  neorv32_uart_print(
602
  "\n"
603
  "BSD 3-Clause License\n"
604
  "\n"
605 42 zero_gravi
  "Copyright (c) 2021, Stephan Nolting. All rights reserved.\n"
606 22 zero_gravi
  "\n"
607
  "Redistribution and use in source and binary forms, with or without modification, are\n"
608
  "permitted provided that the following conditions are met:\n"
609
  "\n"
610
  "1. Redistributions of source code must retain the above copyright notice, this list of\n"
611
  "   conditions and the following disclaimer.\n"
612
  "\n"
613
  "2. Redistributions in binary form must reproduce the above copyright notice, this list of\n"
614
  "   conditions and the following disclaimer in the documentation and/or other materials\n"
615
  "   provided with the distribution.\n"
616
  "\n"
617
  "3. Neither the name of the copyright holder nor the names of its contributors may be used to\n"
618
  "   endorse or promote products derived from this software without specific prior written\n"
619
  "   permission.\n"
620
  "\n"
621
  "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n"
622
  "OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
623
  "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
624
  "COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n"
625
  "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n"
626
  "GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\n"
627
  "AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n"
628
  "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n"
629
  "OF THE POSSIBILITY OF SUCH DAMAGE.\n"
630
  "\n"
631
  "\n"
632
  );
633
}
634
 
635 44 zero_gravi
 
636
/**********************************************************************//**
637
 * NEORV32 runtime environment: Get MISA CSR value according to *compiler/toolchain configuration*.
638
 *
639
 * @return MISA content according to compiler configuration.
640
 **************************************************************************/
641
uint32_t neorv32_rte_get_compiler_isa(void) {
642
 
643
  uint32_t misa_cc = 0;
644
 
645 53 zero_gravi
#if defined __riscv_atomic || defined __riscv_a
646 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_A;
647 44 zero_gravi
#endif
648
 
649 53 zero_gravi
#ifdef __riscv_b
650 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_B;
651 53 zero_gravi
#endif
652
 
653
#if defined __riscv_compressed || defined __riscv_c
654 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_C;
655 44 zero_gravi
#endif
656
 
657 53 zero_gravi
#if (__riscv_flen == 64) || defined __riscv_d
658 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_D;
659 52 zero_gravi
#endif
660
 
661 44 zero_gravi
#ifdef __riscv_32e
662 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_E;
663 44 zero_gravi
#else
664 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_I;
665 44 zero_gravi
#endif
666
 
667 53 zero_gravi
#if (__riscv_flen == 32) || defined __riscv_f
668 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_F;
669 52 zero_gravi
#endif
670
 
671 53 zero_gravi
#if defined __riscv_mul || defined __riscv_m
672 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_M;
673 44 zero_gravi
#endif
674
 
675
#if (__riscv_xlen == 32)
676 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_MXL_LO;
677 44 zero_gravi
#elif (__riscv_xlen == 64)
678 61 zero_gravi
  misa_cc |= 2 << CSR_MISA_MXL_LO;
679 44 zero_gravi
#else
680 61 zero_gravi
  misa_cc |= 3 << CSR_MISA_MXL_LO;
681 44 zero_gravi
#endif
682
 
683
  return misa_cc;
684
}
685
 
686
 
687
/**********************************************************************//**
688
 * NEORV32 runtime environment: Check required ISA extensions (via compiler flags) against available ISA extensions (via MISA csr).
689
 *
690
 * @param[in] silent Show error message (via neorv32.uart) if isa_sw > isa_hw when != 0.
691
 * @return MISA content according to compiler configuration.
692
 **************************************************************************/
693
int neorv32_rte_check_isa(int silent) {
694
 
695
  uint32_t misa_sw = neorv32_rte_get_compiler_isa();
696
  uint32_t misa_hw = neorv32_cpu_csr_read(CSR_MISA);
697
 
698
  // mask hardware features that are not used by software
699
  uint32_t check = misa_hw & misa_sw;
700
 
701
  //
702
  if (check == misa_sw) {
703
    return 0;
704
  }
705
  else {
706 61 zero_gravi
    if ((silent == 0) || (neorv32_uart0_available() == 0)) {
707 44 zero_gravi
      neorv32_uart_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n"
708
                          "SW_ISA = 0x%x (compiler flags)\n"
709
                          "HW_ISA = 0x%x (misa csr)\n\n", misa_sw, misa_hw);
710
    }
711
    return 1;
712
  }
713
}
714
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.