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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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