diff options
-rw-r--r-- | riscv/clint.cc | 1 | ||||
-rw-r--r-- | riscv/csrs.cc | 19 | ||||
-rw-r--r-- | riscv/csrs.h | 15 | ||||
-rw-r--r-- | riscv/processor.cc | 11 | ||||
-rw-r--r-- | riscv/processor.h | 3 |
5 files changed, 49 insertions, 0 deletions
diff --git a/riscv/clint.cc b/riscv/clint.cc index 72d1bbe..3f2d4d7 100644 --- a/riscv/clint.cc +++ b/riscv/clint.cc @@ -82,6 +82,7 @@ void clint_t::increment(reg_t inc) mtime += inc; } for (size_t i = 0; i < procs.size(); i++) { + procs[i]->state.time->sync(mtime); procs[i]->state.mip->backdoor_write_with_mask(MIP_MTIP, 0); if (mtime >= mtimecmp[i]) procs[i]->state.mip->backdoor_write_with_mask(MIP_MTIP, MIP_MTIP); diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 9721f87..8cb9953 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -946,6 +946,25 @@ reg_t wide_counter_csr_t::written_value() const noexcept { return this->val + 1; } +// 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), + shadow_val(0) { +} + +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; +} + +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): csr_t(proc, addr), delegate(delegate) { diff --git a/riscv/csrs.h b/riscv/csrs.h index 8108d1e..34bc9d0 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -509,6 +509,21 @@ class wide_counter_csr_t: public csr_t { typedef std::shared_ptr<wide_counter_csr_t> wide_counter_csr_t_p; +class time_counter_csr_t: public csr_t { + public: + time_counter_csr_t(processor_t* const proc, const reg_t addr); + virtual reg_t read() const noexcept override; + + void sync(const reg_t val) noexcept; + + protected: + virtual bool unlogged_write(const reg_t val) noexcept override { return false; }; + private: + reg_t shadow_val; +}; + +typedef std::shared_ptr<time_counter_csr_t> time_counter_csr_t_p; + // For a CSR that is an alias of another class proxy_csr_t: public csr_t { public: diff --git a/riscv/processor.cc b/riscv/processor.cc index c351d1d..642f1fb 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -204,9 +204,11 @@ 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); minstret = std::make_shared<wide_counter_csr_t>(proc, CSR_MINSTRET); mcycle = std::make_shared<wide_counter_csr_t>(proc, CSR_MCYCLE); + time = std::make_shared<time_counter_csr_t>(proc, CSR_TIME); if (proc->extension_enabled_const(EXT_ZICNTR)) { 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, mcycle); + csrmap[CSR_TIME] = std::make_shared<counter_proxy_csr_t>(proc, CSR_TIME, time); } if (xlen == 32) { csr_t_p minstreth, mcycleh; @@ -215,8 +217,10 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) csrmap[CSR_MCYCLE] = std::make_shared<rv32_low_csr_t>(proc, CSR_MCYCLE, mcycle); csrmap[CSR_MCYCLEH] = mcycleh = std::make_shared<rv32_high_csr_t>(proc, CSR_MCYCLEH, mcycle); if (proc->extension_enabled_const(EXT_ZICNTR)) { + auto timeh = std::make_shared<rv32_high_csr_t>(proc, CSR_TIMEH, time); 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, mcycleh); + csrmap[CSR_TIMEH] = std::make_shared<counter_proxy_csr_t>(proc, CSR_TIMEH, timeh); } } else { csrmap[CSR_MINSTRET] = minstret; @@ -349,6 +353,13 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) (1 << CAUSE_STORE_PAGE_FAULT); csrmap[CSR_HEDELEG] = hedeleg = std::make_shared<masked_csr_t>(proc, CSR_HEDELEG, hedeleg_mask, 0); csrmap[CSR_HCOUNTEREN] = hcounteren = std::make_shared<masked_csr_t>(proc, CSR_HCOUNTEREN, counteren_mask, 0); + htimedelta = std::make_shared<basic_csr_t>(proc, CSR_HTIMEDELTA, 0); + if (xlen == 32) { + csrmap[CSR_HTIMEDELTA] = std::make_shared<rv32_low_csr_t>(proc, CSR_HTIMEDELTA, htimedelta); + csrmap[CSR_HTIMEDELTAH] = std::make_shared<rv32_high_csr_t>(proc, CSR_HTIMEDELTAH, htimedelta); + } else { + csrmap[CSR_HTIMEDELTA] = htimedelta; + } csrmap[CSR_HTVAL] = htval = std::make_shared<basic_csr_t>(proc, CSR_HTVAL, 0); csrmap[CSR_HTINST] = htinst = std::make_shared<basic_csr_t>(proc, CSR_HTINST, 0); csrmap[CSR_HGATP] = hgatp = std::make_shared<hgatp_csr_t>(proc, CSR_HGATP); diff --git a/riscv/processor.h b/riscv/processor.h index 347ae16..b415402 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -191,6 +191,9 @@ struct state_t csr_t_p sstateen[4]; csr_t_p hstateen[4]; + csr_t_p htimedelta; + time_counter_csr_t_p time; + bool serialized; // whether timer CSRs are in a well-defined state // When true, execute a single instruction and then enter debug mode. This |