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

Subversion Repositories neorv32

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

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 65 zero_gravi
static void __neorv32_rte_print_checkbox(int state);
55 33 zero_gravi
static void __neorv32_rte_print_hex_word(uint32_t num);
56 2 zero_gravi
 
57
 
58
/**********************************************************************//**
59 14 zero_gravi
 * Setup NEORV32 runtime environment.
60 2 zero_gravi
 *
61
 * @note This function installs a debug handler for ALL exception and interrupt sources, which
62 14 zero_gravi
 * gives detailed information about the exception/interrupt. Actual handler can be installed afterwards
63
 * via neorv32_rte_exception_install(uint8_t id, void (*handler)(void)).
64 2 zero_gravi
 **************************************************************************/
65 14 zero_gravi
void neorv32_rte_setup(void) {
66 2 zero_gravi
 
67 14 zero_gravi
  // configure trap handler base address
68
  uint32_t mtvec_base = (uint32_t)(&__neorv32_rte_core);
69
  neorv32_cpu_csr_write(CSR_MTVEC, mtvec_base);
70 2 zero_gravi
 
71
  // install debug handler for all sources
72 14 zero_gravi
  uint8_t id;
73
  for (id = 0; id < (sizeof(__neorv32_rte_vector_lut)/sizeof(__neorv32_rte_vector_lut[0])); id++) {
74
    neorv32_rte_exception_uninstall(id); // this will configure the debug handler
75 2 zero_gravi
  }
76
}
77
 
78
 
79
/**********************************************************************//**
80
 * Install exception handler function to NEORV32 runtime environment.
81
 *
82 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)
83
 * and the global interrupt enable bit mstatus.mie via neorv32_cpu_eint(void).
84 2 zero_gravi
 *
85 14 zero_gravi
 * @param[in] id Identifier (type) of the targeted exception. See #NEORV32_RTE_TRAP_enum.
86
 * @param[in] handler The actual handler function for the specified exception (function MUST be of type "void function(void);").
87 18 zero_gravi
 * @return 0 if success, 1 if error (invalid id or targeted exception not supported).
88 2 zero_gravi
 **************************************************************************/
89 14 zero_gravi
int neorv32_rte_exception_install(uint8_t id, void (*handler)(void)) {
90 2 zero_gravi
 
91
  // id valid?
92 48 zero_gravi
  if ((id >= RTE_TRAP_I_MISALIGNED) && (id <= CSR_MIE_FIRQ15E)) {
93 24 zero_gravi
    __neorv32_rte_vector_lut[id] = (uint32_t)handler; // install handler
94 2 zero_gravi
    return 0;
95
  }
96
  return 1;
97
}
98
 
99
 
100
/**********************************************************************//**
101
 * Uninstall exception handler function from NEORV32 runtime environment, which was
102 14 zero_gravi
 * previously installed via neorv32_rte_exception_install(uint8_t id, void (*handler)(void)).
103 2 zero_gravi
 *
104 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)
105
 * and/or the global interrupt enable bit mstatus.mie via neorv32_cpu_dint(void).
106 2 zero_gravi
 *
107 14 zero_gravi
 * @param[in] id Identifier (type) of the targeted exception. See #NEORV32_RTE_TRAP_enum.
108 18 zero_gravi
 * @return 0 if success, 1 if error (invalid id or targeted exception not supported).
109 2 zero_gravi
 **************************************************************************/
110 14 zero_gravi
int neorv32_rte_exception_uninstall(uint8_t id) {
111 2 zero_gravi
 
112
  // id valid?
113 48 zero_gravi
  if ((id >= RTE_TRAP_I_MISALIGNED) && (id <= CSR_MIE_FIRQ15E)) {
114 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
115 2 zero_gravi
    return 0;
116
  }
117
  return 1;
118
}
119
 
120
 
121
/**********************************************************************//**
122 14 zero_gravi
 * This is the core of the NEORV32 RTE.
123
 *
124
 * @note This function must no be explicitly used by the user.
125 33 zero_gravi
 * @note The RTE core uses mscratch CSR to store the trap-causing mepc for further (user-defined) processing.
126
 *
127 14 zero_gravi
 * @warning When using the the RTE, this function is the ONLY function that can use the 'interrupt' attribute!
128 2 zero_gravi
 **************************************************************************/
