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

Subversion Repositories neorv32

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

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 40 zero_gravi
static uint32_t __neorv32_rte_vector_lut[17] __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 14 zero_gravi
  if ((id == RTE_TRAP_I_MISALIGNED) || (id == RTE_TRAP_I_ACCESS)     || (id == RTE_TRAP_I_ILLEGAL) ||
97 40 zero_gravi
      (id == RTE_TRAP_BREAKPOINT)   || (id == RTE_TRAP_L_MISALIGNED) || (id == RTE_TRAP_L_ACCESS)  ||
98
      (id == RTE_TRAP_S_MISALIGNED) || (id == RTE_TRAP_S_ACCESS)     || (id == RTE_TRAP_MENV_CALL) || (id == RTE_TRAP_UENV_CALL) ||
99 14 zero_gravi
      (id == RTE_TRAP_MSI)          || (id == RTE_TRAP_MTI)          || (id == RTE_TRAP_MEI)       ||
100
      (id == RTE_TRAP_FIRQ_0)       || (id == RTE_TRAP_FIRQ_1)       || (id == RTE_TRAP_FIRQ_2)    || (id == RTE_TRAP_FIRQ_3)) {
101 2 zero_gravi
 
102 24 zero_gravi
    __neorv32_rte_vector_lut[id] = (uint32_t)handler; // install handler
103 14 zero_gravi
 
104 2 zero_gravi
    return 0;
105
  }
106
  return 1;
107
}
108
 
109
 
110
/**********************************************************************//**
111
 * Uninstall exception handler function from NEORV32 runtime environment, which was
112 14 zero_gravi
 * previously installed via neorv32_rte_exception_install(uint8_t id, void (*handler)(void)).
113 2 zero_gravi
 *
114 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)
115
 * and/or the global interrupt enable bit mstatus.mie via neorv32_cpu_dint(void).
116 2 zero_gravi
 *
117 14 zero_gravi
 * @param[in] id Identifier (type) of the targeted exception. See #NEORV32_RTE_TRAP_enum.
118 18 zero_gravi
 * @return 0 if success, 1 if error (invalid id or targeted exception not supported).
119 2 zero_gravi
 **************************************************************************/
120 14 zero_gravi
int neorv32_rte_exception_uninstall(uint8_t id) {
121 2 zero_gravi
 
122
  // id valid?
123 14 zero_gravi
  if ((id == RTE_TRAP_I_MISALIGNED) || (id == RTE_TRAP_I_ACCESS)     || (id == RTE_TRAP_I_ILLEGAL) ||
124 40 zero_gravi
      (id == RTE_TRAP_BREAKPOINT)   || (id == RTE_TRAP_L_MISALIGNED) || (id == RTE_TRAP_L_ACCESS)  ||
125
      (id == RTE_TRAP_S_MISALIGNED) || (id == RTE_TRAP_S_ACCESS)     || (id == RTE_TRAP_MENV_CALL) || (id == RTE_TRAP_UENV_CALL) ||
126 14 zero_gravi
      (id == RTE_TRAP_MSI)          || (id == RTE_TRAP_MTI)          || (id == RTE_TRAP_MEI)       ||
127
      (id == RTE_TRAP_FIRQ_0)       || (id == RTE_TRAP_FIRQ_1)       || (id == RTE_TRAP_FIRQ_2)    || (id == RTE_TRAP_FIRQ_3)) {
128 2 zero_gravi
 
129 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
130 2 zero_gravi
 
131
    return 0;
132
  }
133
  return 1;
134
}
135
 
136
 
137
/**********************************************************************//**
138 14 zero_gravi
 * This is the core of the NEORV32 RTE.
139
 *
140
 * @note This function must no be explicitly used by the user.
141 33 zero_gravi
 * @note The RTE core uses mscratch CSR to store the trap-causing mepc for further (user-defined) processing.
142
 *
143 14 zero_gravi
 * @warning When using the the RTE, this function is the ONLY function that can use the 'interrupt' attribute!
144 2 zero_gravi
 **************************************************************************/
