From b5c8c9a1693b6cfcecd1c8449ca257c6e9b9c444 Mon Sep 17 00:00:00 2001 From: "Xu, Zefan" Date: Wed, 10 Jul 2024 22:36:57 +0800 Subject: [PATCH] CSR: add switch for cycle, instret and htimedelta As old CSR module of XiangShan does not support any unpriv counter, it's better to add switch of unpriv counter in NEMU. Also, openSBI asks that time and htimedelta should either implemented or both unimplemented. This patch add some marco to meet this. --- configs/riscv64-xs-ref_defconfig | 10 ++++++---- src/isa/riscv64/Kconfig | 28 +++++++++++++++++++++++++-- src/isa/riscv64/local-include/csr.h | 30 +++++++++++++++++++++++++---- src/isa/riscv64/system/priv.c | 14 +++++++++----- 4 files changed, 67 insertions(+), 15 deletions(-) diff --git a/configs/riscv64-xs-ref_defconfig b/configs/riscv64-xs-ref_defconfig index 5d00e0d43..5ae97fcea 100644 --- a/configs/riscv64-xs-ref_defconfig +++ b/configs/riscv64-xs-ref_defconfig @@ -22,11 +22,13 @@ CONFIG_RVV=y CONFIG_RV_DEBUG=y CONFIG_RVH=y # CONFIG_RV_SDEXT is not set -CONFIG_RV_SDTRIG=y +# CONFIG_RV_SDTRIG is not set CONFIG_TRIGGER_NUM=4 CONFIG_RV_ZICNTR=y +# CONFIG_RV_CSR_CYCLE is not set # CONFIG_RV_CSR_TIME is not set -CONFIG_RV_ZIHPM=y +# CONFIG_RV_CSR_INSTRET is not set +# CONFIG_RV_ZIHPM is not set CONFIG_RV_CSR_MCOUNTINHIBIT=y CONFIG_RV_CSR_MCOUNTINHIBIT_CNTR=y CONFIG_RV_CSR_MCOUNTINHIBIT_HPM=y @@ -39,8 +41,8 @@ CONFIG_RV_PMP_ACTIVE_NUM=16 CONFIG_PMP_GRANULARITY=12 CONFIG_RV_PMP_CHECK=y CONFIG_RV_SVINVAL=y -CONFIG_RV_SSCOFPMF=y -CONFIG_RV_SMSTATEEN=y +# CONFIG_RV_SSCOFPMF is not set +# CONFIG_RV_SMSTATEEN is not set CONFIG_MISA_UNCHANGEABLE=y CONFIG_XTVEC_VECTORED_MODE=y # CONFIG_TVAL_EX_II is not set diff --git a/src/isa/riscv64/Kconfig b/src/isa/riscv64/Kconfig index 9e30e63d7..0866d6b2b 100644 --- a/src/isa/riscv64/Kconfig +++ b/src/isa/riscv64/Kconfig @@ -69,15 +69,39 @@ menuconfig RV_ZICNTR INFO: the CPI (cycles per instruction) of NEMU is set to 1. if RV_ZICNTR +config RV_CSR_CYCLE + bool "Implement CSR cycle (0xc00)" + default n + help + If n, accessing to CSR cycle will raise illegal instruction exception. + + Regardless of how this option is set, the TM bit of m/h/scounteren is + always writable to allow machine-level programs to simulate reading the + cycle register. + config RV_CSR_TIME bool "Implement CSR time (0xc01)" default n help If n, accessing to CSR time will raise illegal instruction exception. + If n, accessing to CSR htimedelta will also raise illegal instruction. + Either both time and htimedelta are implemented by hardware, or access + to both time and htimedelta traps into M-mode for emulation. + + Regardless of how this option is set, the TM bit of m/h/scounteren is + always writable to allow machine-level programs to simulate reading the + time register. + +config RV_CSR_INSTRET + bool "Implement CSR instret (0xc02)" + default n + help + If n, accessing to CSR instret will raise illegal instruction exception. + Regardless of how this option is set, the TM bit of m/h/scounteren is - always writable to allow machine programs to simulate reading the time - register. + always writable to allow machine-level programs to simulate reading the + instret register. endif # RV_ZICNTR diff --git a/src/isa/riscv64/local-include/csr.h b/src/isa/riscv64/local-include/csr.h index 07043279b..60325c6e3 100644 --- a/src/isa/riscv64/local-include/csr.h +++ b/src/isa/riscv64/local-include/csr.h @@ -36,6 +36,13 @@ #endif // CONFIG_FPU_NONE /** Unprivileged Counter/Timers **/ +#ifdef CONFIG_RV_CSR_CYCLE + #define CSRS_UNPRIV_CYCLE(f) \ + f(cycle , 0xC00) +#else // CONFIG_RV_CSR_CYCLE + #define CSRS_UNPRIV_CYCLE(f) +#endif // CONFIG_RV_CSR_CYCLE + #ifdef CONFIG_RV_CSR_TIME #define CSRS_UNPRIV_TIME(f) \ f(csr_time , 0xC01) @@ -43,11 +50,18 @@ #define CSRS_UNPRIV_TIME(f) #endif // CONFIG_RV_CSR_TIME +#ifdef CONFIG_RV_CSR_INSTRET + #define CSRS_UNPRIV_INSTRET(f) \ + f(instret , 0xC02) +#else // CONFIG_RV_CSR_INSTRET + #define CSRS_UNPRIV_INSTRET(f) +#endif // CONFIG_RV_CSR_INSTRET + #ifdef CONFIG_RV_ZICNTR #define CSRS_UNPRIV_CNTR(f) \ - f(cycle , 0xC00) \ + CSRS_UNPRIV_CYCLE(f) \ CSRS_UNPRIV_TIME(f) \ - f(instret , 0xC02) + CSRS_UNPRIV_INSTRET(f) // There is `time_t` type in the C programming language. // So We have to use another name for CSR time. #else // CONFIG_RV_ZICNTR @@ -207,8 +221,12 @@ #endif // CONFIG_RV_SDTRIG /** Hypervisor Counter/Timer Virtualization Registers **/ - #define CSRS_H_CONUTER_TIMER_VIRTUALIZATION(f) \ - f(htimedelta , 0x605) + #ifdef CONFIG_RV_CSR_TIME + #define CSRS_H_CONUTER_TIMER_VIRTUALIZATION(f) \ + f(htimedelta , 0x605) + #else // CONFIG_RV_CSR_TIME + #define CSRS_H_CONUTER_TIMER_VIRTUALIZATION(f) + #endif /** Hypervisor State Enable Registers **/ #ifdef CONFIG_RV_SMSTATEEN @@ -1176,16 +1194,20 @@ void set_mask(uint32_t reg, int idx, uint64_t mask, uint64_t vsew, uint64_t vlmu #endif // CONFIG_RVV #ifdef CONFIG_RV_ZICNTR +#ifdef CONFIG_RV_CSR_CYCLE CSR_STRUCT_START(cycle) CSR_STRUCT_END(cycle) +#endif // CONFIG_RV_CSR_CYCLE #ifdef CONFIG_RV_CSR_TIME CSR_STRUCT_START(csr_time) CSR_STRUCT_END(csr_time) #endif // CONFIG_RV_CSR_TIME +#ifdef CONFIG_RV_CSR_INSTRET CSR_STRUCT_START(instret) CSR_STRUCT_END(instret) +#endif // CONFIG_RV_CSR_INSTRET #endif // CONFIG_RV_ZICNTR #ifdef CONFIG_RV_ZIHPM diff --git a/src/isa/riscv64/system/priv.c b/src/isa/riscv64/system/priv.c index 019942fc3..415d27b68 100644 --- a/src/isa/riscv64/system/priv.c +++ b/src/isa/riscv64/system/priv.c @@ -456,23 +456,27 @@ if (is_read(vsie)) { return (mie->val & (hideleg->val & (mideleg->val return get_minstret(); } #ifdef CONFIG_RV_ZICNTR - else if (is_read(cycle)) { - // NEMU emulates a hart with CPI = 1. - difftest_skip_ref(); - return get_mcycle(); - } + #ifdef CONFIG_RV_CSR_CYCLE + else if (is_read(cycle)) { + // NEMU emulates a hart with CPI = 1. + difftest_skip_ref(); + return get_mcycle(); + } + #endif // CONFIG_RV_CSR_CYCLE #ifdef CONFIG_RV_CSR_TIME else if (is_read(csr_time)) { difftest_skip_ref(); return clint_uptime(); } #endif // CONFIG_RV_CSR_TIME + #ifdef CONFIG_RV_CSR_INSTRET else if (is_read(instret)) { // The number of retired instruction should be the same between dut and ref. // But instruction counter of NEMU is not accurate when enabling Performance optimization. difftest_skip_ref(); return get_minstret(); } + #endif // CONFIG_RV_CSR_INSTRET #endif // CONFIG_RV_ZICNTR #ifndef CONFIG_RVH if (is_read(mip)) { difftest_skip_ref(); }