rvcpp: implement MPRV, and fix up CSR write tracing

This commit is contained in:
Luke Wren 2024-06-02 12:46:41 +01:00
parent 877c6aa5ee
commit e34aa5bb45
3 changed files with 34 additions and 19 deletions

View File

@ -114,6 +114,8 @@ public:
return priv;
}
uint get_effective_priv();
bool get_mstatus_tw() {
return mstatus & 0x00200000u;
}

View File

@ -146,7 +146,6 @@ void RVCore::step(bool trace) {
uint regnum_rd = 0;
std::optional<ux_t> trace_csr_addr;
std::optional<ux_t> trace_csr_result;
std::optional<uint> trace_priv;
std::optional<uint16_t> fetch0 = r16(pc, 0x4u);
@ -571,6 +570,8 @@ void RVCore::step(bool trace) {
if (write_op == RVCSR::WRITE || regnum_rs1 != 0) {
if (!csr.write(csr_addr, rs1, write_op)) {
exception_cause = XCAUSE_INSTR_ILLEGAL;
} else if (trace) {
trace_csr_addr = csr_addr;
}
}
}
@ -582,17 +583,12 @@ void RVCore::step(bool trace) {
if (!rd_wdata) {
exception_cause = XCAUSE_INSTR_ILLEGAL;
}
if (trace && !exception_cause) {
trace_csr_addr = csr_addr;
}
}
if (write_op == RVCSR::WRITE || regnum_rs1 != 0) {
if (!csr.write(csr_addr, regnum_rs1, write_op)) {
exception_cause = XCAUSE_INSTR_ILLEGAL;
}
if (trace && !exception_cause) {
} else if (trace) {
trace_csr_addr = csr_addr;
trace_csr_result = csr.read(csr_addr, false);
}
}
} else if (RVOPC_MATCH(instr, MRET)) {
@ -891,6 +887,9 @@ void RVCore::step(bool trace) {
}
}
// Ensure pending CSR writes are applied before checking IRQ conditions,
// and before reading back the CSR value for tracing
csr.step();
if (trace && !irq_target_pc) {
printf("%08x: ", pc);
@ -910,14 +909,11 @@ void RVCore::step(bool trace) {
if (pc_wdata && gpr_writeback) {
printf(" : pc <- %08x <\n", *pc_wdata);
}
if (trace_csr_result) {
printf(" : #%03x <- %08x :\n", *trace_csr_addr, *trace_csr_result);
if (trace_csr_addr) {
printf(" : #%03x <- %08x :\n", *trace_csr_addr, *csr.read(*trace_csr_addr, false));
}
}
// Ensure pending CSR writes are applied before checking IRQ conditions
csr.step();
if (exception_cause) {
pc_wdata = csr.trap_enter_exception(*exception_cause, pc);
if (trace) {

View File

@ -224,8 +224,11 @@ ux_t RVCSR::trap_enter(uint xcause, ux_t xepc) {
mstatus = (mstatus & ~MSTATUS_MPP) | (priv << 11);
priv = PRV_M;
if (mstatus & MSTATUS_MIE)
if (mstatus & MSTATUS_MIE) {
mstatus |= MSTATUS_MPIE;
} else {
mstatus &= ~MSTATUS_MPIE;
}
mstatus &= ~MSTATUS_MIE;
mcause = xcause;
@ -241,16 +244,28 @@ ux_t RVCSR::trap_enter(uint xcause, ux_t xepc) {
ux_t RVCSR::trap_mret() {
priv = GETBITS(mstatus, 12, 11);
mstatus &= ~MSTATUS_MPP;
if (priv != PRV_M)
if (priv != PRV_M) {
mstatus &= ~MSTATUS_MPRV;
}
if (mstatus & MSTATUS_MPIE)
if (mstatus & MSTATUS_MPIE) {
mstatus |= MSTATUS_MIE;
mstatus &= ~MSTATUS_MPIE;
} else {
mstatus &= ~MSTATUS_MIE;
}
mstatus |= MSTATUS_MPIE;
return mepc;
}
uint RVCSR::get_effective_priv() {
if (mstatus & MSTATUS_MPRV) {
return (mstatus & MSTATUS_MPP) >> __builtin_ctz(MSTATUS_MPP);
} else {
return priv;
}
}
int RVCSR::get_pmp_match(ux_t addr) {
for (int i = 0; i < PMP_REGIONS; ++i) {
if (pmpcfg_a(i) == 0u) {
@ -284,13 +299,15 @@ uint RVCSR::get_pmp_xwr(ux_t addr) {
matching_l = pmpcfg_l(region);
}
if (match) {
// TODO MPRV
if (get_true_priv() == PRV_M && !matching_l) {
if (get_effective_priv() == PRV_M && !matching_l) {
return 0x7u;
} else if (get_true_priv() == PRV_M && !matching_l) {
return matching_xwr | PMP_X;
} else {
return matching_xwr;
}
} else {
return get_true_priv() == PRV_M ? 0x7u : 0x0u;
return get_effective_priv() == PRV_M ? 0x7u :
get_true_priv() == PRV_M ? PMP_X : 0x0u;
}
}