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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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