URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
Compare Revisions
- This comparison shows the changes necessary to convert path
/neorv32/trunk/sw/example/processor_check
- from Rev 63 to Rev 64
- ↔ Reverse comparison
Rev 63 → Rev 64
/check.sh
File deleted
/main.c
50,7 → 50,9
/** UART BAUD rate */ |
#define BAUD_RATE (19200) |
//** Reachable unaligned address */ |
#define ADDR_UNALIGNED (0x00000002) |
#define ADDR_UNALIGNED_1 (0x00000001) |
//** Reachable unaligned address */ |
#define ADDR_UNALIGNED_2 (0x00000002) |
//** Unreachable word-aligned address */ |
#define ADDR_UNREACHABLE (IO_BASE_ADDRESS-4) |
//** external memory base address */ |
115,10 → 117,12
register uint32_t tmp_a, tmp_b; |
uint8_t id; |
|
// disable global interrupts |
neorv32_cpu_dint(); |
|
// init UARTs at default baud rate, no parity bits, no hw flow control |
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE); |
UART1_CT = UART0_CT; // copy configuration to initialize UART1 |
NEORV32_UART1.CTRL = NEORV32_UART0.CTRL; // copy configuration to initialize UART1 |
|
#ifdef SUPPRESS_OPTIONAL_UART_PRINT |
neorv32_uart0_disable(); // do not generate any UART0 output |
157,10 → 161,9
neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, 0); // enable performance counter auto increment (ALL counters) |
neorv32_cpu_csr_write(CSR_MCOUNTEREN, 7); // allow access from user-mode code to standard counters only |
|
// set CMP of machine system timer MTIME to max to prevent an IRQ |
neorv32_mtime_set_timecmp(-1); |
neorv32_mtime_set_time(0); |
// set CMP of machine system timer MTIME to max to prevent an IRQ |
uint64_t mtime_cmp_max = 0xffffffffffffffffULL; |
neorv32_mtime_set_timecmp(mtime_cmp_max); |
|
|
// fancy intro |
190,12 → 193,12
return 1; |
} |
|
// enable interrupt sources |
neorv32_cpu_irq_enable(CSR_MIE_MSIE); // machine software interrupt |
neorv32_cpu_irq_enable(CSR_MIE_MTIE); // machine timer interrupt |
neorv32_cpu_irq_enable(CSR_MIE_MEIE); // machine external interrupt |
// enable FAST IRQ sources only where actually needed |
// clear testbench IRQ triggers |
sim_irq_trigger(0); |
|
// clear all interrupt enables, enable only where needed |
neorv32_cpu_csr_write(CSR_MIE, 0); |
|
// test intro |
PRINT_STANDARD("\nStarting tests...\n\n"); |
|
341,40 → 344,28
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
PRINT_STANDARD("[%i] mcounteren.cy CSR: ", cnt_test); |
|
// skip if U-mode is not implemented |
if (neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_U)) { |
cnt_test++; |
cnt_test++; |
|
// do not allow user-level code to access cycle[h] CSRs |
tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTEREN); |
tmp_a &= ~(1<<CSR_MCOUNTEREN_CY); // clear access right |
neorv32_cpu_csr_write(CSR_MCOUNTEREN, tmp_a); |
// do not allow user-level code to access cycle[h] CSRs |
tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTEREN); |
tmp_a &= ~(1<<CSR_MCOUNTEREN_CY); // clear access right |
neorv32_cpu_csr_write(CSR_MCOUNTEREN, tmp_a); |
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
// access to cycle CSR is no longer allowed |
tmp_a = neorv32_cpu_csr_read(CSR_CYCLE); |
} |
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
// access to cycle CSR is no longer allowed |
tmp_a = neorv32_cpu_csr_read(CSR_CYCLE); |
} |
|
// make sure there was an illegal instruction trap |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
if (tmp_a == 0) { // make sure user-level code CANNOT read locked CSR content! |
test_ok(); |
} |
else { |
test_fail(); |
} |
} |
else { |
test_fail(); |
} |
// make sure there was an illegal instruction trap |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
} |
else { |
PRINT_STANDARD("skipped (n.a.)\n"); |
else { |
test_fail(); |
} |
|
|
// re-allow user-level code to access cycle[h] CSRs |
tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTEREN); |
tmp_a |= (1<<CSR_MCOUNTEREN_CY); // re-allow access right |
381,61 → 372,25
neorv32_cpu_csr_write(CSR_MCOUNTEREN, tmp_a); |
|
|
/* |
// ---------------------------------------------------------- |
// Execute DRET in M-mode (has to trap!) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
PRINT_STANDARD("[%i] DRET in M-mode: ", cnt_test); |
|
// skip if U-mode is not implemented |
if (neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_U)) { |
|
cnt_test++; |
|
asm volatile("dret"); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
|
} |
else { |
PRINT_STANDARD("skipped (n.a. without U-ext)\n"); |
} |
*/ |
|
|
// ---------------------------------------------------------- |
// Execute MRET in U-mode (has to trap!) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
PRINT_STANDARD("[%i] MRET in U-mode: ", cnt_test); |
|
// skip if U-mode is not implemented |
if (SYSINFO_CPU & (1<<SYSINFO_CPU_DEBUGMODE)) { |
cnt_test++; |
|
cnt_test++; |
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
asm volatile ("mret"); |
} |
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
asm volatile("mret"); |
} |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
} |
else { |
PRINT_STANDARD("skipped (n.a. without U-ext)\n"); |
test_fail(); |
} |
|
|
445,7 → 400,7
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
PRINT_STANDARD("[%i] External memory access (@ 0x%x): ", cnt_test, (uint32_t)EXT_MEM_BASE); |
|
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT)) { |
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT)) { |
cnt_test++; |
|
// create test program in RAM |
512,10 → 467,6
|
tmp_a = neorv32_cpu_csr_read(0xfff); // CSR 0xfff not implemented |
|
if (tmp_a != 0) { |
PRINT_CRITICAL("%c[1m<SECURITY FAILURE> %c[0m\n", 27, 27); |
} |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
} |
563,40 → 514,6
|
|
// ---------------------------------------------------------- |
// Test pending interrupt |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
PRINT_STANDARD("[%i] Pending IRQ test (MTIME): ", cnt_test); |
|
cnt_test++; |
|
// disable global interrupts |
neorv32_cpu_dint(); |
|
// prepare MTIME IRQ |
neorv32_mtime_set_time(0x00000000FFFFFFF8ULL); // prepare overflow |
neorv32_mtime_set_timecmp(0x0000000100000000ULL); // IRQ on overflow |
|
// wait some time for the IRQ to arrive the CPU |
asm volatile("nop"); |
asm volatile("nop"); |
|
// no more mtime interrupts |
neorv32_mtime_set_timecmp(-1); |
|
// re-enable global interrupts |
neorv32_cpu_eint(); |
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MTI) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
|
|
// ---------------------------------------------------------- |
// Unaligned instruction address |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
608,16 → 525,16
cnt_test++; |
|
// call unaligned address |
((void (*)(void))ADDR_UNALIGNED)(); |
((void (*)(void))ADDR_UNALIGNED_2)(); |
asm volatile("nop"); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_MISALIGNED) { |
PRINT_STANDARD("ok\n"); |
cnt_ok++; |
test_ok(); |
} |
else { |
PRINT_STANDARD("fail\n"); |
cnt_fail++; |
test_fail(); |
} |
|
} |
else { |
PRINT_STANDARD("skipped (n.a. with C-ext)\n"); |
650,14 → 567,14
|
cnt_test++; |
|
// invalid instruction: using x0=x0 OP x0 with invalid opcode |
CUSTOM_INSTR_R2_TYPE(0b0000000, x0, x0, 0b000, x0, 0b1111111); |
// not allowed outside of debug mode |
asm volatile ("dret"); |
|
// make sure this has cause an illegal exception |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
// make sure this is really the instruction that caused the exception |
// for illegal instructions mtval contains the actual instruction word |
if (neorv32_cpu_csr_read(CSR_MTVAL) == 0x0000007f) { |
// -> for illegal instructions mtval contains the failing instruction word |
if (neorv32_cpu_csr_read(CSR_MTVAL) == 0x7b200073) { |
test_ok(); |
} |
else { |
676,7 → 593,7
PRINT_STANDARD("[%i] CI_ILLEG (illegal compr. instr.) EXC: ", cnt_test); |
|
// skip if C-mode is not implemented |
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_C)) != 0) { |
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_C))) { |
|
cnt_test++; |
|
726,7 → 643,7
cnt_test++; |
|
// load from unaligned address |
neorv32_cpu_load_unsigned_word(ADDR_UNALIGNED); |
neorv32_cpu_load_unsigned_word(ADDR_UNALIGNED_1); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_MISALIGNED) { |
test_ok(); |
762,7 → 679,7
cnt_test++; |
|
// store to unaligned address |
asm volatile ("sw zero, %[input_i](zero)" : : [input_i] "i" (ADDR_UNALIGNED)); |
neorv32_cpu_store_unsigned_word(ADDR_UNALIGNED_2, 0); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_MISALIGNED) { |
test_ok(); |
813,27 → 730,19
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
PRINT_STANDARD("[%i] ENVCALL (ecall instr.) from U-mode EXC: ", cnt_test); |
|
// skip if U-mode is not implemented |
if (neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_U)) { |
cnt_test++; |
|
cnt_test++; |
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
asm volatile("ECALL"); |
} |
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
asm volatile("ECALL"); |
} |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_UENV_CALL) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_UENV_CALL) { |
test_ok(); |
} |
else { |
PRINT_STANDARD("skipped (n.a. without U-ext)\n"); |
test_fail(); |
} |
|
|
845,21 → 754,22
|
cnt_test++; |
|
// configure MTIME IRQ (and check overflow form low owrd to high word) |
// configure MTIME IRQ (and check overflow from low word to high word) |
neorv32_mtime_set_timecmp(-1); |
neorv32_mtime_set_time(0); |
|
neorv32_cpu_csr_write(CSR_MIP, 0); // clear all pending IRQs |
|
// enable interrupt |
neorv32_mtime_set_timecmp(0x0000000100000000ULL); |
neorv32_mtime_set_time( 0x00000000FFFFFFFEULL); |
neorv32_cpu_irq_enable(CSR_MIE_MTIE); |
|
// wait some time for the IRQ to trigger and arrive the CPU |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
|
// disable interrupt |
neorv32_cpu_irq_disable(CSR_MIE_MTIE); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MTI) { |
test_ok(); |
} |
879,6 → 789,9
|
cnt_test++; |
|
// enable interrupt |
neorv32_cpu_irq_enable(CSR_MIE_MSIE); |
|
// trigger IRQ |
sim_irq_trigger(1 << CSR_MIE_MSIE); |
|
886,6 → 799,9
asm volatile("nop"); |
asm volatile("nop"); |
|
// disable interrupt |
neorv32_cpu_irq_disable(CSR_MIE_MSIE); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MSI) { |
test_ok(); |
} |
902,6 → 818,9
|
cnt_test++; |
|
// enable interrupt |
neorv32_cpu_irq_enable(CSR_MIE_MEIE); |
|
// trigger IRQ |
sim_irq_trigger(1 << CSR_MIE_MEIE); |
|
909,6 → 828,9
asm volatile("nop"); |
asm volatile("nop"); |
|
// enable interrupt |
neorv32_cpu_irq_disable(CSR_MIE_MEIE); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MEI) { |
test_ok(); |
} |
918,21 → 840,73
|
|
// ---------------------------------------------------------- |
// Non-maskable interrupt (NMI) via testbench |
// Permanent IRQ (make sure interrupted program advances) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
PRINT_STANDARD("[%i] NMI (via testbench): ", cnt_test); |
PRINT_STANDARD("[%i] Permanent IRQ (MTIME): ", cnt_test); |
|
cnt_test++; |
|
// trigger IRQ |
sim_irq_trigger(1 << 0); |
// fire MTIME IRQ |
neorv32_cpu_irq_enable(CSR_MIE_MTIE); |
neorv32_mtime_set_time(1); // prepare overflow |
neorv32_mtime_set_timecmp(0); // IRQ on overflow |
|
register int test_cnt = 0; |
while(test_cnt < 2) { |
test_cnt++; |
} |
|
// end MTIME IRQ |
neorv32_cpu_irq_disable(CSR_MIE_MTIE); |
neorv32_mtime_set_timecmp(-1); |
|
if (test_cnt == 2) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
|
|
// ---------------------------------------------------------- |
// Test pending interrupt |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
PRINT_STANDARD("[%i] Pending IRQ test (MTIME): ", cnt_test); |
|
cnt_test++; |
|
// enable interrupt |
neorv32_cpu_irq_enable(CSR_MIE_MTIE); |
|
// disable global interrupts |
neorv32_cpu_dint(); |
|
// fire MTIME IRQ |
neorv32_mtime_set_time(1); // prepare overflow |
neorv32_mtime_set_timecmp(0); // IRQ on overflow |
|
// wait some time for the IRQ to arrive the CPU |
asm volatile("nop"); |
asm volatile("nop"); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_NMI) { |
int was_pending = 0; |
if (neorv32_cpu_csr_read(CSR_MIP) & (1 << CSR_MIP_MTIP)) { // should be pending now |
was_pending = 1; |
} |
|
// clear pending MTI |
neorv32_mtime_set_timecmp(-1); |
|
int is_pending = 0; |
if (neorv32_cpu_csr_read(CSR_MIP) & (1 << CSR_MIP_MTIP)) { // should NOT be pending anymore |
is_pending = 1; |
} |
|
neorv32_cpu_irq_disable(CSR_MIE_MTIE); |
|
if ((was_pending == 1) && (is_pending == 0)) { |
test_ok(); |
} |
else { |
939,7 → 913,10
test_fail(); |
} |
|
// re-enable global interrupts |
neorv32_cpu_eint(); |
|
|
// ---------------------------------------------------------- |
// Fast interrupt channel 0 (WDT) |
// ---------------------------------------------------------- |
954,7 → 931,7
|
// configure WDT |
neorv32_wdt_setup(CLK_PRSC_4096, 0, 1); // highest clock prescaler, trigger IRQ on timeout, lock access |
WDT_CT = 0; // try to deactivate WDT (should fail as access is loced) |
NEORV32_WDT.CTRL = 0; // try to deactivate WDT (should fail as access is loced) |
neorv32_wdt_force(); // force watchdog into action |
|
// wait some time for the IRQ to arrive the CPU |
968,11 → 945,11
test_fail(); |
} |
|
// disable fast interrupt |
neorv32_cpu_irq_disable(CSR_MIE_FIRQ0E); |
|
// no more WDT interrupts |
neorv32_wdt_disable(); |
|
// disable fast interrupt |
neorv32_cpu_irq_disable(CSR_MIE_FIRQ0E); |
} |
|
|
980,7 → 957,7
// Fast interrupt channel 1 (CFS) |
// ---------------------------------------------------------- |
PRINT_STANDARD("[%i] FIRQ1 test (via CFS): ", cnt_test); |
PRINT_STANDARD("skipped (n.a.)\n"); |
PRINT_STANDARD("skipped \n"); |
|
|
// ---------------------------------------------------------- |
999,12 → 976,12
while(neorv32_uart0_tx_busy()); |
|
// backup current UART0 configuration |
tmp_a = UART0_CT; |
tmp_a = NEORV32_UART0.CTRL; |
|
// make sure UART is enabled |
UART0_CT |= (1 << UART_CT_EN); |
NEORV32_UART0.CTRL |= (1 << UART_CTRL_EN); |
// make sure sim mode is disabled |
UART0_CT &= ~(1 << UART_CT_SIM_MODE); |
NEORV32_UART0.CTRL &= ~(1 << UART_CTRL_SIM_MODE); |
|
// trigger UART0 RX IRQ |
neorv32_uart0_putc(0); |
1017,7 → 994,7
asm volatile("nop"); |
|
// restore original configuration |
UART0_CT = tmp_a; |
NEORV32_UART0.CTRL = tmp_a; |
|
// disable fast interrupt |
neorv32_cpu_irq_disable(CSR_MIE_FIRQ2E); |
1047,12 → 1024,12
while(neorv32_uart0_tx_busy()); |
|
// backup current UART0 configuration |
tmp_a = UART0_CT; |
tmp_a = NEORV32_UART0.CTRL; |
|
// make sure UART is enabled |
UART0_CT |= (1 << UART_CT_EN); |
NEORV32_UART0.CTRL |= (1 << UART_CTRL_EN); |
// make sure sim mode is disabled |
UART0_CT &= ~(1 << UART_CT_SIM_MODE); |
NEORV32_UART0.CTRL &= ~(1 << UART_CTRL_SIM_MODE); |
|
// trigger UART0 TX IRQ |
neorv32_uart0_putc(0); |
1065,7 → 1042,7
asm volatile("nop"); |
|
// restore original configuration |
UART0_CT = tmp_a; |
NEORV32_UART0.CTRL = tmp_a; |
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ3E); |
|
1091,12 → 1068,12
neorv32_cpu_irq_enable(CSR_MIE_FIRQ4E); |
|
// backup current UART1 configuration |
tmp_a = UART1_CT; |
tmp_a = NEORV32_UART1.CTRL; |
|
// make sure UART is enabled |
UART1_CT |= (1 << UART_CT_EN); |
NEORV32_UART1.CTRL |= (1 << UART_CTRL_EN); |
// make sure sim mode is disabled |
UART1_CT &= ~(1 << UART_CT_SIM_MODE); |
NEORV32_UART1.CTRL &= ~(1 << UART_CTRL_SIM_MODE); |
|
// trigger UART1 RX IRQ |
neorv32_uart1_putc(0); |
1109,7 → 1086,7
asm volatile("nop"); |
|
// restore original configuration |
UART1_CT = tmp_a; |
NEORV32_UART1.CTRL = tmp_a; |
|
// disable fast interrupt |
neorv32_cpu_irq_disable(CSR_MIE_FIRQ4E); |
1136,12 → 1113,12
neorv32_cpu_irq_enable(CSR_MIE_FIRQ5E); |
|
// backup current UART1 configuration |
tmp_a = UART1_CT; |
tmp_a = NEORV32_UART1.CTRL; |
|
// make sure UART is enabled |
UART1_CT |= (1 << UART_CT_EN); |
NEORV32_UART1.CTRL |= (1 << UART_CTRL_EN); |
// make sure sim mode is disabled |
UART1_CT &= ~(1 << UART_CT_SIM_MODE); |
NEORV32_UART1.CTRL &= ~(1 << UART_CTRL_SIM_MODE); |
|
// trigger UART1 TX IRQ |
neorv32_uart1_putc(0); |
1154,7 → 1131,7
asm volatile("nop"); |
|
// restore original configuration |
UART1_CT = tmp_a; |
NEORV32_UART1.CTRL = tmp_a; |
|
// disable fast interrupt |
neorv32_cpu_irq_disable(CSR_MIE_FIRQ5E); |
1258,7 → 1235,8
xirq_err_cnt += neorv32_xirq_install(0, xirq_trap_handler0); // install XIRQ IRQ handler channel 0 |
xirq_err_cnt += neorv32_xirq_install(1, xirq_trap_handler1); // install XIRQ IRQ handler channel 1 |
|
neorv32_xirq_global_enable(); // enable XIRQ FIRQ |
// enable XIRQ FIRQ |
neorv32_cpu_irq_enable(CSR_MIE_FIRQ8E); |
|
// trigger XIRQ channel 1 and 0 |
neorv32_gpio_port_set(3); |
1277,9 → 1255,9
test_fail(); |
} |
|
neorv32_xirq_global_disable(); |
XIRQ_IER = 0; |
XIRQ_IPR = -1; |
neorv32_cpu_irq_disable(CSR_MIE_FIRQ8E); |
NEORV32_XIRQ.IER = 0; |
NEORV32_XIRQ.IPR = -1; |
} |
|
|
1296,6 → 1274,8
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
PRINT_STANDARD("[%i] FIRQ10 & 11 (SLINK): ", cnt_test); |
|
// NOTE: this test requires FIFO sizes = 1 |
|
cnt_test++; |
|
// enable SLINK |
1334,6 → 1314,8
|
// shutdown SLINK |
neorv32_slink_disable(); |
neorv32_cpu_irq_disable(CSR_MIE_FIRQ10E); |
neorv32_cpu_irq_disable(CSR_MIE_FIRQ11E); |
} |
|
|
1352,14 → 1334,17
|
cnt_test++; |
|
// program wake-up timer |
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + 1000); |
|
// clear timeout wait flag |
tmp_a = neorv32_cpu_csr_read(CSR_MSTATUS); |
tmp_a &= ~(1 << CSR_MSTATUS_TW); |
neorv32_cpu_csr_write(CSR_MSTATUS, tmp_a); |
|
// program wake-up timer |
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + 500); |
|
// enable interrupt |
neorv32_cpu_irq_enable(CSR_MIE_MTIE); |
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
1367,6 → 1352,10
asm volatile ("wfi"); // put CPU into sleep mode |
} |
|
// no more mtime interrupts |
neorv32_cpu_irq_disable(CSR_MIE_MTIE); |
neorv32_mtime_set_timecmp(-1); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_MTI) { |
test_fail(); |
} |
1374,10 → 1363,7
test_ok(); |
} |
|
// no more mtime interrupts |
neorv32_mtime_set_timecmp(-1); |
|
|
// ---------------------------------------------------------- |
// Test invalid CSR access in user mode |
// ---------------------------------------------------------- |
1384,32 → 1370,20
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
PRINT_STANDARD("[%i] Invalid CSR access (mstatus) from user mode: ", cnt_test); |
|
// skip if U-mode is not implemented |
if (neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_U)) { |
cnt_test++; |
|
cnt_test++; |
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
// access to misa not allowed for user-level programs |
tmp_a = neorv32_cpu_csr_read(CSR_MISA); |
} |
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
// access to misa not allowed for user-level programs |
tmp_a = neorv32_cpu_csr_read(CSR_MISA); |
} |
|
if (tmp_a != 0) { |
PRINT_CRITICAL("%c[1m<SECURITY FAILURE> %c[0m\n", 27, 27); |
} |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
} |
else { |
PRINT_STANDARD("skipped (n.a. without U-ext)\n"); |
test_fail(); |
} |
|
|
1456,7 → 1430,7
// find out minimal region size (granularity) |
tmp_b = neorv32_cpu_pmp_get_granularity(); |
|
tmp_a = SYSINFO_DSPACE_BASE; // base address of protected region |
tmp_a = NEORV32_SYSINFO.DSPACE_BASE; // base address of protected region |
PRINT_STANDARD("Creating protected page (NAPOT, [!X,!W,!R], %u bytes) @ 0x%x: ", tmp_b, tmp_a); |
|
// configure |
1502,6 → 1476,7
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
tmp_b = 0; |
{ |
tmp_b = neorv32_cpu_load_unsigned_word(tmp_a); // load access -> should fail |
} |
1732,6 → 1707,8
void sim_irq_trigger(uint32_t sel) { |
|
*(IO_REG32 (0xFF000000)) = sel; |
asm volatile("nop"); // interrupt should kick in here (latest) |
*(IO_REG32 (0xFF000000)) = 0; |
} |
|
|
1792,9 → 1769,9
int __neorv32_crt0_after_main(int32_t return_code) { |
|
// make sure sim mode is disabled and UARTs are actually enabled |
UART0_CT |= (1 << UART_CT_EN); |
UART0_CT &= ~(1 << UART_CT_SIM_MODE); |
UART1_CT = UART0_CT; |
NEORV32_UART0.CTRL |= (1 << UART_CTRL_EN); |
NEORV32_UART0.CTRL &= ~(1 << UART_CTRL_SIM_MODE); |
NEORV32_UART1.CTRL = NEORV32_UART0.CTRL; |
|
// minimal result report |
PRINT_CRITICAL("%u/%u\n", (uint32_t)return_code, (uint32_t)cnt_test); |