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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [example/] [processor_check/] [main.c] - Blame information for rev 74

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 59 zero_gravi
// #################################################################################################
2
// # << NEORV32 - Processor Test Program >>                                                        #
3
// # ********************************************************************************************* #
4
// # BSD 3-Clause License                                                                          #
5
// #                                                                                               #
6 70 zero_gravi
// # Copyright (c) 2022, Stephan Nolting. All rights reserved.                                     #
7 59 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 processor_check/main.c
38
 * @author Stephan Nolting
39
 * @brief CPU/Processor test program.
40
 **************************************************************************/
41
 
42
#include <neorv32.h>
43
#include <string.h>
44
 
45
 
46
/**********************************************************************//**
47
 * @name User configuration
48
 **************************************************************************/
49
/**@{*/
50
/** UART BAUD rate */
51
#define BAUD_RATE           (19200)
52
//** Reachable unaligned address */
53 64 zero_gravi
#define ADDR_UNALIGNED_1    (0x00000001)
54
//** Reachable unaligned address */
55
#define ADDR_UNALIGNED_2    (0x00000002)
56 59 zero_gravi
//** Unreachable word-aligned address */
57
#define ADDR_UNREACHABLE    (IO_BASE_ADDRESS-4)
58 70 zero_gravi
//**Read-only word-aligned address */
59
#define ADDR_READONLY       ((uint32_t)&NEORV32_SYSINFO.CLK)
60 59 zero_gravi
//** external memory base address */
61
#define EXT_MEM_BASE        (0xF0000000)
62
/**@}*/
63
 
64
 
65 61 zero_gravi
/**********************************************************************//**
66
 * @name UART print macros
67
 **************************************************************************/
68
/**@{*/
69
//** for simulation only! */
70
#ifdef SUPPRESS_OPTIONAL_UART_PRINT
71
//** print standard output to UART0 */
72
#define PRINT_STANDARD(...) 
73
//** print critical output to UART1 */
74
#define PRINT_CRITICAL(...) neorv32_uart1_printf(__VA_ARGS__)
75
#else
76
//** print standard output to UART0 */
77
#define PRINT_STANDARD(...) neorv32_uart0_printf(__VA_ARGS__)
78
//** print critical output to UART0 */
79
#define PRINT_CRITICAL(...) neorv32_uart0_printf(__VA_ARGS__)
80
#endif
81
/**@}*/
82
 
83
 
84 59 zero_gravi
// Prototypes
85 73 zero_gravi
void __attribute__((naked)) goto_user_mode(void);
86 59 zero_gravi
void sim_irq_trigger(uint32_t sel);
87
void global_trap_handler(void);
88 61 zero_gravi
void xirq_trap_handler0(void);
89
void xirq_trap_handler1(void);
90 59 zero_gravi
void test_ok(void);
91
void test_fail(void);
92
 
93
// Global variables (also test initialization of global vars here)
94
/// Global counter for failing tests
95
int cnt_fail = 0;
96
/// Global counter for successful tests
97
int cnt_ok   = 0;
98
/// Global counter for total number of tests
99
int cnt_test = 0;
100 61 zero_gravi
/// Global number of available HPMs
101 59 zero_gravi
uint32_t num_hpm_cnts_global = 0;
102 61 zero_gravi
/// XIRQ trap handler acknowledge
103
uint32_t xirq_trap_handler_ack = 0;
104 59 zero_gravi
 
105 73 zero_gravi
/// Variable to test store accesses
106
volatile uint32_t store_access_addr[2];
107
 
108 61 zero_gravi
/// Variable to test atomic accesses
109 73 zero_gravi
volatile uint32_t atomic_access_addr;
110 59 zero_gravi
 
111 73 zero_gravi
/// Variable to test PMP
112
volatile uint32_t pmp_access_addr;
113 59 zero_gravi
 
114 73 zero_gravi
 
115 59 zero_gravi
/**********************************************************************//**
116
 * High-level CPU/processor test program.
117
 *
118
 * @note Applications has to be compiler with <USER_FLAGS+=-DRUN_CPUTEST>
119 61 zero_gravi
 * @warning This test is intended for simulation only.
120
 * @warning This test requires all optional extensions/modules to be enabled.
121 59 zero_gravi
 *
122 60 zero_gravi
 * @return 0 if execution was successful
123 59 zero_gravi
 **************************************************************************/
124
int main() {
125
 
126
  register uint32_t tmp_a, tmp_b;
127
  uint8_t id;
128
 
129 64 zero_gravi
  // disable global interrupts
130
  neorv32_cpu_dint();
131 59 zero_gravi
 
132 61 zero_gravi
  // init UARTs at default baud rate, no parity bits, no hw flow control
133
  neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
134 64 zero_gravi
  NEORV32_UART1.CTRL = NEORV32_UART0.CTRL; // copy configuration to initialize UART1
135 59 zero_gravi
 
136 61 zero_gravi
#ifdef SUPPRESS_OPTIONAL_UART_PRINT
137
  neorv32_uart0_disable(); // do not generate any UART0 output
138
#endif
139
 
140 59 zero_gravi
// Disable processor_check compilation by default
141
#ifndef RUN_CHECK
142
  #warning processor_check HAS NOT BEEN COMPILED! Use >>make USER_FLAGS+=-DRUN_CHECK clean_all exe<< to compile it.
143
 
144
  // inform the user if you are actually executing this
145 61 zero_gravi
  PRINT_CRITICAL("ERROR! processor_check has not been compiled. Use >>make USER_FLAGS+=-DRUN_CHECK clean_all exe<< to compile it.\n");
146 59 zero_gravi
 
147 60 zero_gravi
  return 1;
148 59 zero_gravi
#endif
149
 
150
 
151
  // ----------------------------------------------
152
  // setup RTE
153
  neorv32_rte_setup(); // this will install a full-detailed debug handler for ALL traps
154
  // ----------------------------------------------
155
 
156
  // check available hardware extensions and compare with compiler flags
157
  neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
158
 
159
 
160
  // intro
161 61 zero_gravi
  PRINT_STANDARD("\n<< PROCESSOR CHECK >>\n");
162
  PRINT_STANDARD("build: "__DATE__" "__TIME__"\n");
163 69 zero_gravi
  PRINT_STANDARD("is simulation: ");
164
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_IS_SIM)) {
165
    PRINT_STANDARD("yes\n");
166
  }
167
  else {
168
    PRINT_STANDARD("no\n");
169
  }
170 59 zero_gravi
 
171
 
172 73 zero_gravi
  // reset (performance) counters
173 66 zero_gravi
  // neorv32_cpu_csr_write(CSR_MCYCLEH, 0);   -> done in crt0.S
174
  // neorv32_cpu_csr_write(CSR_MCYCLE, 0);    -> done in crt0.S
175
  // neorv32_cpu_csr_write(CSR_MINSTRETH, 0); -> done in crt0.S
176
  // neorv32_cpu_csr_write(CSR_MINSTRET, 0);  -> done in crt0.S
177 59 zero_gravi
  neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, 0); // enable performance counter auto increment (ALL counters)
178
  neorv32_cpu_csr_write(CSR_MCOUNTEREN, 7); // allow access from user-mode code to standard counters only
179
 
180 64 zero_gravi
  // set CMP of machine system timer MTIME to max to prevent an IRQ
181
  neorv32_mtime_set_timecmp(-1);
182 59 zero_gravi
  neorv32_mtime_set_time(0);
183
 
184
 
185
  // fancy intro
186
  // -----------------------------------------------
187 73 zero_gravi
  // show ASCII logo
188 59 zero_gravi
  neorv32_rte_print_logo();
189
 
190
  // show project credits
191
  neorv32_rte_print_credits();
192
 
193 73 zero_gravi
  // show full hardware configuration report
194 59 zero_gravi
  neorv32_rte_print_hw_config();
195
 
196
 
197
  // configure RTE
198
  // -----------------------------------------------
199 66 zero_gravi
  PRINT_STANDARD("\n\nRTE setup... ");
200 59 zero_gravi
 
201
  int install_err = 0;
202
  // initialize ALL provided trap handler (overriding the default debug handlers)
203
  for (id=0; id<NEORV32_RTE_NUM_TRAPS; id++) {
204
    install_err += neorv32_rte_exception_install(id, global_trap_handler);
205
  }
206
  if (install_err) {
207 66 zero_gravi
    PRINT_CRITICAL("ERROR!\n");
208 60 zero_gravi
    return 1;
209 59 zero_gravi
  }
210
 
211 64 zero_gravi
  // clear testbench IRQ triggers
212
  sim_irq_trigger(0);
213 59 zero_gravi
 
214 64 zero_gravi
  // clear all interrupt enables, enable only where needed
215
  neorv32_cpu_csr_write(CSR_MIE, 0);
216
 
217 59 zero_gravi
  // test intro
218 66 zero_gravi
  PRINT_STANDARD("\nStarting tests.\n\n");
219 59 zero_gravi
 
220
  // enable global interrupts
221
  neorv32_cpu_eint();
222
 
223
 
224 63 zero_gravi
  // **********************************************************************************************
225
  // Run CPU and SoC tests
226
  // **********************************************************************************************
227
 
228
 
229 59 zero_gravi
  // ----------------------------------------------------------
230 74 zero_gravi
  // Test fence instructions 
231 73 zero_gravi
  // ----------------------------------------------------------
232 74 zero_gravi
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
233
  PRINT_STANDARD("[%i] FENCE(.I): ", cnt_test);
234
 
235
  cnt_test++;
236
 
237 73 zero_gravi
  asm volatile ("fence");
238
  asm volatile ("fence.i");
239 74 zero_gravi
  asm volatile ("fence");
240
  asm volatile ("fence.i");
241 73 zero_gravi
 
242 74 zero_gravi
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
243
    test_ok();
244
  }
245
  else {
246
    test_fail();
247
  }
248 73 zero_gravi
 
249 74 zero_gravi
 
250 73 zero_gravi
  // ----------------------------------------------------------
251 63 zero_gravi
  // Test performance counter: setup as many events and counter as feasible
252
  // ----------------------------------------------------------
253
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
254 66 zero_gravi
  PRINT_STANDARD("[%i] Setup HPM events: ", cnt_test);
255 63 zero_gravi
 
256
  num_hpm_cnts_global = neorv32_cpu_hpm_get_counters();
257
 
