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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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