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

Subversion Repositories neorv32

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

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 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 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_DEBUGMODE)) {
362 66 zero_gravi
    neorv32_uart0_printf("Debug ");
363 59 zero_gravi
  }
364 71 zero_gravi
 
365
  // CPU extension options
366
  neorv32_uart0_printf("\nExtension options: ");
367 63 zero_gravi
  if (tmp & (1<<SYSINFO_CPU_FASTMUL)) {
368
    neorv32_uart0_printf("FAST_MUL ");
369
  }
370
  if (tmp & (1<<SYSINFO_CPU_FASTSHIFT)) {
371
    neorv32_uart0_printf("FAST_SHIFT ");
372
  }
373
 
374 34 zero_gravi
  // check physical memory protection
375 61 zero_gravi
  neorv32_uart0_printf("\nPMP:               ");
376 42 zero_gravi
  uint32_t pmp_num_regions = neorv32_cpu_pmp_get_num_regions();
377
  if (pmp_num_regions != 0)  {
378 61 zero_gravi
    neorv32_uart0_printf("%u regions, %u bytes minimal granularity\n", pmp_num_regions, neorv32_cpu_pmp_get_granularity());
379 34 zero_gravi
  }
380
  else {
381 61 zero_gravi
    neorv32_uart0_printf("not implemented\n");
382 34 zero_gravi
  }
383
 
384
 
385 6 zero_gravi
  // Memory configuration
386 65 zero_gravi
  neorv32_uart0_printf("\n=== << Memory System >> ===\n");
387 6 zero_gravi
 
388 66 zero_gravi
  neorv32_uart0_printf("Boot Config.:        Boot ");
389 65 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_BOOTLOADER)) {
390
    neorv32_uart0_printf("via Bootloader\n");
391
  }
392
  else {
393
    neorv32_uart0_printf("from memory (@ 0x%x)\n", NEORV32_SYSINFO.ISPACE_BASE);
394
  }
395
 
396 66 zero_gravi
  neorv32_uart0_printf("Instr. base address: 0x%x\n", NEORV32_SYSINFO.ISPACE_BASE);
397 56 zero_gravi
 
398
  // IMEM
399 66 zero_gravi
  neorv32_uart0_printf("Internal IMEM:       ");
400 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_IMEM)) {
401
    neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.IMEM_SIZE);
402 56 zero_gravi
  }
403
  else {
404 61 zero_gravi
    neorv32_uart0_printf("no\n");
405 56 zero_gravi
  }
406 6 zero_gravi
 
407 56 zero_gravi
  // DMEM
408 66 zero_gravi
  neorv32_uart0_printf("Data base address:   0x%x\n", NEORV32_SYSINFO.DSPACE_BASE);
409
  neorv32_uart0_printf("Internal DMEM:       ");
410 65 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_DMEM)) {
411
    neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.DMEM_SIZE);
412
  }
413
  else {
414
    neorv32_uart0_printf("no\n");
415
  }
416 6 zero_gravi
 
417 56 zero_gravi
  // i-cache
418 66 zero_gravi
  neorv32_uart0_printf("Internal i-cache:    ");
419 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_ICACHE)) {
420 65 zero_gravi
    neorv32_uart0_printf("yes, ");
421 41 zero_gravi
 
422 64 zero_gravi
    uint32_t ic_block_size = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_BLOCK_SIZE_0) & 0x0F;
423 41 zero_gravi
    if (ic_block_size) {
424
      ic_block_size = 1 << ic_block_size;
425
    }
426
    else {
427
      ic_block_size = 0;
428
    }
429
 
430 64 zero_gravi
    uint32_t ic_num_blocks = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_NUM_BLOCKS_0) & 0x0F;
431 41 zero_gravi
    if (ic_num_blocks) {
432
      ic_num_blocks = 1 << ic_num_blocks;
433
    }
434
    else {
435
      ic_num_blocks = 0;
436
    }
437
 
438 64 zero_gravi
    uint32_t ic_associativity = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_ASSOCIATIVITY_0) & 0x0F;
439 41 zero_gravi
    ic_associativity = 1 << ic_associativity;
440
 
441 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);
442 45 zero_gravi
    if (ic_associativity == 1) {
443 61 zero_gravi
      neorv32_uart0_printf(" (direct-mapped)\n");
444 41 zero_gravi
    }
445 64 zero_gravi
    else if (((NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_REPLACEMENT_0) & 0x0F) == 1) {
446 61 zero_gravi
      neorv32_uart0_printf(" (LRU replacement policy)\n");
447 41 zero_gravi
    }
448
    else {
449 61 zero_gravi
      neorv32_uart0_printf("\n");
450 41 zero_gravi
    }
451
  }
452 65 zero_gravi
  else {
453
    neorv32_uart0_printf("no\n");
454
  }
455 41 zero_gravi
 
456 66 zero_gravi
  neorv32_uart0_printf("Ext. bus interface:  ");
457 64 zero_gravi
  __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT));
458 66 zero_gravi
  neorv32_uart0_printf("Ext. bus Endianness: ");
459 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT_ENDIAN)) {
460 61 zero_gravi
    neorv32_uart0_printf("big\n");
461 40 zero_gravi
  }
462
  else {
463 61 zero_gravi
    neorv32_uart0_printf("little\n");
464 40 zero_gravi
  }
465 6 zero_gravi
 
466
  // peripherals
467 61 zero_gravi
  neorv32_uart0_printf("\n=== << Peripherals >> ===\n");
468 15 zero_gravi
 
469 64 zero_gravi
  tmp = NEORV32_SYSINFO.SOC;
