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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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