aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2023-07-26 12:45:44 -0700
committerGitHub <noreply@github.com>2023-07-26 12:45:44 -0700
commitc59e80e980e46b1425016d6a31d7f21c8d9ebfa2 (patch)
treeb5398b210a0437b256f9cf69b80ef7280fe2c302
parent60c08b1ea5e3d96a97c235db87d472a7cfb2611b (diff)
parentc927773dd1584d870dd60a1cf86c0a8f0d138dd4 (diff)
downloadriscv-isa-sim-c59e80e980e46b1425016d6a31d7f21c8d9ebfa2.zip
riscv-isa-sim-c59e80e980e46b1425016d6a31d7f21c8d9ebfa2.tar.gz
riscv-isa-sim-c59e80e980e46b1425016d6a31d7f21c8d9ebfa2.tar.bz2
Merge pull request #1381 from rivosinc/smcntrpmf_feature
Add Smcntrpmf support
-rw-r--r--disasm/isa_parser.cc2
-rw-r--r--riscv/csrs.cc47
-rw-r--r--riscv/csrs.h22
-rw-r--r--riscv/encoding.h57
-rw-r--r--riscv/execute.cc2
-rw-r--r--riscv/isa_parser.h1
-rw-r--r--riscv/processor.cc27
-rw-r--r--riscv/processor.h2
8 files changed, 136 insertions, 24 deletions
diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc
index f4d9da4..d5dc439 100644
--- a/disasm/isa_parser.cc
+++ b/disasm/isa_parser.cc
@@ -290,6 +290,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_SMCSRIND] = true;
} else if (ext_str == "sscsrind") {
extension_table[EXT_SSCSRIND] = true;
+ } else if (ext_str == "smcntrpmf") {
+ extension_table[EXT_SMCNTRPMF] = true;
} else if (ext_str[0] == 'x') {
extension_table['X'] = true;
if (ext_str.size() == 1) {
diff --git a/riscv/csrs.cc b/riscv/csrs.cc
index 9849ea2..e3b5ad4 100644
--- a/riscv/csrs.cc
+++ b/riscv/csrs.cc
@@ -999,9 +999,10 @@ bool virtualized_satp_csr_t::unlogged_write(const reg_t val) noexcept {
}
// implement class wide_counter_csr_t
-wide_counter_csr_t::wide_counter_csr_t(processor_t* const proc, const reg_t addr):
+wide_counter_csr_t::wide_counter_csr_t(processor_t* const proc, const reg_t addr, smcntrpmf_csr_t_p config_csr):
csr_t(proc, addr),
- val(0) {
+ val(0),
+ config_csr(config_csr) {
}
reg_t wide_counter_csr_t::read() const noexcept {
@@ -1009,7 +1010,11 @@ reg_t wide_counter_csr_t::read() const noexcept {
}
void wide_counter_csr_t::bump(const reg_t howmuch) noexcept {
- val += howmuch; // to keep log reasonable size, don't log every bump
+ if (is_counting_enabled()) {
+ val += howmuch; // to keep log reasonable size, don't log every bump
+ }
+ // Clear cached value
+ config_csr->reset_prev();
}
bool wide_counter_csr_t::unlogged_write(const reg_t val) noexcept {
@@ -1018,7 +1023,10 @@ bool wide_counter_csr_t::unlogged_write(const reg_t val) noexcept {
// takes precedence over the increment to instret. However, Spike
// unconditionally increments instret after executing an instruction.
// Correct for this artifact by decrementing instret here.
- this->val--;
+ // Ensure that Smctrpmf hasn't disabled counting.
+ if (is_counting_enabled()) {
+ this->val--;
+ }
return true;
}
@@ -1027,6 +1035,20 @@ reg_t wide_counter_csr_t::written_value() const noexcept {
return this->val + 1;
}
+// Returns true if counting is not inhibited by Smcntrpmf.
+// Note that minstretcfg / mcyclecfg / mhpmevent* share the same inhibit bits.
+bool wide_counter_csr_t::is_counting_enabled() const noexcept {
+ auto prv = state->prv_changed ? state->prev_prv : state->prv;
+ auto v = state->v_changed ? state->v : state->prev_v;
+ auto mask = MHPMEVENT_MINH;
+ if (prv == PRV_S) {
+ mask = v ? MHPMEVENT_VSINH : MHPMEVENT_SINH;
+ } else if (prv == PRV_U) {
+ mask = v ? MHPMEVENT_VUINH : MHPMEVENT_UINH;
+ }
+ return (config_csr->read_prev() & mask) == 0;
+}
+
// 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),
@@ -1649,3 +1671,20 @@ csr_t_p sscsrind_reg_csr_t::get_reg() const noexcept {
void sscsrind_reg_csr_t::add_ireg_proxy(const reg_t iselect_value, csr_t_p csr) {
ireg_proxy[iselect_value] = csr;
}
+
+smcntrpmf_csr_t::smcntrpmf_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init) : masked_csr_t(proc, addr, mask, init) {
+}
+
+reg_t smcntrpmf_csr_t::read_prev() const noexcept {
+ reg_t val = prev_val.value_or(read());
+ return val;
+}
+
+void smcntrpmf_csr_t::reset_prev() noexcept {
+ prev_val.reset();
+}
+
+bool smcntrpmf_csr_t::unlogged_write(const reg_t val) noexcept {
+ prev_val = read();
+ return masked_csr_t::unlogged_write(val);
+}
diff --git a/riscv/csrs.h b/riscv/csrs.h
index cf48673..5ca7e15 100644
--- a/riscv/csrs.h
+++ b/riscv/csrs.h
@@ -15,6 +15,8 @@
// For access_type:
#include "memtracer.h"
#include <cassert>
+// For std::optional
+#include <optional>
class processor_t;
struct state_t;
@@ -516,12 +518,16 @@ class virtualized_satp_csr_t: public virtualized_csr_t {
satp_csr_t_p orig_satp;
};
+// Forward declaration
+class smcntrpmf_csr_t;
+typedef std::shared_ptr<smcntrpmf_csr_t> smcntrpmf_csr_t_p;
+
// 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);
+ wide_counter_csr_t(processor_t* const proc, const reg_t addr, smcntrpmf_csr_t_p config_csr);
// Always returns full 64-bit value
virtual reg_t read() const noexcept override;
void bump(const reg_t howmuch) noexcept;
@@ -529,7 +535,9 @@ class wide_counter_csr_t: public csr_t {
virtual bool unlogged_write(const reg_t val) noexcept override;
virtual reg_t written_value() const noexcept override;
private:
+ bool is_counting_enabled() const noexcept;
reg_t val;
+ smcntrpmf_csr_t_p config_csr;
};
typedef std::shared_ptr<wide_counter_csr_t> wide_counter_csr_t_p;
@@ -822,4 +830,16 @@ class sscsrind_reg_csr_t : public csr_t {
csr_t_p get_reg() const noexcept;
};
+// smcntrpmf_csr_t caches the previous state of the CSR in case a CSRW instruction
+// modifies the state that should not be immediately visible to bump()
+class smcntrpmf_csr_t : public masked_csr_t {
+ public:
+ smcntrpmf_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init);
+ reg_t read_prev() const noexcept;
+ void reset_prev() noexcept;
+ protected:
+ virtual bool unlogged_write(const reg_t val) noexcept override;
+ private:
+ std::optional<reg_t> prev_val;
+};
#endif
diff --git a/riscv/encoding.h b/riscv/encoding.h
index 9666774..f1defd4 100644
--- a/riscv/encoding.h
+++ b/riscv/encoding.h
@@ -4,7 +4,7 @@
/*
* This file is auto-generated by running 'make' in
- * https://github.com/riscv/riscv-opcodes (be53d24)
+ * https://github.com/riscv/riscv-opcodes (6790b30)
*/
#ifndef RISCV_CSR_ENCODING_H
@@ -172,6 +172,7 @@
#define MSTATEEN0_FCSR 0x00000002
#define MSTATEEN0_JVT 0x00000004
#define MSTATEEN0_HCONTEXT 0x0200000000000000
+#define MSTATEEN0_CD 0x0100000000000000
#define MSTATEEN0_HENVCFG 0x4000000000000000
#define MSTATEEN_HSTATEEN 0x8000000000000000
@@ -205,6 +206,18 @@
#define HENVCFGH_PBMTE 0x40000000
#define HENVCFGH_STCE 0x80000000
+#define SISELECT_SMCDELEG_START 0x40
+#define SISELECT_SMCDELEG_UNUSED 0x41
+#define SISELECT_SMCDELEG_INSTRET 0x42
+#define SISELECT_SMCDELEG_INSTRETCFG 0x42
+/*
+ * ?iselect values for hpmcounters4..31 and hpmevent4..31
+ * can easily computed, and were elided for brevity.
+ */
+#define SISELECT_SMCDELEG_HPMCOUNTER_3 0x43
+#define SISELECT_SMCDELEG_HPMEVENT_3 0x43
+#define SISELECT_SMCDELEG_END 0x5f
+
#define HSTATEEN0_CS 0x00000001
#define HSTATEEN0_FCSR 0x00000002
#define HSTATEEN0_JVT 0x00000004
@@ -2477,10 +2490,10 @@
#define MASK_VMADD_VV 0xfc00707f
#define MATCH_VMADD_VX 0xa4006057
#define MASK_VMADD_VX 0xfc00707f
-#define MATCH_VMAND_MM 0x64002057
-#define MASK_VMAND_MM 0xfc00707f
-#define MATCH_VMANDN_MM 0x60002057
-#define MASK_VMANDN_MM 0xfc00707f
+#define MATCH_VMAND_MM 0x66002057
+#define MASK_VMAND_MM 0xfe00707f
+#define MATCH_VMANDN_MM 0x62002057
+#define MASK_VMANDN_MM 0xfe00707f
#define MATCH_VMAX_VV 0x1c000057
#define MASK_VMAX_VV 0xfc00707f
#define MATCH_VMAX_VX 0x1c004057
@@ -2523,14 +2536,14 @@
#define MASK_VMINU_VV 0xfc00707f
#define MATCH_VMINU_VX 0x10004057
#define MASK_VMINU_VX 0xfc00707f
-#define MATCH_VMNAND_MM 0x74002057
-#define MASK_VMNAND_MM 0xfc00707f
-#define MATCH_VMNOR_MM 0x78002057
-#define MASK_VMNOR_MM 0xfc00707f
-#define MATCH_VMOR_MM 0x68002057
-#define MASK_VMOR_MM 0xfc00707f
-#define MATCH_VMORN_MM 0x70002057
-#define MASK_VMORN_MM 0xfc00707f
+#define MATCH_VMNAND_MM 0x76002057
+#define MASK_VMNAND_MM 0xfe00707f
+#define MATCH_VMNOR_MM 0x7a002057
+#define MASK_VMNOR_MM 0xfe00707f
+#define MATCH_VMOR_MM 0x6a002057
+#define MASK_VMOR_MM 0xfe00707f
+#define MATCH_VMORN_MM 0x72002057
+#define MASK_VMORN_MM 0xfe00707f
#define MATCH_VMSBC_VV 0x4e000057
#define MASK_VMSBC_VV 0xfe00707f
#define MATCH_VMSBC_VVM 0x4c000057
@@ -2619,10 +2632,10 @@
#define MASK_VMV_V_X 0xfff0707f
#define MATCH_VMV_X_S 0x42002057
#define MASK_VMV_X_S 0xfe0ff07f
-#define MATCH_VMXNOR_MM 0x7c002057
-#define MASK_VMXNOR_MM 0xfc00707f
-#define MATCH_VMXOR_MM 0x6c002057
-#define MASK_VMXOR_MM 0xfc00707f
+#define MATCH_VMXNOR_MM 0x7e002057
+#define MASK_VMXNOR_MM 0xfe00707f
+#define MATCH_VMXOR_MM 0x6e002057
+#define MASK_VMXOR_MM 0xfe00707f
#define MATCH_VNCLIP_WI 0xbc003057
#define MASK_VNCLIP_WI 0xfc00707f
#define MATCH_VNCLIP_WV 0xbc000057
@@ -3051,6 +3064,7 @@
#define CSR_SSTATEEN1 0x10d
#define CSR_SSTATEEN2 0x10e
#define CSR_SSTATEEN3 0x10f
+#define CSR_SCOUNTINHIBIT 0x120
#define CSR_SSCRATCH 0x140
#define CSR_SEPC 0x141
#define CSR_SCAUSE 0x142
@@ -3280,6 +3294,8 @@
#define CSR_MHPMCOUNTER29 0xb1d
#define CSR_MHPMCOUNTER30 0xb1e
#define CSR_MHPMCOUNTER31 0xb1f
+#define CSR_MCYCLECFG 0x321
+#define CSR_MINSTRETCFG 0x322
#define CSR_MHPMEVENT3 0x323
#define CSR_MHPMEVENT4 0x324
#define CSR_MHPMEVENT5 0x325
@@ -3375,6 +3391,8 @@
#define CSR_MSTATEEN2H 0x31e
#define CSR_MSTATEEN3H 0x31f
#define CSR_MIPH 0x354
+#define CSR_MCYCLECFGH 0x721
+#define CSR_MINSTRETCFGH 0x722
#define CSR_MHPMEVENT3H 0x723
#define CSR_MHPMEVENT4H 0x724
#define CSR_MHPMEVENT5H 0x725
@@ -4933,6 +4951,7 @@ DECLARE_CSR(sstateen0, CSR_SSTATEEN0)
DECLARE_CSR(sstateen1, CSR_SSTATEEN1)
DECLARE_CSR(sstateen2, CSR_SSTATEEN2)
DECLARE_CSR(sstateen3, CSR_SSTATEEN3)
+DECLARE_CSR(scountinhibit, CSR_SCOUNTINHIBIT)
DECLARE_CSR(sscratch, CSR_SSCRATCH)
DECLARE_CSR(sepc, CSR_SEPC)
DECLARE_CSR(scause, CSR_SCAUSE)
@@ -5162,6 +5181,8 @@ DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28)
DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29)
DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30)
DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31)
+DECLARE_CSR(mcyclecfg, CSR_MCYCLECFG)
+DECLARE_CSR(minstretcfg, CSR_MINSTRETCFG)
DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3)
DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4)
DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5)
@@ -5257,6 +5278,8 @@ DECLARE_CSR(mstateen1h, CSR_MSTATEEN1H)
DECLARE_CSR(mstateen2h, CSR_MSTATEEN2H)
DECLARE_CSR(mstateen3h, CSR_MSTATEEN3H)
DECLARE_CSR(miph, CSR_MIPH)
+DECLARE_CSR(mcyclecfgh, CSR_MCYCLECFGH)
+DECLARE_CSR(minstretcfgh, CSR_MINSTRETCFGH)
DECLARE_CSR(mhpmevent3h, CSR_MHPMEVENT3H)
DECLARE_CSR(mhpmevent4h, CSR_MHPMEVENT4H)
DECLARE_CSR(mhpmevent5h, CSR_MHPMEVENT5H)
diff --git a/riscv/execute.cc b/riscv/execute.cc
index 591090b..4f5860b 100644
--- a/riscv/execute.cc
+++ b/riscv/execute.cc
@@ -226,6 +226,8 @@ void processor_t::step(size_t n)
size_t instret = 0;
reg_t pc = state.pc;
mmu_t* _mmu = mmu;
+ state.prv_changed = false;
+ state.v_changed = false;
#define advance_pc() \
if (unlikely(invalid_pc(pc))) { \
diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h
index bba5a91..f955e16 100644
--- a/riscv/isa_parser.h
+++ b/riscv/isa_parser.h
@@ -79,6 +79,7 @@ typedef enum {
EXT_INTERNAL_ZFH_MOVE,
EXT_SMCSRIND,
EXT_SSCSRIND,
+ EXT_SMCNTRPMF,
NUM_ISA_EXTENSIONS
} isa_extension_t;
diff --git a/riscv/processor.cc b/riscv/processor.cc
index ff64f5a..0704d8c 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -203,6 +203,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
prv = prev_prv = PRV_M;
v = prev_v = false;
+ prv_changed = false;
+ v_changed = false;
csrmap[CSR_MISA] = misa = std::make_shared<misa_csr_t>(proc, CSR_MISA, max_isa);
mstatus = std::make_shared<mstatus_csr_t>(proc, CSR_MSTATUS);
@@ -217,8 +219,15 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
csrmap[CSR_MSCRATCH] = std::make_shared<basic_csr_t>(proc, CSR_MSCRATCH, 0);
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);
- minstret = std::make_shared<wide_counter_csr_t>(proc, CSR_MINSTRET);
- mcycle = std::make_shared<wide_counter_csr_t>(proc, CSR_MCYCLE);
+
+ auto smcntrpmf_enabled = proc->extension_enabled_const(EXT_SMCNTRPMF);
+ const reg_t mask = smcntrpmf_enabled ? MHPMEVENT_MINH | MHPMEVENT_SINH |
+ MHPMEVENT_UINH | MHPMEVENT_VSINH | MHPMEVENT_VUINH : 0;
+ auto minstretcfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MINSTRETCFG, mask, 0);
+ auto mcyclecfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MCYCLECFG, mask, 0);
+
+ minstret = std::make_shared<wide_counter_csr_t>(proc, CSR_MINSTRET, minstretcfg);
+ mcycle = std::make_shared<wide_counter_csr_t>(proc, CSR_MCYCLE, mcyclecfg);
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);
@@ -564,6 +573,18 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
}
}
+ if (smcntrpmf_enabled) {
+ if (xlen == 32) {
+ csrmap[CSR_MCYCLECFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_MCYCLECFG, mcyclecfg);
+ csrmap[CSR_MCYCLECFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_MCYCLECFGH, mcyclecfg);
+ csrmap[CSR_MINSTRETCFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_MINSTRETCFG, minstretcfg);
+ csrmap[CSR_MINSTRETCFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_MINSTRETCFGH, minstretcfg);
+ } else {
+ csrmap[CSR_MCYCLECFG] = mcyclecfg;
+ csrmap[CSR_MINSTRETCFG] = minstretcfg;
+ }
+ }
+
serialized = false;
log_reg_write.clear();
@@ -766,6 +787,8 @@ void processor_t::set_privilege(reg_t prv, bool virt)
state.prev_v = state.v;
state.prv = legalize_privilege(prv);
state.v = virt && state.prv != PRV_M;
+ state.prv_changed = state.prv != state.prev_prv;
+ state.v_changed = state.v != state.prev_v;
}
const char* processor_t::get_privilege_string()
diff --git a/riscv/processor.h b/riscv/processor.h
index 1b00808..a2e4286 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -84,6 +84,8 @@ struct state_t
std::unordered_map<reg_t, csr_t_p> csrmap;
reg_t prv; // TODO: Can this be an enum instead?
reg_t prev_prv;
+ bool prv_changed;
+ bool v_changed;
bool v;
bool prev_v;
misa_csr_t_p misa;