[sim,sw] add trigger module test case

This commit is contained in:
stnolting 2023-11-30 17:30:19 +01:00
parent 2578fd9da8
commit 741805ec53
2 changed files with 93 additions and 27 deletions

View file

@ -184,7 +184,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/57" & cr & lf);
check_uart(net, uart1_rx_handle, "0/58" & cr & lf);
end if;
-- Wait until all expected data has been received

View file

@ -88,6 +88,8 @@ void rte_service_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 __attribute__ ((interrupt)) hw_breakpoint_handler(void);
void __attribute__ ((noinline)) trigger_module_dummy(void);
void xirq_trap_handler0(void);
void xirq_trap_handler1(void);
void test_ok(void);
@ -96,31 +98,21 @@ void test_fail(void);
// MCAUSE value that will be NEVER set by the hardware
const uint32_t mcause_never_c = 0x80000000UL; // = reserved
// Global variables (also test initialization of global vars here)
/// Global counter for failing tests
int cnt_fail = 0;
/// Global counter for successful tests
int cnt_ok = 0;
/// Global counter for total number of tests
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
volatile uint32_t dma_src;
/// Variable to test store accesses
volatile uint32_t store_access_addr[2];
/// Variable for testing atomic memory accesses
volatile uint32_t amo_var;
/// Variable to test PMP
volatile uint32_t __attribute__((aligned(4))) pmp_access[2];
/// Number of triggered traps
volatile uint32_t trap_cnt;
/// Number of implemented PMP regions
uint32_t pmp_num_regions;
// Global variables
volatile int cnt_fail = 0; // global counter for failing tests
volatile int cnt_ok = 0; // global counter for successful tests
volatile int cnt_test = 0; // global counter for total number of tests
volatile uint32_t num_hpm_cnts_global = 0; // global number of available hpms
volatile int vectored_mei_handler_ack = 0; // vectored mei trap handler acknowledge
volatile uint32_t xirq_trap_handler_ack = 0; // xirq trap handler acknowledge
volatile uint32_t hw_brk_mscratch_ok = 0; // set when mepc was correct in trap handler
volatile uint32_t dma_src; // dma source & destination data
volatile uint32_t store_access_addr[2]; // variable to test store accesses
volatile uint32_t amo_var; // variable for testing atomic memory accesses
volatile uint32_t __attribute__((aligned(4))) pmp_access[2]; // variable to test pmp
volatile uint32_t trap_cnt; // number of triggered traps
volatile uint32_t pmp_num_regions; // number of implemented pmp regions
/**********************************************************************//**
@ -1877,6 +1869,55 @@ int main() {
}
// ----------------------------------------------------------
// Test trigger module (hardware breakpoint)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, mcause_never_c);
PRINT_STANDARD("[%i] Trigger module (HW breakpoint) ", cnt_test);
if (neorv32_cpu_csr_read(CSR_MXISA) & (1 << CSR_MXISA_SDTRIG)) {
cnt_test++;
// back-up RTE
uint32_t rte_bak = neorv32_cpu_csr_read(CSR_MTVEC);
// install hardware-breakpoint handler
neorv32_cpu_csr_write(CSR_MTVEC, (uint32_t)&hw_breakpoint_handler);
// setup test registers
neorv32_cpu_csr_write(CSR_MSCRATCH, 0);
hw_brk_mscratch_ok = 0;
// setup hardware breakpoint
neorv32_cpu_csr_write(CSR_TDATA2, (uint32_t)(&trigger_module_dummy)); // triggering address
neorv32_cpu_csr_write(CSR_TDATA1, (1 << 2) | // exe = 1: enable trigger module execution
(0 << 12)); // action = 0: breakpoint exception, do not enter debug-mode
// call the hw-breakpoint triggering function
trigger_module_dummy();
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_BREAKPOINT) && // correct exception cause
(neorv32_cpu_csr_read(CSR_MSCRATCH) == 4) && // breakpoint-triggering function was finally executed
(neorv32_cpu_csr_read(CSR_MEPC) == neorv32_cpu_csr_read(CSR_TDATA2)) && // mepc has to be set to the triggering instruction address
(neorv32_cpu_csr_read(CSR_TDATA1) & (1 << 22)) && // trigger has fired
(hw_brk_mscratch_ok == 1)) { // make sure mepc was correct in trap handler
test_ok();
}
else {
test_fail();
}
// shut-down and reset trigger
neorv32_cpu_csr_write(CSR_TDATA1, 0);
// restore RTE
neorv32_cpu_csr_write(CSR_MTVEC, rte_bak);
}
else {
PRINT_STANDARD("[n.a.]\n");
}
// ----------------------------------------------------------
// Test atomic lr/sc memory access - failing access
// ----------------------------------------------------------
@ -2232,7 +2273,7 @@ void rte_service_handler(void) {
if (arg0 == 127) {
neorv32_rte_context_put(10, arg1 + arg2); // service result in a0
}
// hack: return in MACHINE MODE
neorv32_cpu_csr_set(CSR_MSTATUS, (1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L));
}
@ -2293,6 +2334,31 @@ void vectored_mei_handler(void) {
}
/**********************************************************************//**
* Hardware-breakpoint trap handler
**************************************************************************/
void __attribute__ ((interrupt)) hw_breakpoint_handler(void) {
// make sure mscratch has not been updated yet
if (neorv32_cpu_csr_read(CSR_MSCRATCH) == 0) {
hw_brk_mscratch_ok += 1;
}
// [NOTE] do not update MEPC here as hardware-breakpoint exceptions will set
// MEPC to the address of the instruction thats has NOT BEEN EXECUTED yet
}
/**********************************************************************//**
* Test function for the trigger module
**************************************************************************/
void __attribute__ ((noinline,naked)) trigger_module_dummy(void) {
asm volatile ("csrwi mscratch, 4 \n" // hardware breakpoint should trigger before executing this
"ret \n");
}
/**********************************************************************//**
* XIRQ handler channel 0.
**************************************************************************/