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

Subversion Repositories neorv32

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

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

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

powered by: WebSVN 2.1.0

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