aboutsummaryrefslogtreecommitdiff
path: root/riscv/csrs.cc
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2022-07-21 09:51:24 -0700
committerGitHub <noreply@github.com>2022-07-21 09:51:24 -0700
commit3ea7494620face7e65c7b53af52898e69951a1ac (patch)
tree46aff4f2fd4d2b991f7781f59a7ac517ce18ef40 /riscv/csrs.cc
parentb0d9782e13156abd5884fa73017a0286441202d1 (diff)
parenteff4011f24390017e4582cb8556ebc6e5ce41d61 (diff)
downloadriscv-isa-sim-3ea7494620face7e65c7b53af52898e69951a1ac.zip
riscv-isa-sim-3ea7494620face7e65c7b53af52898e69951a1ac.tar.gz
riscv-isa-sim-3ea7494620face7e65c7b53af52898e69951a1ac.tar.bz2
Merge pull request #1040 from plctlab/plct-priv-dev
Update for counter related CSR
Diffstat (limited to 'riscv/csrs.cc')
-rw-r--r--riscv/csrs.cc43
1 files changed, 24 insertions, 19 deletions
diff --git a/riscv/csrs.cc b/riscv/csrs.cc
index 7a63cbc..3cb6af2 100644
--- a/riscv/csrs.cc
+++ b/riscv/csrs.cc
@@ -525,6 +525,10 @@ bool rv32_low_csr_t::unlogged_write(const reg_t val) noexcept {
return orig->unlogged_write((orig->written_value() >> 32 << 32) | (val & 0xffffffffU));
}
+reg_t rv32_low_csr_t::written_value() const noexcept {
+ return orig->written_value() & 0xffffffffU;
+}
+
// implement class rv32_high_csr_t
rv32_high_csr_t::rv32_high_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig):
csr_t(proc, addr),
@@ -543,6 +547,10 @@ bool rv32_high_csr_t::unlogged_write(const reg_t val) noexcept {
return orig->unlogged_write((orig->written_value() << 32 >> 32) | ((val & 0xffffffffU) << 32));
}
+reg_t rv32_high_csr_t::written_value() const noexcept {
+ return (orig->written_value() >> 32) & 0xffffffffU;
+}
+
// implement class sstatus_csr_t
sstatus_csr_t::sstatus_csr_t(processor_t* const proc, sstatus_proxy_csr_t_p orig, vsstatus_csr_t_p virt):
virtualized_csr_t(proc, orig, virt),
@@ -934,10 +942,7 @@ void wide_counter_csr_t::bump(const reg_t howmuch) noexcept {
}
bool wide_counter_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;
+ 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.
@@ -951,25 +956,23 @@ reg_t wide_counter_csr_t::written_value() const noexcept {
return this->val + 1;
}
-void wide_counter_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), written_value() >> 32);
-}
-
-counter_top_csr_t::counter_top_csr_t(processor_t* const proc, const reg_t addr, wide_counter_csr_t_p parent):
+// implement class time_counter_csr_t
+time_counter_csr_t::time_counter_csr_t(processor_t* const proc, const reg_t addr):
csr_t(proc, addr),
- parent(parent) {
+ shadow_val(0) {
}
-reg_t counter_top_csr_t::read() const noexcept {
- return parent->read() >> 32;
+reg_t time_counter_csr_t::read() const noexcept {
+ // reading the time CSR in VS or VU mode returns the sum of the contents of
+ // htimedelta and the actual value of time.
+ if (state->v)
+ return shadow_val + state->htimedelta->read();
+ else
+ return shadow_val;
}
-bool counter_top_csr_t::unlogged_write(const reg_t val) noexcept {
- parent->write_upper_half(val);
- return true;
+void time_counter_csr_t::sync(const reg_t val) noexcept {
+ shadow_val = val;
}
proxy_csr_t::proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate):
@@ -1008,11 +1011,13 @@ bool counter_proxy_csr_t::myenable(csr_t_p counteren) const noexcept {
}
void counter_proxy_csr_t::verify_permissions(insn_t insn, bool write) const {
+ proxy_csr_t::verify_permissions(insn, write);
+
const bool mctr_ok = (state->prv < PRV_M) ? myenable(state->mcounteren) : true;
const bool hctr_ok = state->v ? myenable(state->hcounteren) : true;
const bool sctr_ok = (proc->extension_enabled('S') && state->prv < PRV_S) ? myenable(state->scounteren) : true;
- if (write || !mctr_ok)
+ if (!mctr_ok)
throw trap_illegal_instruction(insn.bits());
if (!hctr_ok)
throw trap_virtual_instruction(insn.bits());