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

Subversion Repositories neorv32

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

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

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

powered by: WebSVN 2.1.0

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