145 14 zero_gravi
static void __attribute__((__interrupt__)) __attribute__((aligned(16)))  __neorv32_rte_core(void) {
146 2 zero_gravi
 
147 33 zero_gravi
  register uint32_t rte_mepc = neorv32_cpu_csr_read(CSR_MEPC);
148
  neorv32_cpu_csr_write(CSR_MSCRATCH, rte_mepc); // store for later
149 14 zero_gravi
  register uint32_t rte_mcause = neorv32_cpu_csr_read(CSR_MCAUSE);
150
 
151
  // compute return address
152
  if ((rte_mcause & 0x80000000) == 0) { // modify pc only if exception
153
 
154
    // get low half word of faulting instruction
155
    register uint32_t rte_trap_inst;
156
    asm volatile ("lh %[result], 0(%[input_i])" : [result] "=r" (rte_trap_inst) : [input_i] "r" (rte_mepc));
157
 
158
    if ((rte_trap_inst & 3) == 3) { // faulting instruction is uncompressed instruction
159
      rte_mepc += 4;
160
    }
161
    else { // faulting instruction is compressed instruction
162
      rte_mepc += 2;
163
    }
164
 
165
    // store new return address
166
    neorv32_cpu_csr_write(CSR_MEPC, rte_mepc);
167
  }
168
 
169
  // find according trap handler
170
  register uint32_t rte_handler = (uint32_t)(&__neorv32_rte_debug_exc_handler);
171
  switch (rte_mcause) {
172
    case TRAP_CODE_I_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_MISALIGNED]; break;
173
    case TRAP_CODE_I_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ACCESS]; break;
174
    case TRAP_CODE_I_ILLEGAL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ILLEGAL]; break;
175
    case TRAP_CODE_BREAKPOINT:   rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_BREAKPOINT]; break;
176
    case TRAP_CODE_L_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_L_MISALIGNED]; break;
177
    case TRAP_CODE_L_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_L_ACCESS]; break;
178
    case TRAP_CODE_S_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_S_MISALIGNED]; break;
179
    case TRAP_CODE_S_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_S_ACCESS]; break;
180 40 zero_gravi
    case TRAP_CODE_UENV_CALL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_UENV_CALL]; break;
181 14 zero_gravi
    case TRAP_CODE_MENV_CALL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MENV_CALL]; break;
182
    case TRAP_CODE_MSI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MSI]; break;
183
    case TRAP_CODE_MTI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MTI]; break;
184
    case TRAP_CODE_MEI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MEI]; break;
185
    case TRAP_CODE_FIRQ_0:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_0]; break;
186
    case TRAP_CODE_FIRQ_1:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_1]; break;
187
    case TRAP_CODE_FIRQ_2:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_2]; break;
188
    case TRAP_CODE_FIRQ_3:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_3]; break;
189
    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 15 zero_gravi
  // intro
206 33 zero_gravi
  neorv32_uart_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
  switch (trap_cause) {
211 33 zero_gravi
    case TRAP_CODE_I_MISALIGNED: neorv32_uart_print("Instruction address misaligned"); break;
212
    case TRAP_CODE_I_ACCESS:     neorv32_uart_print("Instruction access fault"); break;
213
    case TRAP_CODE_I_ILLEGAL:    neorv32_uart_print("Illegal instruction"); break;
214
    case TRAP_CODE_BREAKPOINT:   neorv32_uart_print("Breakpoint"); break;
215
    case TRAP_CODE_L_MISALIGNED: neorv32_uart_print("Load address misaligned"); break;
216
    case TRAP_CODE_L_ACCESS:     neorv32_uart_print("Load access fault"); break;
217
    case TRAP_CODE_S_MISALIGNED: neorv32_uart_print("Store address misaligned"); break;
218
    case TRAP_CODE_S_ACCESS:     neorv32_uart_print("Store access fault"); break;
219 40 zero_gravi
    case TRAP_CODE_UENV_CALL:    neorv32_uart_print("Environment call from U-mode"); break;
220
    case TRAP_CODE_MENV_CALL:    neorv32_uart_print("Environment call from M-mode"); break;
221 33 zero_gravi
    case TRAP_CODE_MSI:          neorv32_uart_print("Machine software interrupt"); break;
222
    case TRAP_CODE_MTI:          neorv32_uart_print("Machine timer interrupt"); break;
223
    case TRAP_CODE_MEI:          neorv32_uart_print("Machine external interrupt"); break;
224
    case TRAP_CODE_FIRQ_0:       neorv32_uart_print("Fast interrupt 0"); break;
225
    case TRAP_CODE_FIRQ_1:       neorv32_uart_print("Fast interrupt 1"); break;
226
    case TRAP_CODE_FIRQ_2:       neorv32_uart_print("Fast interrupt 2"); break;
227
    case TRAP_CODE_FIRQ_3:       neorv32_uart_print("Fast interrupt 3"); break;
228
    default:                     neorv32_uart_print("Unknown trap cause: "); __neorv32_rte_print_hex_word(trap_cause); break;
229 2 zero_gravi
  }
