From 763a5cd364b4798940882235af07fe3e33ddded1 Mon Sep 17 00:00:00 2001 From: Luke Wren <wren6991@gmail.com> Date: Sat, 11 Dec 2021 17:50:12 +0000 Subject: [PATCH] Add test for readability of all implemented CSRs --- test/sim/common/hazard3_csr.h | 8 +- test/sim/sw_testcases/csr_readable.c | 155 ++++++++++++++++++ test/sim/sw_testcases/ebreak.c | 2 +- test/sim/sw_testcases/illegal_instr.c | 2 +- .../sim/sw_testcases/load_misalign_halfword.c | 2 +- test/sim/sw_testcases/load_misalign_word.c | 2 +- test/sim/sw_testcases/load_store_fault.c | 2 +- test/sim/sw_testcases/lr_sc_fault.c | 2 +- test/sim/sw_testcases/lr_sc_smoke.c | 2 + .../sw_testcases/store_misalign_halfword.c | 2 +- test/sim/sw_testcases/store_misalign_word.c | 2 +- 11 files changed, 169 insertions(+), 12 deletions(-) create mode 100644 test/sim/sw_testcases/csr_readable.c diff --git a/test/sim/common/hazard3_csr.h b/test/sim/common/hazard3_csr.h index bba805b..3ab5daa 100644 --- a/test/sim/common/hazard3_csr.h +++ b/test/sim/common/hazard3_csr.h @@ -5,10 +5,10 @@ #include "stdint.h" #endif -#define hazard3_csr_midcr 0xbc0 -#define hazard3_csr_meie0 0xbe0 // External interrupt enable IRQ0 -> 31 -#define hazard3_csr_meip0 0xfe0 // External interrupt pending IRQ0 -> 31 -#define hazard3_csr_mlei 0xfe4 // Lowest external interrupt (pending & enabled) +#define hazard3_csr_dmdata0 0xbff // Debug-mode shadow CSR for DM data transfer +#define hazard3_csr_meie0 0xbe0 // External interrupt enable IRQ0 -> 31 +#define hazard3_csr_meip0 0xfe0 // External interrupt pending IRQ0 -> 31 +#define hazard3_csr_mlei 0xfe4 // Lowest external interrupt (pending & enabled) #define _read_csr(csrname) ({ \ uint32_t __csr_tmp_u32; \ diff --git a/test/sim/sw_testcases/csr_readable.c b/test/sim/sw_testcases/csr_readable.c new file mode 100644 index 0000000..b1f35ad --- /dev/null +++ b/test/sim/sw_testcases/csr_readable.c @@ -0,0 +1,155 @@ +#include "tb_cxxrtl_io.h" +#include "hazard3_csr.h" + +// Check all implemented M-mode CSRs are readable, without exception (haha). +// Check reading D-mode CSRs generates illegal instruction exceptions in M-mode. + +// These are new (priv-1.12) and may not be recognised by the toolchain: +#define mconfigptr 0xf15 +#define mstatush 0x310 + +// Exceptions here are: medeleg, mideleg, tdata1, dcsr, dpc, dscratch1, +// dscratch0, dmdata0 (custom). medeleg/mideleg are just a couple of +// unimplemented registers sprinkled in for a sanity check, and the remainder +// are D-mode registers. +// +// Note we permit reads but not writes to tselect, to work around a logic +// error in openocd. Planning to implement triggers at some point, so this +// oddity will vanish. + +/*EXPECTED-OUTPUT*************************************************************** + +-> exception, mcause = 2 +CSR was 302 +-> exception, mcause = 2 +CSR was 303 +-> exception, mcause = 2 +CSR was 7a1 +-> exception, mcause = 2 +CSR was 7b0 +-> exception, mcause = 2 +CSR was 7b1 +-> exception, mcause = 2 +CSR was 7b2 +-> exception, mcause = 2 +CSR was 7b3 +-> exception, mcause = 2 +CSR was bff + +*******************************************************************************/ + +int main() { + (void)read_csr(mvendorid); + (void)read_csr(marchid); + (void)read_csr(mimpid); + (void)read_csr(mhartid); + (void)read_csr(mconfigptr); + (void)read_csr(misa); + + (void)read_csr(mstatus); + (void)read_csr(mstatush); + (void)read_csr(medeleg); + (void)read_csr(mideleg); + (void)read_csr(mie); + (void)read_csr(mip); + (void)read_csr(mtvec); + (void)read_csr(mscratch); + (void)read_csr(mepc); + (void)read_csr(mcause); + (void)read_csr(mtval); + + (void)read_csr(mcycle); + (void)read_csr(mcycleh); + (void)read_csr(minstret); + (void)read_csr(minstreth); + + (void)read_csr(mhpmcounter3); + (void)read_csr(mhpmcounter4); + (void)read_csr(mhpmcounter5); + (void)read_csr(mhpmcounter6); + (void)read_csr(mhpmcounter7); + (void)read_csr(mhpmcounter8); + (void)read_csr(mhpmcounter9); + (void)read_csr(mhpmcounter10); + (void)read_csr(mhpmcounter11); + (void)read_csr(mhpmcounter12); + (void)read_csr(mhpmcounter13); + (void)read_csr(mhpmcounter14); + (void)read_csr(mhpmcounter15); + (void)read_csr(mhpmcounter16); + (void)read_csr(mhpmcounter17); + (void)read_csr(mhpmcounter18); + (void)read_csr(mhpmcounter19); + (void)read_csr(mhpmcounter20); + (void)read_csr(mhpmcounter21); + (void)read_csr(mhpmcounter22); + (void)read_csr(mhpmcounter23); + (void)read_csr(mhpmcounter24); + (void)read_csr(mhpmcounter25); + (void)read_csr(mhpmcounter26); + (void)read_csr(mhpmcounter27); + (void)read_csr(mhpmcounter28); + (void)read_csr(mhpmcounter29); + (void)read_csr(mhpmcounter30); + (void)read_csr(mhpmcounter31); + + (void)read_csr(mhpmcounter3h); + (void)read_csr(mhpmcounter4h); + (void)read_csr(mhpmcounter5h); + (void)read_csr(mhpmcounter6h); + (void)read_csr(mhpmcounter7h); + (void)read_csr(mhpmcounter8h); + (void)read_csr(mhpmcounter9h); + (void)read_csr(mhpmcounter10h); + (void)read_csr(mhpmcounter11h); + (void)read_csr(mhpmcounter12h); + (void)read_csr(mhpmcounter13h); + (void)read_csr(mhpmcounter14h); + (void)read_csr(mhpmcounter15h); + (void)read_csr(mhpmcounter16h); + (void)read_csr(mhpmcounter17h); + (void)read_csr(mhpmcounter18h); + (void)read_csr(mhpmcounter19h); + (void)read_csr(mhpmcounter20h); + (void)read_csr(mhpmcounter21h); + (void)read_csr(mhpmcounter22h); + (void)read_csr(mhpmcounter23h); + (void)read_csr(mhpmcounter24h); + (void)read_csr(mhpmcounter25h); + (void)read_csr(mhpmcounter26h); + (void)read_csr(mhpmcounter27h); + (void)read_csr(mhpmcounter28h); + (void)read_csr(mhpmcounter29h); + (void)read_csr(mhpmcounter30h); + (void)read_csr(mhpmcounter31h); + + (void)read_csr(mcountinhibit); + (void)read_csr(mhpmevent3); + (void)read_csr(tselect); + (void)read_csr(tdata1); + (void)read_csr(dcsr); + (void)read_csr(dpc); + (void)read_csr(dscratch0); + (void)read_csr(dscratch1); + (void)read_csr(hazard3_csr_dmdata0); + (void)read_csr(hazard3_csr_meie0); + (void)read_csr(hazard3_csr_meip0); + (void)read_csr(hazard3_csr_mlei); + + return 0; +} + +void __attribute__((interrupt)) handle_exception() { + tb_printf("-> exception, mcause = %u\n", read_csr(mcause)); + write_csr(mcause, 0); + uint32_t mepc = read_csr(mepc); + if ((*(uint16_t*)mepc & 0x3) == 0x3) { + tb_printf("CSR was %03x\n", *(uint16_t*)(mepc + 2) >> 4); + mepc += 4; + } + else { + tb_puts("Exception on 16-bit instruction?!\n"); + tb_exit(-1); + } + write_csr(mepc, mepc); +} diff --git a/test/sim/sw_testcases/ebreak.c b/test/sim/sw_testcases/ebreak.c index 41f300e..cdb8c54 100644 --- a/test/sim/sw_testcases/ebreak.c +++ b/test/sim/sw_testcases/ebreak.c @@ -51,7 +51,7 @@ int main() { void __attribute__((interrupt)) handle_exception() { tb_printf("mcause = %u\n", read_csr(mcause)); tb_printf("Offset into test: %u, ", read_csr(mepc) - (uintptr_t)&test); - if (*(uint16_t*)read_csr(mepc) & 0x3 == 0x3) { + if ((*(uint16_t*)read_csr(mepc) & 0x3) == 0x3) { tb_puts("32-bit ebreak\n"); write_csr(mepc, read_csr(mepc) + 4); } diff --git a/test/sim/sw_testcases/illegal_instr.c b/test/sim/sw_testcases/illegal_instr.c index a119e3a..f0f92b1 100644 --- a/test/sim/sw_testcases/illegal_instr.c +++ b/test/sim/sw_testcases/illegal_instr.c @@ -50,7 +50,7 @@ void __attribute__((interrupt)) handle_exception() { tb_printf("Exception, mcause = %u\n", mcause); uint16_t i0 = *(uint16_t*)mepc; - if (i0 & 0x3u == 0x3u) { + if ((i0 & 0x3u) == 0x3u) { uint16_t i1 = *(uint16_t*)(mepc + 2); tb_printf("32-bit illegal instruction: %04x%04x\n", i1, i0); mepc += 4; diff --git a/test/sim/sw_testcases/load_misalign_halfword.c b/test/sim/sw_testcases/load_misalign_halfword.c index 0a7e901..d767043 100644 --- a/test/sim/sw_testcases/load_misalign_halfword.c +++ b/test/sim/sw_testcases/load_misalign_halfword.c @@ -58,7 +58,7 @@ int main() { void __attribute__((interrupt)) handle_exception() { tb_printf("-> exception, mcause = %u\n", read_csr(mcause)); write_csr(mcause, 0); - if (*(uint16_t*)read_csr(mepc) & 0x3 == 0x3) { + if ((*(uint16_t*)read_csr(mepc) & 0x3) == 0x3) { write_csr(mepc, read_csr(mepc) + 4); } else { diff --git a/test/sim/sw_testcases/load_misalign_word.c b/test/sim/sw_testcases/load_misalign_word.c index ee96471..19420ba 100644 --- a/test/sim/sw_testcases/load_misalign_word.c +++ b/test/sim/sw_testcases/load_misalign_word.c @@ -37,7 +37,7 @@ int main() { void __attribute__((interrupt)) handle_exception() { tb_printf("-> exception, mcause = %u\n", read_csr(mcause)); write_csr(mcause, 0); - if (*(uint16_t*)read_csr(mepc) & 0x3 == 0x3) { + if ((*(uint16_t*)read_csr(mepc) & 0x3) == 0x3) { write_csr(mepc, read_csr(mepc) + 4); } else { diff --git a/test/sim/sw_testcases/load_store_fault.c b/test/sim/sw_testcases/load_store_fault.c index dee7238..fd30d60 100644 --- a/test/sim/sw_testcases/load_store_fault.c +++ b/test/sim/sw_testcases/load_store_fault.c @@ -51,7 +51,7 @@ void __attribute__((interrupt)) handle_exception() { tb_printf("-> exception, mcause = %u\n", read_csr(mcause)); write_csr(mcause, 0); uint32_t mepc = read_csr(mepc); - if (*(uint16_t*)mepc & 0x3 == 0x3) { + if ((*(uint16_t*)mepc & 0x3) == 0x3) { tb_printf("exception instr: %04x%04x\n", *(uint16_t*)(mepc + 2), *(uint16_t*)mepc); write_csr(mepc, mepc + 4); } diff --git a/test/sim/sw_testcases/lr_sc_fault.c b/test/sim/sw_testcases/lr_sc_fault.c index 2628254..e547fbb 100644 --- a/test/sim/sw_testcases/lr_sc_fault.c +++ b/test/sim/sw_testcases/lr_sc_fault.c @@ -68,7 +68,7 @@ void __attribute__((interrupt)) handle_exception() { tb_printf("-> exception, mcause = %u\n", read_csr(mcause)); write_csr(mcause, 0); uint32_t mepc = read_csr(mepc); - if (*(uint16_t*)mepc & 0x3 == 0x3) { + if ((*(uint16_t*)mepc & 0x3) == 0x3) { tb_printf("exception instr: %04x%04x\n", *(uint16_t*)(mepc + 2), *(uint16_t*)mepc); write_csr(mepc, mepc + 4); } diff --git a/test/sim/sw_testcases/lr_sc_smoke.c b/test/sim/sw_testcases/lr_sc_smoke.c index 84ed4a3..b194039 100644 --- a/test/sim/sw_testcases/lr_sc_smoke.c +++ b/test/sim/sw_testcases/lr_sc_smoke.c @@ -24,6 +24,8 @@ int main() { "lr.w %0, (%2)\n" "nop\n" "sc.w %1, %3, (%2)\n" + // Note the "&": this marks an "earlyclobber" operand, telling GCC it can't + // allocate this output to an input register. (particularly, %0 to %2) : "=&r" (load_result), "=r" (success) : "r" (&scratch[0]), "r" (0x5678) ); diff --git a/test/sim/sw_testcases/store_misalign_halfword.c b/test/sim/sw_testcases/store_misalign_halfword.c index 1f8762d..e06e334 100644 --- a/test/sim/sw_testcases/store_misalign_halfword.c +++ b/test/sim/sw_testcases/store_misalign_halfword.c @@ -37,7 +37,7 @@ int main() { void __attribute__((interrupt)) handle_exception() { tb_printf("-> exception, mcause = %u\n", read_csr(mcause)); write_csr(mcause, 0); - if (*(uint16_t*)read_csr(mepc) & 0x3 == 0x3) { + if ((*(uint16_t*)read_csr(mepc) & 0x3) == 0x3) { write_csr(mepc, read_csr(mepc) + 4); } else { diff --git a/test/sim/sw_testcases/store_misalign_word.c b/test/sim/sw_testcases/store_misalign_word.c index 13b562d..ccdaa1d 100644 --- a/test/sim/sw_testcases/store_misalign_word.c +++ b/test/sim/sw_testcases/store_misalign_word.c @@ -40,7 +40,7 @@ int main() { void __attribute__((interrupt)) handle_exception() { tb_printf("-> exception, mcause = %u\n", read_csr(mcause)); write_csr(mcause, 0); - if (*(uint16_t*)read_csr(mepc) & 0x3 == 0x3) { + if ((*(uint16_t*)read_csr(mepc) & 0x3) == 0x3) { write_csr(mepc, read_csr(mepc) + 4); } else {