Implement counteren (1.10+ spec)

This commit is contained in:
Dolu1990 2023-03-23 08:53:10 +01:00
parent 570720fdd8
commit b01490b5f3
5 changed files with 432 additions and 2 deletions

View File

@ -215,6 +215,7 @@ object Riscv{
def MINSTRET = 0xB02 // MRW Machine instructions-retired counter. def MINSTRET = 0xB02 // MRW Machine instructions-retired counter.
def MCYCLEH = 0xB80 // MRW Upper 32 bits of mcycle, RV32I only. def MCYCLEH = 0xB80 // MRW Upper 32 bits of mcycle, RV32I only.
def MINSTRETH = 0xB82 // MRW Upper 32 bits of minstret, RV32I only. def MINSTRETH = 0xB82 // MRW Upper 32 bits of minstret, RV32I only.
val MCOUNTEREN = 0x306
val SSTATUS = 0x100 val SSTATUS = 0x100
val SIE = 0x104 val SIE = 0x104

View File

@ -1058,6 +1058,28 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
utimeAccess(CSR.UTIMEH, utime(63 downto 32)) utimeAccess(CSR.UTIMEH, utime(63 downto 32))
} }
class Xcounteren(csrId : Int) extends Area{
val IR,TM,CY = RegInit(True) //For backward compatibility
if(ucycleAccess != CsrAccess.NONE) rw(csrId, 0 -> CY)
if(utimeAccess != CsrAccess.NONE) rw(csrId, 1 -> TM)
if(uinstretAccess != CsrAccess.NONE) rw(csrId, 2 -> IR)
}
def xcounterChecks(access : CsrAccess, csrId : Int, enable : Xcounteren => Bool) = {
if(access != CsrAccess.NONE) during(csrId){
if(userGen) when(privilege < 3 && !enable(mcounteren)){ forceFailCsr() }
if(supervisorGen) when(privilege < 1 && !enable(scounteren)){ forceFailCsr() }
}
}
val mcounteren = userGen generate new Xcounteren(CSR.MCOUNTEREN)
val scounteren = supervisorGen generate new Xcounteren(CSR.SCOUNTEREN)
xcounterChecks(ucycleAccess , CSR.UCYCLE , _.CY)
xcounterChecks(ucycleAccess , CSR.UCYCLEH , _.CY)
xcounterChecks(utimeAccess , CSR.UTIME , _.TM)
xcounterChecks(utimeAccess , CSR.UTIMEH , _.TM)
xcounterChecks(uinstretAccess, CSR.UINSTRET , _.IR)
xcounterChecks(uinstretAccess, CSR.UINSTRETH, _.IR)
pipeline(MPP) := mstatus.MPP pipeline(MPP) := mstatus.MPP
} }

View File

@ -1,6 +1,10 @@
.globl _star .globl _star
#define TEST_ID x28 #define TEST_ID x28
#include "privileged.h"
_start: _start:
la x1, fail la x1, fail
csrw mtvec, x1 csrw mtvec, x1
@ -18,12 +22,15 @@ test1:
csrr x2, stvec csrr x2, stvec
bnez x2, fail bnez x2, fail
la x1, fail
csrw mtvec, x1
li x1, 9 li x1, 9
csrw mcause, x1 csrw mcause, x1
csrr x2, mcause csrr x2, mcause
bne x2, x1, fail bne x2, x1, fail
csrr x0, pmpcfg0 /*csrr x0, pmpcfg0
csrw pmpcfg0, x0 csrw pmpcfg0, x0
csrr x0, pmpcfg3 csrr x0, pmpcfg3
@ -33,7 +40,154 @@ test1:
csrw pmpaddr0, x0 csrw pmpaddr0, x0
csrr x0, pmpaddr15 csrr x0, pmpaddr15
csrw pmpaddr15, x0 csrw pmpaddr15, x0*/
li TEST_ID, 2
csrr x1, mcycle
csrr x2, mcycle
bge x1, x2, fail
csrr x1, minstret
csrr x2, minstret
bge x1, x2, fail
csrr x1, cycle
csrr x2, cycle
bge x1, x2, fail
csrr x1, instret
csrr x2, instret
bge x1, x2, fail
csrr x1, time
csrr x2, time
bge x1, x2, fail
//Test access to counters in supervisor
machine_setup_trap
machine_to_supervisor
li TEST_ID, 3
csrr x1, cycle
csrr x2, cycle
bge x1, x2, fail
csrr x1, instret
csrr x2, instret
bge x1, x2, fail
csrr x1, time
csrr x2, time
bge x1, x2, fail
ecall
machine_handle_trap
//Test access to counters in user
machine_setup_trap
machine_to_user
li TEST_ID, 4
csrr x1, cycle
csrr x2, cycle
bge x1, x2, fail
csrr x1, instret
csrr x2, instret
bge x1, x2, fail
csrr x1, time
csrr x2, time
bge x1, x2, fail
ecall
machine_handle_trap
//Remove user access to counters
li x1, -1
csrw mcounteren, x1
li x1, 0
csrw scounteren, x1
machine_setup_trap
machine_to_supervisor
li TEST_ID, 3
csrr x1, cycle
csrr x2, cycle
bge x1, x2, fail
csrr x1, instret
csrr x2, instret
bge x1, x2, fail
csrr x1, time
csrr x2, time
bge x1, x2, fail
ecall
machine_handle_trap
machine_setup_trap
machine_to_user
csrr x1, cycle
j fail
machine_handle_trap
machine_setup_trap
machine_to_user
csrr x1, instret
j fail
machine_handle_trap
machine_setup_trap
machine_to_user
csrr x1, time
j fail
machine_handle_trap
//Remove supervisor access to counters
li x1, 0
csrw mcounteren, x1
li x1, -1
csrw scounteren, x1
machine_setup_trap
machine_to_supervisor
csrr x1, cycle
j fail
machine_handle_trap
machine_setup_trap
machine_to_supervisor
csrr x1, instret
j fail
machine_handle_trap
machine_setup_trap
machine_to_supervisor
csrr x1, time
j fail
machine_handle_trap
machine_setup_trap
machine_to_user
csrr x1, cycle
j fail
machine_handle_trap
machine_setup_trap
machine_to_user
csrr x1, instret
j fail
machine_handle_trap
machine_setup_trap
machine_to_user
csrr x1, time
j fail
machine_handle_trap
j pass j pass