230
 
231 33 zero_gravi
  // instruction address
232 35 zero_gravi
  neorv32_uart_print(" @ PC=");
233 33 zero_gravi
  __neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MSCRATCH)); // rte core stores actual mepc to mscratch
234 15 zero_gravi
 
235 33 zero_gravi
  // additional info
236
  neorv32_uart_print(", MTVAL=");
237
  __neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MTVAL));
238
  neorv32_uart_print(" </RTE>");
239 6 zero_gravi
}
240
 
241
 
242
/**********************************************************************//**
243
 * NEORV32 runtime environment: Print hardware configuration information via UART
244
 **************************************************************************/
245
void neorv32_rte_print_hw_config(void) {
246
 
247
  uint32_t tmp;
248
  int i;
249
  char c;
250
 
251 32 zero_gravi
  neorv32_uart_printf("\n\n<< Hardware Configuration Overview >>\n");
252 6 zero_gravi
 
253
  // CPU configuration
254 40 zero_gravi
  neorv32_uart_printf("\n---- Central Processing Unit ----\n");
255 6 zero_gravi
 
256 23 zero_gravi
  // ID
257 30 zero_gravi
  neorv32_uart_printf("Hart ID:           0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID));
258 6 zero_gravi
 
259 30 zero_gravi
  neorv32_uart_printf("Vendor ID:         0x%x\n", neorv32_cpu_csr_read(CSR_MVENDORID));
260 12 zero_gravi
 
261 23 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MARCHID);
262 30 zero_gravi
  neorv32_uart_printf("Architecture ID:   0x%x", tmp);
263 32 zero_gravi
  if (tmp == NEORV32_ARCHID) {
264
    neorv32_uart_printf(" (NEORV32)");
265
  }
266 23 zero_gravi
 
267 6 zero_gravi
  // HW version
268 30 zero_gravi
  neorv32_uart_printf("\nImplementation ID: 0x%x (", neorv32_cpu_csr_read(CSR_MIMPID));
269 12 zero_gravi
  neorv32_rte_print_hw_version();
270 30 zero_gravi
  neorv32_uart_printf(")\n");
271 6 zero_gravi
 
272
  // CPU architecture
273 30 zero_gravi
  neorv32_uart_printf("Architecture:      ");
274 6 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MISA);
275
  tmp = (tmp >> 30) & 0x03;
276
  if (tmp == 0) {
277
    neorv32_uart_printf("unknown");
278
  }
279
  if (tmp == 1) {
280 41 zero_gravi
    neorv32_uart_printf("rv32");
281 6 zero_gravi
  }
282
  if (tmp == 2) {
283 41 zero_gravi
    neorv32_uart_printf("rv64");
284 6 zero_gravi
  }
285
  if (tmp == 3) {
286 41 zero_gravi
    neorv32_uart_printf("rv128");
287 6 zero_gravi
  }
288
 
289
  // CPU extensions
290 40 zero_gravi
  neorv32_uart_printf("\nEndianness:        ");
291 42 zero_gravi
  if (neorv32_cpu_csr_read(CSR_MSTATUSH) & (1<<CSR_MSTATUSH_MBE)) {
292 40 zero_gravi
    neorv32_uart_printf("big\n");
293
  }
294
  else {
295
    neorv32_uart_printf("little\n");
296
  }
297
 
298
  // CPU extensions
299 42 zero_gravi
  neorv32_uart_printf("Extensions:        ");
