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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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