470 65 zero_gravi
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_GPIO));   neorv32_uart0_printf(" GPIO\n");
471
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_MTIME));  neorv32_uart0_printf(" MTIME\n");
472
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART0));  neorv32_uart0_printf(" UART0\n");
473
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART1));  neorv32_uart0_printf(" UART1\n");
474
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SPI));    neorv32_uart0_printf(" SPI\n");
475
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TWI));    neorv32_uart0_printf(" TWI\n");
476
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_PWM));    neorv32_uart0_printf(" PWM\n");
477
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_WDT));    neorv32_uart0_printf(" WDT\n");
478
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TRNG));   neorv32_uart0_printf(" TRNG\n");
479
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_CFS));    neorv32_uart0_printf(" CFS\n");
480
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SLINK));  neorv32_uart0_printf(" SLINK\n");
481
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_NEOLED)); neorv32_uart0_printf(" NEOLED\n");
482
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_XIRQ));   neorv32_uart0_printf(" XIRQ\n");
483 67 zero_gravi
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_GPTMR));  neorv32_uart0_printf(" GPTMR\n");
484 70 zero_gravi
  __neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_XIP));    neorv32_uart0_printf(" XIP\n");
485 6 zero_gravi
}
486
 
487
 
488
/**********************************************************************//**
489 50 zero_gravi
 * NEORV32 runtime environment: Private function to print yes or no.
490 6 zero_gravi
 * @note This function is used by neorv32_rte_print_hw_config(void) only.
491
 *
492 65 zero_gravi
 * @param[in] state Print 'yes' when !=0, print 'no' when 0
493 6 zero_gravi
 **************************************************************************/
494
static void __neorv32_rte_print_true_false(int state) {
495
 
496
  if (state) {
497 61 zero_gravi
    neorv32_uart0_print("yes\n");
498 6 zero_gravi
  }
499 2 zero_gravi
  else {
500 61 zero_gravi
    neorv32_uart0_print("no\n");
501 2 zero_gravi
  }
502 6 zero_gravi
}
503 2 zero_gravi
 
504
 
505 6 zero_gravi
/**********************************************************************//**
506 65 zero_gravi
 * NEORV32 runtime environment: Private function to print [x] or [ ].
507
 * @note This function is used by neorv32_rte_print_hw_config(void) only.
508
 *
509
 * @param[in] state Print '[x]' when !=0, print '[ ]' when 0
510
 **************************************************************************/
511
static void __neorv32_rte_print_checkbox(int state) {
512
 
513
  neorv32_uart0_putc('[');
514
  if (state) {
515
    neorv32_uart0_putc('x');
516
  }
517
  else {
518
    neorv32_uart0_putc(' ');
519
  }
520
  neorv32_uart0_putc(']');
521
}
522
 
523
 
524
/**********************************************************************//**
525 33 zero_gravi
 * NEORV32 runtime environment: Private function to print 32-bit number
526
 * as 8-digit hexadecimal value (with "0x" suffix).
527
 *
528
 * @param[in] num Number to print as hexadecimal.
529
 **************************************************************************/
530
void __neorv32_rte_print_hex_word(uint32_t num) {
531
 
532
  static const char hex_symbols[16] = "0123456789ABCDEF";
533
 
534 61 zero_gravi
  neorv32_uart0_print("0x");
535 33 zero_gravi
 
536
  int i;
537
  for (i=0; i<8; i++) {
538
    uint32_t index = (num >> (28 - 4*i)) & 0xF;
539 61 zero_gravi
    neorv32_uart0_putc(hex_symbols[index]);
540 33 zero_gravi
  }
541
}
542
 
543
 
544 47 zero_gravi
/**********************************************************************//**
545 41 zero_gravi
 * NEORV32 runtime environment: Print the processor version in human-readable format.
546 6 zero_gravi
 **************************************************************************/
547 12 zero_gravi
void neorv32_rte_print_hw_version(void) {
548 6 zero_gravi
 
549
  uint32_t i;
550
  char tmp, cnt;
551
 
552 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
553
    return; // cannot output anything if UART0 is not implemented
554
  }
555
 
556 6 zero_gravi
  for (i=0; i<4; i++) {
557
 
558 33 zero_gravi
    tmp = (char)(neorv32_cpu_csr_read(CSR_MIMPID) >> (24 - 8*i));
559 6 zero_gravi
 
560
    // serial division
561
    cnt = 0;
562 35 zero_gravi
    while (tmp >= 16) {
563
      tmp = tmp - 16;
564 6 zero_gravi
      cnt++;
565
    }
566
 
567
    if (cnt) {
568 61 zero_gravi
      neorv32_uart0_putc('0' + cnt);
569 6 zero_gravi
    }
570 61 zero_gravi
    neorv32_uart0_putc('0' + tmp);
571 6 zero_gravi
    if (i < 3) {
572 61 zero_gravi
      neorv32_uart0_putc('.');
573 6 zero_gravi
    }
574
  }
575 2 zero_gravi
}
576 11 zero_gravi
 
577
 
578
/**********************************************************************//**
579
 * NEORV32 runtime environment: Print project credits
580
 **************************************************************************/
581
void neorv32_rte_print_credits(void) {
582
 
583 61 zero_gravi
  if (neorv32_uart0_available() == 0) {
584
    return; // cannot output anything if UART0 is not implemented
585
  }
586
 
587 71 zero_gravi
  neorv32_uart0_print("The NEORV32 RISC-V Processor, https://github.com/stnolting/neorv32\n"
588
                      "(c) 2022 by Stephan Nolting, BSD 3-Clause License\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 71 zero_gravi
  "Copyright (c) 2022, 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.