300 6 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MISA);
301
  for (i=0; i<26; i++) {
302
    if (tmp & (1 << i)) {
303
      c = (char)('A' + i);
304
      neorv32_uart_putc(c);
305
      neorv32_uart_putc(' ');
306
    }
307
  }
308 22 zero_gravi
 
309 40 zero_gravi
  // Z* CPU extensions (from custom "mzext" CSR)
310 22 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MZEXT);
311 42 zero_gravi
  if (tmp & (1<<CSR_MZEXT_ZICSR)) {
312 22 zero_gravi
    neorv32_uart_printf("Zicsr ");
313
  }
314 42 zero_gravi
  if (tmp & (1<<CSR_MZEXT_ZIFENCEI)) {
315 22 zero_gravi
    neorv32_uart_printf("Zifencei ");
316
  }
317 44 zero_gravi
  if (tmp & (1<<CSR_MZEXT_ZBB)) {
318
    neorv32_uart_printf("Zbb ");
319
  }
320 6 zero_gravi
 
321 34 zero_gravi
  // check physical memory protection
322 42 zero_gravi
  neorv32_uart_printf("\nPMP:               ");
323
  uint32_t pmp_num_regions = neorv32_cpu_pmp_get_num_regions();
324
  if (pmp_num_regions != 0)  {
325 43 zero_gravi
    neorv32_uart_printf("%u regions, %u bytes minimal granularity\n", pmp_num_regions, neorv32_cpu_pmp_get_granularity());
326 34 zero_gravi
  }
327
  else {
328
    neorv32_uart_printf("not implemented\n");
329
  }
330
 
331 43 zero_gravi
  // check hardware performance monitors
332 42 zero_gravi
  neorv32_uart_printf("HPM Counters:      %u\n", neorv32_cpu_hpm_get_counters());
333 34 zero_gravi
 
334 42 zero_gravi
 
335 34 zero_gravi
  // Misc - system
336 40 zero_gravi
  neorv32_uart_printf("\n\n---- Processor - General ----\n");
337 30 zero_gravi
  neorv32_uart_printf("Clock:   %u Hz\n", SYSINFO_CLK);
338
  neorv32_uart_printf("User ID: 0x%x\n", SYSINFO_USER_CODE);
339 15 zero_gravi
 
340
 
341 6 zero_gravi
  // Memory configuration
342 40 zero_gravi
  neorv32_uart_printf("\n---- Processor - Memory Configuration ----\n");
343 6 zero_gravi
 
344 23 zero_gravi
  neorv32_uart_printf("Instr. base address:  0x%x\n", SYSINFO_ISPACE_BASE);
345 6 zero_gravi
  neorv32_uart_printf("Internal IMEM:        ");
346 12 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM));
347 23 zero_gravi
  neorv32_uart_printf("IMEM size:            %u bytes\n", SYSINFO_IMEM_SIZE);
348 6 zero_gravi
  neorv32_uart_printf("Internal IMEM as ROM: ");
349 12 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM));
350 6 zero_gravi
 
351 42 zero_gravi
  neorv32_uart_printf("Data base address:    0x%x\n", SYSINFO_DSPACE_BASE);
352 6 zero_gravi
  neorv32_uart_printf("Internal DMEM:        ");
353 12 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_DMEM));
354 23 zero_gravi
  neorv32_uart_printf("DMEM size:            %u bytes\n", SYSINFO_DMEM_SIZE);
355 6 zero_gravi
 
356 42 zero_gravi
  neorv32_uart_printf("Internal i-cache:     ");
357 41 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE));
358
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE)) {
359
    neorv32_uart_printf("- ");
360
 
361
    uint32_t ic_block_size = (SYSINFO_CACHE >> SYSINFO_CACHE_IC_BLOCK_SIZE_0) & 0x0F;
362
    if (ic_block_size) {
363
      ic_block_size = 1 << ic_block_size;
364
    }
365
    else {
366
      ic_block_size = 0;
367
    }
368
 
369
    uint32_t ic_num_blocks = (SYSINFO_CACHE >> SYSINFO_CACHE_IC_NUM_BLOCKS_0) & 0x0F;
370
    if (ic_num_blocks) {
371
      ic_num_blocks = 1 << ic_num_blocks;
372
    }
373
    else {
374
      ic_num_blocks = 0;
375
    }
376
 
377
    uint32_t ic_associativity = (SYSINFO_CACHE >> SYSINFO_CACHE_IC_ASSOCIATIVITY_0) & 0x0F;
378
    ic_associativity = 1 << ic_associativity;
379
 
380 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);
381
    if (ic_associativity == 1) {
382
      neorv32_uart_printf(" (direct-mapped)\n");
383 41 zero_gravi
    }
