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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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