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

Subversion Repositories neorv32

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

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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