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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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