aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorScott Johnson <scott.johnson@arilinc.com>2021-09-14 16:29:48 -0700
committerScott Johnson <scott.johnson@arilinc.com>2021-09-16 10:52:14 -0700
commitf19f39f0c11d793e29196f0afc65f7f21c59871e (patch)
tree292c2b7cc6168915990eaad19141bdcfc89437d1 /riscv
parent056fc389d2e63eecf5d47bc9d6f80476959623be (diff)
downloadspike-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.cc35
-rw-r--r--riscv/csrs.h18
-rw-r--r--riscv/execute.cc2
-rw-r--r--riscv/processor.cc31
-rw-r--r--riscv/processor.h2
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;