rvcpp: implement MPRV, and fix up CSR write tracing
This commit is contained in:
parent
877c6aa5ee
commit
e34aa5bb45
|
@ -114,6 +114,8 @@ public:
|
|||
return priv;
|
||||
}
|
||||
|
||||
uint get_effective_priv();
|
||||
|
||||
bool get_mstatus_tw() {
|
||||
return mstatus & 0x00200000u;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue