From 6642c22de441420f967e2898478a4f049a43e2e5 Mon Sep 17 00:00:00 2001 From: Dan Smathers Date: Tue, 6 Feb 2024 15:54:41 -0700 Subject: [PATCH] Add interrupt test cases using clint MSW and MTIMER interrupts requires https://github.com/riscv-software-src/riscv-config/pull/169, https://github.com/riscv-software-src/riscof/pull/106 To include these tests in riscof testlist flow, add Smclint to riscof yaml file, e.g.: spike/spike_isa.yaml: ISA: RV32IMCZicsr_Zifencei_Smclint Signed-off-by: Dan Smathers --- .../rv32i_m/Smclint/src/direct-01.S | 516 +++++++++++++++++ .../rv32i_m/Smclint/src/direct-02.S | 520 +++++++++++++++++ .../rv32i_m/Smclint/src/ecall-01.S | 524 ++++++++++++++++++ .../rv32i_m/Smclint/src/level-01.S | 511 +++++++++++++++++ .../rv32i_m/Smclint/src/level-02.S | 513 +++++++++++++++++ .../rv32i_m/Smclint/src/level-03.S | 516 +++++++++++++++++ .../rv32i_m/Smclint/src/level-04.S | 516 +++++++++++++++++ riscv-test-suite/rv32i_m/Smclint/src/msw-01.S | 513 +++++++++++++++++ .../rv32i_m/Smclint/src/mtimer-01.S | 510 +++++++++++++++++ .../rv32i_m/Smclint/src/nomint-01.S | 507 +++++++++++++++++ .../rv32i_m/Smclint/src/nomint-02.S | 507 +++++++++++++++++ .../rv32i_m/Smclint/src/vectored-01.S | 519 +++++++++++++++++ .../rv32i_m/Smclint/src/vectored-02.S | 523 +++++++++++++++++ riscv-test-suite/rv32i_m/Smclint/src/wfi-01.S | 509 +++++++++++++++++ 14 files changed, 7204 insertions(+) create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/direct-01.S create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/direct-02.S create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/ecall-01.S create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/level-01.S create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/level-02.S create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/level-03.S create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/level-04.S create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/msw-01.S create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/mtimer-01.S create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/nomint-01.S create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/nomint-02.S create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/vectored-01.S create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/vectored-02.S create mode 100644 riscv-test-suite/rv32i_m/Smclint/src/wfi-01.S diff --git a/riscv-test-suite/rv32i_m/Smclint/src/direct-01.S b/riscv-test-suite/rv32i_m/Smclint/src/direct-01.S new file mode 100644 index 000000000..6ae61e6b0 --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/direct-01.S @@ -0,0 +1,516 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: trigger, clear, retrigger same interrupt. +// - enable mie CSR + +// - generate interrupt + +// - enable mstatus.mie + +// - trigger m-mode handler + +// - clear 1st interrupt + +// - generate interrupt + +// - trigger 2nd m-mode handler + +// - clear 2nd interrupt + +// - set mepc to finish + +// - mret to finish + +////////////////// + +////////////////// +// direct-01 settings +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE MIE_MSIE +#endif +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 RVMODEL_CLEAR_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 RVMODEL_CLEAR_MSW_INT +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",direct-01) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test direct-01\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END + diff --git a/riscv-test-suite/rv32i_m/Smclint/src/direct-02.S b/riscv-test-suite/rv32i_m/Smclint/src/direct-02.S new file mode 100644 index 000000000..d7ffd7507 --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/direct-02.S @@ -0,0 +1,520 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: trigger, clear, retrigger single interrupt, no 2nd clear. +// Stimulates pending interrupt after setting mstatus.mpie followed by mret + +// mstatus.mie should be cleared after mret so pending interrupt is not taken + +// - enable mie CSR + +// - generate interrupt + +// - enable mstatus.mie + +// - trigger m-mode handler + +// - clear 1st interrupt + +// - generate interrupt + +// - trigger 2nd m-mode handler + +// - set mepc to finish + +// - clear mstatus.mpie + +// - mret to finish + +////////////////// + +////////////////// +// direct-02 settings +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE MIE_MSIE +#endif +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 RVMODEL_CLEAR_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",direct-02) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test direct-02\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END + diff --git a/riscv-test-suite/rv32i_m/Smclint/src/ecall-01.S b/riscv-test-suite/rv32i_m/Smclint/src/ecall-01.S new file mode 100644 index 000000000..52f2da1a0 --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/ecall-01.S @@ -0,0 +1,524 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: trigger, clear, set interrupt pending, ecall +// Stimulates ecall within an interrupt handler to stimulate mcause.interrupt toggling + +// mstatus.mie should be cleared after mret so pending interrupt is not taken + +// - enable mie CSR + +// - generate interrupt + +// - enable mstatus.mie + +// - trigger m-mode vectored interrupt handler + +// - ecall instruction to trigger (direct) exception handler + +// - set mepc to finish + +// - clear mstatus.mpie + +// - mret to finish + +// - re-trigger interrupt + +////////////////// + +////////////////// +// ecall-01 settings +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE MIE_MSIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 1 +#endif +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL ecall +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",ecall-01) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test ecall-01\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END + diff --git a/riscv-test-suite/rv32i_m/Smclint/src/level-01.S b/riscv-test-suite/rv32i_m/Smclint/src/level-01.S new file mode 100644 index 000000000..2508fd4c7 --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/level-01.S @@ -0,0 +1,511 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: verify interrupt level order, 2 interrupts asserted in 1st interrupt handler, mtvec.mode=direct +// - enable mie CSR + +// - generate interrupt 1 + +// - enable mstatus.mie + +// - trigger m-mode handler + +// - generate interrupt 2 (both interrupts now pending) + +// - trigger 2nd m-mode handler + +// - set mepc to finish + +// - clear mstatus.mpie + +// - mret to finish + +////////////////// + +////////////////// +// level-01 settings +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 RVMODEL_SET_MTIMER_INT +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 RVMODEL_CLEAR_MTIMER_INT +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",level-01) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test level-01\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END + diff --git a/riscv-test-suite/rv32i_m/Smclint/src/level-02.S b/riscv-test-suite/rv32i_m/Smclint/src/level-02.S new file mode 100644 index 000000000..35209facf --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/level-02.S @@ -0,0 +1,513 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: verify interrupt level order, swap 2 interrupt order, mtvec.mode=direct +// - enable mie CSR + +// - generate interrupt 1 + +// - enable mstatus.mie + +// - trigger m-mode handler + +// - generate interrupt 2 (both interrupts now pending) + +// - set mstatus.mie + +// - trigger 2nd m-mode handler + +// - set mepc to finish + +// - clear mstatus.mpie + +// - mret to finish + +////////////////// + +////////////////// +// level-02 settings +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MTIMER_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 RVMODEL_CLEAR_MSW_INT +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",level-02) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test level-02\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END + diff --git a/riscv-test-suite/rv32i_m/Smclint/src/level-03.S b/riscv-test-suite/rv32i_m/Smclint/src/level-03.S new file mode 100644 index 000000000..2adb85582 --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/level-03.S @@ -0,0 +1,516 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: verify interrupt level order, 2 interrupts asserted in 1st interrupt handler, mtvec.mode=vectored +// - enable mie CSR + +// - generate interrupt 1 + +// - enable mstatus.mie + +// - trigger vectored m-mode handler + +// - generate interrupt 2 (both interrupts now pending) + +// - set mstatus.mie + +// - trigger 2nd vectored m-mode handler + +// - set mepc to finish + +// - clear mstatus.mpie + +// - mret to finish + +////////////////// + +////////////////// +// level-03 settings +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 1 +#endif +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 RVMODEL_SET_MTIMER_INT +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 RVMODEL_CLEAR_MTIMER_INT +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",level-03) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test level-03\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END + diff --git a/riscv-test-suite/rv32i_m/Smclint/src/level-04.S b/riscv-test-suite/rv32i_m/Smclint/src/level-04.S new file mode 100644 index 000000000..43d6b9365 --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/level-04.S @@ -0,0 +1,516 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: verify interrupt level order, swap 2 interrupt order, mtvec.mode=vectored +// - enable mie CSR + +// - generate interrupt 1 + +// - enable mstatus.mie + +// - trigger vectored m-mode handler + +// - generate interrupt 2 (both interrupts now pending) + +// - set mstatus.mie + +// - trigger 2nd vectored m-mode handler + +// - set mepc to finish + +// - clear mstatus.mpie + +// - mret to finish + +////////////////// + +////////////////// +// level-04 settings +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 1 +#endif +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MTIMER_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 RVMODEL_CLEAR_MSW_INT +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",level-04) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test level-04\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END + diff --git a/riscv-test-suite/rv32i_m/Smclint/src/msw-01.S b/riscv-test-suite/rv32i_m/Smclint/src/msw-01.S new file mode 100644 index 000000000..9f087747f --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/msw-01.S @@ -0,0 +1,513 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: tests if RVMODEL_SET_MSW_INT is working, hangs in infinite loop otherwise +// - enable mie CSR + +// - generate interrupt + +// - enable mstatus.mie + +// - trigger m-mode handler + +// - clear interrupt + +// - set mepc to finish + +// - mret to finish + +////////////////// + +////////////////// +// msw-01 settings +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE MIE_MSIE +#endif +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 RVMODEL_CLEAR_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 +#endif +#ifndef RVMODEL_WFI + #define RVMODEL_WFI inf_loop: j inf_loop; +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",msw-01) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test msw-01\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END + diff --git a/riscv-test-suite/rv32i_m/Smclint/src/mtimer-01.S b/riscv-test-suite/rv32i_m/Smclint/src/mtimer-01.S new file mode 100644 index 000000000..598ea7095 --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/mtimer-01.S @@ -0,0 +1,510 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: tests if RVMODEL_SET_MTIMER_INT is working, hangs in infinite loop otherwise +// - enable mie CSR + +// - generate interrupt + +// - enable mstatus.mie + +// - trigger m-mode handler + +// - clear interrupt + +// - set mepc to finish + +// - mret to finish + +////////////////// + +////////////////// +// mtimer-01 settings +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MTIMER_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 RVMODEL_CLEAR_MTIMER_INT +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 +#endif +#ifndef RVMODEL_WFI + #define RVMODEL_WFI inf_loop: j inf_loop; +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",mtimer-01) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test mtimer-01\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END + diff --git a/riscv-test-suite/rv32i_m/Smclint/src/nomint-01.S b/riscv-test-suite/rv32i_m/Smclint/src/nomint-01.S new file mode 100644 index 000000000..b7733ae62 --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/nomint-01.S @@ -0,0 +1,507 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: expect interrupts will not trigger in m-mode unless mstatus.mie is set +// - enable mie + +// - generate interrupts + +// - nop + +// - jump to finish + +////////////////// + +////////////////// +// nomint-01 settings +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE 0 +#endif +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 RVMODEL_SET_MTIMER_INT +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 RVMODEL_CLEAR_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 RVMODEL_CLEAR_MTIMER_INT +#endif +#ifndef RVMODEL_WFI + #define RVMODEL_WFI nop +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",nomint-01) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test nomint-01\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END + diff --git a/riscv-test-suite/rv32i_m/Smclint/src/nomint-02.S b/riscv-test-suite/rv32i_m/Smclint/src/nomint-02.S new file mode 100644 index 000000000..6ef844dcf --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/nomint-02.S @@ -0,0 +1,507 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: expect interrupts will not trigger in m-mode unless mie.x is set +// - generate interrupts + +// - enable mstatus.mie + +// - nop + +// - jump to finish + +////////////////// + +////////////////// +// nomint-02 settings +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE 0 +#endif +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 RVMODEL_SET_MTIMER_INT +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 RVMODEL_CLEAR_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 RVMODEL_CLEAR_MTIMER_INT +#endif +#ifndef RVMODEL_WFI + #define RVMODEL_WFI nop +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",nomint-02) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test nomint-02\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END + diff --git a/riscv-test-suite/rv32i_m/Smclint/src/vectored-01.S b/riscv-test-suite/rv32i_m/Smclint/src/vectored-01.S new file mode 100644 index 000000000..bbe042bfb --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/vectored-01.S @@ -0,0 +1,519 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: trigger, clear, retrigger single interrupt, vectored-mode. +// - enable mie CSR + +// - generate interrupt + +// - enable mstatus.mie + +// - trigger vectored m-mode handler + +// - clear 1st interrupt + +// - generate interrupt + +// - trigger 2nd vectored m-mode handler + +// - clear 2nd interrupt + +// - set mepc to finish + +// - mret to finish + +////////////////// + +////////////////// +// vectored-01 settings +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE MIE_MSIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 1 +#endif +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 RVMODEL_CLEAR_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 RVMODEL_CLEAR_MSW_INT +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",vectored-01) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test vectored-01\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END + diff --git a/riscv-test-suite/rv32i_m/Smclint/src/vectored-02.S b/riscv-test-suite/rv32i_m/Smclint/src/vectored-02.S new file mode 100644 index 000000000..a1fe392df --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/vectored-02.S @@ -0,0 +1,523 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: trigger, clear, retrigger single interrupt, no 2nd clear. +// Stimulates pending interrupt after setting mstatus.mpie followed by mret, vectored-mode. + +// mstatus.mie should be cleared after mret so pending interrupt is not taken + +// - enable mie CSR + +// - generate interrupt + +// - enable mstatus.mie + +// - trigger vectored m-mode handler + +// - clear 1st interrupt + +// - generate interrupt + +// - trigger 2nd vectored m-mode handler + +// - set mepc to finish + +// - clear mstatus.mpie + +// - mret to finish + +////////////////// + +////////////////// +// vectored-02 settings +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE MIE_MSIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 1 +#endif +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 RVMODEL_CLEAR_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",vectored-02) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test vectored-02\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END + diff --git a/riscv-test-suite/rv32i_m/Smclint/src/wfi-01.S b/riscv-test-suite/rv32i_m/Smclint/src/wfi-01.S new file mode 100644 index 000000000..87ab2b187 --- /dev/null +++ b/riscv-test-suite/rv32i_m/Smclint/src/wfi-01.S @@ -0,0 +1,509 @@ +// ----------- +// Copyright (c) 2023. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// +////////////////// +// Description: expect wfi to behave like a nop when a single interrupt is pending when mstatus.mie is disabled +// - enable mie CSR + +// - generate interrupts + +// - wfi + +// - wakeup + +// - jump to finish + +////////////////// + +////////////////// +// wfi-01 settings +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE 0 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE MIE_MSIE +#endif +#ifndef RVMODEL_SET_INT1 + #define RVMODEL_SET_INT1 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_SET_INT2 + #define RVMODEL_SET_INT2 RVMODEL_SET_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT1 + #define RVMODEL_CLEAR_INT1 RVMODEL_CLEAR_MSW_INT +#endif +#ifndef RVMODEL_CLEAR_INT2 + #define RVMODEL_CLEAR_INT2 RVMODEL_CLEAR_MSW_INT +#endif + +#include "model_test.h" +#include "arch_test.h" + +///////////////// +// Default msw/mtimer setup. overwrite defaults in model_test.h if necessary. +#ifndef RVMODEL_MCLINTBASE + #define RVMODEL_MCLINTBASE 0x02000000 +#endif + +#ifndef RVMODEL_MSIP_OFFSET + #define RVMODEL_MSIP_OFFSET 0x0 +#endif + +#ifndef RVMODEL_MTIMECMP_OFFSET + #define RVMODEL_MTIMECMP_OFFSET 0x4000 +#endif + +#ifndef RVMODEL_MTIMECMPH_OFFSET + #define RVMODEL_MTIMECMPH_OFFSET 0x4004 +#endif + +#ifndef RVMODEL_SET_MSW_INT +#define RVMODEL_SET_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + li t1, 1; \ + sw t1, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MSW_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MSIP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_SET_MTIMER_INT +#define RVMODEL_SET_MTIMER_INT \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw x0, (t0); \ + +#endif + +#ifndef RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MTIMER_INT \ + addi t1,x0,1; \ + neg t1,t1; \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMPH_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + lui t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET)>> 12); \ + addi t0, t0, ((RVMODEL_MCLINTBASE + RVMODEL_MTIMECMP_OFFSET) & 0xFFF); \ + sw t1, (t0); \ + +#endif + +////////////////// +// test general defaults +#ifndef RVMODEL_WFI + #define RVMODEL_WFI wfi +#endif +#ifndef RVMODEL_CLEAR_ALL_INTS + #define RVMODEL_CLEAR_ALL_INTS \ + RVMODEL_CLEAR_MSW_INT \ + RVMODEL_CLEAR_MTIMER_INT +#endif + +#ifndef RVMODEL_MSTATUS_MIE + #define RVMODEL_MSTATUS_MIE MSTATUS_MIE +#endif +// MIE_MSIE, MIE_MTIE +#ifndef MIE_MSIE + #define MIE_MSIE 0x8 +#endif +#ifndef MIE_MTIE + #define MIE_MTIE 0x80 +#endif +#ifndef RVMODEL_SET_MIE + #define RVMODEL_SET_MIE (MIE_MSIE | MIE_MTIE) +#endif +#ifndef RVMODEL_CLEAR_MSTATUS_MPIE + #define RVMODEL_CLEAR_MSTATUS_MPIE MSTATUS_MPIE +#endif +#ifndef RVMODEL_MTVEC_MODE + #define RVMODEL_MTVEC_MODE 0 +#endif +#ifndef RVMODEL_MSTATUS_MASK + #define RVMODEL_MSTATUS_MASK (MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPP) +#endif +#ifndef RVMODEL_MIP_MASK + #define RVMODEL_MIP_MASK RVMODEL_SET_MIE +#endif +// implementations without s-mode will not have mideleg CSR. +// most implementations and SAIL model probably currently reset midelg to 0 +// implementations with s-mode and mideleg.msi/mti uninitializsed or set to 1 will need to +// initialize mideleg.msi/mti to 0 +// e.g. #define RVMODEL_INITIALIZE_MIDELEG LI(t0,RVMODEL_SET_MIE);csrrc x0,CSR_MIDELEG,t0; +#ifndef RVMODEL_INITIALIZE_MIDELEG + #define RVMODEL_INITIALIZE_MIDELEG +#endif +#ifndef RVMODEL_ECALL + #define RVMODEL_ECALL +#endif + + + +RVTEST_ISA("RV32I_Zicsr") + +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +RVTEST_SIGBASE( a1,signature_a1_m) // a1 will point to signature_a1_m label in the signature region - m-mode + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*Smclint.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",wfi-01) + # --------------------------------------------------------------------------------------------- + LA( t0,first_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrrw s1,CSR_MTVEC, t0 ; // mtvec used by arch_test.h, restore at end of test_case + + LI( t0,0x55555555) + csrrw s2,CSR_MSCRATCH, t0 ; // mscratch used by arch_test.h, restore at end of test_case + + // make sure platform irqs, e.g. mtimer irq, is cleared before starting test + RVMODEL_CLEAR_ALL_INTS + + LI( t0,RVMODEL_SET_MIE) + csrw CSR_MIE, t0 + + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_INITIALIZE_MIDELEG + + RVMODEL_SET_INT1 + + fence; // ensure memory mapped registers are setup + + LI( t0,RVMODEL_MSTATUS_MIE) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode +location_1: + + RVMODEL_WFI + + j finish + + + .align 2 + .global direct_mtvec_handler +direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_1) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,first_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + LA( t0,second_mtvec_handler) + ori t0, t0, RVMODEL_MTVEC_MODE + csrw CSR_MTVEC, t0 + + RVMODEL_CLEAR_INT1 + RVMODEL_SET_INT2 + fence; // ensure memory mapped registers are setup + + RVMODEL_ECALL + + LI( t0,MSTATUS_MIE ) + csrrs x0, CSR_MSTATUS, t0; // enable global interrupts in m-mode + ; // CLINT will nest +location_2: + + LA( t0,finish) + csrw CSR_MEPC, t0 + LI( t0,RVMODEL_CLEAR_MSTATUS_MPIE) + csrrc x0, CSR_MSTATUS, t0; // by default, clear previous global interrupts + LI( t0,MSTATUS_MPP ) + csrrs x0, CSR_MSTATUS, t0; // force return to m-mode + mret + + .align 2 + .global second_direct_mtvec_handler +second_direct_mtvec_handler: + + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSTATUS + LI( t1,RVMODEL_MSTATUS_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MEPC + LA( t1,location_2) + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVAL + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MSCRATCH + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIP + LI( t1,RVMODEL_MIP_MASK) + and t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MIE + RVTEST_SIGUPD( a1,t0) + csrr t0, CSR_MTVEC + LA( t1,second_mtvec_handler) + ori t1, t1, RVMODEL_MTVEC_MODE + sub t0, t0, t1 + RVTEST_SIGUPD( a1,t0) + + RVMODEL_CLEAR_INT2 + fence; // ensure memory mapped registers are setup + + LA( t0,finish) + csrw CSR_MEPC, t0 + + LI( t0,MSTATUS_MPIE ) + csrrc x0, CSR_MSTATUS, t0; // clear mstatus.mpie to disable global interrupts after mret + mret + + .align 2 + .global first_mtvec_handler +first_mtvec_handler: + j direct_mtvec_handler + .align 2 + j vectored_mtvec_handler1 + .align 2 + j vectored_mtvec_handler2 + .align 2 + j vectored_mtvec_handler3 + .align 2 + j vectored_mtvec_handler4 + .align 2 + j vectored_mtvec_handler5 + .align 2 + j vectored_mtvec_handler6 + .align 2 + j vectored_mtvec_handler7 + .align 2 + j vectored_mtvec_handler8 + .align 2 + j vectored_mtvec_handler9 + .align 2 + j vectored_mtvec_handler10 + .align 2 + j vectored_mtvec_handler11 + .align 2 + j vectored_mtvec_handler12 + .align 2 + j vectored_mtvec_handler13 + .align 2 + j vectored_mtvec_handler14 + .align 2 + j vectored_mtvec_handler15 + .align 2 + + .align 2 +vectored_mtvec_handler1: + li t0, 1 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler2: + li t0, 2 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler3: + li t0, 3 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler4: + li t0, 4 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler5: + li t0, 5 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler6: + li t0, 6 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler7: + li t0, 7 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler8: + li t0, 8 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler9: + li t0, 9 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler10: + li t0, 10 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler11: + li t0, 11 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler12: + li t0, 12 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler13: + li t0, 13 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler14: + li t0, 14 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 +vectored_mtvec_handler15: + li t0, 15 + RVTEST_SIGUPD( a1,t0) + j direct_mtvec_handler + + .align 2 + .global second_mtvec_handler +second_mtvec_handler: + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + j second_direct_mtvec_handler + .align 2 + +finish: + csrr t0, CSR_MCAUSE + RVTEST_SIGUPD( a1,t0) + + csrw CSR_MTVEC, s1; // restore CSR_MTVEC + csrw CSR_MSCRATCH, s2; // restore CSR_MSCRATCH + + RVMODEL_IO_WRITE_STR(x30, "# Test part A - test wfi-01\n"); + + RVMODEL_IO_WRITE_STR(x30, "# Test End\n") + + +#endif + + # --------------------------------------------------------------------------------------------- + +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +# Input data section. + .data + .align 4 + +RVTEST_DATA_END + +# Output data section. +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +signature_a1_m: + .fill 32*(XLEN/32),4,0xdeadbeef + +sig_begin_canary: +CANARY; +test_A_res: + .fill 2, 4, 0xdeadbeef + +#ifdef rvtest_mtrap_routine +mtrap_sigptr: + .fill 4, 4, 0xdeadbeef +#endif + +#ifdef rvtest_gpr_save +gpr_save: + .fill 32*(XLEN/32), 4, 0xdeadbeef +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END +