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

Subversion Repositories neorv32

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

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 64 zero_gravi
static void __attribute__((__interrupt__)) __neorv32_rte_core(void) __attribute__((aligned(16)));
52
static void __neorv32_rte_debug_exc_handler(void);
53
static void __neorv32_rte_print_true_false(int state);
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
    case TRAP_CODE_MSI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MSI]; break;
166
    case TRAP_CODE_MTI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MTI]; break;
167
    case TRAP_CODE_MEI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MEI]; break;
168
    case TRAP_CODE_FIRQ_0:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_0]; break;
169
    case TRAP_CODE_FIRQ_1:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_1]; break;
170
    case TRAP_CODE_FIRQ_2:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_2]; break;
171
    case TRAP_CODE_FIRQ_3:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_3]; break;
172 47 zero_gravi
    case TRAP_CODE_FIRQ_4:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_4]; break;
173
    case TRAP_CODE_FIRQ_5:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_5]; break;
174
    case TRAP_CODE_FIRQ_6:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_6]; break;
175
    case TRAP_CODE_FIRQ_7:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_7]; break;
176 48 zero_gravi
    case TRAP_CODE_FIRQ_8:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_8]; break;
177
    case TRAP_CODE_FIRQ_9:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_9]; break;
178
    case TRAP_CODE_FIRQ_10:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_10]; break;
179
    case TRAP_CODE_FIRQ_11:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_11]; break;
180
    case TRAP_CODE_FIRQ_12:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_12]; break;
181
    case TRAP_CODE_FIRQ_13:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_13]; break;
182
    case TRAP_CODE_FIRQ_14:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_14]; break;
183
    case TRAP_CODE_FIRQ_15:      rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_15]; break;
184 14 zero_gravi
    default: break;
185
  }
186
 
187
  // execute handler
188
  void (*handler_pnt)(void);
189
  handler_pnt = (void*)rte_handler;
190
  (*handler_pnt)();
191 2 zero_gravi
}
192
 
193
 
194
/**********************************************************************//**
195
 * NEORV32 runtime environment: Debug exception handler, printing various exception/interrupt information via UART.
196 14 zero_gravi
 * @note This function is used by neorv32_rte_exception_uninstall(void) only.
197 2 zero_gravi
 **************************************************************************/
198
static void __neorv32_rte_debug_exc_handler(void) {
199
 
200 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
201
    return; // handler cannot output anything if UART0 is not implemented
202
  }
203
 
204 48 zero_gravi
  char tmp;
205
 
206 15 zero_gravi
  // intro
207 33 zero_gravi
  neorv32_uart_print("<RTE> ");
208 2 zero_gravi
 
209 15 zero_gravi
  // cause
210 7 zero_gravi
  register uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
211 48 zero_gravi
  tmp = (char)(trap_cause & 0xf);
212
  if (tmp >= 10) {
213
    tmp = 'a' + (tmp - 10);
214
  }
215
  else {
216
    tmp = '0' + tmp;
217
  }
