diff options
author | Scott Johnson <scott.johnson@arilinc.com> | 2021-09-14 16:29:48 -0700 |
---|---|---|
committer | Scott Johnson <scott.johnson@arilinc.com> | 2021-09-16 10:52:14 -0700 |
commit | f19f39f0c11d793e29196f0afc65f7f21c59871e (patch) | |
tree | 292c2b7cc6168915990eaad19141bdcfc89437d1 /riscv | |
parent | 056fc389d2e63eecf5d47bc9d6f80476959623be (diff) | |
download | spike-f19f39f0c11d793e29196f0afc65f7f21c59871e.zip spike-f19f39f0c11d793e29196f0afc65f7f21c59871e.tar.gz spike-f19f39f0c11d793e29196f0afc65f7f21c59871e.tar.bz2 |
Convert minstret to csr_t
This is a little messy in RV32 since it's accessed via two different
CSRs (upper and lower halves).
This changes logging of mcycle[h] to log a change to minstret[h],
since that's how it's always been implemented in Spike. There is no
separate mcycle register.
Diffstat (limited to 'riscv')
-rw-r--r-- | riscv/csrs.cc | 35 | ||||
-rw-r--r-- | riscv/csrs.h | 18 | ||||
-rw-r--r-- | riscv/execute.cc | 2 | ||||
-rw-r--r-- | riscv/processor.cc | 31 | ||||
-rw-r--r-- | riscv/processor.h | 2 |
5 files changed, 63 insertions, 25 deletions
diff --git a/riscv/csrs.cc b/riscv/csrs.cc index a45b839..33b05ee 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -804,3 +804,38 @@ bool virtualized_satp_csr_t::unlogged_write(const reg_t val) noexcept { const reg_t newval = orig_satp->satp_valid(val) ? val : read(); return virtualized_csr_t::unlogged_write(newval); } + + +// implement class minstret_csr_t +minstret_csr_t::minstret_csr_t(processor_t* const proc, const reg_t addr): + csr_t(proc, addr), + val(0) { +} + +reg_t minstret_csr_t::read() const noexcept { + return val; +} + +void minstret_csr_t::bump(const reg_t howmuch) noexcept { + val += howmuch; // to keep log reasonable size, don't log every bump +} + +bool minstret_csr_t::unlogged_write(const reg_t val) noexcept { + if (proc->get_xlen() == 32) + this->val = (this->val >> 32 << 32) | (val & 0xffffffffU); + else + this->val = val; + // The ISA mandates that if an instruction writes instret, the write + // takes precedence over the increment to instret. However, Spike + // unconditionally increments instret after executing an instruction. + // Correct for this artifact by decrementing instret here. + this->val--; + return true; +} + +void minstret_csr_t::write_upper_half(const reg_t val) noexcept { + this->val = (val << 32) | (this->val << 32 >> 32); + this->val--; // See comment above. + // Log upper half only. + log_special_write(address + (CSR_MINSTRETH - CSR_MINSTRET), this->val >> 32); +} diff --git a/riscv/csrs.h b/riscv/csrs.h index a258bd7..99d3770 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -417,4 +417,22 @@ class virtualized_satp_csr_t: public virtualized_csr_t { }; +// For minstret, which is always 64 bits, but in RV32 is split into +// high and low halves. The first class always holds the full 64-bit +// value. +class minstret_csr_t: public csr_t { + public: + minstret_csr_t(processor_t* const proc, const reg_t addr); + // Always returns full 64-bit value + virtual reg_t read() const noexcept override; + void bump(const reg_t howmuch) noexcept; + void write_upper_half(const reg_t val) noexcept; + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; + private: + reg_t val; +}; + +typedef std::shared_ptr<minstret_csr_t> minstret_csr_t_p; + #endif diff --git a/riscv/execute.cc b/riscv/execute.cc index 53f956c..ed64277 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -348,7 +348,7 @@ void processor_t::step(size_t n) n = ++instret; } - state.minstret += instret; + state.minstret->bump(instret); n -= instret; } } diff --git a/riscv/processor.cc b/riscv/processor.cc index f5f8aef..5df8ec0 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -376,7 +376,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) csrmap[CSR_MSCRATCH] = std::make_shared<basic_csr_t>(proc, CSR_MSCRATCH, 0); csrmap[CSR_MTVEC] = mtvec = std::make_shared<tvec_csr_t>(proc, CSR_MTVEC); csrmap[CSR_MCAUSE] = mcause = std::make_shared<cause_csr_t>(proc, CSR_MCAUSE); - minstret = 0; + csrmap[CSR_MINSTRET] = minstret = std::make_shared<minstret_csr_t>(proc, CSR_MINSTRET); csrmap[CSR_MIE] = mie = std::make_shared<mie_csr_t>(proc, CSR_MIE); csrmap[CSR_MIP] = mip = std::make_shared<mip_csr_t>(proc, CSR_MIP); auto sip_sie_accr = std::make_shared<generic_int_accessor_t>(this, @@ -972,22 +972,12 @@ void processor_t::set_csr(int which, reg_t val) VU.vxsat = (val & VCSR_VXSAT) >> VCSR_VXSAT_SHIFT; VU.vxrm = (val & VCSR_VXRM) >> VCSR_VXRM_SHIFT; break; - case CSR_MINSTRET: case CSR_MCYCLE: - if (xlen == 32) - state.minstret = (state.minstret >> 32 << 32) | (val & 0xffffffffU); - else - state.minstret = val; - // The ISA mandates that if an instruction writes instret, the write - // takes precedence over the increment to instret. However, Spike - // unconditionally increments instret after executing an instruction. - // Correct for this artifact by decrementing instret here. - state.minstret--; + state.minstret->write(val); break; case CSR_MINSTRETH: case CSR_MCYCLEH: - state.minstret = (val << 32) | (state.minstret << 32 >> 32); - state.minstret--; // See comment above. + state.minstret->write_upper_half(val); break; case CSR_MTVAL2: state.mtval2 = val; break; case CSR_MTINST: state.mtinst = val; break; @@ -1141,10 +1131,6 @@ void processor_t::set_csr(int which, reg_t val) LOG_CSR(CSR_VXRM); break; - case CSR_MINSTRET: - case CSR_MCYCLE: - case CSR_MINSTRETH: - case CSR_MCYCLEH: case CSR_TSELECT: case CSR_TDATA1: case CSR_TDATA2: @@ -1242,15 +1228,14 @@ reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek) goto throw_illegal; } if (which == CSR_INSTRET || which == CSR_CYCLE) - ret(state.minstret); + ret(state.minstret->read()); else ret(0); - case CSR_MINSTRET: case CSR_MCYCLE: case CSR_MHPMCOUNTER3 ... CSR_MHPMCOUNTER31: case CSR_MHPMEVENT3 ... CSR_MHPMEVENT31: - if (which == CSR_MINSTRET || which == CSR_MCYCLE) - ret(state.minstret); + if (which == CSR_MCYCLE) + ret(state.minstret->read()); else ret(0); case CSR_INSTRETH: @@ -1267,7 +1252,7 @@ reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek) goto throw_illegal; } if (which == CSR_INSTRETH || which == CSR_CYCLEH) - ret(state.minstret >> 32); + ret(state.minstret->read() >> 32); else ret(0); case CSR_MINSTRETH: @@ -1275,7 +1260,7 @@ reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek) case CSR_MHPMCOUNTER3H ... CSR_MHPMCOUNTER31H: if (xlen == 32) { if (which == CSR_MINSTRETH || which == CSR_MCYCLEH) - ret(state.minstret >> 32); + ret(state.minstret->read() >> 32); else ret(0); } diff --git a/riscv/processor.h b/riscv/processor.h index 450d650..6feb61e 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -174,7 +174,7 @@ struct state_t csr_t_p mtval; csr_t_p mtvec; csr_t_p mcause; - reg_t minstret; + minstret_csr_t_p minstret; mie_csr_t_p mie; mip_csr_t_p mip; csr_t_p medeleg; |