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

Subversion Repositories neorv32

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

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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