218 7 zero_gravi
  switch (trap_cause) {
219 33 zero_gravi
    case TRAP_CODE_I_MISALIGNED: neorv32_uart_print("Instruction address misaligned"); break;
220
    case TRAP_CODE_I_ACCESS:     neorv32_uart_print("Instruction access fault"); break;
221
    case TRAP_CODE_I_ILLEGAL:    neorv32_uart_print("Illegal instruction"); break;
222
    case TRAP_CODE_BREAKPOINT:   neorv32_uart_print("Breakpoint"); break;
223
    case TRAP_CODE_L_MISALIGNED: neorv32_uart_print("Load address misaligned"); break;
224
    case TRAP_CODE_L_ACCESS:     neorv32_uart_print("Load access fault"); break;
225
    case TRAP_CODE_S_MISALIGNED: neorv32_uart_print("Store address misaligned"); break;
226
    case TRAP_CODE_S_ACCESS:     neorv32_uart_print("Store access fault"); break;
227 40 zero_gravi
    case TRAP_CODE_UENV_CALL:    neorv32_uart_print("Environment call from U-mode"); break;
228
    case TRAP_CODE_MENV_CALL:    neorv32_uart_print("Environment call from M-mode"); break;
229 33 zero_gravi
    case TRAP_CODE_MSI:          neorv32_uart_print("Machine software interrupt"); break;
230
    case TRAP_CODE_MTI:          neorv32_uart_print("Machine timer interrupt"); break;
231
    case TRAP_CODE_MEI:          neorv32_uart_print("Machine external interrupt"); break;
232 47 zero_gravi
    case TRAP_CODE_FIRQ_0:
233
    case TRAP_CODE_FIRQ_1:
234
    case TRAP_CODE_FIRQ_2:
235
    case TRAP_CODE_FIRQ_3:
236
    case TRAP_CODE_FIRQ_4:
237
    case TRAP_CODE_FIRQ_5:
238
    case TRAP_CODE_FIRQ_6:
239 48 zero_gravi
    case TRAP_CODE_FIRQ_7:
240
    case TRAP_CODE_FIRQ_8:
241
    case TRAP_CODE_FIRQ_9:
242
    case TRAP_CODE_FIRQ_10:
243
    case TRAP_CODE_FIRQ_11:
244
    case TRAP_CODE_FIRQ_12:
245
    case TRAP_CODE_FIRQ_13:
246
    case TRAP_CODE_FIRQ_14:
247
    case TRAP_CODE_FIRQ_15:      neorv32_uart_print("Fast interrupt "); neorv32_uart_putc(tmp); break;
248 33 zero_gravi
    default:                     neorv32_uart_print("Unknown trap cause: "); __neorv32_rte_print_hex_word(trap_cause); break;
249 2 zero_gravi
  }
250
 
251 33 zero_gravi
  // instruction address
252 35 zero_gravi
  neorv32_uart_print(" @ PC=");
253 33 zero_gravi
  __neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MSCRATCH)); // rte core stores actual mepc to mscratch
254 15 zero_gravi
 
255 33 zero_gravi
  // additional info
256
  neorv32_uart_print(", MTVAL=");
257
  __neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MTVAL));
258
  neorv32_uart_print(" </RTE>");
259 6 zero_gravi
}
260
 
261
 
262
/**********************************************************************//**
263
 * NEORV32 runtime environment: Print hardware configuration information via UART
264
 **************************************************************************/
265
void neorv32_rte_print_hw_config(void) {
266
 
267 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
268
    return; // cannot output anything if UART0 is not implemented
269
  }
270
 
271 6 zero_gravi
  uint32_t tmp;
272
  int i;
273
  char c;
274
 
275 49 zero_gravi
  neorv32_uart_printf("\n\n<<< Processor Configuration Overview >>>\n");
276 6 zero_gravi
 
277 49 zero_gravi
  // Processor - general stuff
278 61 zero_gravi
  neorv32_uart0_printf("\n=== << General >> ===\n"
279 64 zero_gravi
                       "Clock speed:   %u Hz\n", NEORV32_SYSINFO.CLK);
280
  neorv32_uart0_printf("Full HW reset: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_HW_RESET));
281 61 zero_gravi
  neorv32_uart0_printf("Boot Config.:  Boot ");
282 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_BOOTLOADER)) {
283 61 zero_gravi
    neorv32_uart0_printf("via Bootloader\n");
284
  }
285
  else {
286 64 zero_gravi
    neorv32_uart0_printf("from memory (@ 0x%x)\n", NEORV32_SYSINFO.ISPACE_BASE);
287 61 zero_gravi
  }
288 64 zero_gravi
  neorv32_uart0_printf("On-chip debug: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_OCD));
289 49 zero_gravi
 
290
 
291 6 zero_gravi
  // CPU configuration
292 61 zero_gravi
  neorv32_uart0_printf("\n=== << CPU >> ===\n");
293 6 zero_gravi
 
294 23 zero_gravi
  // ID
295 61 zero_gravi
  neorv32_uart0_printf("Hart ID:           0x%x\n"
296
                       "Vendor ID:         0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID), neorv32_cpu_csr_read(CSR_MVENDORID));
297 12 zero_gravi
 
298 23 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MARCHID);
299 61 zero_gravi
  neorv32_uart0_printf("Architecture ID:   0x%x", tmp);
300 32 zero_gravi
  if (tmp == NEORV32_ARCHID) {
301 61 zero_gravi
    neorv32_uart0_printf(" (NEORV32)");
302 32 zero_gravi
  }
303 23 zero_gravi
 
304 49 zero_gravi
  // hardware version
305 61 zero_gravi
  neorv32_uart0_printf("\nImplementation ID: 0x%x (", neorv32_cpu_csr_read(CSR_MIMPID));
306 12 zero_gravi
  neorv32_rte_print_hw_version();
307 61 zero_gravi
  neorv32_uart0_putc(')');
308 6 zero_gravi
 
309 60 zero_gravi
  // CPU architecture and endianness
310 61 zero_gravi
  neorv32_uart0_printf("\nArchitecture:      ");
311 6 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MISA);
312
  tmp = (tmp >> 30) & 0x03;
313
  if (tmp == 1) {
314 61 zero_gravi
    neorv32_uart0_printf("rv32-little");
315 6 zero_gravi
  }
316 40 zero_gravi
  else {
317 61 zero_gravi
    neorv32_uart0_printf("unknown");
318 40 zero_gravi
  }
319
 
320
  // CPU extensions
321 61 zero_gravi
  neorv32_uart0_printf("\nISA extensions:    ");
322 6 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MISA);
323
  for (i=0; i<26; i++) {
324
    if (tmp & (1 << i)) {
325
      c = (char)('A' + i);
326 61 zero_gravi
      neorv32_uart0_putc(c);
327
      neorv32_uart0_putc(' ');
328 6 zero_gravi
    }
329
  }
330 22 zero_gravi
 
331 63 zero_gravi
  // Z* CPU extensions
332 64 zero_gravi
  tmp = NEORV32_SYSINFO.CPU;
333 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_ZICSR)) {
334 61 zero_gravi
    neorv32_uart0_printf("Zicsr ");
335 22 zero_gravi
  }
336 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_ZIFENCEI)) {
337 61 zero_gravi
    neorv32_uart0_printf("Zifencei ");
338 22 zero_gravi
  }
339 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_ZMMUL)) {
340 61 zero_gravi
    neorv32_uart0_printf("Zmmul ");
341
  }
342 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_ZBB)) {
343
    neorv32_uart0_printf("Zbb ");
344
  }
345 60 zero_gravi
 
346 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_ZFINX)) {
347 61 zero_gravi
    neorv32_uart0_printf("Zfinx ");
348 53 zero_gravi
  }
349 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_ZXNOCNT)) {
350 61 zero_gravi
    neorv32_uart0_printf("Zxnocnt(!) ");
351 56 zero_gravi
  }
352 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_ZXSCNT)) {
353 61 zero_gravi
    neorv32_uart0_printf("Zxscnt(!) ");
354 56 zero_gravi
  }
355 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_DEBUGMODE)) {
356 61 zero_gravi
    neorv32_uart0_printf("Debug-Mode ");
357 59 zero_gravi
  }
358 6 zero_gravi
 
359 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_FASTMUL)) {
360
    neorv32_uart0_printf("FAST_MUL ");
361
  }
362
  if (tmp & (1<<SYSINFO_CPU_FASTSHIFT)) {
363
    neorv32_uart0_printf("FAST_SHIFT ");
364
  }
365
 
366 34 zero_gravi
  // check physical memory protection
367 61 zero_gravi
  neorv32_uart0_printf("\nPMP:               ");
368 42 zero_gravi
  uint32_t pmp_num_regions = neorv32_cpu_pmp_get_num_regions();
369
  if (pmp_num_regions != 0)  {
370 61 zero_gravi
    neorv32_uart0_printf("%u regions, %u bytes minimal granularity\n", pmp_num_regions, neorv32_cpu_pmp_get_granularity());
371 34 zero_gravi
  }
372
  else {
373 61 zero_gravi
    neorv32_uart0_printf("not implemented\n");
374 34 zero_gravi
  }
375
 
376 43 zero_gravi
  // check hardware performance monitors
377 61 zero_gravi
  neorv32_uart0_printf("HPM Counters:      %u counters, %u-bit wide\n", neorv32_cpu_hpm_get_counters(), neorv32_cpu_hpm_get_size());
378 34 zero_gravi
 
379 42 zero_gravi
 
380 6 zero_gravi
  // Memory configuration
381 61 zero_gravi
  neorv32_uart0_printf("\n=== << Memory Configuration >> ===\n");
382 6 zero_gravi
 
383 64 zero_gravi
  neorv32_uart0_printf("Instr. base address:  0x%x\n", NEORV32_SYSINFO.ISPACE_BASE);
384 56 zero_gravi
 
385
  // IMEM
386 61 zero_gravi
  neorv32_uart0_printf("Internal IMEM:        ");
387 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_IMEM)) {
388
    neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.IMEM_SIZE);
389 56 zero_gravi
  }
390
  else {
391 61 zero_gravi
    neorv32_uart0_printf("no\n");
392 56 zero_gravi
  }
393 6 zero_gravi
 
394 56 zero_gravi
  // DMEM
395 64 zero_gravi
  neorv32_uart0_printf("Data base address:    0x%x\n", NEORV32_SYSINFO.DSPACE_BASE);
396 61 zero_gravi
  neorv32_uart0_printf("Internal DMEM:        ");
397 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_DMEM)) { neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.DMEM_SIZE); }
398 61 zero_gravi
  else {  neorv32_uart0_printf("no\n"); }
399 6 zero_gravi
 
400 56 zero_gravi
  // i-cache
401 61 zero_gravi
  neorv32_uart0_printf("Internal i-cache:     ");
402 64 zero_gravi
  __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_ICACHE));
403
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_ICACHE)) {
404 61 zero_gravi
    neorv32_uart0_printf("- ");
405 41 zero_gravi
 
406 64 zero_gravi
    uint32_t ic_block_size = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_BLOCK_SIZE_0) & 0x0F;
407 41 zero_gravi
    if (ic_block_size) {
408
      ic_block_size = 1 << ic_block_size;
409
    }
410
    else {
411
      ic_block_size = 0;
412
    }
413
 
414 64 zero_gravi
    uint32_t ic_num_blocks = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_NUM_BLOCKS_0) & 0x0F;
415 41 zero_gravi
    if (ic_num_blocks) {
416
      ic_num_blocks = 1 << ic_num_blocks;
417
    }
418
    else {
419
      ic_num_blocks = 0;
420
    }
421
 
422 64 zero_gravi
    uint32_t ic_associativity = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_ASSOCIATIVITY_0) & 0x0F;
423 41 zero_gravi
    ic_associativity = 1 << ic_associativity;
424
 
425 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);
426 45 zero_gravi
    if (ic_associativity == 1) {
427 61 zero_gravi
      neorv32_uart0_printf(" (direct-mapped)\n");
428 41 zero_gravi
    }
429 64 zero_gravi
    else if (((NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_REPLACEMENT_0) & 0x0F) == 1) {
430 61 zero_gravi
      neorv32_uart0_printf(" (LRU replacement policy)\n");
431 41 zero_gravi
    }
432
    else {
433 61 zero_gravi
      neorv32_uart0_printf("\n");
434 41 zero_gravi
    }
435
  }
436
 
437 61 zero_gravi
  neorv32_uart0_printf("Ext. bus interface:   ");
438 64 zero_gravi
  __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT));
439 61 zero_gravi
  neorv32_uart0_printf("Ext. bus Endianness:  ");
440 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT_ENDIAN)) {
441 61 zero_gravi
    neorv32_uart0_printf("big\n");
442 40 zero_gravi
  }
443
  else {
444 61 zero_gravi
    neorv32_uart0_printf("little\n");
445 40 zero_gravi
  }
446 6 zero_gravi
 
447
  // peripherals
