diff options
Diffstat (limited to 'riscv/csrs.h')
-rw-r--r-- | riscv/csrs.h | 161 |
1 files changed, 114 insertions, 47 deletions
diff --git a/riscv/csrs.h b/riscv/csrs.h index fb27ae6..70fa2f4 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -53,11 +53,14 @@ class csr_t { private: const unsigned csr_priv; const bool csr_read_only; + + // For access to written_value() and unlogged_write(): + friend class rv32_high_csr_t; + friend class rv32_low_csr_t; }; typedef std::shared_ptr<csr_t> csr_t_p; - // Basic CSRs, with XLEN bits fully readable and writable. class basic_csr_t: public csr_t { public: @@ -73,7 +76,6 @@ class basic_csr_t: public csr_t { reg_t val; }; - class pmpaddr_csr_t: public csr_t { public: pmpaddr_csr_t(processor_t* const proc, const reg_t addr); @@ -89,6 +91,11 @@ class pmpaddr_csr_t: public csr_t { // Is the specified access allowed given the pmpcfg privileges? bool access_ok(access_type type, reg_t mode) const noexcept; + // To check lock bit status from outside like mseccfg + bool is_locked() const noexcept { + return cfg & PMP_L; + } + protected: virtual bool unlogged_write(const reg_t val) noexcept override; private: @@ -117,11 +124,24 @@ typedef std::shared_ptr<pmpaddr_csr_t> pmpaddr_csr_t_p; class pmpcfg_csr_t: public csr_t { public: pmpcfg_csr_t(processor_t* const proc, const reg_t addr); + virtual void verify_permissions(insn_t insn, bool write) const override; virtual reg_t read() const noexcept override; protected: virtual bool unlogged_write(const reg_t val) noexcept override; }; +class mseccfg_csr_t: public basic_csr_t { + public: + mseccfg_csr_t(processor_t* const proc, const reg_t addr); + virtual void verify_permissions(insn_t insn, bool write) const override; + bool get_mml() const noexcept; + bool get_mmwp() const noexcept; + bool get_rlb() const noexcept; + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; +}; + +typedef std::shared_ptr<mseccfg_csr_t> mseccfg_csr_t_p; // For CSRs that have a virtualized copy under another name. Each // instance of virtualized_csr_t will read/write one of two CSRs, @@ -158,7 +178,6 @@ class epc_csr_t: public csr_t { reg_t val; }; - // For mtvec, stvec, and vstvec class tvec_csr_t: public csr_t { public: @@ -171,7 +190,6 @@ class tvec_csr_t: public csr_t { reg_t val; }; - // For mcause, scause, and vscause class cause_csr_t: public basic_csr_t { public: @@ -180,7 +198,6 @@ class cause_csr_t: public basic_csr_t { virtual reg_t read() const noexcept override; }; - // For *status family of CSRs class base_status_csr_t: public csr_t { public: @@ -202,7 +219,6 @@ class base_status_csr_t: public csr_t { typedef std::shared_ptr<base_status_csr_t> base_status_csr_t_p; - // For vsstatus, which is its own separate architectural register // (unlike sstatus) class vsstatus_csr_t final: public base_status_csr_t { @@ -221,7 +237,6 @@ class vsstatus_csr_t final: public base_status_csr_t { typedef std::shared_ptr<vsstatus_csr_t> vsstatus_csr_t_p; - class mstatus_csr_t final: public base_status_csr_t { public: mstatus_csr_t(processor_t* const proc, const reg_t addr); @@ -233,24 +248,37 @@ class mstatus_csr_t final: public base_status_csr_t { protected: virtual bool unlogged_write(const reg_t val) noexcept override; private: + reg_t compute_mstatus_initial_value() const noexcept; reg_t val; - friend class mstatush_csr_t; }; typedef std::shared_ptr<mstatus_csr_t> mstatus_csr_t_p; - -class mstatush_csr_t: public csr_t { +// For RV32 CSRs that are split into two, e.g. mstatus/mstatush +// CSRW should only modify the lower half +class rv32_low_csr_t: public csr_t { public: - mstatush_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus); + rv32_low_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig); virtual reg_t read() const noexcept override; + virtual void verify_permissions(insn_t insn, bool write) const override; protected: virtual bool unlogged_write(const reg_t val) noexcept override; + virtual reg_t written_value() const noexcept override; private: - mstatus_csr_t_p mstatus; - const reg_t mask; + csr_t_p orig; }; +class rv32_high_csr_t: public csr_t { + public: + rv32_high_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig); + virtual reg_t read() const noexcept override; + virtual void verify_permissions(insn_t insn, bool write) const override; + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; + virtual reg_t written_value() const noexcept override; + private: + csr_t_p orig; +}; class sstatus_proxy_csr_t final: public base_status_csr_t { public: @@ -283,7 +311,6 @@ class sstatus_csr_t: public virtualized_csr_t { typedef std::shared_ptr<sstatus_csr_t> sstatus_csr_t_p; - class misa_csr_t final: public basic_csr_t { public: misa_csr_t(processor_t* const proc, const reg_t addr, const reg_t max_isa); @@ -299,12 +326,11 @@ class misa_csr_t final: public basic_csr_t { private: const reg_t max_isa; const reg_t write_mask; - const reg_t dependency(const reg_t val, const char feature, const char depends_on) const noexcept; + reg_t dependency(const reg_t val, const char feature, const char depends_on) const noexcept; }; typedef std::shared_ptr<misa_csr_t> misa_csr_t_p; - class mip_or_mie_csr_t: public csr_t { public: mip_or_mie_csr_t(processor_t* const proc, const reg_t addr); @@ -319,7 +345,6 @@ class mip_or_mie_csr_t: public csr_t { virtual reg_t write_mask() const noexcept = 0; }; - // mip is special because some of the bits are driven by hardware pins class mip_csr_t: public mip_or_mie_csr_t { public: @@ -333,7 +358,6 @@ class mip_csr_t: public mip_or_mie_csr_t { typedef std::shared_ptr<mip_csr_t> mip_csr_t_p; - class mie_csr_t: public mip_or_mie_csr_t { public: mie_csr_t(processor_t* const proc, const reg_t addr); @@ -343,7 +367,6 @@ class mie_csr_t: public mip_or_mie_csr_t { typedef std::shared_ptr<mie_csr_t> mie_csr_t_p; - // For sip, hip, hvip, vsip, sie, hie, vsie which are all just (masked // & shifted) views into mip or mie. Each pair will have one of these // objects describing the view, e.g. one for sip+sie, one for hip+hie, @@ -375,7 +398,6 @@ class generic_int_accessor_t { typedef std::shared_ptr<generic_int_accessor_t> generic_int_accessor_t_p; - // For all CSRs that are simply (masked & shifted) views into mip class mip_proxy_csr_t: public csr_t { public: @@ -398,8 +420,6 @@ class mie_proxy_csr_t: public csr_t { generic_int_accessor_t_p accr; }; - - class mideleg_csr_t: public basic_csr_t { public: mideleg_csr_t(processor_t* const proc, const reg_t addr); @@ -409,7 +429,6 @@ class mideleg_csr_t: public basic_csr_t { virtual bool unlogged_write(const reg_t val) noexcept override; }; - class medeleg_csr_t: public basic_csr_t { public: medeleg_csr_t(processor_t* const proc, const reg_t addr); @@ -420,7 +439,6 @@ class medeleg_csr_t: public basic_csr_t { const reg_t hypervisor_exceptions; }; - // For CSRs with certain bits hardwired class masked_csr_t: public basic_csr_t { public: @@ -431,6 +449,21 @@ class masked_csr_t: public basic_csr_t { const reg_t mask; }; +// henvcfg.pbmte is read_only 0 when menvcfg.pbmte = 0 +// henvcfg.stce is read_only 0 when menvcfg.stce = 0 +class henvcfg_csr_t final: public masked_csr_t { + public: + henvcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init, csr_t_p menvcfg); + + reg_t read() const noexcept override { + return (menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE)) & masked_csr_t::read(); + } + + virtual void verify_permissions(insn_t insn, bool write) const override; + + private: + csr_t_p menvcfg; +}; // For satp and vsatp // These are three classes in order to handle the [V]TVM bits permission checks @@ -462,7 +495,6 @@ class virtualized_satp_csr_t: public virtualized_csr_t { satp_csr_t_p orig_satp; }; - // 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. @@ -472,7 +504,6 @@ class wide_counter_csr_t: public csr_t { // 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; virtual reg_t written_value() const noexcept override; @@ -482,20 +513,20 @@ 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/mcycle -class counter_top_csr_t: public csr_t { +class time_counter_csr_t: public csr_t { public: - counter_top_csr_t(processor_t* const proc, const reg_t addr, wide_counter_csr_t_p parent); + 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; + virtual bool unlogged_write(const reg_t UNUSED val) noexcept override { return false; }; private: - wide_counter_csr_t_p parent; + reg_t shadow_val; }; -typedef std::shared_ptr<counter_top_csr_t> counter_top_csr_t_p; - +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 { @@ -508,7 +539,6 @@ class proxy_csr_t: public csr_t { csr_t_p delegate; }; - // For a CSR with a fixed, unchanging value class const_csr_t: public csr_t { public: @@ -520,7 +550,6 @@ class const_csr_t: public csr_t { const reg_t val; }; - // For a CSR that is an unprivileged accessor of a privileged counter class counter_proxy_csr_t: public proxy_csr_t { public: @@ -530,7 +559,6 @@ class counter_proxy_csr_t: public proxy_csr_t { bool myenable(csr_t_p counteren) const noexcept; }; - // For machine-level CSRs that only exist with Hypervisor class hypervisor_csr_t: public basic_csr_t { public: @@ -538,7 +566,6 @@ class hypervisor_csr_t: public basic_csr_t { virtual void verify_permissions(insn_t insn, bool write) const override; }; - class hideleg_csr_t: public masked_csr_t { public: hideleg_csr_t(processor_t* const proc, const reg_t addr, csr_t_p mideleg); @@ -547,7 +574,6 @@ class hideleg_csr_t: public masked_csr_t { csr_t_p mideleg; }; - class hgatp_csr_t: public basic_csr_t { public: hgatp_csr_t(processor_t* const proc, const reg_t addr); @@ -556,7 +582,6 @@ class hgatp_csr_t: public basic_csr_t { virtual bool unlogged_write(const reg_t val) noexcept override; }; - class tselect_csr_t: public basic_csr_t { public: tselect_csr_t(processor_t* const proc, const reg_t addr); @@ -564,7 +589,6 @@ class tselect_csr_t: public basic_csr_t { virtual bool unlogged_write(const reg_t val) noexcept override; }; - class tdata1_csr_t: public csr_t { public: tdata1_csr_t(processor_t* const proc, const reg_t addr); @@ -590,7 +614,6 @@ class debug_mode_csr_t: public basic_csr_t { typedef std::shared_ptr<tdata2_csr_t> tdata2_csr_t_p; - class dpc_csr_t: public epc_csr_t { public: dpc_csr_t(processor_t* const proc, const reg_t addr); @@ -618,7 +641,6 @@ class dcsr_csr_t: public csr_t { typedef std::shared_ptr<dcsr_csr_t> dcsr_csr_t_p; - class float_csr_t final: public masked_csr_t { public: float_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init); @@ -629,7 +651,6 @@ class float_csr_t final: public masked_csr_t { typedef std::shared_ptr<float_csr_t> float_csr_t_p; - // For a CSR like FCSR, that is actually a view into multiple // underlying registers. class composite_csr_t: public csr_t { @@ -646,7 +667,6 @@ class composite_csr_t: public csr_t { const unsigned upper_lsb; }; - class seed_csr_t: public csr_t { public: seed_csr_t(processor_t* const proc, const reg_t addr); @@ -656,7 +676,6 @@ class seed_csr_t: public csr_t { virtual bool unlogged_write(const reg_t val) noexcept override; }; - class vector_csr_t: public basic_csr_t { public: vector_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init=0); @@ -671,7 +690,6 @@ class vector_csr_t: public basic_csr_t { typedef std::shared_ptr<vector_csr_t> vector_csr_t_p; - // For CSRs shared between Vector and P extensions (vxsat) class vxsat_csr_t: public masked_csr_t { public: @@ -681,4 +699,53 @@ class vxsat_csr_t: public masked_csr_t { virtual bool unlogged_write(const reg_t val) noexcept override; }; +class hstateen_csr_t: public masked_csr_t { + public: + hstateen_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init, uint8_t index); + virtual reg_t read() const noexcept override; + virtual void verify_permissions(insn_t insn, bool write) const override; + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; +protected: + uint8_t index; +}; + +class sstateen_csr_t: public hstateen_csr_t { + public: + sstateen_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init, uint8_t index); + virtual reg_t read() const noexcept override; + virtual void verify_permissions(insn_t insn, bool write) const override; + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; +}; + +class senvcfg_csr_t final: public masked_csr_t { + public: + senvcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init); + virtual void verify_permissions(insn_t insn, bool write) const override; +}; + +class stimecmp_csr_t: public basic_csr_t { + public: + stimecmp_csr_t(processor_t* const proc, const reg_t addr, const reg_t imask); + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; + private: + reg_t intr_mask; +}; + +class virtualized_stimecmp_csr_t: public virtualized_csr_t { + public: + virtualized_stimecmp_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt); + virtual void verify_permissions(insn_t insn, bool write) const override; +}; + +class scountovf_csr_t: public csr_t { + public: + scountovf_csr_t(processor_t* const proc, const reg_t addr); + virtual void verify_permissions(insn_t insn, bool write) const override; + virtual reg_t read() const noexcept override; + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; +}; #endif |