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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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