diff options
author | Scott Johnson <scott.johnson@arilinc.com> | 2021-09-14 20:17:14 -0700 |
---|---|---|
committer | Scott Johnson <scott.johnson@arilinc.com> | 2021-09-20 12:54:45 -0700 |
commit | 55a272562ea12abc2fe3057e89247615525b7cc7 (patch) | |
tree | cda22a46368e2bccf7687733c5bfdc87bcf1e881 /riscv | |
parent | 3092501627f8d3f7e0aae6dc271a6edc15c80da1 (diff) | |
download | spike-55a272562ea12abc2fe3057e89247615525b7cc7.zip spike-55a272562ea12abc2fe3057e89247615525b7cc7.tar.gz spike-55a272562ea12abc2fe3057e89247615525b7cc7.tar.bz2 |
Convert unprivileged counter shadows to csr_t
Soon I will simplify some of these cpp macros.
Diffstat (limited to 'riscv')
-rw-r--r-- | riscv/csrs.cc | 41 | ||||
-rw-r--r-- | riscv/csrs.h | 7 | ||||
-rw-r--r-- | riscv/processor.cc | 72 |
3 files changed, 61 insertions, 59 deletions
diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 6d111d7..4b2e417 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -883,3 +883,44 @@ reg_t const_csr_t::read() const noexcept { bool const_csr_t::unlogged_write(const reg_t val) noexcept { return false; } + + +counter_proxy_csr_t::counter_proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate): + proxy_csr_t(proc, addr, delegate) { +} + +void counter_proxy_csr_t::verify_permissions(insn_t insn, bool write) const { + proxy_csr_t::verify_permissions(insn, write); +#define mcounteren_ok(__which) \ +({ \ + bool __ctr_ok = true; \ + if (state->prv < PRV_M) \ + __ctr_ok = (state->mcounteren->read() >> (__which & 31)) & 1; \ + __ctr_ok; \ +}) +#define hcounteren_ok(__which) \ +({ \ + bool __ctr_ok = true; \ + if (state->v) \ + __ctr_ok = (state->hcounteren->read() >> (__which & 31)) & 1; \ + __ctr_ok; \ +}) +#define scounteren_ok(__which) \ +({ \ + bool __ctr_ok = true; \ + if (proc->extension_enabled('S') && state->prv < PRV_S) \ + __ctr_ok = (state->scounteren->read() >> (__which & 31)) & 1; \ + __ctr_ok; \ +}) + + if (!mcounteren_ok(address)) + throw trap_illegal_instruction(insn.bits()); + if (!hcounteren_ok(address)) + throw trap_virtual_instruction(insn.bits()); + if (!scounteren_ok(address)) { + if (state->v) + throw trap_virtual_instruction(insn.bits()); + else + throw trap_illegal_instruction(insn.bits()); + } +} diff --git a/riscv/csrs.h b/riscv/csrs.h index de37c11..392bb4d 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -474,4 +474,11 @@ class const_csr_t: public csr_t { }; +// For a CSR that is an unprivileged accessor of a privileged counter +class counter_proxy_csr_t: public proxy_csr_t { + public: + counter_proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate); + virtual void verify_permissions(insn_t insn, bool write) const override; +}; + #endif diff --git a/riscv/processor.cc b/riscv/processor.cc index bd2d641..d3009d2 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -378,22 +378,32 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) csrmap[CSR_MCAUSE] = mcause = std::make_shared<cause_csr_t>(proc, CSR_MCAUSE); csrmap[CSR_MINSTRET] = minstret = std::make_shared<minstret_csr_t>(proc, CSR_MINSTRET); csrmap[CSR_MCYCLE] = std::make_shared<proxy_csr_t>(proc, CSR_MCYCLE, minstret); + csrmap[CSR_INSTRET] = std::make_shared<counter_proxy_csr_t>(proc, CSR_INSTRET, minstret); + csrmap[CSR_CYCLE] = std::make_shared<counter_proxy_csr_t>(proc, CSR_CYCLE, minstret); if (xlen == 32) { minstreth_csr_t_p minstreth; csrmap[CSR_MINSTRETH] = minstreth = std::make_shared<minstreth_csr_t>(proc, CSR_MINSTRETH, minstret); csrmap[CSR_MCYCLEH] = std::make_shared<proxy_csr_t>(proc, CSR_MCYCLEH, minstreth); + csrmap[CSR_INSTRETH] = std::make_shared<counter_proxy_csr_t>(proc, CSR_INSTRETH, minstreth); + csrmap[CSR_CYCLEH] = std::make_shared<counter_proxy_csr_t>(proc, CSR_CYCLEH, minstreth); } for (reg_t i=3; i<=31; ++i) { - const reg_t which_mcounter = CSR_MHPMCOUNTER3 + i - 3; const reg_t which_mevent = CSR_MHPMEVENT3 + i - 3; + const reg_t which_mcounter = CSR_MHPMCOUNTER3 + i - 3; const reg_t which_mcounterh = CSR_MHPMCOUNTER3H + i - 3; - auto mcounter = std::make_shared<const_csr_t>(proc, which_mcounter, 0); + const reg_t which_counter = CSR_HPMCOUNTER3 + i - 3; + const reg_t which_counterh = CSR_HPMCOUNTER3H + i - 3; auto mevent = std::make_shared<const_csr_t>(proc, which_mevent, 0); - csrmap[which_mcounter] = mcounter; + auto mcounter = std::make_shared<const_csr_t>(proc, which_mcounter, 0); + auto counter = std::make_shared<counter_proxy_csr_t>(proc, which_counter, mcounter); csrmap[which_mevent] = mevent; + csrmap[which_mcounter] = mcounter; + csrmap[which_counter] = counter; if (xlen == 32) { auto mcounterh = std::make_shared<const_csr_t>(proc, which_mcounterh, 0); + auto counterh = std::make_shared<counter_proxy_csr_t>(proc, which_counterh, mcounterh); csrmap[which_mcounterh] = mcounterh; + csrmap[which_counterh] = counterh; } } csrmap[CSR_MIE] = mie = std::make_shared<mie_csr_t>(proc, CSR_MIE); @@ -1162,28 +1172,6 @@ void processor_t::set_csr(int which, reg_t val) // side effects on reads. reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek) { -#define mcounteren_ok(__which) \ -({ \ - bool __ctr_ok = true; \ - if (state.prv < PRV_M) \ - __ctr_ok = (state.mcounteren->read() >> (__which & 31)) & 1; \ - __ctr_ok; \ -}) -#define hcounteren_ok(__which) \ -({ \ - bool __ctr_ok = true; \ - if (state.v) \ - __ctr_ok = (state.hcounteren->read() >> (__which & 31)) & 1; \ - __ctr_ok; \ -}) -#define scounteren_ok(__which) \ -({ \ - bool __ctr_ok = true; \ - if (extension_enabled('S') && state.prv < PRV_S) \ - __ctr_ok = (state.scounteren->read() >> (__which & 31)) & 1; \ - __ctr_ok; \ -}) - reg_t res = 0; #define ret(n) do { \ res = (n); \ @@ -1226,40 +1214,6 @@ reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek) if (!extension_enabled('V')) break; ret((VU.vxsat << VCSR_VXSAT_SHIFT) | (VU.vxrm << VCSR_VXRM_SHIFT)); - case CSR_INSTRET: - case CSR_CYCLE: - case CSR_HPMCOUNTER3 ... CSR_HPMCOUNTER31: - if (!mcounteren_ok(which)) - goto throw_illegal; - if (!hcounteren_ok(which)) - goto throw_virtual; - if (!scounteren_ok(which)) { - if (state.v) - goto throw_virtual; - else - goto throw_illegal; - } - if (which == CSR_INSTRET || which == CSR_CYCLE) - ret(state.minstret->read()); - else - ret(0); - case CSR_INSTRETH: - case CSR_CYCLEH: - case CSR_HPMCOUNTER3H ... CSR_HPMCOUNTER31H: - if (!mcounteren_ok(which) || xlen != 32) - goto throw_illegal; - if (!hcounteren_ok(which)) - goto throw_virtual; - if (!scounteren_ok(which)) { - if (state.v) - goto throw_virtual; - else - goto throw_illegal; - } - if (which == CSR_INSTRETH || which == CSR_CYCLEH) - ret(state.minstret->read() >> 32); - else - ret(0); case CSR_MCOUNTINHIBIT: ret(0); case CSR_MSTATUSH: if (xlen == 32) |