384 45 zero_gravi
    else if (((SYSINFO_CACHE >> SYSINFO_CACHE_IC_REPLACEMENT_0) & 0x0F) == 1) {
385
      neorv32_uart_printf(" (LRU replacement policy)\n");
386 41 zero_gravi
    }
387
    else {
388 45 zero_gravi
      neorv32_uart_printf("\n");
389 41 zero_gravi
    }
390
  }
391
 
392 42 zero_gravi
  neorv32_uart_printf("Bootloader:           ");
393 12 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_BOOTLOADER));
394 6 zero_gravi
 
395 42 zero_gravi
  neorv32_uart_printf("Ext. bus interface:   ");
396 12 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT));
397 42 zero_gravi
  neorv32_uart_printf("Ext. bus Endianness:  ");
398 40 zero_gravi
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT_ENDIAN)) {
399
    neorv32_uart_printf("big\n");
400
  }
401
  else {
402
    neorv32_uart_printf("little\n");
403
  }
404 6 zero_gravi
 
405
  // peripherals
406 40 zero_gravi
  neorv32_uart_printf("\n\n---- Processor - Peripherals ----\n");
407 15 zero_gravi
 
408 12 zero_gravi
  tmp = SYSINFO_FEATURES;
409 6 zero_gravi
 
410 39 zero_gravi
  neorv32_uart_printf("GPIO  - ");
411 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_GPIO));
412 6 zero_gravi
 
413 39 zero_gravi
  neorv32_uart_printf("MTIME - ");
414 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_MTIME));
415 6 zero_gravi
 
416 39 zero_gravi
  neorv32_uart_printf("UART  - ");
417 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_UART));
418 6 zero_gravi
 
419 39 zero_gravi
  neorv32_uart_printf("SPI   - ");
420 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_SPI));
421 6 zero_gravi
 
422 39 zero_gravi
  neorv32_uart_printf("TWI   - ");
423 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TWI));
424 6 zero_gravi
 
425 39 zero_gravi
  neorv32_uart_printf("PWM   - ");
426 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_PWM));
427 6 zero_gravi
 
428 39 zero_gravi
  neorv32_uart_printf("WDT   - ");
429 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_WDT));
430 6 zero_gravi
 
431 39 zero_gravi
  neorv32_uart_printf("TRNG  - ");
432 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TRNG));
433 6 zero_gravi
 
434 39 zero_gravi
  neorv32_uart_printf("CFU0  - ");
435 34 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_CFU0));
436
 
437 39 zero_gravi
  neorv32_uart_printf("CFU1  - ");
438 34 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_CFU1));
439 6 zero_gravi
}
440
 
441
 
442
/**********************************************************************//**
443
 * NEORV32 runtime environment: Private function to print true or false.
444
 * @note This function is used by neorv32_rte_print_hw_config(void) only.
445
 *
446
 * @param[in] state Print TRUE when !=0, print FALSE when 0
447
 **************************************************************************/
448
static void __neorv32_rte_print_true_false(int state) {
449
 
450
  if (state) {
451 33 zero_gravi
    neorv32_uart_print("True\n");
452 6 zero_gravi
  }
453 2 zero_gravi
  else {
454 33 zero_gravi
    neorv32_uart_print("False\n");
455 2 zero_gravi
  }
456 6 zero_gravi
}
457 2 zero_gravi
 
458
 
459 6 zero_gravi
/**********************************************************************//**
460 33 zero_gravi
 * NEORV32 runtime environment: Private function to print 32-bit number
461
 * as 8-digit hexadecimal value (with "0x" suffix).
462
 *
463
 * @param[in] num Number to print as hexadecimal.
464
 **************************************************************************/
