aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRupert Swarbrick <rswarbrick@gmail.com>2022-02-18 12:57:52 +0000
committerRupert Swarbrick <rswarbrick@gmail.com>2022-02-18 17:11:55 +0000
commitcd668d2f067d802879a7842bc3bed50fa61b2ead (patch)
tree5bdc8d9736752de4e9a8f1cf65c31ff7372000e8
parent24953e7c0072e372fc8f7315715f2ba435209e30 (diff)
downloadspike-cd668d2f067d802879a7842bc3bed50fa61b2ead.zip
spike-cd668d2f067d802879a7842bc3bed50fa61b2ead.tar.gz
spike-cd668d2f067d802879a7842bc3bed50fa61b2ead.tar.bz2
Split out MINSTRET and MCYCLE
Before this change, the MCYCLE CSR was just a proxy for MINSTRET. Similarly, CYCLE was a proxy for INSTRET. This models a machine where every instruction takes exactly one cycle to execute. That's not quite precise enough if you want to do cosimulation: there, you're going to want to MCYCLE to actually match the behaviour of your processor (because you need reads from the relevant CSRs to give the expected result). This commit splits the two CSRs, leaving the other proxy relationships unchanged. The code in processor_t::step() which bumps MINSTRET now bumps MCYCLE by the same amount, maintaining the previous behaviour. Of course, now a cosimulation environment can update the value of MCYCLE to fix things up for multi-cycle instructions after they run.
-rw-r--r--riscv/csrs.h8
-rw-r--r--riscv/execute.cc8
-rw-r--r--riscv/processor.cc10
-rw-r--r--riscv/processor.h1
4 files changed, 18 insertions, 9 deletions
diff --git a/riscv/csrs.h b/riscv/csrs.h
index 074d9dc..e3cbdd7 100644
--- a/riscv/csrs.h
+++ b/riscv/csrs.h
@@ -436,9 +436,9 @@ 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.
+// For minstret and mcycle, which are always 64 bits, but in RV32 are
+// split into high and low halves. The first class always holds the
+// full 64-bit value.
class wide_counter_csr_t: public csr_t {
public:
wide_counter_csr_t(processor_t* const proc, const reg_t addr);
@@ -456,7 +456,7 @@ class wide_counter_csr_t: public csr_t {
typedef std::shared_ptr<wide_counter_csr_t> wide_counter_csr_t_p;
-// A simple proxy to read/write the upper half of minstret
+// A simple proxy to read/write the upper half of minstret/mcycle
class counter_top_csr_t: public csr_t {
public:
counter_top_csr_t(processor_t* const proc, const reg_t addr, wide_counter_csr_t_p parent);
diff --git a/riscv/execute.cc b/riscv/execute.cc
index 3f7584e..41a15b7 100644
--- a/riscv/execute.cc
+++ b/riscv/execute.cc
@@ -349,6 +349,14 @@ void processor_t::step(size_t n)
}
state.minstret->bump(instret);
+
+ // By default, bump the MCYCLE register by the same delta. This models a
+ // machine where each instruction takes exactly one cycle to retire. In a
+ // cosimulation environment, the RTL might manually update MCYCLE
+ // separately. It should do that between the end of this step() and the
+ // start of the next one.
+ state.mcycle->bump(instret);
+
n -= instret;
}
}
diff --git a/riscv/processor.cc b/riscv/processor.cc
index ad73b29..a0513b8 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -423,15 +423,15 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
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);
csrmap[CSR_MINSTRET] = minstret = std::make_shared<wide_counter_csr_t>(proc, CSR_MINSTRET);
- csrmap[CSR_MCYCLE] = std::make_shared<proxy_csr_t>(proc, CSR_MCYCLE, minstret);
+ csrmap[CSR_MCYCLE] = mcycle = std::make_shared<wide_counter_csr_t>(proc, CSR_MCYCLE);
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);
+ csrmap[CSR_CYCLE] = std::make_shared<counter_proxy_csr_t>(proc, CSR_CYCLE, mcycle);
if (xlen == 32) {
- counter_top_csr_t_p minstreth;
+ counter_top_csr_t_p minstreth, mcycleh;
csrmap[CSR_MINSTRETH] = minstreth = std::make_shared<counter_top_csr_t>(proc, CSR_MINSTRETH, minstret);
- csrmap[CSR_MCYCLEH] = std::make_shared<proxy_csr_t>(proc, CSR_MCYCLEH, minstreth);
+ csrmap[CSR_MCYCLEH] = mcycleh = std::make_shared<counter_top_csr_t>(proc, CSR_MCYCLEH, mcycle);
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);
+ csrmap[CSR_CYCLEH] = std::make_shared<counter_proxy_csr_t>(proc, CSR_CYCLEH, mcycleh);
}
for (reg_t i=3; i<=31; ++i) {
const reg_t which_mevent = CSR_MHPMEVENT3 + i - 3;
diff --git a/riscv/processor.h b/riscv/processor.h
index 986431d..f58ec4b 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -177,6 +177,7 @@ struct state_t
csr_t_p mtvec;
csr_t_p mcause;
wide_counter_csr_t_p minstret;
+ wide_counter_csr_t_p mcycle;
mie_csr_t_p mie;
mip_csr_t_p mip;
csr_t_p medeleg;