View File

@ -0,0 +1,159 @@
#pragma once
#include "riscv_asm.h"
#define trap_setup \
la x1, 1f; \
csrw mtvec, x1; \
addi x1, x1, 0x123; \
csrw mtval, x1; \
#define trap_handle \
j fail; \
j fail; \
j fail; \
j fail; \
.align 4; \
1: \
csrr x1, mepc; \
csrr x1, mcause; \
csrr x1, mstatus; \
csrr x1, mtval; \
csrr x1, mip; \
#define trap_handle_setup \
trap_handle \
trap_setup \
#define supervisor_read \
csrr x1, sepc; \
csrr x1, scause; \
csrr x1, sstatus; \
csrr x1, stval; \
csrr x1, sip;
#define machine_read \
csrr x1, mepc; \
csrr x1, mcause; \
csrr x1, mstatus; \
csrr x1, mtval; \
csrr x1, mip; \
supervisor_read
#define user_read
#define machine_to_supervisor \
la x1,1f ;\
csrw mepc, x1 ;\
li x1, MSTATUS_MPP_SUPERVISOR ;\
csrw mstatus, x1 ;\
mret ;\
j fail ;\
j fail ;\
j fail ;\
j fail ;\
1: ;\
supervisor_read
#define machine_to_supervisor_x1 \
csrw mepc, x1 ;\
li x1, MSTATUS_MPP_SUPERVISOR ;\
csrw mstatus, x1 ;\
mret ;\
j fail ;\
j fail ;\
j fail ;\
j fail ;\
#define machine_to_user \
la x1,1f ;\
csrw mepc, x1 ;\
li x1, MSTATUS_MPP_USER ;\
csrw mstatus, x1 ;\
mret ;\
j fail ;\
j fail ;\
j fail ;\
j fail ;\
1: ;\
user_read
#define machine_setup_trap \
la x1, 2f ;\
csrw mtvec,x1;
#define machine_handle_trap \
j fail ;\
.align 4 ;\
2: ;\
machine_read
#define supervisor_setup_trap \
la x1, 3f ;\
csrw stvec,x1;
#define supervisor_handle_trap \
j fail ;\
.align 4 ;\
3: ;\
supervisor_read
#define supervisor_check \
supervisor_setup_trap \
csrr x1, mstatus; \
supervisor_handle_trap \
supervisor_read
#define supervisor_external_interrupt_set \
li x1, SUPERVISOR_EXTERNAL_INTERRUPT_CTRL; \
li x2, 1; \
sw x2, 0(x1);
#define supervisor_external_interrupt_clear \
li x1, SUPERVISOR_EXTERNAL_INTERRUPT_CTRL; \
sw x0, 0(x1);
#define wait_interrupt nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;j fail;
#define delay_long nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
#define machine_enable_supervisor_external_interrupt \
li x1, 1 << CAUSE_SUPERVISOR_EXTERNAL; \
csrw mie, x1; \
li x1, MSTATUS_MIE ; \
csrw mstatus, x1 ;
#define supervisor_enable_supervisor_external_interrupt \
li x1, 1 << CAUSE_SUPERVISOR_EXTERNAL; \
csrw sie, x1; \
li x1, MSTATUS_SIE ; \
csrw sstatus, x1 ;
#define machine_trap_failure \
la x1, 1f; \
csrw mtvec, x1; \
j 4f \
1: \
nop; \
j fail; \
4:
#define supervisor_trap_failure \
la x1, 1f; \
csrw stvec, x1; \
j 4f; \
.align 4; \
1: \
nop; \
j fail; \
4:

View File

@ -0,0 +1,94 @@
#pragma once
//exceptions
#define CAUSE_ILLEGAL_INSTRUCTION 2
#define CAUSE_UCALL 8
#define CAUSE_SCALL 9
//interrupts
#define CAUSE_MACHINE_SOFTWARE 3
#define CAUSE_MACHINE_TIMER 7
#define CAUSE_MACHINE_EXTERNAL 11
#define CAUSE_SUPERVISOR_SOFTWARE 1
#define CAUSE_SUPERVISOR_TIMER 5
#define CAUSE_SUPERVISOR_EXTERNAL 9
#define MIE_MTIE (1 << CAUSE_MACHINE_TIMER)
#define MIE_MEIE (1 << CAUSE_MACHINE_EXTERNAL)
#define MIE_MSIE (1 << CAUSE_MACHINE_SOFTWARE)
#define MIE_SEIE (1 << CAUSE_SUPERVISOR_EXTERNAL)
#define MEDELEG_INSTRUCTION_PAGE_FAULT (1 << 12)
#define MEDELEG_LOAD_PAGE_FAULT (1 << 13)
#define MEDELEG_STORE_PAGE_FAULT (1 << 15)
#define MEDELEG_USER_ENVIRONNEMENT_CALL (1 << 8)
#define MIDELEG_SUPERVISOR_SOFTWARE (1 << 1)
#define MIDELEG_SUPERVISOR_TIMER (1 << 5)
#define MIDELEG_SUPERVISOR_EXTERNAL (1 << 9)
#define MSTATUS_UIE 0x00000001
#define MSTATUS_SIE 0x00000002
#define MSTATUS_HIE 0x00000004
#define MSTATUS_MIE 0x00000008
#define MSTATUS_UPIE 0x00000010
#define MSTATUS_SPIE 0x00000020
#define MSTATUS_HPIE 0x00000040
#define MSTATUS_MPIE 0x00000080
#define MSTATUS_SPP 0x00000100
#define MSTATUS_HPP 0x00000600
#define MSTATUS_MPP 0x00001800
#define MSTATUS_FS 0x00006000
#define MSTATUS_XS 0x00018000
#define MSTATUS_MPRV 0x00020000
#define MSTATUS_SUM 0x00040000
#define MSTATUS_MXR 0x00080000
#define MSTATUS_TVM 0x00100000
#define MSTATUS_TW 0x00200000
#define MSTATUS_TSR 0x00400000
#define MSTATUS32_SD 0x80000000
#define MSTATUS_UXL 0x0000000300000000
#define MSTATUS_SXL 0x0000000C00000000
#define MSTATUS64_SD 0x8000000000000000
#define MSTATUS_FS_INITIAL (1 << 13)
#define MSTATUS_FS_CLEAN (2 << 13)
#define MSTATUS_FS_DIRTY (3 << 13)
#define MSTATUS_FS_MASK (3 << 13)
#define MSTATUS_MPP_SUPERVISOR 0x00000800
#define MSTATUS_MPP_USER 0x00000000
#define SSTATUS_UIE 0x00000001
#define SSTATUS_SIE 0x00000002
#define SSTATUS_UPIE 0x00000010
#define SSTATUS_SPIE 0x00000020
#define SSTATUS_SPP 0x00000100
#define SSTATUS_FS 0x00006000
#define SSTATUS_XS 0x00018000
#define SSTATUS_SUM 0x00040000
#define SSTATUS_MXR 0x00080000
#define SSTATUS32_SD 0x80000000
#define SSTATUS_UXL 0x0000000300000000
#define SSTATUS64_SD 0x8000000000000000
#define PMP_R 0x01
#define PMP_W 0x02
#define PMP_X 0x04
#define PMP_A 0x18
#define PMP_L 0x80
#define PMP_SHIFT 2
#define PMP_TOR 0x08
#define PMP_NA4 0x10
#define PMP_NAPOT 0x18
#define RDCYCLE 0xC00 //Read-only cycle Cycle counter for RDCYCLE instruction.
#define RDTIME 0xC01 //Read-only time Timer for RDTIME instruction.
#define RDINSTRET 0xC02 //Read-only instret Instructions-retired counter for RDINSTRET instruction.
#define RDCYCLEH 0xC80 //Read-only cycleh Upper 32 bits of cycle, RV32I only.
#define RDTIMEH 0xC81 //Read-only timeh Upper 32 bits of time, RV32I only.
#define RDINSTRETH 0xC82 //Read-only instreth Upper 32 bits of instret, RV32I only.