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

Subversion Repositories neorv32

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

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 71 zero_gravi
 
327 40 zero_gravi
  // 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 72 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MXISA);
340
  if (tmp & (1<<CSR_MXISA_ZICSR)) {
341 61 zero_gravi
    neorv32_uart0_printf("Zicsr ");
342 22 zero_gravi
  }
343 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_ZICNTR)) {
344 66 zero_gravi
    neorv32_uart0_printf("Zicntr ");
345
  }
346 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_ZIHPM)) {
347 66 zero_gravi
    neorv32_uart0_printf("Zihpm ");
348
  }
349 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_ZIFENCEI)) {
350 61 zero_gravi
    neorv32_uart0_printf("Zifencei ");
351 22 zero_gravi
  }
352 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_ZMMUL)) {
353 61 zero_gravi
    neorv32_uart0_printf("Zmmul ");
354
  }
355 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_ZFINX)) {
356 61 zero_gravi
    neorv32_uart0_printf("Zfinx ");
357 53 zero_gravi
  }
358 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_ZXCFU)) {
359
    neorv32_uart0_printf("Zxcfu ");
360
  }
361
  if (tmp & (1<<CSR_MXISA_ZXSCNT)) {
362 61 zero_gravi
    neorv32_uart0_printf("Zxscnt(!) ");
363 56 zero_gravi
  }
364 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_DEBUGMODE)) {
365
    neorv32_uart0_printf("DebugMode ");
366 59 zero_gravi
  }
367 71 zero_gravi
 
368
  // CPU extension options
369
  neorv32_uart0_printf("\nExtension options: ");
370 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_FASTMUL)) {
371 63 zero_gravi
    neorv32_uart0_printf("FAST_MUL ");
372
  }
373 72 zero_gravi
  if (tmp & (1<<CSR_MXISA_FASTSHIFT)) {
374 63 zero_gravi
    neorv32_uart0_printf("FAST_SHIFT ");
375
  }
376
 
377 34 zero_gravi
  // check physical memory protection
378 61 zero_gravi
  neorv32_uart0_printf("\nPMP:               ");
379 42 zero_gravi
  uint32_t pmp_num_regions = neorv32_cpu_pmp_get_num_regions();
380
  if (pmp_num_regions != 0)  {
381 61 zero_gravi
    neorv32_uart0_printf("%u regions, %u bytes minimal granularity\n", pmp_num_regions, neorv32_cpu_pmp_get_granularity());
382 34 zero_gravi
  }
383
  else {
384 61 zero_gravi
    neorv32_uart0_printf("not implemented\n");
385 34 zero_gravi
  }
386
 
387
 
388 6 zero_gravi
  // Memory configuration
389 65 zero_gravi
  neorv32_uart0_printf("\n=== << Memory System >> ===\n");
390 6 zero_gravi
 
391 66 zero_gravi
  neorv32_uart0_printf("Boot Config.:        Boot ");
392 65 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_BOOTLOADER)) {
393
    neorv32_uart0_printf("via Bootloader\n");
394
  }
395
  else {
396
    neorv32_uart0_printf("from memory (@ 0x%x)\n", NEORV32_SYSINFO.ISPACE_BASE);
397
  }
398
 
399 66 zero_gravi
  neorv32_uart0_printf("Instr. base address: 0x%x\n", NEORV32_SYSINFO.ISPACE_BASE);
400 56 zero_gravi
 
401
  // IMEM
402 66 zero_gravi
  neorv32_uart0_printf("Internal IMEM:       ");
403 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_IMEM)) {
404
    neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.IMEM_SIZE);
405 56 zero_gravi
  }
406
  else {
407 61 zero_gravi
    neorv32_uart0_printf("no\n");
408 56 zero_gravi
  }
409 6 zero_gravi
 
410 56 zero_gravi
  // DMEM
411 66 zero_gravi
  neorv32_uart0_printf("Data base address:   0x%x\n", NEORV32_SYSINFO.DSPACE_BASE);
412
  neorv32_uart0_printf("Internal DMEM:       ");
413 65 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_DMEM)) {
414
    neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.DMEM_SIZE);
415
  }
416
  else {
417
    neorv32_uart0_printf("no\n");
418
  }
419 6 zero_gravi
 
420 56 zero_gravi
  // i-cache
421 66 zero_gravi
  neorv32_uart0_printf("Internal i-cache:    ");
422 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_ICACHE)) {
423 65 zero_gravi
    neorv32_uart0_printf("yes, ");
424 41 zero_gravi
 
425 64 zero_gravi
    uint32_t ic_block_size = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_BLOCK_SIZE_0) & 0x0F;
426 41 zero_gravi
    if (ic_block_size) {
427
      ic_block_size = 1 << ic_block_size;
428
    }
429
    else {
430
      ic_block_size = 0;
431
    }
432
 
433 64 zero_gravi
    uint32_t ic_num_blocks = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_NUM_BLOCKS_0) & 0x0F;
434 41 zero_gravi
    if (ic_num_blocks) {
435
      ic_num_blocks = 1 << ic_num_blocks;
436
    }
437
    else {
438
      ic_num_blocks = 0;
439
    }
440
 
441 64 zero_gravi
    uint32_t ic_associativity = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_ASSOCIATIVITY_0) & 0x0F;
442 41 zero_gravi
    ic_associativity = 1 << ic_associativity;
443
 
444 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);
445 45 zero_gravi
    if (ic_associativity == 1) {
446 61 zero_gravi
      neorv32_uart0_printf(" (direct-mapped)\n");
447 41 zero_gravi
    }
448 64 zero_gravi
    else if (((NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_REPLACEMENT_0) & 0x0F) == 1) {
449 61 zero_gravi
      neorv32_uart0_printf(" (LRU replacement policy)\n");
450 41 zero_gravi
    }
451
    else {
452 61 zero_gravi
      neorv32_uart0_printf("\n");
453 41 zero_gravi
    }
454
  }
455 65 zero_gravi
  else {
456
    neorv32_uart0_printf("no\n");
457
  }
458 41 zero_gravi
 
459 66 zero_gravi
  neorv32_uart0_printf("Ext. bus interface:  ");
460 64 zero_gravi
  __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT));
461 66 zero_gravi
  neorv32_uart0_printf("Ext. bus Endianness: ");
462 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT_ENDIAN)) {
463 61 zero_gravi
    neorv32_uart0_printf("big\n");
464 40 zero_gravi
  }
465
  else {
466 61 zero_gravi
    neorv32_uart0_printf("little\n");
467 40 zero_gravi
  }
468 6 zero_gravi
 
469
  // peripherals
470 61 zero_gravi
  neorv32_uart0_printf("\n=== << Peripherals >> ===\n");
471 15 zero_gravi
 
472 64 zero_gravi
  tmp = NEORV32_SYSINFO.SOC;
473 65 zero_gravi
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_GPIO));   neorv32_uart0_printf(" GPIO\n");
474
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_MTIME));  neorv32_uart0_printf(" MTIME\n");
475
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART0));  neorv32_uart0_printf(" UART0\n");
476
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART1));  neorv32_uart0_printf(" UART1\n");
477
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SPI));    neorv32_uart0_printf(" SPI\n");
478
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TWI));    neorv32_uart0_printf(" TWI\n");
479
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_PWM));    neorv32_uart0_printf(" PWM\n");
480
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_WDT));    neorv32_uart0_printf(" WDT\n");
481
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TRNG));   neorv32_uart0_printf(" TRNG\n");
482
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_CFS));    neorv32_uart0_printf(" CFS\n");
483
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SLINK));  neorv32_uart0_printf(" SLINK\n");
484
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_NEOLED)); neorv32_uart0_printf(" NEOLED\n");
485
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_XIRQ));   neorv32_uart0_printf(" XIRQ\n");
486 67 zero_gravi
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_GPTMR));  neorv32_uart0_printf(" GPTMR\n");
487 70 zero_gravi
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_XIP));    neorv32_uart0_printf(" XIP\n");
488 6 zero_gravi
}
489
 
490
 
491
/**********************************************************************//**
492 50 zero_gravi
 * NEORV32 runtime environment: Private function to print yes or no.
493 6 zero_gravi
 * @note This function is used by neorv32_rte_print_hw_config(void) only.
494
 *
495 65 zero_gravi
 * @param[in] state Print 'yes' when !=0, print 'no' when 0
496 6 zero_gravi
 **************************************************************************/
497
static void __neorv32_rte_print_true_false(int state) {
498
 
499
  if (state) {
500 61 zero_gravi
    neorv32_uart0_print("yes\n");
501 6 zero_gravi
  }
502 2 zero_gravi
  else {
503 61 zero_gravi
    neorv32_uart0_print("no\n");
504 2 zero_gravi
  }
505 6 zero_gravi
}
506 2 zero_gravi
 
507
 
508 6 zero_gravi
/**********************************************************************//**
509 65 zero_gravi
 * NEORV32 runtime environment: Private function to print [x] or [ ].
510
 * @note This function is used by neorv32_rte_print_hw_config(void) only.
511
 *
512
 * @param[in] state Print '[x]' when !=0, print '[ ]' when 0
513
 **************************************************************************/
514
static void __neorv32_rte_print_checkbox(int state) {
515
 
516
  neorv32_uart0_putc('[');
517
  if (state) {
518
    neorv32_uart0_putc('x');
519
  }
520
  else {
521
    neorv32_uart0_putc(' ');
522
  }
523
  neorv32_uart0_putc(']');
524
}
525
 
526
 
527
/**********************************************************************//**
528 33 zero_gravi
 * NEORV32 runtime environment: Private function to print 32-bit number
529
 * as 8-digit hexadecimal value (with "0x" suffix).
530
 *
531
 * @param[in] num Number to print as hexadecimal.
532
 **************************************************************************/
533
void __neorv32_rte_print_hex_word(uint32_t num) {
534
 
535
  static const char hex_symbols[16] = "0123456789ABCDEF";
536
 
537 61 zero_gravi
  neorv32_uart0_print("0x");
538 33 zero_gravi
 
539
  int i;
540
  for (i=0; i<8; i++) {
541
    uint32_t index = (num >> (28 - 4*i)) & 0xF;
542 61 zero_gravi
    neorv32_uart0_putc(hex_symbols[index]);
543 33 zero_gravi
  }
544
}
545
 
546
 
547 47 zero_gravi
/**********************************************************************//**
548 41 zero_gravi
 * NEORV32 runtime environment: Print the processor version in human-readable format.
549 6 zero_gravi
 **************************************************************************/
550 12 zero_gravi
void neorv32_rte_print_hw_version(void) {
551 6 zero_gravi
 
552
  uint32_t i;
553
  char tmp, cnt;
554
 
555 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
556
    return; // cannot output anything if UART0 is not implemented
557
  }
558
 
559 6 zero_gravi
  for (i=0; i<4; i++) {
560
 
561 33 zero_gravi
    tmp = (char)(neorv32_cpu_csr_read(CSR_MIMPID) >> (24 - 8*i));
562 6 zero_gravi
 
563
    // serial division
564
    cnt = 0;
565 35 zero_gravi
    while (tmp >= 16) {
566
      tmp = tmp - 16;
567 6 zero_gravi
      cnt++;
568
    }
569
 
570
    if (cnt) {
571 61 zero_gravi
      neorv32_uart0_putc('0' + cnt);
572 6 zero_gravi
    }
573 61 zero_gravi
    neorv32_uart0_putc('0' + tmp);
574 6 zero_gravi
    if (i < 3) {
575 61 zero_gravi
      neorv32_uart0_putc('.');
576 6 zero_gravi
    }
577
  }
578 2 zero_gravi
}
579 11 zero_gravi
 
580
 
581
/**********************************************************************//**
582
 * NEORV32 runtime environment: Print project credits
583
 **************************************************************************/
584
void neorv32_rte_print_credits(void) {
585
 
586 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
587
    return; // cannot output anything if UART0 is not implemented
588
  }
589
 
590 71 zero_gravi
  neorv32_uart0_print("The NEORV32 RISC-V Processor, https://github.com/stnolting/neorv32\n"
591
                      "(c) 2022 by Stephan Nolting, BSD 3-Clause License\n\n");
592 11 zero_gravi
}
593
 
594 22 zero_gravi
 
595
/**********************************************************************//**
596 41 zero_gravi
 * NEORV32 runtime environment: Print project logo
597 37 zero_gravi
 **************************************************************************/
598
void neorv32_rte_print_logo(void) {
599
 
600 40 zero_gravi
  const uint32_t logo_data_c[11][4] =
601
  {
602
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000},
603
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
604
    {0b01100000110001111111110001111111,0b10000111111110001100000011000111,0b11111000011111111000000110000000,0b11111111111111110000000000000000},
605
    {0b11110000110011000000000011000000,0b11001100000011001100000011001100,0b00001100110000001100000110000011,0b11000000000000111100000000000000},
606
    {0b11011000110011000000000011000000,0b11001100000011001100000011000000,0b00001100000000011000000110000000,0b11000111111000110000000000000000},
607
    {0b11001100110011111111100011000000,0b11001111111110001100000011000000,0b11111000000001100000000110000011,0b11000111111000111100000000000000},
608
    {0b11000110110011000000000011000000,0b11001100001100000110000110000000,0b00001100000110000000000110000000,0b11000111111000110000000000000000},
609
    {0b11000011110011000000000011000000,0b11001100000110000011001100001100,0b00001100011000000000000110000011,0b11000000000000111100000000000000},
610
    {0b11000001100001111111110001111111,0b10001100000011000000110000000111,0b11111000111111111100000110000000,0b11111111111111110000000000000000},
611
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
612
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000}
613
  };
614
 
615
  int u,v,w;
616
  uint32_t tmp;
617
 
618 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
619
    return; // cannot output anything if UART0 is not implemented
620
  }
621
 
622 40 zero_gravi
  for (u=0; u<11; u++) {
623 61 zero_gravi
    neorv32_uart0_print("\n");
624 40 zero_gravi
    for (v=0; v<4; v++) {
625
      tmp = logo_data_c[u][v];
626
      for (w=0; w<32; w++){
627 61 zero_gravi
        if (((int32_t)tmp) < 0) { // check MSB
628
          neorv32_uart0_putc('#');
629 40 zero_gravi
        }
630
        else {
631 61 zero_gravi
          neorv32_uart0_putc(' ');
632 40 zero_gravi
        }
633 47 zero_gravi
        tmp <<= 1;
634 40 zero_gravi
      }
635
    }
636
  }
637 61 zero_gravi
  neorv32_uart0_print("\n");
638 37 zero_gravi
}
639
 
640
 
641
/**********************************************************************//**
642 22 zero_gravi
 * NEORV32 runtime environment: Print project license
643
 **************************************************************************/
644
void neorv32_rte_print_license(void) {
645
 
646 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
647
    return; // cannot output anything if UART0 is not implemented
648
  }
649
 
650 65 zero_gravi
  neorv32_uart0_print(
651 22 zero_gravi
  "\n"
652
  "BSD 3-Clause License\n"
653
  "\n"
654 71 zero_gravi
  "Copyright (c) 2022, Stephan Nolting. All rights reserved.\n"
655 22 zero_gravi
  "\n"
656
  "Redistribution and use in source and binary forms, with or without modification, are\n"
657
  "permitted provided that the following conditions are met:\n"
658
  "\n"
659
  "1. Redistributions of source code must retain the above copyright notice, this list of\n"
660
  "   conditions and the following disclaimer.\n"
661
  "\n"
662
  "2. Redistributions in binary form must reproduce the above copyright notice, this list of\n"
663
  "   conditions and the following disclaimer in the documentation and/or other materials\n"
664
  "   provided with the distribution.\n"
665
  "\n"
666
  "3. Neither the name of the copyright holder nor the names of its contributors may be used to\n"
667
  "   endorse or promote products derived from this software without specific prior written\n"
668
  "   permission.\n"
669
  "\n"
670
  "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n"
671
  "OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
672
  "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
673
  "COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n"
674
  "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n"
675
  "GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\n"
676
  "AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n"
677
  "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n"
678
  "OF THE POSSIBILITY OF SUCH DAMAGE.\n"
679
  "\n"
680
  "\n"
681
  );
