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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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