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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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