465
void __neorv32_rte_print_hex_word(uint32_t num) {
466
 
467
  static const char hex_symbols[16] = "0123456789ABCDEF";
468
 
469
  neorv32_uart_print("0x");
470
 
471
  int i;
472
  for (i=0; i<8; i++) {
473
    uint32_t index = (num >> (28 - 4*i)) & 0xF;
474
    neorv32_uart_putc(hex_symbols[index]);
475
  }
476
}
477
 
478
 
479
 
480
/**********************************************************************//**
481 41 zero_gravi
 * NEORV32 runtime environment: Print the processor version in human-readable format.
482 6 zero_gravi
 **************************************************************************/
483 12 zero_gravi
void neorv32_rte_print_hw_version(void) {
484 6 zero_gravi
 
485
  uint32_t i;
486
  char tmp, cnt;
487
 
488
  for (i=0; i<4; i++) {
489
 
490 33 zero_gravi
    tmp = (char)(neorv32_cpu_csr_read(CSR_MIMPID) >> (24 - 8*i));
491 6 zero_gravi
 
492
    // serial division
493
    cnt = 0;
494 35 zero_gravi
    while (tmp >= 16) {
495
      tmp = tmp - 16;
496 6 zero_gravi
      cnt++;
497
    }
498
 
499
    if (cnt) {
500
      neorv32_uart_putc('0' + cnt);
501
    }
502
    neorv32_uart_putc('0' + tmp);
503
    if (i < 3) {
504
      neorv32_uart_putc('.');
505
    }
506
  }
507 2 zero_gravi
}
508 11 zero_gravi
 
509
 
510
/**********************************************************************//**
511
 * NEORV32 runtime environment: Print project credits
512
 **************************************************************************/
513
void neorv32_rte_print_credits(void) {
514
 
515 42 zero_gravi
  neorv32_uart_print("The NEORV32 Processor Project\n"
516
                     "Copyright 2021, Stephan Nolting\n"
517
                     "BSD 3-Clause License\n"
518 39 zero_gravi
                     "https://github.com/stnolting/neorv32\n\n");
519 11 zero_gravi
}
520
 
521 22 zero_gravi
 
522
/**********************************************************************//**
523 41 zero_gravi
 * NEORV32 runtime environment: Print project logo
524 37 zero_gravi
 **************************************************************************/
525
void neorv32_rte_print_logo(void) {
526
 
527 40 zero_gravi
  const uint32_t logo_data_c[11][4] =
528
  {
529
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000},
530
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
531
    {0b01100000110001111111110001111111,0b10000111111110001100000011000111,0b11111000011111111000000110000000,0b11111111111111110000000000000000},
532
    {0b11110000110011000000000011000000,0b11001100000011001100000011001100,0b00001100110000001100000110000011,0b11000000000000111100000000000000},
533
    {0b11011000110011000000000011000000,0b11001100000011001100000011000000,0b00001100000000011000000110000000,0b11000111111000110000000000000000},
534
    {0b11001100110011111111100011000000,0b11001111111110001100000011000000,0b11111000000001100000000110000011,0b11000111111000111100000000000000},
535
    {0b11000110110011000000000011000000,0b11001100001100000110000110000000,0b00001100000110000000000110000000,0b11000111111000110000000000000000},
536
    {0b11000011110011000000000011000000,0b11001100000110000011001100001100,0b00001100011000000000000110000011,0b11000000000000111100000000000000},
537
    {0b11000001100001111111110001111111,0b10001100000011000000110000000111,0b11111000111111111100000110000000,0b11111111111111110000000000000000},
538
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000},
539
    {0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000}
540
  };
541
 
542
  int u,v,w;
543
  uint32_t tmp;
544
 
545
  for (u=0; u<11; u++) {
546
    neorv32_uart_print("\n");
547
    for (v=0; v<4; v++) {
548
      tmp = logo_data_c[u][v];
549
      for (w=0; w<32; w++){
550
        if (tmp & (1 << (31-w))) {
551
          neorv32_uart_putc('#');
552
        }
553
        else {
554
          neorv32_uart_putc(' ');
555
        }
556
      }
557
    }
558
  }
559
  neorv32_uart_print("\n");
560 37 zero_gravi
}
561
 
