Skip to content

Commit

Permalink
[processor_check] test vectored mtvec mode
Browse files Browse the repository at this point in the history
  • Loading branch information
NikLeberg committed Sep 24, 2023
1 parent 0006ad4 commit 50a7f8a
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 1 deletion.
2 changes: 1 addition & 1 deletion sim/neorv32_tb.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ begin
if ci_mode then
-- No need to send the full expectation in one big chunk
check_uart(net, uart1_rx_handle, nul & nul);
check_uart(net, uart1_rx_handle, "0/55" & cr & lf);
check_uart(net, uart1_rx_handle, "0/56" & cr & lf);
end if;

-- Wait until all expected data has been received
Expand Down
103 changes: 103 additions & 0 deletions sw/example/processor_check/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@
// Prototypes
void sim_irq_trigger(uint32_t sel);
void global_trap_handler(void);
void vectored_irq_table(void) __attribute__((naked, aligned(128)));
void vectored_global_handler(void) __attribute__((interrupt("machine")));
void vectored_mei_handler(void) __attribute__((interrupt("machine")));
void xirq_trap_handler0(void);
void xirq_trap_handler1(void);
void test_ok(void);
Expand All @@ -101,6 +104,8 @@ int cnt_ok = 0;
int cnt_test = 0;
/// Global number of available HPMs
uint32_t num_hpm_cnts_global = 0;
/// Vectored MEI trap handler acknowledge
volatile int vectored_mei_handler_ack = 0;
/// XIRQ trap handler acknowledge
uint32_t xirq_trap_handler_ack = 0;
/// DMA source & destination data
Expand Down Expand Up @@ -1014,6 +1019,49 @@ int main() {
}


// ----------------------------------------------------------
// Test vectored interrupt via testbench external interrupt
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, mcause_never_c);
PRINT_STANDARD("[%i] Vectored IRQ (sim) ", cnt_test);

if (neorv32_cpu_csr_read(CSR_MXISA) & (1 << CSR_MXISA_IS_SIM)) {
cnt_test++;

// back-up RTE
uint32_t mtvec_bak = neorv32_cpu_csr_read(CSR_MTVEC);

// install vector table and enable vector mode (mtvec[1:0] = 0b01)
neorv32_cpu_csr_write(CSR_MTVEC, (uint32_t)&vectored_irq_table | 0x1);

// enable interrupt
neorv32_cpu_csr_write(CSR_MIE, 1 << CSR_MIE_MEIE);

// trigger IRQ
sim_irq_trigger(1 << CSR_MIE_MEIE);

// wait some time for the IRQ to arrive the CPU
asm volatile ("nop");
asm volatile ("nop");

neorv32_cpu_csr_write(CSR_MIE, 0);
sim_irq_trigger(0);

if (vectored_mei_handler_ack == 1) {
test_ok();
}
else {
test_fail();
}

// restore RTE
neorv32_cpu_csr_write(CSR_MTVEC, mtvec_bak);
}
else {
PRINT_STANDARD("[n.a.]\n");
}


// ----------------------------------------------------------
// Fast interrupt channel 0 (WDT)
// ----------------------------------------------------------
Expand Down Expand Up @@ -2094,6 +2142,61 @@ void global_trap_handler(void) {
}


/**********************************************************************//**
* Vectored mtvec mode jump table.
**************************************************************************/
void vectored_irq_table(void) {
asm volatile(
".org vectored_irq_table + 0*4 \n"
"jal zero, %[glb] \n" // 0
".org vectored_irq_table + 3*4 \n"
"jal zero, %[glb] \n" // 3
".org vectored_irq_table + 7*4 \n"
"jal zero, %[glb] \n" // 7
".org vectored_irq_table + 11*4 \n"
"jal zero, %[mei] \n" // 11
".org vectored_irq_table + 16*4 \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] \n"
"jal zero, %[glb] "
: : [glb] "i" ((uint32_t)&vectored_global_handler), [mei] "i" ((uint32_t)&vectored_mei_handler)
);
}


/**********************************************************************//**
* Vectored trap handler for ALL exceptions/interrupts.
**************************************************************************/
void vectored_global_handler(void) {

// Call the default trap handler, cannot be put into the vector table directly
// as all function in the table must have the gcc attribute "interrupt".
global_trap_handler();
}


/**********************************************************************//**
* Machine external interrupt handler.
**************************************************************************/
void vectored_mei_handler(void) {

vectored_mei_handler_ack = 1; // successfully called
}


/**********************************************************************//**
* XIRQ handler channel 0.
**************************************************************************/
Expand Down

0 comments on commit 50a7f8a

Please sign in to comment.