258
  if (num_hpm_cnts_global != 0) {
259
    cnt_test++;
260
 
261
    neorv32_cpu_csr_write(CSR_MHPMCOUNTER3,  0); neorv32_cpu_csr_write(CSR_MHPMEVENT3,  1 << HPMCNT_EVENT_CIR);
262
    neorv32_cpu_csr_write(CSR_MHPMCOUNTER4,  0); neorv32_cpu_csr_write(CSR_MHPMEVENT4,  1 << HPMCNT_EVENT_WAIT_IF);
263
    neorv32_cpu_csr_write(CSR_MHPMCOUNTER5,  0); neorv32_cpu_csr_write(CSR_MHPMEVENT5,  1 << HPMCNT_EVENT_WAIT_II);
264
    neorv32_cpu_csr_write(CSR_MHPMCOUNTER6,  0); neorv32_cpu_csr_write(CSR_MHPMEVENT6,  1 << HPMCNT_EVENT_WAIT_MC);
265
    neorv32_cpu_csr_write(CSR_MHPMCOUNTER7,  0); neorv32_cpu_csr_write(CSR_MHPMEVENT7,  1 << HPMCNT_EVENT_LOAD);
266
    neorv32_cpu_csr_write(CSR_MHPMCOUNTER8,  0); neorv32_cpu_csr_write(CSR_MHPMEVENT8,  1 << HPMCNT_EVENT_STORE);
267
    neorv32_cpu_csr_write(CSR_MHPMCOUNTER9,  0); neorv32_cpu_csr_write(CSR_MHPMEVENT9,  1 << HPMCNT_EVENT_WAIT_LS);
268
    neorv32_cpu_csr_write(CSR_MHPMCOUNTER10, 0); neorv32_cpu_csr_write(CSR_MHPMEVENT10, 1 << HPMCNT_EVENT_JUMP);
269
    neorv32_cpu_csr_write(CSR_MHPMCOUNTER11, 0); neorv32_cpu_csr_write(CSR_MHPMEVENT11, 1 << HPMCNT_EVENT_BRANCH);
270
    neorv32_cpu_csr_write(CSR_MHPMCOUNTER12, 0); neorv32_cpu_csr_write(CSR_MHPMEVENT12, 1 << HPMCNT_EVENT_TBRANCH);
271
    neorv32_cpu_csr_write(CSR_MHPMCOUNTER13, 0); neorv32_cpu_csr_write(CSR_MHPMEVENT13, 1 << HPMCNT_EVENT_TRAP);
272
    neorv32_cpu_csr_write(CSR_MHPMCOUNTER14, 0); neorv32_cpu_csr_write(CSR_MHPMEVENT14, 1 << HPMCNT_EVENT_ILLEGAL);
273
 
274
    neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, 0); // enable all counters
275
 
276
    // make sure there was no exception
277
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
278
      test_ok();
279
    }
280
    else {
281
      test_fail();
282
    }
283
  }
284
  else {
285
    PRINT_STANDARD("skipped (n.a.)\n");
286
  }
287
 
288
 
289 74 zero_gravi
  // ----------------------------------------------------------
290
  // Test standard RISC-V performance counter [m]cycle[h]
291
  // ----------------------------------------------------------
292
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
293
  PRINT_STANDARD("[%i] cycle counter: ", cnt_test);
294 59 zero_gravi
 
295 74 zero_gravi
  cnt_test++;
296 59 zero_gravi
 
297 74 zero_gravi
  // make sure counter is enabled
298
  asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_CY));
299 59 zero_gravi
 
300 74 zero_gravi
  // prepare overflow
301
  neorv32_cpu_set_mcycle(0x00000000FFFFFFFFULL);
302 59 zero_gravi
 
303 74 zero_gravi
  // get current cycle counter HIGH
304
  tmp_a = neorv32_cpu_csr_read(CSR_MCYCLEH);
305
 
306
  // make sure cycle counter high has incremented and there was no exception during access
307
  if ((tmp_a == 1) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
308
    test_ok();
309
  }
310
  else {
311
    test_fail();
312
  }
313
 
314
 
315 59 zero_gravi
  // ----------------------------------------------------------
316 74 zero_gravi
  // Test standard RISC-V performance counter [m]instret[h]
317
  // ----------------------------------------------------------
318
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
319
  PRINT_STANDARD("[%i] instret counter: ", cnt_test);
320
 
321
  cnt_test++;
322
 
323
  // make sure counter is enabled
324
  asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_IR));
325
 
326
  // prepare overflow
327
  neorv32_cpu_set_minstret(0x00000000FFFFFFFFULL);
328
 
329
  // get instruction counter HIGH
330
  tmp_a = neorv32_cpu_csr_read(CSR_INSTRETH);
331
 
332
  // make sure instruction counter high has incremented and there was no exception during access
333
  if ((tmp_a == 1) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
334
    test_ok();
335
  }
336
  else {
337
    test_fail();
338
  }
339
 
340
 
341
  // ----------------------------------------------------------
342 59 zero_gravi
  // Test mcountinhibt: inhibit auto-inc of [m]cycle
343
  // ----------------------------------------------------------
344
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
345 61 zero_gravi
  PRINT_STANDARD("[%i] mcountinhibt.cy CSR: ", cnt_test);
346 59 zero_gravi
 
347
  cnt_test++;
348
 
349
  // inhibit [m]cycle CSR
350
  tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTINHIBIT);
351
  tmp_a |= (1<<CSR_MCOUNTINHIBIT_CY); // inhibit cycle counter auto-increment
352
  neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, tmp_a);
353
 
354
  // get current cycle counter
355
  tmp_a = neorv32_cpu_csr_read(CSR_CYCLE);
356
 
357
  // wait some time to have a nice "increment" (there should be NO increment at all!)
358
  asm volatile ("nop");
359
  asm volatile ("nop");
360
 
361
  tmp_b = neorv32_cpu_csr_read(CSR_CYCLE);
362
 
363
  // make sure instruction counter has NOT incremented and there was no exception during access
364
  if ((tmp_a == tmp_b) && (tmp_a != 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
365
    test_ok();
366
  }
367
  else {
368
    test_fail();
369
  }
370
 
371
  // re-enable [m]cycle CSR
372
  tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTINHIBIT);
373
  tmp_a &= ~(1<<CSR_MCOUNTINHIBIT_CY); // clear inhibit of cycle counter auto-increment
374
  neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, tmp_a);
375
 
376
 
377
  // ----------------------------------------------------------
378
  // Test mcounteren: do not allow cycle[h] access from user-mode
379
  // ----------------------------------------------------------
380
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
381 61 zero_gravi
  PRINT_STANDARD("[%i] mcounteren.cy CSR: ", cnt_test);
382 59 zero_gravi
 
383 64 zero_gravi
  cnt_test++;
384 59 zero_gravi
 
385 64 zero_gravi
  // do not allow user-level code to access cycle[h] CSRs
386
  tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTEREN);
387
  tmp_a &= ~(1<<CSR_MCOUNTEREN_CY); // clear access right
388
  neorv32_cpu_csr_write(CSR_MCOUNTEREN, tmp_a);
389 59 zero_gravi
 
390 74 zero_gravi
  neorv32_cpu_csr_write(CSR_MCYCLE, 0);
391
  neorv32_cpu_csr_write(CSR_MCYCLEH, 123); // make sure CSR is != 0 for this test
392 65 zero_gravi
 
393 64 zero_gravi
  // switch to user mode (hart will be back in MACHINE mode when trap handler returns)
394 73 zero_gravi
  goto_user_mode();
395 64 zero_gravi
  {
396
    // access to cycle CSR is no longer allowed
397 74 zero_gravi
    asm volatile (" li    %[result], 0xcc11aa22       \n" // initialize
398
                  " csrrw %[result], cycleh, %[input]   " // read and write CSR_CYCLE, not allowed and should not alter [result] nor CSR
399
                  : [result] "=r" (tmp_a) : [input] "r" (tmp_a) );
400 64 zero_gravi
  }
401 59 zero_gravi
 
402 64 zero_gravi
  // make sure there was an illegal instruction trap
403 73 zero_gravi
  if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) &&
404 74 zero_gravi
      (neorv32_cpu_csr_read(CSR_CYCLEH) == 123) && // csr not altered
405 73 zero_gravi
      (tmp_a == 0xcc11aa22)) { // destination register not altered
406 64 zero_gravi
    test_ok();
407 59 zero_gravi
  }
408 64 zero_gravi
  else {
409
    test_fail();
410 59 zero_gravi
  }
411
 
412
  // re-allow user-level code to access cycle[h] CSRs
413
  tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTEREN);
414
  tmp_a |= (1<<CSR_MCOUNTEREN_CY); // re-allow access right
415
  neorv32_cpu_csr_write(CSR_MCOUNTEREN, tmp_a);
416
 
417
 
418
  // ----------------------------------------------------------
419 62 zero_gravi
  // Execute MRET in U-mode (has to trap!)
420
  // ----------------------------------------------------------
421
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
422
  PRINT_STANDARD("[%i] MRET in U-mode: ", cnt_test);
423
 
424 64 zero_gravi
  cnt_test++;
425 62 zero_gravi
 
426 64 zero_gravi
  // switch to user mode (hart will be back in MACHINE mode when trap handler returns)
427 73 zero_gravi
  goto_user_mode();
428 64 zero_gravi
  {
429
    asm volatile ("mret");
430
  }
431 62 zero_gravi
 
432 64 zero_gravi
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
433
    test_ok();
434 62 zero_gravi
  }
435
  else {
436 64 zero_gravi
    test_fail();
437 62 zero_gravi
  }
438
 
439
 
440
  // ----------------------------------------------------------
441 59 zero_gravi
  // External memory interface test
442
  // ----------------------------------------------------------
443
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
444 73 zero_gravi
  PRINT_STANDARD("[%i] Ext. memory access (@ 0x%x): ", cnt_test, (uint32_t)EXT_MEM_BASE);
445 59 zero_gravi
 
446 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT)) {
447 61 zero_gravi
    cnt_test++;
448 59 zero_gravi
 
449 61 zero_gravi
    // create test program in RAM
450
    static const uint32_t dummy_ext_program[2] __attribute__((aligned(8))) = {
451
      0x3407D073, // csrwi mscratch, 15
452
      0x00008067  // ret (32-bit)
453
    };
454 59 zero_gravi
 
455 61 zero_gravi
    // copy to external memory
456
    if (memcpy((void*)EXT_MEM_BASE, (void*)&dummy_ext_program, (size_t)sizeof(dummy_ext_program)) == NULL) {
457
      test_fail();
458
    }
459
    else {
460 59 zero_gravi
 
461 61 zero_gravi
      // execute program
462
      tmp_a = (uint32_t)EXT_MEM_BASE; // call the dummy sub program
463
      asm volatile ("jalr ra, %[input_i]" :  : [input_i] "r" (tmp_a));
464
 
465 69 zero_gravi
      if ((neorv32_cpu_csr_read(CSR_MCAUSE) == 0) && // make sure there was no exception
466
          (neorv32_cpu_csr_read(CSR_MSCRATCH) == 15)) { // make sure the program was executed in the right way
467
        test_ok();
468 59 zero_gravi
      }
469 61 zero_gravi
      else {
470
        test_fail();
471
      }
472 59 zero_gravi
    }
473
  }
474
  else {
475 61 zero_gravi
    PRINT_STANDARD("skipped (n.a.)\n");
476 59 zero_gravi
  }
477
 
478
 
479 61 zero_gravi
  // ----------------------------------------------------------
480 59 zero_gravi
  // Illegal CSR access (CSR not implemented)
481
  // ----------------------------------------------------------