448 61 zero_gravi
  neorv32_uart0_printf("\n=== << Peripherals >> ===\n");
449 15 zero_gravi
 
450 64 zero_gravi
  tmp = NEORV32_SYSINFO.SOC;
451
  neorv32_uart0_printf("GPIO   - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_GPIO));
452
  neorv32_uart0_printf("MTIME  - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_MTIME));
453
  neorv32_uart0_printf("UART0  - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_UART0));
454
  neorv32_uart0_printf("UART1  - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_UART1));
455
  neorv32_uart0_printf("SPI    - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_SPI));
456
  neorv32_uart0_printf("TWI    - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_TWI));
457
  neorv32_uart0_printf("PWM    - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_PWM));
458
  neorv32_uart0_printf("WDT    - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_WDT));
459
  neorv32_uart0_printf("TRNG   - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_TRNG));
460
  neorv32_uart0_printf("CFS    - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_CFS));
461
  neorv32_uart0_printf("SLINK  - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_SLINK));
462
  neorv32_uart0_printf("NEOLED - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_NEOLED));
463
  neorv32_uart0_printf("XIRQ   - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_XIRQ));
464 6 zero_gravi
}
465
 
466
 
467
/**********************************************************************//**
468 50 zero_gravi
 * NEORV32 runtime environment: Private function to print yes or no.
469 6 zero_gravi
 * @note This function is used by neorv32_rte_print_hw_config(void) only.
470
 *
471 50 zero_gravi
 * @param[in] state Print 'yes' when !=0, print '0' when 0
472 6 zero_gravi
 **************************************************************************/
473
static void __neorv32_rte_print_true_false(int state) {
474
 
475
  if (state) {
476 61 zero_gravi
    neorv32_uart0_print("yes\n");
477 6 zero_gravi
  }
478 2 zero_gravi
  else {
479 61 zero_gravi
    neorv32_uart0_print("no\n");
480 2 zero_gravi
  }
481 6 zero_gravi
}
482 2 zero_gravi
 
483
 
484 6 zero_gravi
/**********************************************************************//**
485 33 zero_gravi
 * NEORV32 runtime environment: Private function to print 32-bit number
486
 * as 8-digit hexadecimal value (with "0x" suffix).
487
 *
488
 * @param[in] num Number to print as hexadecimal.
489
 **************************************************************************/
490
void __neorv32_rte_print_hex_word(uint32_t num) {
491
 
492
  static const char hex_symbols[16] = "0123456789ABCDEF";
493
 
494 61 zero_gravi
  neorv32_uart0_print("0x");
495 33 zero_gravi
 
496
  int i;
497
  for (i=0; i<8; i++) {
498
    uint32_t index = (num >> (28 - 4*i)) & 0xF;
499 61 zero_gravi
    neorv32_uart0_putc(hex_symbols[index]);
500 33 zero_gravi
  }
501
}
502
 
503
 
504 47 zero_gravi
/**********************************************************************//**
505 41 zero_gravi
 * NEORV32 runtime environment: Print the processor version in human-readable format.
506 6 zero_gravi
 **************************************************************************/
507 12 zero_gravi
void neorv32_rte_print_hw_version(void) {
508 6 zero_gravi
 
509
  uint32_t i;
510
  char tmp, cnt;
511
 
512 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
513
    return; // cannot output anything if UART0 is not implemented
514
  }
515
 
516 6 zero_gravi
  for (i=0; i<4; i++) {
517
 
518 33 zero_gravi
    tmp = (char)(neorv32_cpu_csr_read(CSR_MIMPID) >> (24 - 8*i));
519 6 zero_gravi
 
520
    // serial division
521
    cnt = 0;
522 35 zero_gravi
    while (tmp >= 16) {
523
      tmp = tmp - 16;
524 6 zero_gravi
      cnt++;
525
    }
526
 
527
    if (cnt) {
528 61 zero_gravi
      neorv32_uart0_putc('0' + cnt);
529 6 zero_gravi
    }
530 61 zero_gravi
    neorv32_uart0_putc('0' + tmp);
531 6 zero_gravi
    if (i < 3) {
532 61 zero_gravi
      neorv32_uart0_putc('.');
533 6 zero_gravi
    }
534
  }
535 2 zero_gravi
}
536 11 zero_gravi
 
537
 
538
/**********************************************************************//**
539
 * NEORV32 runtime environment: Print project credits
540
 **************************************************************************/
541
void neorv32_rte_print_credits(void) {
542
 
543 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
544
    return; // cannot output anything if UART0 is not implemented
545
  }
546
 
547
  neorv32_uart0_print("The NEORV32 RISC-V Processor\n"
548 64 zero_gravi
                      "(c) 2021, Stephan Nolting\n"
549 61 zero_gravi
                      "BSD 3-Clause License\n"
550
                      "https://github.com/stnolting/neorv32\n\n");
551 11 zero_gravi
}
552
 
553 22 zero_gravi
 
554
/**********************************************************************//**
555 41 zero_gravi
 * NEORV32 runtime environment: Print project logo
556 37 zero_gravi
 **************************************************************************/
557
void neorv32_rte_print_logo(void) {
558
 
559 40 zero_gravi
  const uint32_t logo_data_c[11][4] =
560
  {
561
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000},
562
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
563
    {0b01100000110001111111110001111111,0b10000111111110001100000011000111,0b11111000011111111000000110000000,0b11111111111111110000000000000000},
564
    {0b11110000110011000000000011000000,0b11001100000011001100000011001100,0b00001100110000001100000110000011,0b11000000000000111100000000000000},
565
    {0b11011000110011000000000011000000,0b11001100000011001100000011000000,0b00001100000000011000000110000000,0b11000111111000110000000000000000},
566
    {0b11001100110011111111100011000000,0b11001111111110001100000011000000,0b11111000000001100000000110000011,0b11000111111000111100000000000000},
567
    {0b11000110110011000000000011000000,0b11001100001100000110000110000000,0b00001100000110000000000110000000,0b11000111111000110000000000000000},
568
    {0b11000011110011000000000011000000,0b11001100000110000011001100001100,0b00001100011000000000000110000011,0b11000000000000111100000000000000},
569
    {0b11000001100001111111110001111111,0b10001100000011000000110000000111,0b11111000111111111100000110000000,0b11111111111111110000000000000000},
570
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
571
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000}
572
  };
573
 
574
  int u,v,w;
575
  uint32_t tmp;
576
 
577 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
578
    return; // cannot output anything if UART0 is not implemented
579
  }
580
 
581 40 zero_gravi
  for (u=0; u<11; u++) {
582 61 zero_gravi
    neorv32_uart0_print("\n");
583 40 zero_gravi
    for (v=0; v<4; v++) {
584
      tmp = logo_data_c[u][v];
585
      for (w=0; w<32; w++){
586 61 zero_gravi
        if (((int32_t)tmp) < 0) { // check MSB
587
          neorv32_uart0_putc('#');
588 40 zero_gravi
        }
589
        else {
590 61 zero_gravi
          neorv32_uart0_putc(' ');
591 40 zero_gravi
        }
592 47 zero_gravi
        tmp <<= 1;
593 40 zero_gravi
      }
594
    }
595
  }
596 61 zero_gravi
  neorv32_uart0_print("\n");
597 37 zero_gravi
}
598
 
599
 
600
/**********************************************************************//**
601 22 zero_gravi
 * NEORV32 runtime environment: Print project license
602
 **************************************************************************/
603
void neorv32_rte_print_license(void) {
604
 
605 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
606
    return; // cannot output anything if UART0 is not implemented
607
  }
608
 
609 22 zero_gravi
  neorv32_uart_print(
610
  "\n"
611
  "BSD 3-Clause License\n"
612
  "\n"
613 42 zero_gravi
  "Copyright (c) 2021, Stephan Nolting. All rights reserved.\n"
614 22 zero_gravi
  "\n"
615
  "Redistribution and use in source and binary forms, with or without modification, are\n"
616
  "permitted provided that the following conditions are met:\n"
617
  "\n"
618
  "1. Redistributions of source code must retain the above copyright notice, this list of\n"
619
  "   conditions and the following disclaimer.\n"
620
  "\n"
621
  "2. Redistributions in binary form must reproduce the above copyright notice, this list of\n"
622
  "   conditions and the following disclaimer in the documentation and/or other materials\n"
623
  "   provided with the distribution.\n"
624
  "\n"
625
  "3. Neither the name of the copyright holder nor the names of its contributors may be used to\n"
626
  "   endorse or promote products derived from this software without specific prior written\n"
627
  "   permission.\n"
628
  "\n"
629
  "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n"
630
  "OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
631
  "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
632
  "COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n"
633
  "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n"
634
  "GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\n"
635
  "AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n"
636
  "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n"
637
  "OF THE POSSIBILITY OF SUCH DAMAGE.\n"
638
  "\n"
639
  "\n"
640
  );
641
}
642
 
643 44 zero_gravi
 
644
/**********************************************************************//**
645
 * NEORV32 runtime environment: Get MISA CSR value according to *compiler/toolchain configuration*.
646
 *
647
 * @return MISA content according to compiler configuration.
648
 **************************************************************************/
649
uint32_t neorv32_rte_get_compiler_isa(void) {
650
 
651
  uint32_t misa_cc = 0;
652
 
653 53 zero_gravi
#if defined __riscv_atomic || defined __riscv_a
654 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_A;
655 44 zero_gravi
#endif
656
 
657 53 zero_gravi
#ifdef __riscv_b
658 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_B;
659 53 zero_gravi
#endif
660
 
661
#if defined __riscv_compressed || defined __riscv_c
662 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_C;
663 44 zero_gravi
#endif
664
 
665 53 zero_gravi
#if (__riscv_flen == 64) || defined __riscv_d
666 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_D;
667 52 zero_gravi
#endif
668
 
669 44 zero_gravi
#ifdef __riscv_32e
670 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_E;
671 44 zero_gravi
#else
672 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_I;
673 44 zero_gravi
#endif
674
 
675 53 zero_gravi
#if (__riscv_flen == 32) || defined __riscv_f
676 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_F;
677 52 zero_gravi
#endif
678
 
679 53 zero_gravi
#if defined __riscv_mul || defined __riscv_m
680 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_M;
681 44 zero_gravi
#endif
682
 
683
#if (__riscv_xlen == 32)
684 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_MXL_LO;
685 44 zero_gravi
#elif (__riscv_xlen == 64)
686 61 zero_gravi
  misa_cc |= 2 << CSR_MISA_MXL_LO;
687 44 zero_gravi
#else
688 61 zero_gravi
  misa_cc |= 3 << CSR_MISA_MXL_LO;
689 44 zero_gravi
#endif
690
 
691
  return misa_cc;
692
}
693
 
694
 
695
/**********************************************************************//**
696
 * NEORV32 runtime environment: Check required ISA extensions (via compiler flags) against available ISA extensions (via MISA csr).
697
 *
698
 * @param[in] silent Show error message (via neorv32.uart) if isa_sw > isa_hw when != 0.
699
 * @return MISA content according to compiler configuration.
700
 **************************************************************************/
701
int neorv32_rte_check_isa(int silent) {
702
 
703
  uint32_t misa_sw = neorv32_rte_get_compiler_isa();
704
  uint32_t misa_hw = neorv32_cpu_csr_read(CSR_MISA);
705
 
706
  // mask hardware features that are not used by software
707
  uint32_t check = misa_hw & misa_sw;
708
 
709
  //
710
  if (check == misa_sw) {
711
    return 0;
712
  }
713
  else {
714 61 zero_gravi
    if ((silent == 0) || (neorv32_uart0_available() == 0)) {
715 44 zero_gravi
      neorv32_uart_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n"
716
                          "SW_ISA = 0x%x (compiler flags)\n"
717
                          "HW_ISA = 0x%x (misa csr)\n\n", misa_sw, misa_hw);
718
    }
719
    return 1;
720
  }
721
}
722
 

powered by: WebSVN 2.1.0

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