129 14 zero_gravi
static void __attribute__((__interrupt__)) __attribute__((aligned(16)))  __neorv32_rte_core(void) {
130 2 zero_gravi
 
131 33 zero_gravi
  register uint32_t rte_mepc = neorv32_cpu_csr_read(CSR_MEPC);
132
  neorv32_cpu_csr_write(CSR_MSCRATCH, rte_mepc); // store for later
133 14 zero_gravi
  register uint32_t rte_mcause = neorv32_cpu_csr_read(CSR_MCAUSE);
134
 
135
  // compute return address
136 61 zero_gravi
  if (((int32_t)rte_mcause) >= 0) { // modify pc only if exception (MSB cleared)
137 14 zero_gravi
 
138
    // get low half word of faulting instruction
139
    register uint32_t rte_trap_inst;
140
    asm volatile ("lh %[result], 0(%[input_i])" : [result] "=r" (rte_trap_inst) : [input_i] "r" (rte_mepc));
141
 
142
    if ((rte_trap_inst & 3) == 3) { // faulting instruction is uncompressed instruction
143
      rte_mepc += 4;
144
    }
145
    else { // faulting instruction is compressed instruction
146
      rte_mepc += 2;
147
    }
148
 
149
    // store new return address
150
    neorv32_cpu_csr_write(CSR_MEPC, rte_mepc);
151
  }
152
 
153
  // find according trap handler
154
  register uint32_t rte_handler = (uint32_t)(&__neorv32_rte_debug_exc_handler);
155
  switch (rte_mcause) {
156
    case TRAP_CODE_I_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_MISALIGNED]; break;
157
    case TRAP_CODE_I_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ACCESS]; break;
158
    case TRAP_CODE_I_ILLEGAL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ILLEGAL]; break;
159
    case TRAP_CODE_BREAKPOINT:   rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_BREAKPOINT]; break;
160
    case TRAP_CODE_L_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_L_MISALIGNED]; break;
161
    case TRAP_CODE_L_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_L_ACCESS]; break;
162
    case TRAP_CODE_S_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_S_MISALIGNED]; break;
163
    case TRAP_CODE_S_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_S_ACCESS]; break;
164 40 zero_gravi
    case TRAP_CODE_UENV_CALL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_UENV_CALL]; break;
165 14 zero_gravi
    case TRAP_CODE_MENV_CALL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MENV_CALL]; break;
166
    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 15 zero_gravi
  // intro
206 65 zero_gravi
  neorv32_uart0_print("<RTE> ");
207 2 zero_gravi
 
208 15 zero_gravi
  // cause
209 7 zero_gravi
  register uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
210 66 zero_gravi
  register char tmp = (char)(trap_cause & 0xf);
211 48 zero_gravi
  if (tmp >= 10) {
212
    tmp = 'a' + (tmp - 10);
213
  }
214
  else {
215
    tmp = '0' + tmp;
216
  }
217 7 zero_gravi
  switch (trap_cause) {
218 65 zero_gravi
    case TRAP_CODE_I_MISALIGNED: neorv32_uart0_print("Instruction address misaligned"); break;
219
    case TRAP_CODE_I_ACCESS:     neorv32_uart0_print("Instruction access fault"); break;
220
    case TRAP_CODE_I_ILLEGAL:    neorv32_uart0_print("Illegal instruction"); break;
221
    case TRAP_CODE_BREAKPOINT:   neorv32_uart0_print("Breakpoint"); break;
222
    case TRAP_CODE_L_MISALIGNED: neorv32_uart0_print("Load address misaligned"); break;
223
    case TRAP_CODE_L_ACCESS:     neorv32_uart0_print("Load access fault"); break;
224
    case TRAP_CODE_S_MISALIGNED: neorv32_uart0_print("Store address misaligned"); break;
225
    case TRAP_CODE_S_ACCESS:     neorv32_uart0_print("Store access fault"); break;
226
    case TRAP_CODE_UENV_CALL:    neorv32_uart0_print("Environment call from U-mode"); break;
227
    case TRAP_CODE_MENV_CALL:    neorv32_uart0_print("Environment call from M-mode"); break;
228
    case TRAP_CODE_MSI:          neorv32_uart0_print("Machine software interrupt"); break;
229
    case TRAP_CODE_MTI:          neorv32_uart0_print("Machine timer interrupt"); break;
230
    case TRAP_CODE_MEI:          neorv32_uart0_print("Machine external interrupt"); break;
231 47 zero_gravi
    case TRAP_CODE_FIRQ_0:
232
    case TRAP_CODE_FIRQ_1:
233
    case TRAP_CODE_FIRQ_2:
234
    case TRAP_CODE_FIRQ_3:
235
    case TRAP_CODE_FIRQ_4:
236
    case TRAP_CODE_FIRQ_5:
237
    case TRAP_CODE_FIRQ_6:
238 48 zero_gravi
    case TRAP_CODE_FIRQ_7:
239
    case TRAP_CODE_FIRQ_8:
240
    case TRAP_CODE_FIRQ_9:
241
    case TRAP_CODE_FIRQ_10:
242
    case TRAP_CODE_FIRQ_11:
243
    case TRAP_CODE_FIRQ_12:
244
    case TRAP_CODE_FIRQ_13:
245
    case TRAP_CODE_FIRQ_14:
246 65 zero_gravi
    case TRAP_CODE_FIRQ_15:      neorv32_uart0_print("Fast interrupt "); neorv32_uart0_putc(tmp); break;
247
    default:                     neorv32_uart0_print("Unknown trap cause: "); __neorv32_rte_print_hex_word(trap_cause); break;
248 2 zero_gravi
  }
249
 
250 66 zero_gravi
  // check cause if bus access fault exception
251
  if ((trap_cause == TRAP_CODE_I_ACCESS) || (trap_cause == TRAP_CODE_L_ACCESS) || (trap_cause == TRAP_CODE_S_ACCESS)) {
252
    register uint32_t bus_err = NEORV32_BUSKEEPER.CTRL;
253
    if (bus_err & (1<<BUSKEEPER_ERR_FLAG)) { // exception caused by bus system?
254
      if (bus_err & (1<<BUSKEEPER_ERR_TYPE)) {
255
        neorv32_uart0_print(" [TIMEOUT_ERR]");
256
      }
257
      else {
258
        neorv32_uart0_print(" [DEVICE_ERR]");
259
      }
260
    }
261
    else { // exception was not caused by bus system -> has to be caused by PMP rule violation
262
      neorv32_uart0_print(" [PMP_ERR]");
263
    }
264
  }
265
 
266 33 zero_gravi
  // instruction address
267 65 zero_gravi
  neorv32_uart0_print(" @ PC=");
268 66 zero_gravi
  __neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MSCRATCH)); // rte core stores original mepc to mscratch
269 15 zero_gravi
 
270 33 zero_gravi
  // additional info
271 65 zero_gravi
  neorv32_uart0_print(", MTVAL=");
272 33 zero_gravi
  __neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MTVAL));
273 65 zero_gravi
  neorv32_uart0_print(" </RTE>");
274 6 zero_gravi
}
275
 
276
 
277
/**********************************************************************//**
278
 * NEORV32 runtime environment: Print hardware configuration information via UART
279
 **************************************************************************/
280
void neorv32_rte_print_hw_config(void) {
281
 
282 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
283
    return; // cannot output anything if UART0 is not implemented
284
  }
285
 
286 6 zero_gravi
  uint32_t tmp;
287
  int i;
288
  char c;
289
 
290 65 zero_gravi
  neorv32_uart0_printf("\n\n<<< Processor Configuration Overview >>>\n");
291 6 zero_gravi
 
292
  // CPU configuration
293 61 zero_gravi
  neorv32_uart0_printf("\n=== << CPU >> ===\n");
294 6 zero_gravi
 
295 65 zero_gravi
  // general
296
  neorv32_uart0_printf("Clock speed:       %u Hz\n", NEORV32_SYSINFO.CLK);
297
  neorv32_uart0_printf("Full HW reset:     "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_HW_RESET));
298
  neorv32_uart0_printf("On-chip debugger:  "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_OCD));
299 23 zero_gravi
  // ID
300 61 zero_gravi
  neorv32_uart0_printf("Hart ID:           0x%x\n"
301
                       "Vendor ID:         0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID), neorv32_cpu_csr_read(CSR_MVENDORID));
302 12 zero_gravi
 
303 23 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MARCHID);
304 61 zero_gravi
  neorv32_uart0_printf("Architecture ID:   0x%x", tmp);
305 32 zero_gravi
  if (tmp == NEORV32_ARCHID) {
306 61 zero_gravi
    neorv32_uart0_printf(" (NEORV32)");
307 32 zero_gravi
  }
308 23 zero_gravi
 
309 49 zero_gravi
  // hardware version
310 61 zero_gravi
  neorv32_uart0_printf("\nImplementation ID: 0x%x (", neorv32_cpu_csr_read(CSR_MIMPID));
311 12 zero_gravi
  neorv32_rte_print_hw_version();
312 61 zero_gravi
  neorv32_uart0_putc(')');
313 6 zero_gravi
 
314 60 zero_gravi
  // CPU architecture and endianness
315 61 zero_gravi
  neorv32_uart0_printf("\nArchitecture:      ");
316 6 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MISA);
317
  tmp = (tmp >> 30) & 0x03;
318
  if (tmp == 1) {
319 61 zero_gravi
    neorv32_uart0_printf("rv32-little");
320 6 zero_gravi
  }
321 40 zero_gravi
  else {
322 61 zero_gravi
    neorv32_uart0_printf("unknown");
323 40 zero_gravi
  }
324
 
325
  // CPU extensions
326 61 zero_gravi
  neorv32_uart0_printf("\nISA extensions:    ");
327 6 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MISA);
328
  for (i=0; i<26; i++) {
329
    if (tmp & (1 << i)) {
330
      c = (char)('A' + i);
331 61 zero_gravi
      neorv32_uart0_putc(c);
332
      neorv32_uart0_putc(' ');
333 6 zero_gravi
    }
334
  }
335 22 zero_gravi
 
336 63 zero_gravi
  // Z* CPU extensions
337 64 zero_gravi
  tmp = NEORV32_SYSINFO.CPU;
338 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_ZICSR)) {
339 61 zero_gravi
    neorv32_uart0_printf("Zicsr ");
340 22 zero_gravi
  }
341 66 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_ZICNTR)) {
342
    neorv32_uart0_printf("Zicntr ");
343
  }
344
  if (tmp & (1<<SYSINFO_CPU_ZIHPM)) {
345
    neorv32_uart0_printf("Zihpm ");
346
  }
347 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_ZIFENCEI)) {
348 61 zero_gravi
    neorv32_uart0_printf("Zifencei ");
349 22 zero_gravi
  }
350 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_ZMMUL)) {
351 61 zero_gravi
    neorv32_uart0_printf("Zmmul ");
352
  }
353 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_ZFINX)) {
354 61 zero_gravi
    neorv32_uart0_printf("Zfinx ");
355 53 zero_gravi
  }
356 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_ZXSCNT)) {
357 61 zero_gravi
    neorv32_uart0_printf("Zxscnt(!) ");
358 56 zero_gravi
  }
359 66 zero_gravi
 
360 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_DEBUGMODE)) {
361 66 zero_gravi
    neorv32_uart0_printf("Debug ");
362 59 zero_gravi
  }
363 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_FASTMUL)) {
364
    neorv32_uart0_printf("FAST_MUL ");
365
  }
366
  if (tmp & (1<<SYSINFO_CPU_FASTSHIFT)) {
367
    neorv32_uart0_printf("FAST_SHIFT ");
368
  }
369
 
370 34 zero_gravi
  // check physical memory protection
371 61 zero_gravi
  neorv32_uart0_printf("\nPMP:               ");
372 42 zero_gravi
  uint32_t pmp_num_regions = neorv32_cpu_pmp_get_num_regions();
373
  if (pmp_num_regions != 0)  {
374 61 zero_gravi
    neorv32_uart0_printf("%u regions, %u bytes minimal granularity\n", pmp_num_regions, neorv32_cpu_pmp_get_granularity());
375 34 zero_gravi
  }
376
  else {
377 61 zero_gravi
    neorv32_uart0_printf("not implemented\n");
378 34 zero_gravi
  }
379
 
380
 
381 6 zero_gravi
  // Memory configuration
382 65 zero_gravi
  neorv32_uart0_printf("\n=== << Memory System >> ===\n");
383 6 zero_gravi
 
384 66 zero_gravi
  neorv32_uart0_printf("Boot Config.:        Boot ");
385 65 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_BOOTLOADER)) {
386
    neorv32_uart0_printf("via Bootloader\n");
387
  }
388
  else {
389
    neorv32_uart0_printf("from memory (@ 0x%x)\n", NEORV32_SYSINFO.ISPACE_BASE);
390
  }
391
 
392 66 zero_gravi
  neorv32_uart0_printf("Instr. base address: 0x%x\n", NEORV32_SYSINFO.ISPACE_BASE);
393 56 zero_gravi
 
394
  // IMEM
395 66 zero_gravi
  neorv32_uart0_printf("Internal IMEM:       ");
396 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_IMEM)) {
397
    neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.IMEM_SIZE);
398 56 zero_gravi
  }
399
  else {
400 61 zero_gravi
    neorv32_uart0_printf("no\n");
401 56 zero_gravi
  }
402 6 zero_gravi
 
403 56 zero_gravi
  // DMEM
404 66 zero_gravi
  neorv32_uart0_printf("Data base address:   0x%x\n", NEORV32_SYSINFO.DSPACE_BASE);
405
  neorv32_uart0_printf("Internal DMEM:       ");
406 65 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_DMEM)) {
407
    neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.DMEM_SIZE);
408
  }
409
  else {
410
    neorv32_uart0_printf("no\n");
411
  }
412 6 zero_gravi
 
413 56 zero_gravi
  // i-cache
414 66 zero_gravi
  neorv32_uart0_printf("Internal i-cache:    ");
415 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_ICACHE)) {
416 65 zero_gravi
    neorv32_uart0_printf("yes, ");
417 41 zero_gravi
 
418 64 zero_gravi
    uint32_t ic_block_size = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_BLOCK_SIZE_0) & 0x0F;
419 41 zero_gravi
    if (ic_block_size) {
420
      ic_block_size = 1 << ic_block_size;
421
    }
422
    else {
423
      ic_block_size = 0;
424
    }
425
 
426 64 zero_gravi
    uint32_t ic_num_blocks = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_NUM_BLOCKS_0) & 0x0F;
427 41 zero_gravi
    if (ic_num_blocks) {
428
      ic_num_blocks = 1 << ic_num_blocks;
429
    }
430
    else {
431
      ic_num_blocks = 0;
432
    }
433
 
434 64 zero_gravi
    uint32_t ic_associativity = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_ASSOCIATIVITY_0) & 0x0F;
435 41 zero_gravi
    ic_associativity = 1 << ic_associativity;
436
 
437 65 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);
438 45 zero_gravi
    if (ic_associativity == 1) {
439 61 zero_gravi
      neorv32_uart0_printf(" (direct-mapped)\n");
440 41 zero_gravi
    }
441 64 zero_gravi
    else if (((NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_REPLACEMENT_0) & 0x0F) == 1) {
442 61 zero_gravi
      neorv32_uart0_printf(" (LRU replacement policy)\n");
443 41 zero_gravi
    }
444
    else {
445 61 zero_gravi
      neorv32_uart0_printf("\n");
446 41 zero_gravi
    }
447
  }
448 65 zero_gravi
  else {
449
    neorv32_uart0_printf("no\n");
450
  }
451 41 zero_gravi
 
452 66 zero_gravi
  neorv32_uart0_printf("Ext. bus interface:  ");
453 64 zero_gravi
  __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT));
454 66 zero_gravi
  neorv32_uart0_printf("Ext. bus Endianness: ");
455 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT_ENDIAN)) {
456 61 zero_gravi
    neorv32_uart0_printf("big\n");
457 40 zero_gravi
  }
458
  else {
459 61 zero_gravi
    neorv32_uart0_printf("little\n");
460 40 zero_gravi
  }
461 6 zero_gravi
 
462
  // peripherals
463 61 zero_gravi
  neorv32_uart0_printf("\n=== << Peripherals >> ===\n");
464 15 zero_gravi
 
465 64 zero_gravi
  tmp = NEORV32_SYSINFO.SOC;
466 65 zero_gravi
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_GPIO));   neorv32_uart0_printf(" GPIO\n");
467
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_MTIME));  neorv32_uart0_printf(" MTIME\n");
468
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART0));  neorv32_uart0_printf(" UART0\n");
469
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART1));  neorv32_uart0_printf(" UART1\n");
470
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SPI));    neorv32_uart0_printf(" SPI\n");
471
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TWI));    neorv32_uart0_printf(" TWI\n");
472
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_PWM));    neorv32_uart0_printf(" PWM\n");
473
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_WDT));    neorv32_uart0_printf(" WDT\n");
474
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TRNG));   neorv32_uart0_printf(" TRNG\n");
475
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_CFS));    neorv32_uart0_printf(" CFS\n");
476
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SLINK));  neorv32_uart0_printf(" SLINK\n");
477
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_NEOLED)); neorv32_uart0_printf(" NEOLED\n");
478
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_XIRQ));   neorv32_uart0_printf(" XIRQ\n");
479 6 zero_gravi
}
480
 
481
 
482
/**********************************************************************//**
483 50 zero_gravi
 * NEORV32 runtime environment: Private function to print yes or no.
484 6 zero_gravi
 * @note This function is used by neorv32_rte_print_hw_config(void) only.
485
 *
486 65 zero_gravi
 * @param[in] state Print 'yes' when !=0, print 'no' when 0
487 6 zero_gravi
 **************************************************************************/
488
static void __neorv32_rte_print_true_false(int state) {
489
 
490
  if (state) {
491 61 zero_gravi
    neorv32_uart0_print("yes\n");
492 6 zero_gravi
  }
493 2 zero_gravi
  else {
494 61 zero_gravi
    neorv32_uart0_print("no\n");
495 2 zero_gravi
  }
496 6 zero_gravi
}
497 2 zero_gravi
 
498
 
499 6 zero_gravi
/**********************************************************************//**
500 65 zero_gravi
 * NEORV32 runtime environment: Private function to print [x] or [ ].
501
 * @note This function is used by neorv32_rte_print_hw_config(void) only.
502
 *
503
 * @param[in] state Print '[x]' when !=0, print '[ ]' when 0
504
 **************************************************************************/
505
static void __neorv32_rte_print_checkbox(int state) {
506
 
507
  neorv32_uart0_putc('[');
508
  if (state) {
509
    neorv32_uart0_putc('x');
510
  }
511
  else {
512
    neorv32_uart0_putc(' ');
513
  }
514
  neorv32_uart0_putc(']');
515
}
516
 
517
 
518
/**********************************************************************//**
519 33 zero_gravi
 * NEORV32 runtime environment: Private function to print 32-bit number
520
 * as 8-digit hexadecimal value (with "0x" suffix).
521
 *
522
 * @param[in] num Number to print as hexadecimal.
523
 **************************************************************************/
524
void __neorv32_rte_print_hex_word(uint32_t num) {
525
 
526
  static const char hex_symbols[16] = "0123456789ABCDEF";
527
 
528 61 zero_gravi
  neorv32_uart0_print("0x");
529 33 zero_gravi
 
530
  int i;
531
  for (i=0; i<8; i++) {
532
    uint32_t index = (num >> (28 - 4*i)) & 0xF;
533 61 zero_gravi
    neorv32_uart0_putc(hex_symbols[index]);
534 33 zero_gravi
  }
535
}
536
 
537
 
538 47 zero_gravi
/**********************************************************************//**
539 41 zero_gravi
 * NEORV32 runtime environment: Print the processor version in human-readable format.
540 6 zero_gravi
 **************************************************************************/
541 12 zero_gravi
void neorv32_rte_print_hw_version(void) {
542 6 zero_gravi
 
543
  uint32_t i;
544
  char tmp, cnt;
545
 
546 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
547
    return; // cannot output anything if UART0 is not implemented
548
  }
549
 