482
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
483 73 zero_gravi
  PRINT_STANDARD("[%i] Non-existent CSR: ", cnt_test);
484 59 zero_gravi
 
485
  cnt_test++;
486
 
487 61 zero_gravi
  tmp_a = neorv32_cpu_csr_read(0xfff); // CSR 0xfff not implemented
488 59 zero_gravi
 
489
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
490
    test_ok();
491
  }
492
  else {
493
    test_fail();
494
  }
495
 
496
 
497
  // ----------------------------------------------------------
498
  // Write-access to read-only CSR
499
  // ----------------------------------------------------------
500
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
501 73 zero_gravi
  PRINT_STANDARD("[%i] Read-only CSR write: ", cnt_test);
502 59 zero_gravi
 
503
  cnt_test++;
504
 
505
  neorv32_cpu_csr_write(CSR_TIME, 0); // time CSR is read-only
506
 
507
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
508
    test_ok();
509
  }
510
  else {
511
    test_fail();
512
  }
513
 
514
 
515 74 zero_gravi
  // ----------------------------------------------------------
516
  // No "real" CSR write access (because rs1 = r0)
517
  // ----------------------------------------------------------
518
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
519
  PRINT_STANDARD("[%i] Read-only CSR 'no-write' (rs1=0) access: ", cnt_test);
520 59 zero_gravi
 
521 74 zero_gravi
  cnt_test++;
522 59 zero_gravi
 
523 74 zero_gravi
  // time CSR is read-only, but no actual write is performed because rs1=r0
524
  // -> should cause no exception
525
  asm volatile("csrrs zero, time, zero");
526
 
527
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
528
    test_ok();
529
  }
530
  else {
531
    test_fail();
532
  }
533
 
534
 
535 59 zero_gravi
  // ----------------------------------------------------------
536
  // Unaligned instruction address
537
  // ----------------------------------------------------------
538
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
539 73 zero_gravi
  PRINT_STANDARD("[%i] I_ALIGN (instr. align) EXC: ", cnt_test);
540 59 zero_gravi
 
541
  // skip if C-mode is implemented
542 61 zero_gravi
  if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_C)) == 0) {
543 59 zero_gravi
 
544
    cnt_test++;
545
 
546
    // call unaligned address
547 64 zero_gravi
    ((void (*)(void))ADDR_UNALIGNED_2)();
548
    asm volatile("nop");
549 59 zero_gravi
 
550
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_MISALIGNED) {
551 64 zero_gravi
      test_ok();
552 59 zero_gravi
    }
553
    else {
554 64 zero_gravi
      test_fail();
555 59 zero_gravi
    }
556 64 zero_gravi
 
557 59 zero_gravi
  }
558
  else {
559 61 zero_gravi
    PRINT_STANDARD("skipped (n.a. with C-ext)\n");
560 59 zero_gravi
  }
561
 
562
 
563
  // ----------------------------------------------------------
564
  // Instruction access fault
565
  // ----------------------------------------------------------
566
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
567 61 zero_gravi
  PRINT_STANDARD("[%i] I_ACC (instr. bus access) EXC: ", cnt_test);
568 59 zero_gravi
  cnt_test++;
569
 
570
  // call unreachable aligned address
571
  ((void (*)(void))ADDR_UNREACHABLE)();
572
 
573
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ACCESS) {
574
    test_ok();
575
  }
576
  else {
577
    test_fail();
578
  }
579
 
580
 
581
  // ----------------------------------------------------------
582
  // Illegal instruction
583
  // ----------------------------------------------------------
584
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
585 61 zero_gravi
  PRINT_STANDARD("[%i] I_ILLEG (illegal instr.) EXC: ", cnt_test);
586 59 zero_gravi
 
587
  cnt_test++;
588
 
589 74 zero_gravi
  // clear mstatus.mie and set mstatus.mpie
590
  tmp_a = neorv32_cpu_csr_read(CSR_MSTATUS);
591
  tmp_a &= ~(1 << CSR_MSTATUS_MIE);
592
  tmp_a |=  (1 << CSR_MSTATUS_MPIE);
593
  neorv32_cpu_csr_write(CSR_MSTATUS, tmp_a);
594
 
595
  // illegal 32-bit instruction (MRET with incorrect opcode)
596 66 zero_gravi
  asm volatile (".align 4 \n"
597 74 zero_gravi
                ".word 0x3020007f");
598 59 zero_gravi
 
599
  // make sure this has cause an illegal exception
600 74 zero_gravi
  if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) && // illegal instruction exception
601
      (neorv32_cpu_csr_read(CSR_MTVAL) == 0x3020007f) && // correct instruction word
602
      ((neorv32_cpu_csr_read(CSR_MSTATUS) & (1 << CSR_MSTATUS_MIE)) == 0)) { // MIE should still be cleared
603
    test_ok();
604 59 zero_gravi
  }
605
  else {
606
    test_fail();
607
  }
608
 
609 74 zero_gravi
  // clear mstatus.mie
610
  neorv32_cpu_dint();
611 59 zero_gravi
 
612 74 zero_gravi
 
613 59 zero_gravi
  // ----------------------------------------------------------
614
  // Illegal compressed instruction
615
  // ----------------------------------------------------------
616
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
617 61 zero_gravi
  PRINT_STANDARD("[%i] CI_ILLEG (illegal compr. instr.) EXC: ", cnt_test);
618 59 zero_gravi
 
619
  // skip if C-mode is not implemented
620 64 zero_gravi
  if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_C))) {
621 59 zero_gravi
 
622
    cnt_test++;
623
 
624 66 zero_gravi
    // illegal 16-bit instruction (official UNIMP instruction)
625
    asm volatile (".align 2     \n"
626
                  ".half 0x0001 \n" // NOP
627
                  ".half 0x0000");  // UNIMP
628 59 zero_gravi
 
629
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
630
      test_ok();
631
    }
632
    else {
633
      test_fail();
634
    }
635
  }
636
  else {
637 61 zero_gravi
    PRINT_STANDARD("skipped (n.a. with C-ext)\n");
638 59 zero_gravi
  }
639
 
640
 
641
  // ----------------------------------------------------------
642
  // Breakpoint instruction
643
  // ----------------------------------------------------------
644
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
645 73 zero_gravi
  PRINT_STANDARD("[%i] BREAK EXC: ", cnt_test);
646 59 zero_gravi
  cnt_test++;
647
 
648
  asm volatile("EBREAK");
649
 
650
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_BREAKPOINT) {
651
    test_ok();
652
  }
653
  else {
654
    test_fail();
655
  }
656
 
657
 
658
  // ----------------------------------------------------------
659
  // Unaligned load address
660
  // ----------------------------------------------------------
661
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
662 73 zero_gravi
  PRINT_STANDARD("[%i] L_ALIGN (load align) EXC: ", cnt_test);
663 59 zero_gravi
  cnt_test++;
664
 
665
  // load from unaligned address
666 73 zero_gravi
  asm volatile ("li %[da], 0xcafe1230 \n" // initialize destination register with known value
667
                "lw %[da], 0(%[ad])     " // must not update destination register to to exception
668
                : [da] "=r" (tmp_b) : [ad] "r" (ADDR_UNALIGNED_1));
669 59 zero_gravi
 
670 66 zero_gravi
  if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_MISALIGNED) &&
671 73 zero_gravi
      (neorv32_cpu_csr_read(CSR_MTVAL) == ADDR_UNALIGNED_1) &&
672
      (tmp_b == 0xcafe1230)) { // make sure dest. reg is not updated
673 59 zero_gravi
    test_ok();
674
  }
675
  else {
676
    test_fail();
677
  }
678
 
679
 
680
  // ----------------------------------------------------------
681
  // Load access fault
682
  // ----------------------------------------------------------
683
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
684 73 zero_gravi
  PRINT_STANDARD("[%i] L_ACC (load access) EXC: ", cnt_test);
685 59 zero_gravi
  cnt_test++;
686
 
687 70 zero_gravi
  tmp_a = (1 << BUSKEEPER_ERR_FLAG) | (1 << BUSKEEPER_ERR_TYPE);
688
 
689 59 zero_gravi
  // load from unreachable aligned address
690 73 zero_gravi
  asm volatile ("li %[da], 0xcafe1230 \n" // initialize destination register with known value
691
                "lw %[da], 0(%[ad])     " // must not update destination register to to exception
692
                : [da] "=r" (tmp_b) : [ad] "r" (ADDR_UNREACHABLE));
693 59 zero_gravi
 
694 70 zero_gravi
  if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_ACCESS) && // load bus access error exception
695 73 zero_gravi
      (neorv32_cpu_csr_read(CSR_MTVAL) == ADDR_UNREACHABLE) &&
696
      (tmp_b == 0xcafe1230) && // make sure dest. reg is not updated
697
      (NEORV32_BUSKEEPER.CTRL = tmp_a)) { // buskeeper: error flag + timeout error
698 59 zero_gravi
    test_ok();
699
  }
700
  else {
701
    test_fail();
702
  }
703
 
704
 
705
  // ----------------------------------------------------------
706
  // Unaligned store address
707
  // ----------------------------------------------------------
708
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
709 73 zero_gravi
  PRINT_STANDARD("[%i] S_ALIGN (store align) EXC: ", cnt_test);
710 59 zero_gravi
  cnt_test++;
711
 
712 73 zero_gravi
  // initialize test variable
713
  store_access_addr[0] = 0x11223344;
714
  store_access_addr[1] = 0x55667788;
715
  tmp_a = (uint32_t)(&store_access_addr[0]);
716
  tmp_a += 2; // make word-unaligned
717
 
718 59 zero_gravi
  // store to unaligned address
719 73 zero_gravi
  neorv32_cpu_store_unsigned_word(tmp_a, 0);
720 59 zero_gravi
 
721 73 zero_gravi
  if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_MISALIGNED) &&
722
      (neorv32_cpu_csr_read(CSR_MTVAL) == tmp_a) &&
723
      (store_access_addr[0] == 0x11223344) &&
724
      (store_access_addr[1] == 0x55667788)) { // make sure memory was not altered
725 59 zero_gravi
    test_ok();
726
  }
727
  else {
728
    test_fail();
729
  }
730
 
731
 
732
  // ----------------------------------------------------------
733
  // Store access fault
734
  // ----------------------------------------------------------
735
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
736 73 zero_gravi
  PRINT_STANDARD("[%i] S_ACC (store access) EXC: ", cnt_test);
737 59 zero_gravi
  cnt_test++;
738
 
739 70 zero_gravi
  tmp_a = (1 << BUSKEEPER_ERR_FLAG) | (0 << BUSKEEPER_ERR_TYPE);
740
 
741 59 zero_gravi
  // store to unreachable aligned address
742 70 zero_gravi
  neorv32_cpu_store_unsigned_word(ADDR_READONLY, 0);
743 59 zero_gravi
 
744 70 zero_gravi
  if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) && // store bus access error exception
745 73 zero_gravi
      (neorv32_cpu_csr_read(CSR_MTVAL) == ADDR_READONLY) &&
746 70 zero_gravi
      (NEORV32_BUSKEEPER.CTRL == tmp_a)) { // buskeeper: error flag + device error
747 59 zero_gravi
    test_ok();
748
  }
749
  else {
750
    test_fail();
751
  }
752
 
753
 
754
  // ----------------------------------------------------------
755
  // Environment call from M-mode
756
  // ----------------------------------------------------------
757
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
758 73 zero_gravi
  PRINT_STANDARD("[%i] ENVCALL M-mode EXC: ", cnt_test);
759 59 zero_gravi
  cnt_test++;
760
 
761 73 zero_gravi
  asm volatile("ecall");
762 59 zero_gravi
 
763
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MENV_CALL) {
764
    test_ok();
765
  }
766
  else {
767
    test_fail();
768
  }
769
 
770
 
771
  // ----------------------------------------------------------
772
  // Environment call from U-mode
773
  // ----------------------------------------------------------
774
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
775 73 zero_gravi
  PRINT_STANDARD("[%i] ENVCALL U-mode EXC: ", cnt_test);
776 59 zero_gravi
 
777 64 zero_gravi
  cnt_test++;
778 59 zero_gravi
 
779 64 zero_gravi
  // switch to user mode (hart will be back in MACHINE mode when trap handler returns)
780 73 zero_gravi
  goto_user_mode();
781 64 zero_gravi
  {
782 73 zero_gravi
    asm volatile("ecall");
783 64 zero_gravi
  }
784 59 zero_gravi
 
785 64 zero_gravi
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_UENV_CALL) {
786
    test_ok();
787 59 zero_gravi
  }
788
  else {
789 64 zero_gravi
    test_fail();
790 59 zero_gravi
  }
791
 
792
 
793
  // ----------------------------------------------------------
794
  // Machine timer interrupt (MTIME)
795
  // ----------------------------------------------------------
796
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
797 65 zero_gravi
  PRINT_STANDARD("[%i] MTI (MTIME): ", cnt_test);
798 59 zero_gravi
 
799 61 zero_gravi
  cnt_test++;
800 59 zero_gravi
 
801 64 zero_gravi
  // configure MTIME IRQ (and check overflow from low word to high word)
802 61 zero_gravi
  neorv32_mtime_set_timecmp(-1);
803
  neorv32_mtime_set_time(0);
804 59 zero_gravi
 
805 64 zero_gravi
  // enable interrupt
806 61 zero_gravi
  neorv32_mtime_set_timecmp(0x0000000100000000ULL);
807
  neorv32_mtime_set_time(   0x00000000FFFFFFFEULL);
808 64 zero_gravi
  neorv32_cpu_irq_enable(CSR_MIE_MTIE);
809 59 zero_gravi
 
810 61 zero_gravi
  // wait some time for the IRQ to trigger and arrive the CPU
811
  asm volatile("nop");
812
  asm volatile("nop");
813 59 zero_gravi
 
814 64 zero_gravi
  // disable interrupt
815
  neorv32_cpu_irq_disable(CSR_MIE_MTIE);
816
 
817 61 zero_gravi
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MTI) {
818
    test_ok();
819 59 zero_gravi
  }
820
  else {
821 61 zero_gravi
    test_fail();
822 59 zero_gravi
  }
823
 
824 61 zero_gravi
  // no more mtime interrupts
825
  neorv32_mtime_set_timecmp(-1);
826 59 zero_gravi
 
827 61 zero_gravi
 
828 59 zero_gravi
  // ----------------------------------------------------------
829
  // Machine software interrupt (MSI) via testbench
830
  // ----------------------------------------------------------
831
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
832 65 zero_gravi
  PRINT_STANDARD("[%i] MSI (testbench): ", cnt_test);
833 59 zero_gravi
 
834 61 zero_gravi
  cnt_test++;
835 59 zero_gravi
 
836 64 zero_gravi
  // enable interrupt
837
  neorv32_cpu_irq_enable(CSR_MIE_MSIE);
838
 
839 61 zero_gravi
  // trigger IRQ
840
  sim_irq_trigger(1 << CSR_MIE_MSIE);
841 59 zero_gravi
 
842 61 zero_gravi
  // wait some time for the IRQ to arrive the CPU
843
  asm volatile("nop");
844
  asm volatile("nop");
845 59 zero_gravi
 
846 64 zero_gravi
  // disable interrupt
847
  neorv32_cpu_irq_disable(CSR_MIE_MSIE);
848
 
849 61 zero_gravi
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MSI) {
850
    test_ok();
851 59 zero_gravi
  }
852
  else {
853 61 zero_gravi
    test_fail();
854 59 zero_gravi
  }
855
 
856
 
857
  // ----------------------------------------------------------
858
  // Machine external interrupt (MEI) via testbench
859
  // ----------------------------------------------------------
860
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
861 65 zero_gravi
  PRINT_STANDARD("[%i] MEI (testbench): ", cnt_test);
862 59 zero_gravi
 
863 61 zero_gravi
  cnt_test++;
864 59 zero_gravi
 
865 64 zero_gravi
  // enable interrupt
866
  neorv32_cpu_irq_enable(CSR_MIE_MEIE);
867
 
868 61 zero_gravi
  // trigger IRQ
869
  sim_irq_trigger(1 << CSR_MIE_MEIE);
870 59 zero_gravi
 
871 61 zero_gravi
  // wait some time for the IRQ to arrive the CPU
872
  asm volatile("nop");
873
  asm volatile("nop");
874 59 zero_gravi
 
875 64 zero_gravi
  // enable interrupt
876
  neorv32_cpu_irq_disable(CSR_MIE_MEIE);
877
 
878 61 zero_gravi
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MEI) {
879
    test_ok();
880 59 zero_gravi
  }
881
  else {
882 61 zero_gravi
    test_fail();
883 59 zero_gravi
  }
884
 
885
 
886
  // ----------------------------------------------------------
887 64 zero_gravi
  // Permanent IRQ (make sure interrupted program advances)
888 59 zero_gravi
  // ----------------------------------------------------------
889
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
890 64 zero_gravi
  PRINT_STANDARD("[%i] Permanent IRQ (MTIME): ", cnt_test);
891 59 zero_gravi
 
892 61 zero_gravi
  cnt_test++;
893 59 zero_gravi
 
894 64 zero_gravi
  // fire MTIME IRQ
895
  neorv32_cpu_irq_enable(CSR_MIE_MTIE);
896
  neorv32_mtime_set_time(1); // prepare overflow
897
  neorv32_mtime_set_timecmp(0); // IRQ on overflow
898 59 zero_gravi
 
899 64 zero_gravi
  register int test_cnt = 0;
900
  while(test_cnt < 2) {
901
    test_cnt++;
902
  }
903
 
904
  // end MTIME IRQ
905
  neorv32_cpu_irq_disable(CSR_MIE_MTIE);
906
  neorv32_mtime_set_timecmp(-1);
907
 
908
  if (test_cnt == 2) {
909
    test_ok();
910
  }
911
  else {
912
    test_fail();
913
  }
914
 
915
 
916
  // ----------------------------------------------------------
917
  // Test pending interrupt
918
  // ----------------------------------------------------------
919
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
920 65 zero_gravi
  PRINT_STANDARD("[%i] Pending IRQ (MTIME): ", cnt_test);
921 64 zero_gravi
 
922
  cnt_test++;
923
 
924
  // enable interrupt
925
  neorv32_cpu_irq_enable(CSR_MIE_MTIE);
926
 
927
  // disable global interrupts
928
  neorv32_cpu_dint();
929
 
930
  // fire MTIME IRQ
931
  neorv32_mtime_set_time(1); // prepare overflow
932
  neorv32_mtime_set_timecmp(0); // IRQ on overflow
933
 
934 61 zero_gravi
  // wait some time for the IRQ to arrive the CPU
935
  asm volatile("nop");
936
  asm volatile("nop");
937 59 zero_gravi
 
938 64 zero_gravi
  int was_pending = 0;
939
  if (neorv32_cpu_csr_read(CSR_MIP) & (1 << CSR_MIP_MTIP)) { // should be pending now
940
    was_pending = 1;
941
  }
942
 
943
  // clear pending MTI
944
  neorv32_mtime_set_timecmp(-1);
945
 
946
  int is_pending = 0;
947
  if (neorv32_cpu_csr_read(CSR_MIP) & (1 << CSR_MIP_MTIP)) { // should NOT be pending anymore
948
    is_pending = 1;
949
  }
950
 
951
  neorv32_cpu_irq_disable(CSR_MIE_MTIE);
952
 
953
  if ((was_pending == 1) && (is_pending == 0)) {
954 61 zero_gravi
    test_ok();
955 59 zero_gravi
  }
956
  else {
957 61 zero_gravi
    test_fail();
958 59 zero_gravi
  }
959
 
960 64 zero_gravi
  // re-enable global interrupts
961
  neorv32_cpu_eint();
962 59 zero_gravi
 
963 64 zero_gravi
 
964 59 zero_gravi
  // ----------------------------------------------------------
965
  // Fast interrupt channel 0 (WDT)
966
  // ----------------------------------------------------------
967 61 zero_gravi
  if (neorv32_wdt_available()) {
968
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
969 65 zero_gravi
    PRINT_STANDARD("[%i] FIRQ0 (WDT): ", cnt_test);
970 59 zero_gravi
 
971
    cnt_test++;
972
 
973
    // enable fast interrupt
974
    neorv32_cpu_irq_enable(CSR_MIE_FIRQ0E);
975
 
976
    // configure WDT
977
    neorv32_wdt_setup(CLK_PRSC_4096, 0, 1); // highest clock prescaler, trigger IRQ on timeout, lock access
978 69 zero_gravi
    NEORV32_WDT.CTRL = 0; // try to deactivate WDT (should fail as access is locked)
979 59 zero_gravi
    neorv32_wdt_force(); // force watchdog into action
980
 
981
    // wait some time for the IRQ to arrive the CPU
982
    asm volatile("nop");
983 65 zero_gravi
    neorv32_cpu_irq_disable(CSR_MIE_FIRQ0E);
984 59 zero_gravi
 
985
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_0) {
986
      test_ok();
987
    }
988
    else {
989
      test_fail();
990
    }
991
 
992
    // no more WDT interrupts
993
    neorv32_wdt_disable();
994
  }
995
 
996
 
997
  // ----------------------------------------------------------
998
  // Fast interrupt channel 1 (CFS)
999
  // ----------------------------------------------------------
1000 65 zero_gravi
  PRINT_STANDARD("[%i] FIRQ1 (CFS): ", cnt_test);
1001 64 zero_gravi
  PRINT_STANDARD("skipped \n");
1002 59 zero_gravi
 
1003
 
1004
  // ----------------------------------------------------------
1005
  // Fast interrupt channel 2 (UART0.RX)
1006
  // ----------------------------------------------------------
1007 61 zero_gravi
  if (neorv32_uart1_available()) {
1008
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1009 65 zero_gravi
    PRINT_STANDARD("[%i] FIRQ2 (UART0.RX): ", cnt_test);
1010 59 zero_gravi
 
1011
    cnt_test++;
1012
 
1013
    // wait for UART0 to finish transmitting
1014 61 zero_gravi
    while(neorv32_uart0_tx_busy());
1015 59 zero_gravi
 
1016
    // backup current UART0 configuration
1017 64 zero_gravi
    tmp_a = NEORV32_UART0.CTRL;
1018 59 zero_gravi
 
1019 61 zero_gravi
    // make sure UART is enabled
1020 64 zero_gravi
    NEORV32_UART0.CTRL |= (1 << UART_CTRL_EN);
1021 61 zero_gravi
    // make sure sim mode is disabled
1022 64 zero_gravi
    NEORV32_UART0.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
1023 59 zero_gravi
 
1024 69 zero_gravi
    // enable fast interrupt
1025
    neorv32_cpu_irq_enable(CSR_MIE_FIRQ2E);
1026
 
1027 59 zero_gravi
    // trigger UART0 RX IRQ
1028 61 zero_gravi
    neorv32_uart0_putc(0);
1029 59 zero_gravi
    // wait for UART0 to finish transmitting
1030 61 zero_gravi
    while(neorv32_uart0_tx_busy());
1031 59 zero_gravi
 
1032
    // wait some time for the IRQ to arrive the CPU
1033
    asm volatile("nop");
1034 65 zero_gravi
    neorv32_cpu_irq_disable(CSR_MIE_FIRQ2E);
1035 59 zero_gravi
 
1036 61 zero_gravi
    // restore original configuration
1037 64 zero_gravi
    NEORV32_UART0.CTRL = tmp_a;
1038 59 zero_gravi
 
1039
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_2) {
1040
      test_ok();
1041
    }
1042
    else {
1043
      test_fail();
1044
    }
1045
  }
1046
 
1047
 
1048
  // ----------------------------------------------------------
1049
  // Fast interrupt channel 3 (UART0.TX)
1050
  // ----------------------------------------------------------
1051 61 zero_gravi
  if (neorv32_uart0_available()) {
1052
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1053 65 zero_gravi
    PRINT_STANDARD("[%i] FIRQ3 (UART0.TX): ", cnt_test);
1054 59 zero_gravi
 
1055 61 zero_gravi
    cnt_test++;
1056 59 zero_gravi
 
1057 61 zero_gravi
    // wait for UART0 to finish transmitting
1058
    while(neorv32_uart0_tx_busy());
1059 59 zero_gravi
 
1060 61 zero_gravi
    // backup current UART0 configuration
1061 64 zero_gravi
    tmp_a = NEORV32_UART0.CTRL;
1062 59 zero_gravi
 
1063 61 zero_gravi
    // make sure UART is enabled
1064 64 zero_gravi
    NEORV32_UART0.CTRL |= (1 << UART_CTRL_EN);
1065 61 zero_gravi
    // make sure sim mode is disabled
1066 64 zero_gravi
    NEORV32_UART0.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
1067 59 zero_gravi
 
1068 69 zero_gravi
    // UART0 TX interrupt enable
1069
    neorv32_cpu_irq_enable(CSR_MIE_FIRQ3E);
1070
 
1071 61 zero_gravi
    // trigger UART0 TX IRQ
1072
    neorv32_uart0_putc(0);
1073
    // wait for UART to finish transmitting
1074
    while(neorv32_uart0_tx_busy());
1075 59 zero_gravi
 
1076 61 zero_gravi
    // wait some time for the IRQ to arrive the CPU
1077
    asm volatile("nop");
1078 65 zero_gravi
    neorv32_cpu_irq_disable(CSR_MIE_FIRQ3E);
1079 59 zero_gravi
 
1080 61 zero_gravi
    // restore original configuration
1081 64 zero_gravi
    NEORV32_UART0.CTRL = tmp_a;
1082 59 zero_gravi
 
1083 61 zero_gravi
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_3) {
1084
      test_ok();
1085
    }
1086
    else {
1087
      test_fail();
1088
    }
1089 59 zero_gravi
  }
1090
 
1091
 
1092
  // ----------------------------------------------------------
1093
  // Fast interrupt channel 4 (UART1.RX)
1094
  // ----------------------------------------------------------
1095 61 zero_gravi
  if (neorv32_uart1_available()) {
1096
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1097 65 zero_gravi
    PRINT_STANDARD("[%i] FIRQ4 (UART1.RX): ", cnt_test);
1098 59 zero_gravi
 
1099
    cnt_test++;
1100
 
1101 61 zero_gravi
    // backup current UART1 configuration
1102 64 zero_gravi
    tmp_a = NEORV32_UART1.CTRL;
1103 59 zero_gravi
 
1104 61 zero_gravi
    // make sure UART is enabled
1105 64 zero_gravi
    NEORV32_UART1.CTRL |= (1 << UART_CTRL_EN);
1106 61 zero_gravi
    // make sure sim mode is disabled
1107 64 zero_gravi
    NEORV32_UART1.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
1108 61 zero_gravi
 
1109 69 zero_gravi
    // UART1 RX interrupt enable
1110
    neorv32_cpu_irq_enable(CSR_MIE_FIRQ4E);
1111
 
1112 59 zero_gravi
    // trigger UART1 RX IRQ
1113 61 zero_gravi
    neorv32_uart1_putc(0);
1114 59 zero_gravi
    // wait for UART1 to finish transmitting
1115
    while(neorv32_uart1_tx_busy());
1116
 
1117
    // wait some time for the IRQ to arrive the CPU
1118
    asm volatile("nop");
1119 65 zero_gravi
    neorv32_cpu_irq_disable(CSR_MIE_FIRQ4E);
1120 59 zero_gravi
 
1121 61 zero_gravi
    // restore original configuration
1122 64 zero_gravi
    NEORV32_UART1.CTRL = tmp_a;
1123 59 zero_gravi
 
1124
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_4) {
1125
      test_ok();
1126
    }
1127
    else {
1128
      test_fail();
1129
    }
1130
  }
1131
 
1132
 
1133
  // ----------------------------------------------------------
1134
  // Fast interrupt channel 5 (UART1.TX)
1135
  // ----------------------------------------------------------
1136 61 zero_gravi
  if (neorv32_uart1_available()) {
1137
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1138 65 zero_gravi
    PRINT_STANDARD("[%i] FIRQ5 (UART1.TX): ", cnt_test);
1139 59 zero_gravi
 
1140
    cnt_test++;
1141
 
1142 61 zero_gravi
    // backup current UART1 configuration
1143 64 zero_gravi
    tmp_a = NEORV32_UART1.CTRL;
1144 59 zero_gravi
 
1145 61 zero_gravi
    // make sure UART is enabled
1146 64 zero_gravi
    NEORV32_UART1.CTRL |= (1 << UART_CTRL_EN);
1147 61 zero_gravi
    // make sure sim mode is disabled
1148 64 zero_gravi
    NEORV32_UART1.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
1149 61 zero_gravi
 
1150 69 zero_gravi
    // UART1 RX interrupt enable
1151
    neorv32_cpu_irq_enable(CSR_MIE_FIRQ5E);
1152
 
1153 59 zero_gravi
    // trigger UART1 TX IRQ
1154 61 zero_gravi
    neorv32_uart1_putc(0);
1155 59 zero_gravi
    // wait for UART1 to finish transmitting
1156
    while(neorv32_uart1_tx_busy());
1157
 
1158
    // wait some time for the IRQ to arrive the CPU
1159
    asm volatile("nop");
1160 65 zero_gravi
    neorv32_cpu_irq_disable(CSR_MIE_FIRQ5E);
1161 59 zero_gravi
 
1162 61 zero_gravi
    // restore original configuration
1163 64 zero_gravi
    NEORV32_UART1.CTRL = tmp_a;
1164 59 zero_gravi
 
1165
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_5) {
1166
      test_ok();
1167
    }
1168
    else {
1169
      test_fail();
1170
    }
1171
  }
1172
 
1173
 
1174
  // ----------------------------------------------------------
1175
  // Fast interrupt channel 6 (SPI)
1176
  // ----------------------------------------------------------
1177 61 zero_gravi
  if (neorv32_spi_available()) {
1178
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1179 65 zero_gravi
    PRINT_STANDARD("[%i] FIRQ6 (SPI): ", cnt_test);
1180 59 zero_gravi
 
1181
    cnt_test++;
1182
 
1183
    // configure SPI
1184 65 zero_gravi
    neorv32_spi_setup(CLK_PRSC_2, 0, 0, 0);
1185 59 zero_gravi
 
1186 68 zero_gravi
    // enable fast interrupt
1187
    neorv32_cpu_irq_enable(CSR_MIE_FIRQ6E);
1188
 
1189 59 zero_gravi
    // trigger SPI IRQ
1190
    neorv32_spi_trans(0);
1191
    while(neorv32_spi_busy()); // wait for current transfer to finish
1192
 
1193
    // wait some time for the IRQ to arrive the CPU
1194
    asm volatile("nop");
1195 65 zero_gravi
    neorv32_cpu_irq_disable(CSR_MIE_FIRQ6E);
1196 59 zero_gravi
 
1197
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_6) {
1198
      test_ok();
1199
    }
1200
    else {
1201
      test_fail();
1202
    }
1203
 
1204
    // disable SPI
1205
    neorv32_spi_disable();
1206
  }
1207
 
1208
 
1209
  // ----------------------------------------------------------
1210
  // Fast interrupt channel 7 (TWI)
1211
  // ----------------------------------------------------------
1212 61 zero_gravi
  if (neorv32_twi_available()) {
1213
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1214 65 zero_gravi
    PRINT_STANDARD("[%i] FIRQ7 (TWI): ", cnt_test);
1215 59 zero_gravi
 
1216
    cnt_test++;
1217
 
1218 68 zero_gravi
    // configure TWI, fastest clock
1219
    neorv32_twi_setup(CLK_PRSC_2);
1220 59 zero_gravi
 
1221 68 zero_gravi
    // enable TWI FIRQ
1222
    neorv32_cpu_irq_enable(CSR_MIE_FIRQ7E);
1223
 
1224 59 zero_gravi
    // trigger TWI IRQ
1225
    neorv32_twi_generate_start();
1226
 
1227
    // wait some time for the IRQ to arrive the CPU
1228
    asm volatile("nop");
1229 65 zero_gravi
    neorv32_cpu_irq_disable(CSR_MIE_FIRQ7E);
1230 59 zero_gravi
 
1231
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_7) {
1232
      test_ok();
1233
    }
1234
    else {
1235
      test_fail();
1236
    }
1237
 
1238
    // disable TWI
1239
    neorv32_twi_disable();
1240
  }
1241
 
1242
 
1243
  // ----------------------------------------------------------
1244 61 zero_gravi
  // Fast interrupt channel 8 (XIRQ)
1245 59 zero_gravi
  // ----------------------------------------------------------
1246
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1247 65 zero_gravi
  PRINT_STANDARD("[%i] FIRQ8 (XIRQ): ", cnt_test);
1248 61 zero_gravi
  if (neorv32_xirq_available()) {
1249 59 zero_gravi
 
1250 61 zero_gravi
    cnt_test++;
1251 59 zero_gravi
 
1252 61 zero_gravi
    int xirq_err_cnt = 0;
1253
    xirq_trap_handler_ack = 0;
1254 59 zero_gravi
 
1255 61 zero_gravi
    xirq_err_cnt += neorv32_xirq_setup(); // initialize XIRQ
1256
    xirq_err_cnt += neorv32_xirq_install(0, xirq_trap_handler0); // install XIRQ IRQ handler channel 0
1257
    xirq_err_cnt += neorv32_xirq_install(1, xirq_trap_handler1); // install XIRQ IRQ handler channel 1
1258 59 zero_gravi
 
1259 64 zero_gravi
    // enable XIRQ FIRQ
1260
    neorv32_cpu_irq_enable(CSR_MIE_FIRQ8E);
1261 59 zero_gravi
 
1262 61 zero_gravi
    // trigger XIRQ channel 1 and 0
1263
    neorv32_gpio_port_set(3);
1264 59 zero_gravi
 
1265 61 zero_gravi
    // wait for IRQs to arrive CPU
1266
    asm volatile("nop");
1267
    asm volatile("nop");
1268 65 zero_gravi
    neorv32_cpu_irq_disable(CSR_MIE_FIRQ8E);
1269 59 zero_gravi
 
1270 61 zero_gravi
    if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_8) && // FIRQ8 IRQ
1271
        (xirq_err_cnt == 0) && // no errors during XIRQ configuration
1272
        (xirq_trap_handler_ack == 4)) { // XIRQ channel handler 0 executed before handler 1
1273
      test_ok();
1274 59 zero_gravi
    }
1275
    else {
1276 61 zero_gravi
      test_fail();
1277 59 zero_gravi
    }
1278 61 zero_gravi
 
1279 64 zero_gravi
    NEORV32_XIRQ.IER = 0;
1280
    NEORV32_XIRQ.IPR = -1;
1281 59 zero_gravi
  }
1282
 
1283
 
1284
  // ----------------------------------------------------------
1285 61 zero_gravi
  // Fast interrupt channel 9 (NEOLED)
1286 59 zero_gravi
  // ----------------------------------------------------------
1287 68 zero_gravi
  if (neorv32_neoled_available()) {
1288
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1289
    PRINT_STANDARD("[%i] FIRQ9 (NEOLED): ", cnt_test);
1290 59 zero_gravi
 
1291 68 zero_gravi
    cnt_test++;
1292 59 zero_gravi
 
1293 68 zero_gravi
    // enable fast interrupt
1294
    neorv32_cpu_irq_enable(CSR_MIE_FIRQ9E);
1295
 
1296
    // configure NEOLED
1297
    neorv32_neoled_setup(CLK_PRSC_2, 0, 0, 0);
1298
 
1299
    // send dummy data
1300
    neorv32_neoled_write_nonblocking(0);
1301
 
1302
    // wait some time for the IRQ to arrive the CPU
1303
    asm volatile("nop");
1304
    neorv32_cpu_irq_disable(CSR_MIE_FIRQ9E);
1305
 
1306
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_9) {
1307
      test_ok();
1308
    }
1309
    else {
1310
      test_fail();
1311
    }
1312
 
1313
    // no more NEOLED interrupts
1314
    neorv32_neoled_disable();
1315
  }
1316
 
1317
 
1318 59 zero_gravi
  // ----------------------------------------------------------
1319 69 zero_gravi
  // Fast interrupt channel 10 (SLINK RX)
1320 59 zero_gravi
  // ----------------------------------------------------------
1321 61 zero_gravi
  if (neorv32_slink_available()) {
1322
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1323 69 zero_gravi
    PRINT_STANDARD("[%i] FIRQ10 (SLINK RX): ", cnt_test);
1324 59 zero_gravi
 
1325
    cnt_test++;
1326
 
1327 68 zero_gravi
    // enable SLINK
1328
    neorv32_slink_enable();
1329
 
1330 61 zero_gravi
    // enable SLINK FIRQs
1331 69 zero_gravi
    neorv32_slink_rx_irq_config(0, SLINK_IRQ_ENABLE, SLINK_IRQ_RX_NOT_EMPTY);
1332
    neorv32_cpu_irq_enable(SLINK_RX_FIRQ_ENABLE);
1333 61 zero_gravi
 
1334
    tmp_a = 0; // error counter
1335
 
1336
    // send single data word via link 0
1337
    if (neorv32_slink_tx0_nonblocking(0xA1B2C3D4)) {
1338 69 zero_gravi
      tmp_a += 1; // sending failed
1339 59 zero_gravi
    }
1340
 
1341 65 zero_gravi
    // wait some time for the IRQ to arrive the CPU
1342
    asm volatile("nop");
1343
 
1344 69 zero_gravi
    // check if RX link fires IRQ
1345
    if (neorv32_cpu_csr_read(CSR_MCAUSE) != SLINK_RX_TRAP_CODE) {
1346
      tmp_a += 2;
1347 65 zero_gravi
    }
1348 69 zero_gravi
    neorv32_cpu_irq_disable(SLINK_RX_FIRQ_ENABLE);
1349 65 zero_gravi
 
1350 61 zero_gravi
    // get single data word from link 0
1351
    uint32_t slink_rx_data;
1352
    if (neorv32_slink_rx0_nonblocking(&slink_rx_data)) {
1353 69 zero_gravi
      tmp_a += 4; // receiving failed
1354 61 zero_gravi
    }
1355 59 zero_gravi
 
1356 65 zero_gravi
    if ((tmp_a == 0) && // local error counter = 0
1357 61 zero_gravi
        (slink_rx_data == 0xA1B2C3D4)) { // correct data read-back
1358
      test_ok();
1359 59 zero_gravi
    }
1360 61 zero_gravi
    else {
1361
      test_fail();
1362
    }
1363 59 zero_gravi
 
1364 61 zero_gravi
    // shutdown SLINK
1365
    neorv32_slink_disable();
1366 59 zero_gravi
  }
1367
 
1368
 
1369 67 zero_gravi
  // ----------------------------------------------------------
1370 69 zero_gravi
  // Fast interrupt channel 11 (SLINK TX)
1371
  // ----------------------------------------------------------
1372
  if (neorv32_slink_available()) {
1373
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1374
    PRINT_STANDARD("[%i] FIRQ11 (SLINK TX): ", cnt_test);
1375
 
1376
    cnt_test++;
1377
 
1378
    // enable SLINK
1379
    neorv32_slink_enable();
1380
 
1381
    // enable SLINK FIRQs
1382
    neorv32_slink_tx_irq_config(0, SLINK_IRQ_ENABLE, SLINK_IRQ_TX_NOT_FULL);
1383
    neorv32_cpu_irq_enable(SLINK_TX_FIRQ_ENABLE);
1384
 
1385
    tmp_a = 0; // error counter
1386
 
1387
    // send single data word via link 0
1388
    if (neorv32_slink_tx0_nonblocking(0x11223344)) {
1389
      tmp_a += 1; // sending failed
1390
    }
1391
 
1392
    // wait some time for the IRQ to arrive the CPU
1393
    asm volatile("nop");
1394
 
1395
    // check if TX link fires IRQ
1396
    if (neorv32_cpu_csr_read(CSR_MCAUSE) != SLINK_TX_TRAP_CODE) {
1397
      tmp_a += 2;
1398
    }
1399
    neorv32_cpu_irq_disable(SLINK_RX_FIRQ_ENABLE);
1400
 
1401
    if (tmp_a == 0) { // local error counter = 0
1402
      test_ok();
1403
    }
1404
    else {
1405
      test_fail();
1406
    }
1407
 
1408
    // shutdown SLINK
1409
    neorv32_slink_disable();
1410
  }
1411
 
1412
 
1413
  // ----------------------------------------------------------
1414 67 zero_gravi
  // Fast interrupt channel 12 (GPTMR)
1415
  // ----------------------------------------------------------
1416
  if (neorv32_slink_available()) {
1417
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1418
    PRINT_STANDARD("[%i] FIRQ12 (GPTMR): ", cnt_test);
1419
 
1420
    cnt_test++;
1421
 
1422
    // enable GPTMR FIRQ
1423
    neorv32_cpu_irq_enable(CSR_MIE_FIRQ12E);
1424
 
1425 68 zero_gravi
    // configure timer IRQ for one-shot mode after 2*3 clock cycles
1426
    neorv32_gptmr_setup(CLK_PRSC_2, 0, 3);
1427 67 zero_gravi
 
1428
    // wait some time for the IRQ to arrive the CPU
1429
    asm volatile("nop");
1430
    asm volatile("nop");
1431
 
1432
    // disable GPTMR interrupt
1433
    neorv32_cpu_irq_disable(CSR_MIE_FIRQ12E);
1434
 
1435
    // check if RX FIFO fires IRQ
1436
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_12) {
1437
      test_ok();
1438
    }
1439
    else {
1440
      test_fail();
1441
    }
1442
 
1443
    // disable GPTMR
1444
    neorv32_gptmr_disable();
1445
  }
1446
 
1447
 
1448 61 zero_gravi
//// ----------------------------------------------------------
1449 67 zero_gravi
//// Fast interrupt channel 13..15 (reserved)
1450 61 zero_gravi
//// ----------------------------------------------------------
1451 67 zero_gravi
//PRINT_STANDARD("[%i] FIRQ13..15: ", cnt_test);
1452 61 zero_gravi
//PRINT_STANDARD("skipped (n.a.)\n");
1453 59 zero_gravi
 
1454 61 zero_gravi
 
1455 59 zero_gravi
  // ----------------------------------------------------------
1456 73 zero_gravi
  // Test WFI ("sleep") instruction (executed in user mode), wakeup via MTIME
1457 59 zero_gravi
  // ----------------------------------------------------------
1458
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1459 74 zero_gravi
  PRINT_STANDARD("[%i] WFI (wake-up via MTIME): ", cnt_test);
1460 59 zero_gravi
 
1461 61 zero_gravi
  cnt_test++;
1462 59 zero_gravi
 
1463 64 zero_gravi
  // program wake-up timer
1464
  neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + 500);
1465
 
1466 65 zero_gravi
  // enable mtime interrupt
1467 64 zero_gravi
  neorv32_cpu_irq_enable(CSR_MIE_MTIE);
1468
 
1469 73 zero_gravi
  // clear mstatus.TW to allow execution of WFI also in user-mode
1470
  neorv32_cpu_csr_write(CSR_MSTATUS, neorv32_cpu_csr_read(CSR_MSTATUS) & ~(1<<CSR_MSTATUS_TW));
1471 62 zero_gravi
 
1472 73 zero_gravi
  // put CPU into sleep mode (from user mode)
1473
  goto_user_mode();
1474
  {
1475
    asm volatile ("wfi");
1476
  }
1477
 
1478 64 zero_gravi
  // no more mtime interrupts
1479
  neorv32_cpu_irq_disable(CSR_MIE_MTIE);
1480
  neorv32_mtime_set_timecmp(-1);
1481
 
1482 61 zero_gravi
  if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_MTI) {
1483
    test_fail();
1484 59 zero_gravi
  }
1485
  else {
1486 61 zero_gravi
    test_ok();
1487 59 zero_gravi
  }
1488
 
1489
 
1490
  // ----------------------------------------------------------
1491 74 zero_gravi
  // Test unallowed WFI ("sleep") instruction (executed in user mode)
1492
  // ----------------------------------------------------------
1493
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1494
  PRINT_STANDARD("[%i] WFI (not allowed in u-mode): ", cnt_test);
1495
 
1496
  cnt_test++;
1497
 
1498
  // set mstatus.TW to disallow execution of WFI in user-mode
1499
  neorv32_cpu_csr_write(CSR_MSTATUS, neorv32_cpu_csr_read(CSR_MSTATUS) | (1<<CSR_MSTATUS_TW));
1500
 
1501
  // put CPU into sleep mode (from user mode)
1502
  goto_user_mode();
1503
  {
1504
    asm volatile ("wfi"); // this has to fail
1505
  }
1506
 
1507
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
1508
    test_ok();
1509
  }
1510
  else {
1511
    test_fail();
1512
  }
1513
 
1514
 
1515
  // ----------------------------------------------------------
1516 59 zero_gravi
  // Test invalid CSR access in user mode
1517
  // ----------------------------------------------------------
1518
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1519 61 zero_gravi
  PRINT_STANDARD("[%i] Invalid CSR access (mstatus) from user mode: ", cnt_test);
1520 59 zero_gravi
 
1521 64 zero_gravi
  cnt_test++;
1522 59 zero_gravi
 
1523 64 zero_gravi
  // switch to user mode (hart will be back in MACHINE mode when trap handler returns)
1524 73 zero_gravi
  goto_user_mode();
1525 64 zero_gravi
  {
1526
    // access to misa not allowed for user-level programs
1527
    tmp_a = neorv32_cpu_csr_read(CSR_MISA);
1528
  }
1529 59 zero_gravi
 
1530 64 zero_gravi
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
1531
    test_ok();
1532 59 zero_gravi
  }
1533
  else {
1534 64 zero_gravi
    test_fail();
1535 59 zero_gravi
  }
1536
 
1537
 
1538
  // ----------------------------------------------------------
1539
  // Test RTE debug trap handler
1540
  // ----------------------------------------------------------
1541
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1542 61 zero_gravi
  PRINT_STANDARD("[%i] RTE debug trap handler: ", cnt_test);
1543 59 zero_gravi
 
1544
  cnt_test++;
1545
 
1546
  // uninstall custom handler and use default RTE debug handler
1547
  neorv32_rte_exception_uninstall(RTE_TRAP_I_ILLEGAL);
1548
 
1549
  // trigger illegal instruction exception
1550
  neorv32_cpu_csr_read(0xfff); // CSR not available
1551
 
1552 61 zero_gravi
  PRINT_STANDARD(" ");
1553 59 zero_gravi
  if (neorv32_cpu_csr_read(CSR_MCAUSE) != 0) {
1554
    test_ok();
1555
  }
1556
  else {
1557
    test_fail();
1558
  }
1559
 
1560
  // restore original handler
1561
  neorv32_rte_exception_install(RTE_TRAP_I_ILLEGAL, global_trap_handler);
1562
 
1563
 
1564
  // ----------------------------------------------------------
1565
  // Test physical memory protection
1566
  // ----------------------------------------------------------
1567 73 zero_gravi
  PRINT_STANDARD("[%i] PMP:\n", cnt_test);
1568 59 zero_gravi
 
1569 73 zero_gravi
  // check if PMP is implemented (two regions are required for these tests)
1570
  if (neorv32_cpu_pmp_get_num_regions() > 1)  {
1571 59 zero_gravi
 
1572
    // Create PMP protected region
1573
    // ---------------------------------------------
1574
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1575
    cnt_test++;
1576
 
1577 73 zero_gravi
    tmp_a = (uint32_t)(&pmp_access_addr); // base address of protected region
1578
    tmp_b = PMP_TOR << PMPCFG_A_LSB; // enable region, but absolutely no access rights
1579 59 zero_gravi
 
1580
    // configure
1581 73 zero_gravi
    int pmp_res = 0;
1582
    PRINT_STANDARD("Setup region 0 OFF [ -, -, -] @ 0x%x\n", tmp_a);
1583
    pmp_res += neorv32_cpu_pmp_configure_region(0, tmp_a, 0);
1584
    PRINT_STANDARD("Setup region 1 TOR [!X,!W,!R] @ 0x%x ", tmp_a+4);
1585
    pmp_res += neorv32_cpu_pmp_configure_region(1, tmp_a+4, tmp_b);
1586
    if ((pmp_res == 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
1587 59 zero_gravi
      test_ok();
1588
    }
1589
    else {
1590
      test_fail();
1591
    }
1592
 
1593
 
1594
    // ------ EXECUTE: should fail ------
1595 61 zero_gravi
    PRINT_STANDARD("[%i] PMP: U-mode execute: ", cnt_test);
1596 59 zero_gravi
    cnt_test++;
1597
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1598
 
1599
    // switch to user mode (hart will be back in MACHINE mode when trap handler returns)
1600 73 zero_gravi
    goto_user_mode();
1601 59 zero_gravi
    {
1602
      asm volatile ("jalr ra, %[input_i]" :  : [input_i] "r" (tmp_a)); // call address to execute -> should fail
1603
    }
1604
 
1605 73 zero_gravi
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ACCESS) {
1606
      asm volatile ("ecall"); // switch back to machine mode (if not already)
1607
      test_ok();
1608 59 zero_gravi
    }
1609
    else {
1610 73 zero_gravi
      asm volatile ("ecall"); // switch back to machine mode (if not already)
1611
      test_fail();
1612 59 zero_gravi
    }
1613
 
1614
 
1615 61 zero_gravi
    // ------ LOAD: should fail ------
1616
    PRINT_STANDARD("[%i] PMP: U-mode read: ", cnt_test);
1617 59 zero_gravi
    cnt_test++;
1618
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1619
 
1620
    // switch to user mode (hart will be back in MACHINE mode when trap handler returns)
1621 73 zero_gravi
    goto_user_mode();
1622 59 zero_gravi
    {
1623 73 zero_gravi
      asm volatile ("li %[da], 0xcafe0000 \n" // initialize destination register with known value
1624
                    "lw %[da], 0(%[ad])     " // must not update destination register to to exception
1625
                    : [da] "=r" (tmp_b) : [ad] "r" (tmp_a));
1626 59 zero_gravi
    }
1627
 
1628 73 zero_gravi
    if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_ACCESS) &&
1629
        (tmp_b == 0xcafe0000)) { // destination register not altered
1630 61 zero_gravi
      // switch back to machine mode (if not already)
1631 59 zero_gravi
      asm volatile ("ecall");
1632
 
1633
      test_ok();
1634
    }
1635
    else {
1636 61 zero_gravi
      // switch back to machine mode (if not already)
1637 59 zero_gravi
      asm volatile ("ecall");
1638
 
1639
      test_fail();
1640
    }
1641
 
1642
 
1643
    // ------ STORE: should fail ------
1644 61 zero_gravi
    PRINT_STANDARD("[%i] PMP: U-mode write: ", cnt_test);
1645 59 zero_gravi
    cnt_test++;
1646
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1647
 
1648
    // switch to user mode (hart will be back in MACHINE mode when trap handler returns)
1649 73 zero_gravi
    goto_user_mode();
1650 59 zero_gravi
    {
1651 61 zero_gravi
      neorv32_cpu_store_unsigned_word(tmp_a, 0); // store access -> should fail
1652 59 zero_gravi
    }
1653
 
1654
    if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) {
1655 61 zero_gravi
      // switch back to machine mode (if not already)
1656 59 zero_gravi
      asm volatile ("ecall");
1657
 
1658
      test_ok();
1659
    }
1660
    else {
1661 61 zero_gravi
      // switch back to machine mode (if not already)
1662 59 zero_gravi
      asm volatile ("ecall");
1663
 
1664
      test_fail();
1665
    }
1666
 
1667
 
1668
    // ------ Lock test - pmpcfg0.0 / pmpaddr0 ------
1669 61 zero_gravi
    PRINT_STANDARD("[%i] PMP: Entry [mode=off] lock: ", cnt_test);
1670 59 zero_gravi
    cnt_test++;
1671
    neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1672
 
1673
    neorv32_cpu_csr_write(CSR_PMPCFG0, 0b10000001); // locked, but entry is deactivated (mode = off)
1674
 
1675
    // make sure a locked cfg cannot be written
1676
    tmp_a = neorv32_cpu_csr_read(CSR_PMPCFG0);
1677
    neorv32_cpu_csr_write(CSR_PMPCFG0, 0b00011001); // try to re-write CFG content
1678
 
1679
    tmp_b = neorv32_cpu_csr_read(CSR_PMPADDR0);
1680
    neorv32_cpu_csr_write(CSR_PMPADDR0, 0xABABCDCD); // try to re-write ADDR content
1681
 
1682
    if ((tmp_a != neorv32_cpu_csr_read(CSR_PMPCFG0)) || (tmp_b != neorv32_cpu_csr_read(CSR_PMPADDR0)) || (neorv32_cpu_csr_read(CSR_MCAUSE) != 0)) {
1683
      test_fail();
1684
    }
1685
    else {
1686
      test_ok();
1687
    }
1688
 
1689
  }
1690
  else {
1691 61 zero_gravi
    PRINT_STANDARD("skipped (n.a.)\n");
1692 59 zero_gravi
  }
1693
 
1694
 
1695
  // ----------------------------------------------------------
1696
  // Test atomic LR/SC operation - should succeed
1697
  // ----------------------------------------------------------
1698
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1699 61 zero_gravi
  PRINT_STANDARD("[%i] Atomic access (LR+SC succeeding access): ", cnt_test);
1700 59 zero_gravi
 
1701
#ifdef __riscv_atomic
1702
  // skip if A-mode is not implemented
1703 61 zero_gravi
  if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A)) != 0) {
1704 59 zero_gravi
 
1705
    cnt_test++;
1706
 
1707
    neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0x11223344);
1708
 
1709
    tmp_a = neorv32_cpu_load_reservate_word((uint32_t)&atomic_access_addr); // make reservation
1710
    asm volatile ("nop");
1711
    tmp_b = neorv32_cpu_store_conditional((uint32_t)&atomic_access_addr, 0x22446688);
1712
 
1713
    // atomic access
1714
    if ((tmp_b == 0) && // status: success
1715
        (tmp_a == 0x11223344) && // correct data read
1716
        (neorv32_cpu_load_unsigned_word((uint32_t)&atomic_access_addr) == 0x22446688) && // correct data write
1717
        (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { // no exception triggered
1718
      test_ok();
1719
    }
1720
    else {
1721
      test_fail();
1722
    }
1723
  }
1724
  else {
1725 61 zero_gravi
    PRINT_STANDARD("skipped (n.a.)\n");
1726 59 zero_gravi
  }
1727
#else
1728 61 zero_gravi
  PRINT_STANDARD("skipped (n.a.)\n");
1729 59 zero_gravi
#endif
1730
 
1731
 
1732
  // ----------------------------------------------------------
1733
  // Test atomic LR/SC operation - should fail
1734
  // ----------------------------------------------------------
1735
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1736 61 zero_gravi
  PRINT_STANDARD("[%i] Atomic access (LR+SC failing access 1): ", cnt_test);
1737 59 zero_gravi
 
1738
#ifdef __riscv_atomic
1739
  // skip if A-mode is not implemented
1740 61 zero_gravi
  if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A)) != 0) {
1741 59 zero_gravi
 
1742
    cnt_test++;
1743
 
1744
    neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0xAABBCCDD);
1745
 
1746
    // atomic access
1747
    tmp_a = neorv32_cpu_load_reservate_word((uint32_t)&atomic_access_addr); // make reservation
1748 65 zero_gravi
    // neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0xDEADDEAD); // destroy reservation
1749
    neorv32_cpu_load_unsigned_word((uint32_t)&atomic_access_addr); // destroy reservation
1750 59 zero_gravi
    tmp_b = neorv32_cpu_store_conditional((uint32_t)&atomic_access_addr, 0x22446688);
1751
 
1752
    if ((tmp_b != 0) && // status: fail
1753
        (tmp_a == 0xAABBCCDD) && // correct data read
1754 65 zero_gravi
        (neorv32_cpu_load_unsigned_word((uint32_t)&atomic_access_addr) == 0xAABBCCDD)) { // correct data write
1755 59 zero_gravi
      test_ok();
1756
    }
1757
    else {
1758
      test_fail();
1759
    }
1760
  }
1761
  else {
1762 61 zero_gravi
    PRINT_STANDARD("skipped (n.a.)\n");
1763 59 zero_gravi
  }
1764
#else
1765 61 zero_gravi
  PRINT_STANDARD("skipped (n.a.)\n");
1766 59 zero_gravi
#endif
1767
 
1768
 
1769
  // ----------------------------------------------------------
1770
  // Test atomic LR/SC operation - should fail
1771
  // ----------------------------------------------------------
1772
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
1773 61 zero_gravi
  PRINT_STANDARD("[%i] Atomic access (LR+SC failing access 2): ", cnt_test);
1774 59 zero_gravi
 
1775
#ifdef __riscv_atomic
1776
  // skip if A-mode is not implemented
1777 61 zero_gravi
  if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A)) != 0) {
1778 59 zero_gravi
 
1779
    cnt_test++;
1780
 
1781
    neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0x12341234);
1782
 
1783
    // atomic access
1784
    tmp_a = neorv32_cpu_load_reservate_word((uint32_t)&atomic_access_addr); // make reservation
1785
    asm volatile ("ecall"); // destroy reservation via trap (simulate a context switch)
1786
    tmp_b = neorv32_cpu_store_conditional((uint32_t)&atomic_access_addr, 0xDEADBEEF);
1787
 
1788
    if ((tmp_b != 0) && // status: fail
1789
        (tmp_a == 0x12341234) && // correct data read
1790
        (neorv32_cpu_load_unsigned_word((uint32_t)&atomic_access_addr) == 0x12341234)) { // correct data write
1791
      test_ok();
1792
    }
1793
    else {
1794
      test_fail();
1795
    }
1796
  }
1797
  else {
1798 61 zero_gravi
    PRINT_STANDARD("skipped (on real HW)\n");
1799 59 zero_gravi
  }
1800
#else
1801 61 zero_gravi
  PRINT_STANDARD("skipped (n.a.)\n");
1802 59 zero_gravi
#endif
1803
 
1804
 
1805
  // ----------------------------------------------------------
1806
  // HPM reports
1807
  // ----------------------------------------------------------
1808
  neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, -1); // stop all counters
1809 61 zero_gravi
  PRINT_STANDARD("\n\n-- HPM reports LOW (%u HPMs available) --\n", num_hpm_cnts_global);
1810 70 zero_gravi
  PRINT_STANDARD("#IR Instr.:   %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_INSTRET)); // = "HPM_0"
1811
//PRINT_STANDARD("#TM Time:     %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_TIME));    // = "HPM_1"
1812
  PRINT_STANDARD("#CY CLKs:     %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_CYCLE));   // = "HPM_2"
1813
  PRINT_STANDARD("#03 Compr.:   %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER3));
1814
  PRINT_STANDARD("#04 IF wait:  %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER4));
1815
  PRINT_STANDARD("#05 II wait:  %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER5));
1816
  PRINT_STANDARD("#06 ALU wait: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER6));
1817
  PRINT_STANDARD("#07 Loads:    %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER7));
1818
  PRINT_STANDARD("#08 Stores:   %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER8));
1819
  PRINT_STANDARD("#09 MEM wait: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER9));
1820
  PRINT_STANDARD("#10 Jumps:    %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER10));
1821
  PRINT_STANDARD("#11 Branches: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER11));
1822
  PRINT_STANDARD("#12 - Taken:  %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER12));
1823
  PRINT_STANDARD("#13 Traps:    %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER13));
1824
  PRINT_STANDARD("#14 Illegals: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER14));
1825 59 zero_gravi
 
1826
 
1827
  // ----------------------------------------------------------
1828
  // Final test reports
1829
  // ----------------------------------------------------------
1830 61 zero_gravi
  PRINT_CRITICAL("\n\nTest results:\nPASS: %i/%i\nFAIL: %i/%i\n\n", cnt_ok, cnt_test, cnt_fail, cnt_test);
1831 59 zero_gravi
 
1832
  // final result
1833
  if (cnt_fail == 0) {
1834 61 zero_gravi
    PRINT_STANDARD("%c[1m[CPU TEST COMPLETED SUCCESSFULLY!]%c[0m\n", 27, 27);
1835 59 zero_gravi
  }
1836
  else {
1837 61 zero_gravi
    PRINT_STANDARD("%c[1m[CPU TEST FAILED!]%c[0m\n", 27, 27);
1838 59 zero_gravi
  }
1839
 
1840 61 zero_gravi
  return (int)cnt_fail; // return error counter for after-main handler
1841 59 zero_gravi
}
1842
 
1843
 
1844 73 zero_gravi
 
1845 59 zero_gravi
/**********************************************************************//**
1846 73 zero_gravi
 * Switch from privilege mode MACHINE to privilege mode USER.
1847 59 zero_gravi
 *
1848 73 zero_gravi
 * @warning This function requires the U extension to be implemented.
1849
 **************************************************************************/
1850
void __attribute__((naked)) goto_user_mode(void) {
1851
 
1852
  // make sure to use NO registers in here! -> naked
1853
 
1854
  asm volatile ("csrw mepc, ra           \n" // move return address to mepc so we can return using "mret". also, we can now use ra as temp register
1855
                "li ra, %[input_imm]     \n" // bit mask to clear the two MPP bits
1856
                "csrrc zero, mstatus, ra \n" // clear MPP bits -> MPP=u-mode
1857
                "mret                    \n" // return and switch to user mode
1858
                :  : [input_imm] "i" ((1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L)));
1859
}
1860
 
1861
 
1862
/**********************************************************************//**
1863
 * Simulation-based function to trigger CPU interrupts (MSI, MEI).
1864
 *
1865 59 zero_gravi
 * @param[in] sel IRQ select mask (bit positions according to #NEORV32_CSR_MIE_enum).
1866
 **************************************************************************/
1867
void sim_irq_trigger(uint32_t sel) {
1868
 
1869
  *(IO_REG32 (0xFF000000)) = sel;
1870 64 zero_gravi
  asm volatile("nop"); // interrupt should kick in here (latest)
1871
  *(IO_REG32 (0xFF000000)) = 0;
1872 59 zero_gravi
}
1873
 
1874
 
1875
/**********************************************************************//**
1876
 * Trap handler for ALL exceptions/interrupts.
1877
 **************************************************************************/
1878
void global_trap_handler(void) {
1879
 
1880 69 zero_gravi
  // clear all pending FIRQs
1881 73 zero_gravi
  neorv32_cpu_csr_write(CSR_MIP, 0);
1882 69 zero_gravi
 
1883 59 zero_gravi
  // hack: always come back in MACHINE MODE
1884
  register uint32_t mask = (1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L);
1885
  asm volatile ("csrrs zero, mstatus, %[input_j]" :  : [input_j] "r" (mask));
1886
}
1887
 
1888
 
1889
/**********************************************************************//**
1890 61 zero_gravi
 * XIRQ handler channel 0.
1891
 **************************************************************************/
1892
void xirq_trap_handler0(void) {
1893
 
1894
  xirq_trap_handler_ack += 2;
1895
}
1896
 
1897
 
1898
/**********************************************************************//**
1899
 * XIRQ handler channel 1.
1900
 **************************************************************************/
1901
void xirq_trap_handler1(void) {
1902
 
1903
  xirq_trap_handler_ack *= 2;
1904
}
1905
 
1906
 
1907
/**********************************************************************//**
1908 59 zero_gravi
 * Test results helper function: Shows "[ok]" and increments global cnt_ok
1909
 **************************************************************************/
1910
void test_ok(void) {
1911
 
1912 61 zero_gravi
  PRINT_STANDARD("%c[1m[ok]%c[0m\n", 27, 27);
1913 59 zero_gravi
  cnt_ok++;
1914
}
1915
 
1916
 
1917
/**********************************************************************//**
1918 61 zero_gravi
 * Test results helper function: Shows "[FAIL]" and increments global cnt_fail
1919 59 zero_gravi
 **************************************************************************/
1920
void test_fail(void) {
1921
 
1922 61 zero_gravi
  PRINT_CRITICAL("%c[1m[FAIL]%c[0m\n", 27, 27);
1923 59 zero_gravi
  cnt_fail++;
1924
}
1925 61 zero_gravi
 
1926
 
1927
/**********************************************************************//**
1928
 * "after-main" handler that is executed after the application's
1929
 * main function returns (called by crt0.S start-up code): Output minimal
1930
 * test report to physical UART
1931
 **************************************************************************/
1932 73 zero_gravi
void __neorv32_crt0_after_main(int32_t return_code) {
1933 61 zero_gravi
 
1934
  // make sure sim mode is disabled and UARTs are actually enabled
1935 64 zero_gravi
  NEORV32_UART0.CTRL |=  (1 << UART_CTRL_EN);
1936
  NEORV32_UART0.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
1937
  NEORV32_UART1.CTRL = NEORV32_UART0.CTRL;
1938 61 zero_gravi
 
1939
  // minimal result report
1940
  PRINT_CRITICAL("%u/%u\n", (uint32_t)return_code, (uint32_t)cnt_test);
1941
}

powered by: WebSVN 2.1.0

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