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

Subversion Repositories neorv32

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

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