682
}
683
 
684 44 zero_gravi
 
685
/**********************************************************************//**
686
 * NEORV32 runtime environment: Get MISA CSR value according to *compiler/toolchain configuration*.
687
 *
688
 * @return MISA content according to compiler configuration.
689
 **************************************************************************/
690
uint32_t neorv32_rte_get_compiler_isa(void) {
691
 
692
  uint32_t misa_cc = 0;
693
 
694 53 zero_gravi
#if defined __riscv_atomic || defined __riscv_a
695 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_A;
696 44 zero_gravi
#endif
697
 
698 53 zero_gravi
#ifdef __riscv_b
699 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_B;
700 53 zero_gravi
#endif
701
 
702
#if defined __riscv_compressed || defined __riscv_c
703 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_C;
704 44 zero_gravi
#endif
705
 
706 53 zero_gravi
#if (__riscv_flen == 64) || defined __riscv_d
707 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_D;
708 52 zero_gravi
#endif
709
 
710 44 zero_gravi
#ifdef __riscv_32e
711 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_E;
712 44 zero_gravi
#else
713 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_I;
714 44 zero_gravi
#endif
715
 
716 53 zero_gravi
#if (__riscv_flen == 32) || defined __riscv_f
717 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_F;
718 52 zero_gravi
#endif
719
 
720 53 zero_gravi
#if defined __riscv_mul || defined __riscv_m
721 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_M;
722 44 zero_gravi
#endif
723
 
724
#if (__riscv_xlen == 32)
725 61 zero_gravi
  misa_cc |= 1 << CSR_MISA_MXL_LO;
726 44 zero_gravi
#elif (__riscv_xlen == 64)
727 61 zero_gravi
  misa_cc |= 2 << CSR_MISA_MXL_LO;
728 44 zero_gravi
#else
729 61 zero_gravi
  misa_cc |= 3 << CSR_MISA_MXL_LO;
730 44 zero_gravi
#endif
731
 
732
  return misa_cc;
733
}
734
 
735
 
736
/**********************************************************************//**
737
 * NEORV32 runtime environment: Check required ISA extensions (via compiler flags) against available ISA extensions (via MISA csr).
738
 *
739 68 zero_gravi
 * @param[in] silent Show error message (via neorv32.uart) if isa_sw > isa_hw when = 0.
740 44 zero_gravi
 * @return MISA content according to compiler configuration.
741
 **************************************************************************/
742
int neorv32_rte_check_isa(int silent) {
743
 
744
  uint32_t misa_sw = neorv32_rte_get_compiler_isa();
745
  uint32_t misa_hw = neorv32_cpu_csr_read(CSR_MISA);
746
 
747
  // mask hardware features that are not used by software
748
  uint32_t check = misa_hw & misa_sw;
749
 
750
  //
751
  if (check == misa_sw) {
752
    return 0;
753
  }
754
  else {
755 68 zero_gravi
    if ((silent == 0) && (neorv32_uart0_available() != 0)) {
756 65 zero_gravi
      neorv32_uart0_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n"
757 44 zero_gravi
                          "SW_ISA = 0x%x (compiler flags)\n"
758
                          "HW_ISA = 0x%x (misa csr)\n\n", misa_sw, misa_hw);
759
    }
760
    return 1;
761
  }
762
}
763
 

powered by: WebSVN 2.1.0

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