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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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