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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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