Browse Source

Implement Ssccfg & Smcdeleg for spike

Signed-off-by: muhammad.moiz.hussain@semidynamics.com
pull/1965/head
Muhammad Moiz Hussain 12 months ago
parent
commit
4764d3c029
  1. 4
      disasm/isa_parser.cc
  2. 60
      riscv/csr_init.cc
  3. 93
      riscv/csrs.cc
  4. 10
      riscv/csrs.h
  5. 2
      riscv/isa_parser.h
  6. 1
      riscv/processor.h

4
disasm/isa_parser.cc

@ -331,6 +331,10 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_SSCSRIND] = true;
} else if (ext_str == "smcntrpmf") {
extension_table[EXT_SMCNTRPMF] = true;
} else if (ext_str == "smcdeleg") {
extension_table[EXT_SMCDELEG] = true;
} else if (ext_str == "ssccfg") {
extension_table[EXT_SSCCFG] = true;
} else if (ext_str == "zimop") {
extension_table[EXT_ZIMOP] = true;
} else if (ext_str == "zcmop") {

60
riscv/csr_init.cc

@ -250,7 +250,8 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
(proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) |
(proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0) |
(proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0) |
(proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0);
(proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0)|
(proc->extension_enabled(EXT_SMCSRIND) ? MENVCFG_CDE : 0);
menvcfg = std::make_shared<envcfg_csr_t>(proc, CSR_MENVCFG, menvcfg_mask, 0);
if (xlen == 32) {
add_user_csr(CSR_MENVCFG, std::make_shared<rv32_low_csr_t>(proc, CSR_MENVCFG, menvcfg));
@ -337,6 +338,10 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
const reg_t ssp_mask = -reg_t(xlen / 8);
add_ext_csr(EXT_ZICFISS, CSR_SSP, ssp = std::make_shared<ssp_csr_t>(proc, CSR_SSP, ssp_mask, 0));
// Smcdeleg
if (proc->extension_enabled_const(EXT_SMCDELEG) || proc->extension_enabled_const(EXT_SSCCFG)) {
add_supervisor_csr(CSR_SCOUNTINHIBIT, scountinhibit = std::make_shared<scntinhibit_csr_t>(proc, CSR_SCOUNTINHIBIT, mcountinhibit));
}
// Smcsrind / Sscsrind
if (proc->extension_enabled_const(EXT_SMCSRIND)) {
@ -363,6 +368,59 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
auto sireg = std::make_shared<sscsrind_reg_csr_t>(proc, sireg_csrs[i], siselect);
add_supervisor_csr(sireg_csrs[i], std::make_shared<virtualized_indirect_csr_t>(proc, sireg, vsireg));
// Smcdeleg
if (proc->extension_enabled(EXT_SSCCFG) || proc->extension_enabled(EXT_SMCDELEG)) {
switch (sireg_csrs[i]) {
case CSR_SIREG:
if (proc->extension_enabled_const(EXT_ZICNTR)) {
sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, mcycle);
sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRET, minstret);
}
if (proc->extension_enabled_const(EXT_ZIHPM)) {
for (size_t j = 0; j < (SISELECT_SMCDELEG_END - SISELECT_SMCDELEG_HPMEVENT_3 + 1); j++)
sireg->add_ireg_proxy(SISELECT_SMCDELEG_HPMCOUNTER_3 + j, csrmap[CSR_HPMCOUNTER3 + j]);
}
break;
case CSR_SIREG4:
if (xlen == 32) {
if (proc->extension_enabled_const(EXT_ZICNTR)) {
sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, csrmap[CSR_CYCLEH]);
sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRET, csrmap[CSR_INSTRETH]);
}
if (proc->extension_enabled_const(EXT_ZIHPM)) {
for (size_t j = 0; j < (SISELECT_SMCDELEG_END - SISELECT_SMCDELEG_HPMEVENT_3 + 1); j++)
sireg->add_ireg_proxy(SISELECT_SMCDELEG_HPMCOUNTER_3 + j, csrmap[CSR_HPMCOUNTER3H + j]);
}
}
break;
case CSR_SIREG2:
if (proc->extension_enabled_const(EXT_ZICNTR)) {
sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, mcyclecfg);
sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRETCFG, minstretcfg);
}
if (proc->extension_enabled_const(EXT_ZIHPM)) {
for (size_t j = 0; j < (SISELECT_SMCDELEG_END - SISELECT_SMCDELEG_HPMEVENT_3 + 1); j++)
sireg->add_ireg_proxy(SISELECT_SMCDELEG_HPMEVENT_3 + j, csrmap[CSR_MHPMEVENT3H + j]);
}
break;
case CSR_SIREG5:
if (xlen == 32) {
if (proc->extension_enabled_const(EXT_ZICNTR)) {
sireg->add_ireg_proxy(SISELECT_SMCDELEG_START, mcycle);
sireg->add_ireg_proxy(SISELECT_SMCDELEG_INSTRET, minstret);
}
if (proc->extension_enabled_const(EXT_ZIHPM)) {
for (size_t j = 0; j < (SISELECT_SMCDELEG_END - SISELECT_SMCDELEG_HPMEVENT_3); j++)
sireg->add_ireg_proxy(SISELECT_SMCDELEG_HPMCOUNTER_3 + j, csrmap[CSR_HPMCOUNTER3 + j]);
}
}
case CSR_SIREG3:
case CSR_SIREG6:
default:
break;
}
}
}
}

93
riscv/csrs.cc

@ -1677,6 +1677,14 @@ scountovf_csr_t::scountovf_csr_t(processor_t* const proc, const reg_t addr):
void scountovf_csr_t::verify_permissions(insn_t insn, bool write) const {
if (!proc->extension_enabled(EXT_SSCOFPMF))
throw trap_illegal_instruction(insn.bits());
if (proc->extension_enabled('H') &&
(proc->extension_enabled_const(EXT_SMCDELEG) || proc->extension_enabled(EXT_SSCCFG))
) {
if (state->v && (state->menvcfg->read() & MENVCFG_CDE)) {
throw trap_virtual_instruction(insn.bits());
}
}
csr_t::verify_permissions(insn, write);
}
@ -1750,6 +1758,68 @@ void sscsrind_reg_csr_t::verify_permissions(insn_t insn, bool write) const {
if (insn.csr() == address)
csr_t::verify_permissions(insn, write);
if (proc->extension_enabled(EXT_SMSTATEEN)) {
if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_CSRIND))
throw trap_illegal_instruction(insn.bits());
if (state->v && !(state->hstateen[0]->read() & HSTATEEN0_CSRIND))
throw trap_virtual_instruction(insn.bits());
}
if (proc->extension_enabled(EXT_SMCDELEG)) {
if (insn.csr() >= CSR_VSIREG && insn.csr() <= CSR_VSIREG6) {
if (!state->v) {
// An attempt to access any vsireg* from M or S mode raises an illegal instruction exception.
throw trap_illegal_instruction(insn.bits());
} else {
if (state->prv == PRV_S) {
// An attempt from VS-mode to access any vsireg raises an illegal instruction
// exception if menvcfg.CDE = 0, or a virtual instruction exception if menvcfg.CDE = 1
if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) {
throw trap_illegal_instruction(insn.bits());
} else {
throw trap_virtual_instruction(insn.bits());
}
} else {
throw trap_virtual_instruction(insn.bits());
}
}
}
if (insn.csr() >= CSR_SIREG && insn.csr() <= CSR_SIREG6) {
// attempts to access any sireg* when menvcfg.CDE = 0;
if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) {
if (!state->v) {
throw trap_illegal_instruction(insn.bits());
} else {
if (state->prv == PRV_S) {
// An attempt from VS-mode to access any sireg* causes illegal instruction exception if menvcfg.CDE = 0
throw trap_illegal_instruction(insn.bits());
} else {
throw trap_virtual_instruction(insn.bits());
}
}
} else {
// menvcfg.CDE = 1;
if (state->v) {
// An attempt from VS-mode to access any sireg* causes a virtual instruction exception if menvcfg.CDE = 1
throw trap_virtual_instruction(insn.bits());
}
// counter selected by siselect is not delegated to S-mode (the corresponding bit in mcounteren = 0).
auto iselect_addr = iselect->read();
if (iselect_addr >= SISELECT_SMCDELEG_START && iselect_addr <= SISELECT_SMCDELEG_END) {
reg_t counter_id_offset = iselect_addr - SISELECT_SMCDELEG_START;
if (!(state->mcounteren->read() & (1U << counter_id_offset))) {
if (!state->v) {
throw trap_illegal_instruction(insn.bits());
} else {
throw trap_virtual_instruction(insn.bits());
}
}
}
}
}
}
csr_t_p proxy_csr = get_reg();
if (proxy_csr == nullptr) {
if (!state->v) {
@ -1880,3 +1950,26 @@ bool hstatus_csr_t::unlogged_write(const reg_t val) noexcept {
proc->get_mmu()->flush_tlb();
return basic_csr_t::unlogged_write(new_hstatus);
}
scntinhibit_csr_t::scntinhibit_csr_t(processor_t* const proc, const reg_t addr, csr_t_p mcountinhibit):
basic_csr_t(proc, addr, mcountinhibit->read()) {
}
void scntinhibit_csr_t::verify_permissions(insn_t insn, bool write) const {
if (insn.csr() == address) {
csr_t::verify_permissions(insn, write);
}
if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) {
throw trap_illegal_instruction(insn.bits());
}
}
bool scntinhibit_csr_t::unlogged_write(const reg_t val) noexcept {
state->mcountinhibit->write(state->mcounteren->read() & val);
return true;
}
reg_t scntinhibit_csr_t::read() const noexcept {
return state->mcounteren->read() & state->mcountinhibit->read();
}

10
riscv/csrs.h

@ -899,4 +899,14 @@ class hstatus_csr_t final: public basic_csr_t {
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
};
class scntinhibit_csr_t: public basic_csr_t {
public:
scntinhibit_csr_t(processor_t* const proc, const reg_t addr, csr_t_p mcountinhibit);
reg_t read() const noexcept override;
virtual void verify_permissions(insn_t insn, bool write) const override;
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
};
#endif

2
riscv/isa_parser.h

@ -76,6 +76,8 @@ typedef enum {
EXT_INTERNAL_ZFH_MOVE,
EXT_SMCSRIND,
EXT_SSCSRIND,
EXT_SMCDELEG,
EXT_SSCCFG,
EXT_SMCNTRPMF,
EXT_ZIMOP,
EXT_ZCMOP,

1
riscv/processor.h

@ -109,6 +109,7 @@ struct state_t
csr_t_p stvec;
virtualized_csr_t_p satp;
csr_t_p scause;
csr_t_p scountinhibit;
// When taking a trap into HS-mode, we must access the nonvirtualized HS-mode CSRs directly:
csr_t_p nonvirtual_stvec;

Loading…
Cancel
Save