Line 48... |
Line 48... |
**************************************************************************/
|
**************************************************************************/
|
/**@{*/
|
/**@{*/
|
/** UART BAUD rate */
|
/** UART BAUD rate */
|
#define BAUD_RATE (19200)
|
#define BAUD_RATE (19200)
|
//** Reachable unaligned address */
|
//** Reachable unaligned address */
|
#define ADDR_UNALIGNED (0x00000002)
|
#define ADDR_UNALIGNED_1 (0x00000001)
|
|
//** Reachable unaligned address */
|
|
#define ADDR_UNALIGNED_2 (0x00000002)
|
//** Unreachable word-aligned address */
|
//** Unreachable word-aligned address */
|
#define ADDR_UNREACHABLE (IO_BASE_ADDRESS-4)
|
#define ADDR_UNREACHABLE (IO_BASE_ADDRESS-4)
|
//** external memory base address */
|
//** external memory base address */
|
#define EXT_MEM_BASE (0xF0000000)
|
#define EXT_MEM_BASE (0xF0000000)
|
/**@}*/
|
/**@}*/
|
Line 113... |
Line 115... |
int main() {
|
int main() {
|
|
|
register uint32_t tmp_a, tmp_b;
|
register uint32_t tmp_a, tmp_b;
|
uint8_t id;
|
uint8_t id;
|
|
|
|
// disable global interrupts
|
|
neorv32_cpu_dint();
|
|
|
// init UARTs at default baud rate, no parity bits, no hw flow control
|
// init UARTs at default baud rate, no parity bits, no hw flow control
|
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
|
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
|
#ifdef SUPPRESS_OPTIONAL_UART_PRINT
|
neorv32_uart0_disable(); // do not generate any UART0 output
|
neorv32_uart0_disable(); // do not generate any UART0 output
|
#endif
|
#endif
|
|
|
Line 155... |
Line 159... |
neorv32_cpu_csr_write(CSR_MINSTRETH, 0);
|
neorv32_cpu_csr_write(CSR_MINSTRETH, 0);
|
neorv32_cpu_csr_write(CSR_MINSTRET, 0);
|
neorv32_cpu_csr_write(CSR_MINSTRET, 0);
|
neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, 0); // enable performance counter auto increment (ALL counters)
|
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
|
neorv32_cpu_csr_write(CSR_MCOUNTEREN, 7); // allow access from user-mode code to standard counters only
|
|
|
neorv32_mtime_set_time(0);
|
|
// set CMP of machine system timer MTIME to max to prevent an IRQ
|
// set CMP of machine system timer MTIME to max to prevent an IRQ
|
uint64_t mtime_cmp_max = 0xffffffffffffffffULL;
|
neorv32_mtime_set_timecmp(-1);
|
neorv32_mtime_set_timecmp(mtime_cmp_max);
|
neorv32_mtime_set_time(0);
|
|
|
|
|
// fancy intro
|
// fancy intro
|
// -----------------------------------------------
|
// -----------------------------------------------
|
// logo
|
// logo
|
Line 188... |
Line 191... |
if (install_err) {
|
if (install_err) {
|
PRINT_CRITICAL("RTE install error (%i)!\n", install_err);
|
PRINT_CRITICAL("RTE install error (%i)!\n", install_err);
|
return 1;
|
return 1;
|
}
|
}
|
|
|
// enable interrupt sources
|
// clear testbench IRQ triggers
|
neorv32_cpu_irq_enable(CSR_MIE_MSIE); // machine software interrupt
|
sim_irq_trigger(0);
|
neorv32_cpu_irq_enable(CSR_MIE_MTIE); // machine timer interrupt
|
|
neorv32_cpu_irq_enable(CSR_MIE_MEIE); // machine external interrupt
|
// clear all interrupt enables, enable only where needed
|
// enable FAST IRQ sources only where actually needed
|
neorv32_cpu_csr_write(CSR_MIE, 0);
|
|
|
// test intro
|
// test intro
|
PRINT_STANDARD("\nStarting tests...\n\n");
|
PRINT_STANDARD("\nStarting tests...\n\n");
|
|
|
// enable global interrupts
|
// enable global interrupts
|
Line 339... |
Line 342... |
// Test mcounteren: do not allow cycle[h] access from user-mode
|
// Test mcounteren: do not allow cycle[h] access from user-mode
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] mcounteren.cy CSR: ", cnt_test);
|
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
|
// do not allow user-level code to access cycle[h] CSRs
|
tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTEREN);
|
tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTEREN);
|
tmp_a &= ~(1<<CSR_MCOUNTEREN_CY); // clear access right
|
tmp_a &= ~(1<<CSR_MCOUNTEREN_CY); // clear access right
|
Line 357... |
Line 358... |
tmp_a = neorv32_cpu_csr_read(CSR_CYCLE);
|
tmp_a = neorv32_cpu_csr_read(CSR_CYCLE);
|
}
|
}
|
|
|
// make sure there was an illegal instruction trap
|
// make sure there was an illegal instruction trap
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
|
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();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
}
|
|
else {
|
|
test_fail();
|
|
}
|
|
}
|
|
else {
|
|
PRINT_STANDARD("skipped (n.a.)\n");
|
|
}
|
|
|
|
|
|
// re-allow user-level code to access cycle[h] CSRs
|
// re-allow user-level code to access cycle[h] CSRs
|
tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTEREN);
|
tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTEREN);
|
tmp_a |= (1<<CSR_MCOUNTEREN_CY); // re-allow access right
|
tmp_a |= (1<<CSR_MCOUNTEREN_CY); // re-allow access right
|
neorv32_cpu_csr_write(CSR_MCOUNTEREN, tmp_a);
|
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!)
|
// Execute MRET in U-mode (has to trap!)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] MRET in U-mode: ", cnt_test);
|
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)
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
|
neorv32_cpu_goto_user_mode();
|
neorv32_cpu_goto_user_mode();
|
{
|
{
|
Line 431... |
Line 391... |
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
}
|
|
else {
|
|
PRINT_STANDARD("skipped (n.a. without U-ext)\n");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// External memory interface test
|
// External memory interface test
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] External memory access (@ 0x%x): ", cnt_test, (uint32_t)EXT_MEM_BASE);
|
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++;
|
cnt_test++;
|
|
|
// create test program in RAM
|
// create test program in RAM
|
static const uint32_t dummy_ext_program[2] __attribute__((aligned(8))) = {
|
static const uint32_t dummy_ext_program[2] __attribute__((aligned(8))) = {
|
0x3407D073, // csrwi mscratch, 15
|
0x3407D073, // csrwi mscratch, 15
|
Line 510... |
Line 465... |
|
|
cnt_test++;
|
cnt_test++;
|
|
|
tmp_a = neorv32_cpu_csr_read(0xfff); // CSR 0xfff not implemented
|
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) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
Line 561... |
Line 512... |
test_fail();
|
test_fail();
|
}
|
}
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// 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
|
// Unaligned instruction address
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] I_ALIGN (instr. alignment) EXC: ", cnt_test);
|
PRINT_STANDARD("[%i] I_ALIGN (instr. alignment) EXC: ", cnt_test);
|
|
|
Line 606... |
Line 523... |
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_C)) == 0) {
|
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_C)) == 0) {
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// call unaligned address
|
// 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) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_MISALIGNED) {
|
PRINT_STANDARD("ok\n");
|
test_ok();
|
cnt_ok++;
|
|
}
|
}
|
else {
|
else {
|
PRINT_STANDARD("fail\n");
|
test_fail();
|
cnt_fail++;
|
|
}
|
}
|
|
|
}
|
}
|
else {
|
else {
|
PRINT_STANDARD("skipped (n.a. with C-ext)\n");
|
PRINT_STANDARD("skipped (n.a. with C-ext)\n");
|
}
|
}
|
|
|
Line 648... |
Line 565... |
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] I_ILLEG (illegal instr.) EXC: ", cnt_test);
|
PRINT_STANDARD("[%i] I_ILLEG (illegal instr.) EXC: ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// invalid instruction: using x0=x0 OP x0 with invalid opcode
|
// not allowed outside of debug mode
|
CUSTOM_INSTR_R2_TYPE(0b0000000, x0, x0, 0b000, x0, 0b1111111);
|
asm volatile ("dret");
|
|
|
// make sure this has cause an illegal exception
|
// make sure this has cause an illegal exception
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
|
// make sure this is really the instruction that caused the exception
|
// make sure this is really the instruction that caused the exception
|
// for illegal instructions mtval contains the actual instruction word
|
// -> for illegal instructions mtval contains the failing instruction word
|
if (neorv32_cpu_csr_read(CSR_MTVAL) == 0x0000007f) {
|
if (neorv32_cpu_csr_read(CSR_MTVAL) == 0x7b200073) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
Line 674... |
Line 591... |
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] CI_ILLEG (illegal compr. instr.) EXC: ", cnt_test);
|
PRINT_STANDARD("[%i] CI_ILLEG (illegal compr. instr.) EXC: ", cnt_test);
|
|
|
// skip if C-mode is not implemented
|
// 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++;
|
cnt_test++;
|
|
|
// create test program in RAM
|
// create test program in RAM
|
static const uint32_t dummy_sub_program_ci[2] __attribute__((aligned(8))) = {
|
static const uint32_t dummy_sub_program_ci[2] __attribute__((aligned(8))) = {
|
Line 724... |
Line 641... |
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] L_ALIGN (load addr alignment) EXC: ", cnt_test);
|
PRINT_STANDARD("[%i] L_ALIGN (load addr alignment) EXC: ", cnt_test);
|
cnt_test++;
|
cnt_test++;
|
|
|
// load from unaligned address
|
// 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) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_MISALIGNED) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
Line 760... |
Line 677... |
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] S_ALIGN (store addr alignment) EXC: ", cnt_test);
|
PRINT_STANDARD("[%i] S_ALIGN (store addr alignment) EXC: ", cnt_test);
|
cnt_test++;
|
cnt_test++;
|
|
|
// store to unaligned address
|
// 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) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_MISALIGNED) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
Line 811... |
Line 728... |
// Environment call from U-mode
|
// Environment call from U-mode
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] ENVCALL (ecall instr.) from U-mode EXC: ", cnt_test);
|
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)
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
|
neorv32_cpu_goto_user_mode();
|
neorv32_cpu_goto_user_mode();
|
{
|
{
|
Line 829... |
Line 743... |
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
}
|
|
else {
|
|
PRINT_STANDARD("skipped (n.a. without U-ext)\n");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Machine timer interrupt (MTIME)
|
// Machine timer interrupt (MTIME)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] MTI (via MTIME): ", cnt_test);
|
PRINT_STANDARD("[%i] MTI (via MTIME): ", cnt_test);
|
|
|
cnt_test++;
|
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_timecmp(-1);
|
neorv32_mtime_set_time(0);
|
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_timecmp(0x0000000100000000ULL);
|
neorv32_mtime_set_time( 0x00000000FFFFFFFEULL);
|
neorv32_mtime_set_time( 0x00000000FFFFFFFEULL);
|
|
neorv32_cpu_irq_enable(CSR_MIE_MTIE);
|
|
|
// wait some time for the IRQ to trigger and arrive the CPU
|
// wait some time for the IRQ to trigger and arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
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) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MTI) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
Line 877... |
Line 787... |
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] MSI (via testbench): ", cnt_test);
|
PRINT_STANDARD("[%i] MSI (via testbench): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
|
// enable interrupt
|
|
neorv32_cpu_irq_enable(CSR_MIE_MSIE);
|
|
|
// trigger IRQ
|
// trigger IRQ
|
sim_irq_trigger(1 << CSR_MIE_MSIE);
|
sim_irq_trigger(1 << CSR_MIE_MSIE);
|
|
|
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
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) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MSI) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
Line 900... |
Line 816... |
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] MEI (via testbench): ", cnt_test);
|
PRINT_STANDARD("[%i] MEI (via testbench): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
|
// enable interrupt
|
|
neorv32_cpu_irq_enable(CSR_MIE_MEIE);
|
|
|
// trigger IRQ
|
// trigger IRQ
|
sim_irq_trigger(1 << CSR_MIE_MEIE);
|
sim_irq_trigger(1 << CSR_MIE_MEIE);
|
|
|
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
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) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MEI) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Non-maskable interrupt (NMI) via testbench
|
// Permanent IRQ (make sure interrupted program advances)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
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++;
|
cnt_test++;
|
|
|
// trigger IRQ
|
// fire MTIME IRQ
|
sim_irq_trigger(1 << 0);
|
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
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
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();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
|
// re-enable global interrupts
|
|
neorv32_cpu_eint();
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Fast interrupt channel 0 (WDT)
|
// Fast interrupt channel 0 (WDT)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
if (neorv32_wdt_available()) {
|
if (neorv32_wdt_available()) {
|
Line 952... |
Line 929... |
// enable fast interrupt
|
// enable fast interrupt
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ0E);
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ0E);
|
|
|
// configure WDT
|
// configure WDT
|
neorv32_wdt_setup(CLK_PRSC_4096, 0, 1); // highest clock prescaler, trigger IRQ on timeout, lock access
|
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
|
neorv32_wdt_force(); // force watchdog into action
|
|
|
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
Line 966... |
Line 943... |
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
// no more WDT interrupts
|
|
neorv32_wdt_disable();
|
|
|
|
// disable fast interrupt
|
// disable fast interrupt
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ0E);
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ0E);
|
|
|
|
// no more WDT interrupts
|
|
neorv32_wdt_disable();
|
}
|
}
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Fast interrupt channel 1 (CFS)
|
// Fast interrupt channel 1 (CFS)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
PRINT_STANDARD("[%i] FIRQ1 test (via CFS): ", cnt_test);
|
PRINT_STANDARD("[%i] FIRQ1 test (via CFS): ", cnt_test);
|
PRINT_STANDARD("skipped (n.a.)\n");
|
PRINT_STANDARD("skipped \n");
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Fast interrupt channel 2 (UART0.RX)
|
// Fast interrupt channel 2 (UART0.RX)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
Line 997... |
Line 974... |
|
|
// wait for UART0 to finish transmitting
|
// wait for UART0 to finish transmitting
|
while(neorv32_uart0_tx_busy());
|
while(neorv32_uart0_tx_busy());
|
|
|
// backup current UART0 configuration
|
// backup current UART0 configuration
|
tmp_a = UART0_CT;
|
tmp_a = NEORV32_UART0.CTRL;
|
|
|
// make sure UART is enabled
|
// make sure UART is enabled
|
UART0_CT |= (1 << UART_CT_EN);
|
NEORV32_UART0.CTRL |= (1 << UART_CTRL_EN);
|
// make sure sim mode is disabled
|
// 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
|
// trigger UART0 RX IRQ
|
neorv32_uart0_putc(0);
|
neorv32_uart0_putc(0);
|
|
|
// wait for UART0 to finish transmitting
|
// wait for UART0 to finish transmitting
|
Line 1015... |
Line 992... |
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
|
|
// restore original configuration
|
// restore original configuration
|
UART0_CT = tmp_a;
|
NEORV32_UART0.CTRL = tmp_a;
|
|
|
// disable fast interrupt
|
// disable fast interrupt
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ2E);
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ2E);
|
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_2) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_2) {
|
Line 1045... |
Line 1022... |
|
|
// wait for UART0 to finish transmitting
|
// wait for UART0 to finish transmitting
|
while(neorv32_uart0_tx_busy());
|
while(neorv32_uart0_tx_busy());
|
|
|
// backup current UART0 configuration
|
// backup current UART0 configuration
|
tmp_a = UART0_CT;
|
tmp_a = NEORV32_UART0.CTRL;
|
|
|
// make sure UART is enabled
|
// make sure UART is enabled
|
UART0_CT |= (1 << UART_CT_EN);
|
NEORV32_UART0.CTRL |= (1 << UART_CTRL_EN);
|
// make sure sim mode is disabled
|
// 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
|
// trigger UART0 TX IRQ
|
neorv32_uart0_putc(0);
|
neorv32_uart0_putc(0);
|
|
|
// wait for UART to finish transmitting
|
// wait for UART to finish transmitting
|
Line 1063... |
Line 1040... |
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
|
|
// restore original configuration
|
// restore original configuration
|
UART0_CT = tmp_a;
|
NEORV32_UART0.CTRL = tmp_a;
|
|
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ3E);
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ3E);
|
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_3) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_3) {
|
test_ok();
|
test_ok();
|
Line 1089... |
Line 1066... |
|
|
// UART1 RX interrupt enable
|
// UART1 RX interrupt enable
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ4E);
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ4E);
|
|
|
// backup current UART1 configuration
|
// backup current UART1 configuration
|
tmp_a = UART1_CT;
|
tmp_a = NEORV32_UART1.CTRL;
|
|
|
// make sure UART is enabled
|
// make sure UART is enabled
|
UART1_CT |= (1 << UART_CT_EN);
|
NEORV32_UART1.CTRL |= (1 << UART_CTRL_EN);
|
// make sure sim mode is disabled
|
// 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
|
// trigger UART1 RX IRQ
|
neorv32_uart1_putc(0);
|
neorv32_uart1_putc(0);
|
|
|
// wait for UART1 to finish transmitting
|
// wait for UART1 to finish transmitting
|
Line 1107... |
Line 1084... |
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
|
|
// restore original configuration
|
// restore original configuration
|
UART1_CT = tmp_a;
|
NEORV32_UART1.CTRL = tmp_a;
|
|
|
// disable fast interrupt
|
// disable fast interrupt
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ4E);
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ4E);
|
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_4) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_4) {
|
Line 1134... |
Line 1111... |
|
|
// UART1 RX interrupt enable
|
// UART1 RX interrupt enable
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ5E);
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ5E);
|
|
|
// backup current UART1 configuration
|
// backup current UART1 configuration
|
tmp_a = UART1_CT;
|
tmp_a = NEORV32_UART1.CTRL;
|
|
|
// make sure UART is enabled
|
// make sure UART is enabled
|
UART1_CT |= (1 << UART_CT_EN);
|
NEORV32_UART1.CTRL |= (1 << UART_CTRL_EN);
|
// make sure sim mode is disabled
|
// 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
|
// trigger UART1 TX IRQ
|
neorv32_uart1_putc(0);
|
neorv32_uart1_putc(0);
|
|
|
// wait for UART1 to finish transmitting
|
// wait for UART1 to finish transmitting
|
Line 1152... |
Line 1129... |
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
|
|
// restore original configuration
|
// restore original configuration
|
UART1_CT = tmp_a;
|
NEORV32_UART1.CTRL = tmp_a;
|
|
|
// disable fast interrupt
|
// disable fast interrupt
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ5E);
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ5E);
|
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_5) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_5) {
|
Line 1256... |
Line 1233... |
|
|
xirq_err_cnt += neorv32_xirq_setup(); // initialize XIRQ
|
xirq_err_cnt += neorv32_xirq_setup(); // initialize XIRQ
|
xirq_err_cnt += neorv32_xirq_install(0, xirq_trap_handler0); // install XIRQ IRQ handler channel 0
|
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
|
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
|
// trigger XIRQ channel 1 and 0
|
neorv32_gpio_port_set(3);
|
neorv32_gpio_port_set(3);
|
|
|
// wait for IRQs to arrive CPU
|
// wait for IRQs to arrive CPU
|
Line 1275... |
Line 1253... |
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
neorv32_xirq_global_disable();
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ8E);
|
XIRQ_IER = 0;
|
NEORV32_XIRQ.IER = 0;
|
XIRQ_IPR = -1;
|
NEORV32_XIRQ.IPR = -1;
|
}
|
}
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Fast interrupt channel 9 (NEOLED)
|
// Fast interrupt channel 9 (NEOLED)
|
Line 1294... |
Line 1272... |
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
if (neorv32_slink_available()) {
|
if (neorv32_slink_available()) {
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] FIRQ10 & 11 (SLINK): ", cnt_test);
|
PRINT_STANDARD("[%i] FIRQ10 & 11 (SLINK): ", cnt_test);
|
|
|
|
// NOTE: this test requires FIFO sizes = 1
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// enable SLINK
|
// enable SLINK
|
neorv32_slink_enable();
|
neorv32_slink_enable();
|
|
|
Line 1332... |
Line 1312... |
test_fail();
|
test_fail();
|
}
|
}
|
|
|
// shutdown SLINK
|
// shutdown SLINK
|
neorv32_slink_disable();
|
neorv32_slink_disable();
|
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ10E);
|
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ11E);
|
}
|
}
|
|
|
|
|
//// ----------------------------------------------------------
|
//// ----------------------------------------------------------
|
//// Fast interrupt channel 12..15 (reserved)
|
//// Fast interrupt channel 12..15 (reserved)
|
Line 1350... |
Line 1332... |
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] WFI (sleep instruction) test (wake-up via MTIME): ", cnt_test);
|
PRINT_STANDARD("[%i] WFI (sleep instruction) test (wake-up via MTIME): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// program wake-up timer
|
|
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + 1000);
|
|
|
|
// clear timeout wait flag
|
// clear timeout wait flag
|
tmp_a = neorv32_cpu_csr_read(CSR_MSTATUS);
|
tmp_a = neorv32_cpu_csr_read(CSR_MSTATUS);
|
tmp_a &= ~(1 << CSR_MSTATUS_TW);
|
tmp_a &= ~(1 << CSR_MSTATUS_TW);
|
neorv32_cpu_csr_write(CSR_MSTATUS, tmp_a);
|
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)
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
|
neorv32_cpu_goto_user_mode();
|
neorv32_cpu_goto_user_mode();
|
{
|
{
|
// only when mstatus.TW = 0 executing WFI in user mode is allowed
|
// only when mstatus.TW = 0 executing WFI in user mode is allowed
|
asm volatile ("wfi"); // put CPU into sleep mode
|
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) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_MTI) {
|
test_fail();
|
test_fail();
|
}
|
}
|
else {
|
else {
|
test_ok();
|
test_ok();
|
}
|
}
|
|
|
// no more mtime interrupts
|
|
neorv32_mtime_set_timecmp(-1);
|
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Test invalid CSR access in user mode
|
// Test invalid CSR access in user mode
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] Invalid CSR access (mstatus) from user mode: ", cnt_test);
|
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)
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
|
neorv32_cpu_goto_user_mode();
|
neorv32_cpu_goto_user_mode();
|
{
|
{
|
// access to misa not allowed for user-level programs
|
// access to misa not allowed for user-level programs
|
tmp_a = neorv32_cpu_csr_read(CSR_MISA);
|
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) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
}
|
|
else {
|
|
PRINT_STANDARD("skipped (n.a. without U-ext)\n");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Test RTE debug trap handler
|
// Test RTE debug trap handler
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
Line 1454... |
Line 1428... |
cnt_test++;
|
cnt_test++;
|
|
|
// find out minimal region size (granularity)
|
// find out minimal region size (granularity)
|
tmp_b = neorv32_cpu_pmp_get_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);
|
PRINT_STANDARD("Creating protected page (NAPOT, [!X,!W,!R], %u bytes) @ 0x%x: ", tmp_b, tmp_a);
|
|
|
// configure
|
// configure
|
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
|
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
|
|
|
Line 1500... |
Line 1474... |
cnt_test++;
|
cnt_test++;
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
|
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
|
neorv32_cpu_goto_user_mode();
|
neorv32_cpu_goto_user_mode();
|
|
tmp_b = 0;
|
{
|
{
|
tmp_b = neorv32_cpu_load_unsigned_word(tmp_a); // load access -> should fail
|
tmp_b = neorv32_cpu_load_unsigned_word(tmp_a); // load access -> should fail
|
}
|
}
|
|
|
if (tmp_b != 0) {
|
if (tmp_b != 0) {
|
Line 1730... |
Line 1705... |
* @param[in] sel IRQ select mask (bit positions according to #NEORV32_CSR_MIE_enum).
|
* @param[in] sel IRQ select mask (bit positions according to #NEORV32_CSR_MIE_enum).
|
**************************************************************************/
|
**************************************************************************/
|
void sim_irq_trigger(uint32_t sel) {
|
void sim_irq_trigger(uint32_t sel) {
|
|
|
*(IO_REG32 (0xFF000000)) = sel;
|
*(IO_REG32 (0xFF000000)) = sel;
|
|
asm volatile("nop"); // interrupt should kick in here (latest)
|
|
*(IO_REG32 (0xFF000000)) = 0;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Trap handler for ALL exceptions/interrupts.
|
* Trap handler for ALL exceptions/interrupts.
|
Line 1790... |
Line 1767... |
* test report to physical UART
|
* test report to physical UART
|
**************************************************************************/
|
**************************************************************************/
|
int __neorv32_crt0_after_main(int32_t return_code) {
|
int __neorv32_crt0_after_main(int32_t return_code) {
|
|
|
// make sure sim mode is disabled and UARTs are actually enabled
|
// make sure sim mode is disabled and UARTs are actually enabled
|
UART0_CT |= (1 << UART_CT_EN);
|
NEORV32_UART0.CTRL |= (1 << UART_CTRL_EN);
|
UART0_CT &= ~(1 << UART_CT_SIM_MODE);
|
NEORV32_UART0.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
|
UART1_CT = UART0_CT;
|
NEORV32_UART1.CTRL = NEORV32_UART0.CTRL;
|
|
|
// minimal result report
|
// minimal result report
|
PRINT_CRITICAL("%u/%u\n", (uint32_t)return_code, (uint32_t)cnt_test);
|
PRINT_CRITICAL("%u/%u\n", (uint32_t)return_code, (uint32_t)cnt_test);
|
|
|
return 0;
|
return 0;
|