[dv] Add recoverable NMI handling to cosim

Ibex implements a custom recoverable NMI handling scheme. This adds
modeling of it to the cosim.
This commit is contained in:
Greg Chadwick 2021-11-05 11:17:35 +00:00 committed by Greg Chadwick
parent 587dc364e9
commit cedabf062a
2 changed files with 36 additions and 4 deletions

View file

@ -105,10 +105,6 @@ bool SpikeCosim::step(uint32_t write_reg, uint32_t write_reg_data, uint32_t pc,
bool sync_trap) {
assert(write_reg < 32);
if (pc_is_mret(pc)) {
nmi_mode = false;
}
uint32_t initial_pc = (processor->get_state()->pc & 0xffffffff);
bool initial_pc_match = initial_pc == pc;
@ -172,6 +168,11 @@ bool SpikeCosim::step(uint32_t write_reg, uint32_t write_reg_data, uint32_t pc,
return false;
}
if (!sync_trap && pc_is_mret(pc) && nmi_mode) {
// Do handling for recoverable NMI
leave_nmi_mode();
}
// Check register writes from executed instruction match what is expected
auto &reg_changes = processor->get_state()->log_reg_write;
@ -288,6 +289,19 @@ void SpikeCosim::on_csr_write(const commit_log_reg_t::value_type &reg_change) {
fixup_csr(cosim_write_csr, cosim_write_csr_data);
}
void SpikeCosim::leave_nmi_mode() {
nmi_mode = false;
// Restore CSR status from mstack
uint32_t mstatus = processor->get_csr(CSR_MSTATUS);
mstatus = set_field(mstatus, MSTATUS_MPP, mstack.mpp);
mstatus = set_field(mstatus, MSTATUS_MPIE, mstack.mpie);
processor->set_csr(CSR_MSTATUS, mstatus);
processor->set_csr(CSR_MEPC, mstack.epc);
processor->set_csr(CSR_MCAUSE, mstack.cause);
}
void SpikeCosim::set_mip(uint32_t mip) {
processor->get_state()->mip->write_with_mask(0xffffffff, mip);
}
@ -296,6 +310,13 @@ void SpikeCosim::set_nmi(bool nmi) {
if (nmi && !nmi_mode && !processor->get_state()->debug_mode) {
processor->get_state()->nmi = true;
nmi_mode = true;
// When NMI is set it is guaranteed NMI trap will be taken at the next step
// so save CSR state for recoverable NMI to mstack now.
mstack.mpp = get_field(processor->get_csr(CSR_MSTATUS), MSTATUS_MPP);
mstack.mpie = get_field(processor->get_csr(CSR_MSTATUS), MSTATUS_MPIE);
mstack.epc = processor->get_csr(CSR_MEPC);
mstack.cause = processor->get_csr(CSR_MCAUSE);
}
}

View file

@ -26,6 +26,15 @@ class SpikeCosim : public simif_t, public Cosim {
std::vector<std::string> errors;
bool nmi_mode;
typedef struct {
uint8_t mpp;
bool mpie;
uint32_t epc;
uint32_t cause;
} mstack_t;
mstack_t mstack;
void fixup_csr(int csr_num, uint32_t csr_val);
struct PendingMemAccess {
@ -54,6 +63,8 @@ class SpikeCosim : public simif_t, public Cosim {
void on_csr_write(const commit_log_reg_t::value_type &reg_change);
void leave_nmi_mode();
int insn_cnt;
public: