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

Subversion Repositories neorv32

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

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 59 zero_gravi
  neorv32_uart_printf("On-chip debug: "); __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_OCD));
281 49 zero_gravi
 
282
 
283 6 zero_gravi
  // CPU configuration
284 49 zero_gravi
  neorv32_uart_printf("\n=== << CPU >> ===\n");
285 6 zero_gravi
 
286 23 zero_gravi
  // ID
287 30 zero_gravi
  neorv32_uart_printf("Hart ID:           0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID));
288
  neorv32_uart_printf("Vendor ID:         0x%x\n", neorv32_cpu_csr_read(CSR_MVENDORID));
289 12 zero_gravi
 
290 23 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MARCHID);
291 30 zero_gravi
  neorv32_uart_printf("Architecture ID:   0x%x", tmp);
292 32 zero_gravi
  if (tmp == NEORV32_ARCHID) {
293
    neorv32_uart_printf(" (NEORV32)");
294
  }
295 23 zero_gravi
 
296 49 zero_gravi
  // hardware version
297 30 zero_gravi
  neorv32_uart_printf("\nImplementation ID: 0x%x (", neorv32_cpu_csr_read(CSR_MIMPID));
298 12 zero_gravi
  neorv32_rte_print_hw_version();
299 60 zero_gravi
  neorv32_uart_putc(')');
300 6 zero_gravi
 
301 60 zero_gravi
  // CPU architecture and endianness
302
  neorv32_uart_printf("\nArchitecture:      ");
303 6 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MISA);
304
  tmp = (tmp >> 30) & 0x03;
305
  if (tmp == 1) {
306 60 zero_gravi
    neorv32_uart_printf("rv32-little");
307 6 zero_gravi
  }
308 40 zero_gravi
  else {
309 60 zero_gravi
    neorv32_uart_printf("unknown");
310 40 zero_gravi
  }
311
 
312
  // CPU extensions
313 60 zero_gravi
  neorv32_uart_printf("\nExtensions:        ");
314 6 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MISA);
315
  for (i=0; i<26; i++) {
316
    if (tmp & (1 << i)) {
317
      c = (char)('A' + i);
318
      neorv32_uart_putc(c);
319
      neorv32_uart_putc(' ');
320
    }
321
  }
322 22 zero_gravi
 
323 40 zero_gravi
  // Z* CPU extensions (from custom "mzext" CSR)
324 22 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MZEXT);
325 42 zero_gravi
  if (tmp & (1<<CSR_MZEXT_ZICSR)) {
326 22 zero_gravi
    neorv32_uart_printf("Zicsr ");
327
  }
328 42 zero_gravi
  if (tmp & (1<<CSR_MZEXT_ZIFENCEI)) {
329 22 zero_gravi
    neorv32_uart_printf("Zifencei ");
330
  }
331 60 zero_gravi
 
332 53 zero_gravi
  if (tmp & (1<<CSR_MZEXT_ZFINX)) {
333
    neorv32_uart_printf("Zfinx ");
334
  }
335 56 zero_gravi
  if (tmp & (1<<CSR_MZEXT_ZXNOCNT)) {
336
    neorv32_uart_printf("Zxnocnt(!) ");
337
  }
338
  if (tmp & (1<<CSR_MZEXT_ZXSCNT)) {
339
    neorv32_uart_printf("Zxscnt(!) ");
340
  }
341 59 zero_gravi
  if (tmp & (1<<CSR_MZEXT_DEBUGMODE)) {
342
    neorv32_uart_printf("Debug-Mode ");
343
  }
344 6 zero_gravi
 
345 34 zero_gravi
  // check physical memory protection
346 42 zero_gravi
  neorv32_uart_printf("\nPMP:               ");
347
  uint32_t pmp_num_regions = neorv32_cpu_pmp_get_num_regions();
348
  if (pmp_num_regions != 0)  {
349 43 zero_gravi
    neorv32_uart_printf("%u regions, %u bytes minimal granularity\n", pmp_num_regions, neorv32_cpu_pmp_get_granularity());
350 34 zero_gravi
  }
351
  else {
352
    neorv32_uart_printf("not implemented\n");
353
  }
354
 
355 43 zero_gravi
  // check hardware performance monitors
356 58 zero_gravi
  neorv32_uart_printf("HPM Counters:      %u counters, %u-bit wide\n", neorv32_cpu_hpm_get_counters(), neorv32_cpu_hpm_get_size());
357 34 zero_gravi
 
358 42 zero_gravi
 
359 6 zero_gravi
  // Memory configuration
360 49 zero_gravi
  neorv32_uart_printf("\n=== << Memory Configuration >> ===\n");
361 6 zero_gravi
 
362 23 zero_gravi
  neorv32_uart_printf("Instr. base address:  0x%x\n", SYSINFO_ISPACE_BASE);
363 56 zero_gravi
 
364
  // IMEM
365 6 zero_gravi
  neorv32_uart_printf("Internal IMEM:        ");
366 56 zero_gravi
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM)) {
367
    neorv32_uart_printf("yes, %u bytes", SYSINFO_IMEM_SIZE);
368
    if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)) {
369
      neorv32_uart_printf(", read-only (ROM)");
370
    }
371
  }
372
  else {
373
    neorv32_uart_printf("no");
374
  }
375
  neorv32_uart_printf("\n");
376 6 zero_gravi
 
377 56 zero_gravi
  // DMEM
378 42 zero_gravi
  neorv32_uart_printf("Data base address:    0x%x\n", SYSINFO_DSPACE_BASE);
379 6 zero_gravi
  neorv32_uart_printf("Internal DMEM:        ");
380 56 zero_gravi
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_DMEM)) { neorv32_uart_printf("yes, %u bytes\n", SYSINFO_DMEM_SIZE); }
381
  else {  neorv32_uart_printf("no\n"); }
382 6 zero_gravi
 
383 56 zero_gravi
  // i-cache
384 42 zero_gravi
  neorv32_uart_printf("Internal i-cache:     ");
385 41 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE));
386
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE)) {
387
    neorv32_uart_printf("- ");
388
 
389
    uint32_t ic_block_size = (SYSINFO_CACHE >> SYSINFO_CACHE_IC_BLOCK_SIZE_0) & 0x0F;
390
    if (ic_block_size) {
391
      ic_block_size = 1 << ic_block_size;
392
    }
393
    else {
394
      ic_block_size = 0;
395
    }
396
 
397
    uint32_t ic_num_blocks = (SYSINFO_CACHE >> SYSINFO_CACHE_IC_NUM_BLOCKS_0) & 0x0F;
398
    if (ic_num_blocks) {
399
      ic_num_blocks = 1 << ic_num_blocks;
400
    }
401
    else {
402
      ic_num_blocks = 0;
403
    }
404
 
405
    uint32_t ic_associativity = (SYSINFO_CACHE >> SYSINFO_CACHE_IC_ASSOCIATIVITY_0) & 0x0F;
406
    ic_associativity = 1 << ic_associativity;
407
 
408 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);
409
    if (ic_associativity == 1) {
410
      neorv32_uart_printf(" (direct-mapped)\n");
411 41 zero_gravi
    }
412 45 zero_gravi
    else if (((SYSINFO_CACHE >> SYSINFO_CACHE_IC_REPLACEMENT_0) & 0x0F) == 1) {
413
      neorv32_uart_printf(" (LRU replacement policy)\n");
414 41 zero_gravi
    }
415
    else {
416 45 zero_gravi
      neorv32_uart_printf("\n");
417 41 zero_gravi
    }
418
  }
419
 
420 42 zero_gravi
  neorv32_uart_printf("Bootloader:           ");
421 12 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_BOOTLOADER));
422 6 zero_gravi
 
423 42 zero_gravi
  neorv32_uart_printf("Ext. bus interface:   ");
424 12 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT));
425 42 zero_gravi
  neorv32_uart_printf("Ext. bus Endianness:  ");
426 40 zero_gravi
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT_ENDIAN)) {
427
    neorv32_uart_printf("big\n");
428
  }
429
  else {
430
    neorv32_uart_printf("little\n");
431
  }
432 6 zero_gravi
 
433
  // peripherals
434 49 zero_gravi
  neorv32_uart_printf("\n=== << Peripherals >> ===\n");
435 15 zero_gravi
 
436 12 zero_gravi
  tmp = SYSINFO_FEATURES;
437 6 zero_gravi
 
438 52 zero_gravi
  neorv32_uart_printf("GPIO   - ");
439 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_GPIO));
440 6 zero_gravi
 
441 52 zero_gravi
  neorv32_uart_printf("MTIME  - ");
442 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_MTIME));
443 6 zero_gravi
 
444 52 zero_gravi
  neorv32_uart_printf("UART0  - ");
445 50 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_UART0));
446 6 zero_gravi
 
447 52 zero_gravi
  neorv32_uart_printf("UART1  - ");
448 50 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_UART1));
449
 
450 52 zero_gravi
  neorv32_uart_printf("SPI    - ");
451 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_SPI));
452 6 zero_gravi
 
453 52 zero_gravi
  neorv32_uart_printf("TWI    - ");
454 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TWI));
455 6 zero_gravi
 
456 52 zero_gravi
  neorv32_uart_printf("PWM    - ");
457 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_PWM));
458 6 zero_gravi
 
459 52 zero_gravi
  neorv32_uart_printf("WDT    - ");
460 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_WDT));
461 6 zero_gravi
 
462 52 zero_gravi
  neorv32_uart_printf("TRNG   - ");
463 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TRNG));
464 6 zero_gravi
 
465 52 zero_gravi
  neorv32_uart_printf("CFS    - ");
466 47 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_CFS));
467 49 zero_gravi
 
468 52 zero_gravi
  neorv32_uart_printf("NCO    - ");
469 49 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_NCO));
470 52 zero_gravi
 
471
  neorv32_uart_printf("NEOLED - ");
472
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_NEOLED));
473 6 zero_gravi
}
474
 
475
 
476
/**********************************************************************//**
477 50 zero_gravi
 * NEORV32 runtime environment: Private function to print yes or no.
478 6 zero_gravi
 * @note This function is used by neorv32_rte_print_hw_config(void) only.
479
 *
480 50 zero_gravi
 * @param[in] state Print 'yes' when !=0, print '0' when 0
481 6 zero_gravi
 **************************************************************************/
482
static void __neorv32_rte_print_true_false(int state) {
483
 
484
  if (state) {
485 50 zero_gravi
    neorv32_uart_print("yes\n");
486 6 zero_gravi
  }
487 2 zero_gravi
  else {
488 50 zero_gravi
    neorv32_uart_print("no\n");
489 2 zero_gravi
  }
490 6 zero_gravi
}
491 2 zero_gravi
 
492
 
493 6 zero_gravi
/**********************************************************************//**
494 33 zero_gravi
 * NEORV32 runtime environment: Private function to print 32-bit number
495
 * as 8-digit hexadecimal value (with "0x" suffix).
496
 *
497
 * @param[in] num Number to print as hexadecimal.
498
 **************************************************************************/
499
void __neorv32_rte_print_hex_word(uint32_t num) {
500
 
501
  static const char hex_symbols[16] = "0123456789ABCDEF";
502
 
503
  neorv32_uart_print("0x");
504
 
505
  int i;
506
  for (i=0; i<8; i++) {
507
    uint32_t index = (num >> (28 - 4*i)) & 0xF;
508
    neorv32_uart_putc(hex_symbols[index]);
509
  }
510
}
511
 
512
 
513 47 zero_gravi
/**********************************************************************//**
514 41 zero_gravi
 * NEORV32 runtime environment: Print the processor version in human-readable format.
515 6 zero_gravi
 **************************************************************************/
516 12 zero_gravi
void neorv32_rte_print_hw_version(void) {
517 6 zero_gravi
 
518
  uint32_t i;
519
  char tmp, cnt;
520
 
521
  for (i=0; i<4; i++) {
522
 
523 33 zero_gravi
    tmp = (char)(neorv32_cpu_csr_read(CSR_MIMPID) >> (24 - 8*i));
524 6 zero_gravi
 
525
    // serial division
526
    cnt = 0;
527 35 zero_gravi
    while (tmp >= 16) {
528
      tmp = tmp - 16;
529 6 zero_gravi
      cnt++;
530
    }
531
 
532
    if (cnt) {
533
      neorv32_uart_putc('0' + cnt);
534
    }
535
    neorv32_uart_putc('0' + tmp);
536
    if (i < 3) {
537
      neorv32_uart_putc('.');
538
    }
539
  }
540 2 zero_gravi
}
541 11 zero_gravi
 
542
 
543
/**********************************************************************//**
544
 * NEORV32 runtime environment: Print project credits
545
 **************************************************************************/
546
void neorv32_rte_print_credits(void) {
547
 
548 42 zero_gravi
  neorv32_uart_print("The NEORV32 Processor Project\n"
549
                     "Copyright 2021, Stephan Nolting\n"
550
                     "BSD 3-Clause License\n"
551 39 zero_gravi
                     "https://github.com/stnolting/neorv32\n\n");
552 11 zero_gravi
}
553
 
554 22 zero_gravi
 
555
/**********************************************************************//**
556 41 zero_gravi
 * NEORV32 runtime environment: Print project logo
557 37 zero_gravi
 **************************************************************************/
558
void neorv32_rte_print_logo(void) {
559
 
560 40 zero_gravi
  const uint32_t logo_data_c[11][4] =
561
  {
562
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000},
563
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
564
    {0b01100000110001111111110001111111,0b10000111111110001100000011000111,0b11111000011111111000000110000000,0b11111111111111110000000000000000},
565
    {0b11110000110011000000000011000000,0b11001100000011001100000011001100,0b00001100110000001100000110000011,0b11000000000000111100000000000000},
566
    {0b11011000110011000000000011000000,0b11001100000011001100000011000000,0b00001100000000011000000110000000,0b11000111111000110000000000000000},
567
    {0b11001100110011111111100011000000,0b11001111111110001100000011000000,0b11111000000001100000000110000011,0b11000111111000111100000000000000},
568
    {0b11000110110011000000000011000000,0b11001100001100000110000110000000,0b00001100000110000000000110000000,0b11000111111000110000000000000000},
569
    {0b11000011110011000000000011000000,0b11001100000110000011001100001100,0b00001100011000000000000110000011,0b11000000000000111100000000000000},
570
    {0b11000001100001111111110001111111,0b10001100000011000000110000000111,0b11111000111111111100000110000000,0b11111111111111110000000000000000},
571
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
572
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000}
573
  };
574
 
575
  int u,v,w;
576
  uint32_t tmp;
577
 
578
  for (u=0; u<11; u++) {
579
    neorv32_uart_print("\n");
580
    for (v=0; v<4; v++) {
581
      tmp = logo_data_c[u][v];
582
      for (w=0; w<32; w++){
583 47 zero_gravi
        if (tmp & 0x80000000UL) { // check MSB
584 40 zero_gravi
          neorv32_uart_putc('#');
585
        }
586
        else {
587
          neorv32_uart_putc(' ');
588
        }
589 47 zero_gravi
        tmp <<= 1;
590 40 zero_gravi
      }
591
    }
592
  }
593
  neorv32_uart_print("\n");
594 37 zero_gravi
}
595
 
596
 
597
/**********************************************************************//**
598 22 zero_gravi
 * NEORV32 runtime environment: Print project license
599
 **************************************************************************/
600
void neorv32_rte_print_license(void) {
601
 
602
  neorv32_uart_print(
603
  "\n"
604
  "BSD 3-Clause License\n"
605
  "\n"
606 42 zero_gravi
  "Copyright (c) 2021, Stephan Nolting. All rights reserved.\n"
607 22 zero_gravi
  "\n"
608
  "Redistribution and use in source and binary forms, with or without modification, are\n"
609
  "permitted provided that the following conditions are met:\n"
610
  "\n"
611
  "1. Redistributions of source code must retain the above copyright notice, this list of\n"
612
  "   conditions and the following disclaimer.\n"
613
  "\n"
614
  "2. Redistributions in binary form must reproduce the above copyright notice, this list of\n"
615
  "   conditions and the following disclaimer in the documentation and/or other materials\n"
616
  "   provided with the distribution.\n"
617
  "\n"
618
  "3. Neither the name of the copyright holder nor the names of its contributors may be used to\n"
619
  "   endorse or promote products derived from this software without specific prior written\n"
620
  "   permission.\n"
621
  "\n"
622
  "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n"
623
  "OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
624
  "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
625
  "COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n"
626
  "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n"
627
  "GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\n"
628
  "AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n"
629
  "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n"
630
  "OF THE POSSIBILITY OF SUCH DAMAGE.\n"
631
  "\n"
632
  "\n"
633
  );
634
}
635
 
636 44 zero_gravi
 
637
/**********************************************************************//**
638
 * NEORV32 runtime environment: Get MISA CSR value according to *compiler/toolchain configuration*.
639
 *
640
 * @return MISA content according to compiler configuration.
641
 **************************************************************************/
642
uint32_t neorv32_rte_get_compiler_isa(void) {
643
 
644
  uint32_t misa_cc = 0;
645
 
646 53 zero_gravi
#if defined __riscv_atomic || defined __riscv_a
647 44 zero_gravi
  misa_cc |= 1 << CSR_MISA_A_EXT;
648
#endif
649
 
650 53 zero_gravi
#ifdef __riscv_b
651
  misa_cc |= 1 << CSR_MISA_B_EXT;
652
#endif
653
 
654
#if defined __riscv_compressed || defined __riscv_c
655 44 zero_gravi
  misa_cc |= 1 << CSR_MISA_C_EXT;
656
#endif
657
 
658 53 zero_gravi
#if (__riscv_flen == 64) || defined __riscv_d
659 52 zero_gravi
  misa_cc |= 1 << CSR_MISA_D_EXT;
660
#endif
661
 
662 44 zero_gravi
#ifdef __riscv_32e
663
  misa_cc |= 1 << CSR_MISA_E_EXT;
664
#else
665
  misa_cc |= 1 << CSR_MISA_I_EXT;
666
#endif
667
 
668 53 zero_gravi
#if (__riscv_flen == 32) || defined __riscv_f
669 52 zero_gravi
  misa_cc |= 1 << CSR_MISA_F_EXT;
670
#endif
671
 
672 53 zero_gravi
#if defined __riscv_mul || defined __riscv_m
673 44 zero_gravi
  misa_cc |= 1 << CSR_MISA_M_EXT;
674
#endif
675
 
676
#if (__riscv_xlen == 32)
677
  misa_cc |= 1 << CSR_MISA_MXL_LO_EXT;
678
#elif (__riscv_xlen == 64)
679
  misa_cc |= 2 << CSR_MISA_MXL_LO_EXT;
680
#else
681
  misa_cc |= 3 << CSR_MISA_MXL_LO_EXT;
682
#endif
683
 
684
  return misa_cc;
685
}
686
 
687
 
688
/**********************************************************************//**
689
 * NEORV32 runtime environment: Check required ISA extensions (via compiler flags) against available ISA extensions (via MISA csr).
690
 *
691
 * @param[in] silent Show error message (via neorv32.uart) if isa_sw > isa_hw when != 0.
692
 * @return MISA content according to compiler configuration.
693
 **************************************************************************/
694
int neorv32_rte_check_isa(int silent) {
695
 
696
  uint32_t misa_sw = neorv32_rte_get_compiler_isa();
697
  uint32_t misa_hw = neorv32_cpu_csr_read(CSR_MISA);
698
 
699
  // mask hardware features that are not used by software
700
  uint32_t check = misa_hw & misa_sw;
701
 
702
  //
703
  if (check == misa_sw) {
704
    return 0;
705
  }
706
  else {
707
    if (silent == 0) {
708
      neorv32_uart_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n"
709
                          "SW_ISA = 0x%x (compiler flags)\n"
710
                          "HW_ISA = 0x%x (misa csr)\n\n", misa_sw, misa_hw);
711
    }
712
    return 1;
713
  }
714
}
715
 

powered by: WebSVN 2.1.0

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