550 6 zero_gravi
  for (i=0; i<4; i++) {
551
 
552 33 zero_gravi
    tmp = (char)(neorv32_cpu_csr_read(CSR_MIMPID) >> (24 - 8*i));
553 6 zero_gravi
 
554
    // serial division
555
    cnt = 0;
556 35 zero_gravi
    while (tmp >= 16) {
557
      tmp = tmp - 16;
558 6 zero_gravi
      cnt++;
559
    }
560
 
561
    if (cnt) {
562 61 zero_gravi
      neorv32_uart0_putc('0' + cnt);
563 6 zero_gravi
    }
564 61 zero_gravi
    neorv32_uart0_putc('0' + tmp);
565 6 zero_gravi
    if (i < 3) {
566 61 zero_gravi
      neorv32_uart0_putc('.');
567 6 zero_gravi
    }
568
  }
569 2 zero_gravi
}
570 11 zero_gravi
 
571
 
572
/**********************************************************************//**
573
 * NEORV32 runtime environment: Print project credits
574
 **************************************************************************/
575
void neorv32_rte_print_credits(void) {
576
 
577 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
578
    return; // cannot output anything if UART0 is not implemented
579
  }
580
 
581
  neorv32_uart0_print("The NEORV32 RISC-V Processor\n"
582 64 zero_gravi
                      "(c) 2021, Stephan Nolting\n"
583 61 zero_gravi
                      "BSD 3-Clause License\n"
584
                      "https://github.com/stnolting/neorv32\n\n");
585 11 zero_gravi
}
586
 
587 22 zero_gravi
 
588
/**********************************************************************//**
589 41 zero_gravi
 * NEORV32 runtime environment: Print project logo
590 37 zero_gravi
 **************************************************************************/
591
void neorv32_rte_print_logo(void) {
592
 
593 40 zero_gravi
  const uint32_t logo_data_c[11][4] =
594
  {
595
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000},
596
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
597
    {0b01100000110001111111110001111111,0b10000111111110001100000011000111,0b11111000011111111000000110000000,0b11111111111111110000000000000000},
598
    {0b11110000110011000000000011000000,0b11001100000011001100000011001100,0b00001100110000001100000110000011,0b11000000000000111100000000000000},
599
    {0b11011000110011000000000011000000,0b11001100000011001100000011000000,0b00001100000000011000000110000000,0b11000111111000110000000000000000},
600
    {0b11001100110011111111100011000000,0b11001111111110001100000011000000,0b11111000000001100000000110000011,0b11000111111000111100000000000000},
601
    {0b11000110110011000000000011000000,0b11001100001100000110000110000000,0b00001100000110000000000110000000,0b11000111111000110000000000000000},
602
    {0b11000011110011000000000011000000,0b11001100000110000011001100001100,0b00001100011000000000000110000011,0b11000000000000111100000000000000},
603
    {0b11000001100001111111110001111111,0b10001100000011000000110000000111,0b11111000111111111100000110000000,0b11111111111111110000000000000000},
604
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
605
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000}
606
  };
607
 
608
  int u,v,w;
609
  uint32_t tmp;
610
 
611 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
612
    return; // cannot output anything if UART0 is not implemented
613
  }
614
 
615 40 zero_gravi
  for (u=0; u<11; u++) {
616 61 zero_gravi
    neorv32_uart0_print("\n");
617 40 zero_gravi
    for (v=0; v<4; v++) {
618
      tmp = logo_data_c[u][v];
619
      for (w=0; w<32; w++){
620 61 zero_gravi
        if (((int32_t)tmp) < 0) { // check MSB
621
          neorv32_uart0_putc('#');
622 40 zero_gravi
        }
623
        else {
624 61 zero_gravi
          neorv32_uart0_putc(' ');
625 40 zero_gravi
        }
626 47 zero_gravi
        tmp <<= 1;
627 40 zero_gravi
      }
628
    }
629
  }
630 61 zero_gravi
  neorv32_uart0_print("\n");
631 37 zero_gravi
}
632
 
633
 
634
/**********************************************************************//**
635 22 zero_gravi
 * NEORV32 runtime environment: Print project license
636
 **************************************************************************/
637
void neorv32_rte_print_license(void) {
638
 
639 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
640
    return; // cannot output anything if UART0 is not implemented
641
  }
642
 
