Implement WFI in rvcpp. The umode_wfi test still does not pass, because it relies on a bug in Hazard3 (mstatus.mie disables IRQs in U-mode as well as M-mode, but is supposed to be ignored in U-mode).
This commit is contained in:
parent
78260e86e7
commit
194c9a9052
|
@ -13,6 +13,7 @@ struct RVCore {
|
||||||
RVCSR csr;
|
RVCSR csr;
|
||||||
bool load_reserved;
|
bool load_reserved;
|
||||||
MemBase32 &mem;
|
MemBase32 &mem;
|
||||||
|
bool stalled_on_wfi;
|
||||||
|
|
||||||
// A single flat RAM is handled as a special case, in addition to whatever
|
// A single flat RAM is handled as a special case, in addition to whatever
|
||||||
// is in `mem`, because this avoids virtual calls for the majority of
|
// is in `mem`, because this avoids virtual calls for the majority of
|
||||||
|
@ -27,6 +28,7 @@ struct RVCore {
|
||||||
std::fill(std::begin(regs), std::end(regs), 0);
|
std::fill(std::begin(regs), std::end(regs), 0);
|
||||||
pc = reset_vector;
|
pc = reset_vector;
|
||||||
load_reserved = false;
|
load_reserved = false;
|
||||||
|
stalled_on_wfi = false;
|
||||||
ram_base = ram_base_;
|
ram_base = ram_base_;
|
||||||
ram_top = ram_base_ + ram_size_;
|
ram_top = ram_base_ + ram_size_;
|
||||||
ram = new ux_t[ram_size_ / sizeof(ux_t)];
|
ram = new ux_t[ram_size_ / sizeof(ux_t)];
|
||||||
|
|
|
@ -112,6 +112,10 @@ public:
|
||||||
return priv;
|
return priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get_mstatus_tw() {
|
||||||
|
return mstatus & 0x00200000u;
|
||||||
|
}
|
||||||
|
|
||||||
void set_irq_t(bool irq) {
|
void set_irq_t(bool irq) {
|
||||||
irq_t = irq;
|
irq_t = irq;
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,6 +151,10 @@ void RVCore::step(bool trace) {
|
||||||
std::optional<ux_t> irq_target_pc = csr.trap_check_enter_irq(pc);
|
std::optional<ux_t> irq_target_pc = csr.trap_check_enter_irq(pc);
|
||||||
if (irq_target_pc) {
|
if (irq_target_pc) {
|
||||||
// Replace current instruction with IRQ entry
|
// Replace current instruction with IRQ entry
|
||||||
|
stalled_on_wfi = false;
|
||||||
|
} else if (stalled_on_wfi) {
|
||||||
|
// Replace current instruction with jump-to-self
|
||||||
|
pc_wdata = pc;
|
||||||
} else if (!fetch0 || ((*fetch0 & 0x3) == 0x3 && (!fetch1 || pmp_straddle))) {
|
} else if (!fetch0 || ((*fetch0 & 0x3) == 0x3 && (!fetch1 || pmp_straddle))) {
|
||||||
exception_cause = XCAUSE_INSTR_FAULT;
|
exception_cause = XCAUSE_INSTR_FAULT;
|
||||||
} else if ((instr & 0x3) == 0x3) {
|
} else if ((instr & 0x3) == 0x3) {
|
||||||
|
@ -588,6 +592,12 @@ void RVCore::step(bool trace) {
|
||||||
exception_cause = XCAUSE_ECALL_U + csr.get_true_priv();
|
exception_cause = XCAUSE_ECALL_U + csr.get_true_priv();
|
||||||
} else if (RVOPC_MATCH(instr, EBREAK)) {
|
} else if (RVOPC_MATCH(instr, EBREAK)) {
|
||||||
exception_cause = XCAUSE_EBREAK;
|
exception_cause = XCAUSE_EBREAK;
|
||||||
|
} else if (RVOPC_MATCH(instr, WFI)) {
|
||||||
|
if (csr.get_true_priv() == PRV_U && csr.get_mstatus_tw()) {
|
||||||
|
exception_cause = XCAUSE_INSTR_ILLEGAL;
|
||||||
|
} else {
|
||||||
|
stalled_on_wfi = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
exception_cause = XCAUSE_INSTR_ILLEGAL;
|
exception_cause = XCAUSE_INSTR_ILLEGAL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue