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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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