643 65 zero_gravi
  neorv32_uart0_print(
644 22 zero_gravi
  "\n"
645
  "BSD 3-Clause License\n"
646
  "\n"
647 42 zero_gravi
  "Copyright (c) 2021, Stephan Nolting. All rights reserved.\n"
648 22 zero_gravi
  "\n"
649
  "Redistribution and use in source and binary forms, with or without modification, are\n"
650
  "permitted provided that the following conditions are met:\n"
651
  "\n"
652
  "1. Redistributions of source code must retain the above copyright notice, this list of\n"
653
  "   conditions and the following disclaimer.\n"
654
  "\n"
655
  "2. Redistributions in binary form must reproduce the above copyright notice, this list of\n"
656
  "   conditions and the following disclaimer in the documentation and/or other materials\n"
657
  "   provided with the distribution.\n"
658
  "\n"
659
  "3. Neither the name of the copyright holder nor the names of its contributors may be used to\n"
660
  "   endorse or promote products derived from this software without specific prior written\n"
661
  "   permission.\n"
662
  "\n"
663
  "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n"
664
  "OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
665
  "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
666
  "COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n"
667
  "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n"
668
  "GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\n"
669
  "AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n"
670
  "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n"
671
  "OF THE POSSIBILITY OF SUCH DAMAGE.\n"
672
  "\n"
673
  "\n"
674
  );
675
}
676
 
677 44 zero_gravi
 
678
/**********************************************************************//**
679
 * NEORV32 runtime environment: Get MISA CSR value according to *compiler/toolchain configuration*.
680
 *
681
 * @return MISA content according to compiler configuration.
682
 **************************************************************************/
683
uint32_t neorv32_rte_get_compiler_isa(void) {
684
 
685
  uint32_t misa_cc = 0;
686
 
687 53 zero_gravi
#if defined __riscv_atomic || defined __riscv_a
688 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_A;
689 44 zero_gravi
#endif
690
 
691 53 zero_gravi
#ifdef __riscv_b
692 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_B;
693 53 zero_gravi
#endif
694
 
695
#if defined __riscv_compressed || defined __riscv_c
696 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_C;
697 44 zero_gravi
#endif
698
 
699 53 zero_gravi
#if (__riscv_flen == 64) || defined __riscv_d
700 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_D;
701 52 zero_gravi
#endif
702
 
703 44 zero_gravi
#ifdef __riscv_32e
704 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_E;
705 44 zero_gravi
#else
706 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_I;
707 44 zero_gravi
#endif
708
 
709 53 zero_gravi
#if (__riscv_flen == 32) || defined __riscv_f
710 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_F;
711 52 zero_gravi
#endif
712
 
713 53 zero_gravi
#if defined __riscv_mul || defined __riscv_m
714 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_M;
715 44 zero_gravi
#endif
716
 
717
#if (__riscv_xlen == 32)
718 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_MXL_LO;
719 44 zero_gravi
#elif (__riscv_xlen == 64)
720 61 zero_gravi
  misa_cc |= 2 << CSR_MISA_MXL_LO;
721 44 zero_gravi
#else
722 61 zero_gravi
  misa_cc |= 3 << CSR_MISA_MXL_LO;
723 44 zero_gravi
#endif
724
 
725
  return misa_cc;
726
}
727
 
728
 
729
/**********************************************************************//**
730
 * NEORV32 runtime environment: Check required ISA extensions (via compiler flags) against available ISA extensions (via MISA csr).
731
 *
732
 * @param[in] silent Show error message (via neorv32.uart) if isa_sw > isa_hw when != 0.
733
 * @return MISA content according to compiler configuration.
734
 **************************************************************************/
735
int neorv32_rte_check_isa(int silent) {
736
 
737
  uint32_t misa_sw = neorv32_rte_get_compiler_isa();
738
  uint32_t misa_hw = neorv32_cpu_csr_read(CSR_MISA);
739
 
740
  // mask hardware features that are not used by software
741
  uint32_t check = misa_hw & misa_sw;
742
 
743
  //
744
  if (check == misa_sw) {
745
    return 0;
746
  }
747
  else {
748 61 zero_gravi
    if ((silent == 0) || (neorv32_uart0_available() == 0)) {
749 65 zero_gravi
      neorv32_uart0_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n"
750 44 zero_gravi
                          "SW_ISA = 0x%x (compiler flags)\n"
751
                          "HW_ISA = 0x%x (misa csr)\n\n", misa_sw, misa_hw);
752
    }
753
    return 1;
754
  }
755
}
756
 

powered by: WebSVN 2.1.0

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