aboutsummaryrefslogtreecommitdiff
path: root/riscv/csrs.h
diff options
context:
space:
mode:
Diffstat (limited to 'riscv/csrs.h')
-rw-r--r--riscv/csrs.h161
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