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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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