562
 
563
/**********************************************************************//**
564 22 zero_gravi
 * NEORV32 runtime environment: Print project license
565
 **************************************************************************/
566
void neorv32_rte_print_license(void) {
567
 
568
  neorv32_uart_print(
569
  "\n"
570
  "BSD 3-Clause License\n"
571
  "\n"
572 42 zero_gravi
  "Copyright (c) 2021, Stephan Nolting. All rights reserved.\n"
573 22 zero_gravi
  "\n"
574
  "Redistribution and use in source and binary forms, with or without modification, are\n"
575
  "permitted provided that the following conditions are met:\n"
576
  "\n"
577
  "1. Redistributions of source code must retain the above copyright notice, this list of\n"
578
  "   conditions and the following disclaimer.\n"
579
  "\n"
580
  "2. Redistributions in binary form must reproduce the above copyright notice, this list of\n"
581
  "   conditions and the following disclaimer in the documentation and/or other materials\n"
582
  "   provided with the distribution.\n"
583
  "\n"
584
  "3. Neither the name of the copyright holder nor the names of its contributors may be used to\n"
585
  "   endorse or promote products derived from this software without specific prior written\n"
586
  "   permission.\n"
587
  "\n"
588
  "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n"
589
  "OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
590
  "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
591
  "COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n"
592
  "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n"
593
  "GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\n"
594
  "AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n"
595
  "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n"
596
  "OF THE POSSIBILITY OF SUCH DAMAGE.\n"
597
  "\n"
598
  "\n"
599
  );
600
}
601
 
602 44 zero_gravi
 
603
/**********************************************************************//**
604
 * NEORV32 runtime environment: Get MISA CSR value according to *compiler/toolchain configuration*.
605
 *
606
 * @return MISA content according to compiler configuration.
607
 **************************************************************************/
608
uint32_t neorv32_rte_get_compiler_isa(void) {
609
 
610
  uint32_t misa_cc = 0;
611
 
612
#ifdef __riscv_atomic
613
  misa_cc |= 1 << CSR_MISA_A_EXT;
614
#endif
615
 
616
#ifdef __riscv_compressed
617
  misa_cc |= 1 << CSR_MISA_C_EXT;
618
#endif
619
 
620
#ifdef __riscv_32e
621
  misa_cc |= 1 << CSR_MISA_E_EXT;
622
#else
623
  misa_cc |= 1 << CSR_MISA_I_EXT;
624
#endif
625
 
626
#ifdef __riscv_mul
627
  misa_cc |= 1 << CSR_MISA_M_EXT;
628
#endif
629
 
630
#if (__riscv_xlen == 32)
631
  misa_cc |= 1 << CSR_MISA_MXL_LO_EXT;
632
#elif (__riscv_xlen == 64)
633
  misa_cc |= 2 << CSR_MISA_MXL_LO_EXT;
634
#else
635
  misa_cc |= 3 << CSR_MISA_MXL_LO_EXT;
636
#endif
637
 
638
  return misa_cc;
639
}
640
 
641
 
642
/**********************************************************************//**
643
 * NEORV32 runtime environment: Check required ISA extensions (via compiler flags) against available ISA extensions (via MISA csr).
644
 *
645
 * @param[in] silent Show error message (via neorv32.uart) if isa_sw > isa_hw when != 0.
646
 * @return MISA content according to compiler configuration.
647
 **************************************************************************/
648
int neorv32_rte_check_isa(int silent) {
649
 
650
  uint32_t misa_sw = neorv32_rte_get_compiler_isa();
651
  uint32_t misa_hw = neorv32_cpu_csr_read(CSR_MISA);
652
 
653
  // mask hardware features that are not used by software
654
  uint32_t check = misa_hw & misa_sw;
655
 
656
  //
657
  if (check == misa_sw) {
658
    return 0;
659
  }
660
  else {
661
    if (silent == 0) {
662
      neorv32_uart_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n"
663
                          "SW_ISA = 0x%x (compiler flags)\n"
664
                          "HW_ISA = 0x%x (misa csr)\n\n", misa_sw, misa_hw);
665
    }
666
    return 1;
667
  }
668
}
669
 

powered by: WebSVN 2.1.0

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