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

Subversion Repositories neorv32

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

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

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

powered by: WebSVN 2.1.0

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