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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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