aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riscv/csrs.cc42
-rw-r--r--riscv/csrs.h9
-rw-r--r--riscv/isa_parser.cc2
-rw-r--r--riscv/isa_parser.h1
-rw-r--r--riscv/processor.cc17
-rw-r--r--riscv/processor.h1
6 files changed, 65 insertions, 7 deletions
diff --git a/riscv/csrs.cc b/riscv/csrs.cc
index 50cbfb3..f50ac6e 100644
--- a/riscv/csrs.cc
+++ b/riscv/csrs.cc
@@ -681,6 +681,7 @@ void mip_csr_t::backdoor_write_with_mask(const reg_t mask, const reg_t val) noex
reg_t mip_csr_t::write_mask() const noexcept {
// MIP_STIP is writable unless SSTC exists and STCE is set in MENVCFG
const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | ((state->menvcfg->read() & MENVCFG_STCE) ? 0 : MIP_STIP) | MIP_SEIP : 0;
+ const reg_t lscof_int = proc->extension_enabled(EXT_SSCOFPMF) ? MIP_LCOFIP : 0;
const reg_t vssip_int = proc->extension_enabled('H') ? MIP_VSSIP : 0;
const reg_t hypervisor_ints = proc->extension_enabled('H') ? MIP_HS_MASK : 0;
// We must mask off sgeip, vstip, and vseip. All three of these
@@ -688,8 +689,8 @@ reg_t mip_csr_t::write_mask() const noexcept {
// * sgeip is read-only -- write hgeip instead
// * vseip is read-only -- write hvip instead
// * vstip is read-only -- write hvip instead
- return (supervisor_ints | hypervisor_ints) &
- (MIP_SEIP | MIP_SSIP | MIP_STIP | vssip_int);
+ return (supervisor_ints | hypervisor_ints | lscof_int) &
+ (MIP_SEIP | MIP_SSIP | MIP_STIP | MIP_LCOFIP | vssip_int);
}
mie_csr_t::mie_csr_t(processor_t* const proc, const reg_t addr):
@@ -698,9 +699,10 @@ mie_csr_t::mie_csr_t(processor_t* const proc, const reg_t addr):
reg_t mie_csr_t::write_mask() const noexcept {
const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | MIP_STIP | MIP_SEIP : 0;
+ const reg_t lscof_int = proc->extension_enabled(EXT_SSCOFPMF) ? MIP_LCOFIP : 0;
const reg_t hypervisor_ints = proc->extension_enabled('H') ? MIP_HS_MASK : 0;
const reg_t coprocessor_ints = (reg_t)proc->any_custom_extensions() << IRQ_COP;
- const reg_t delegable_ints = supervisor_ints | coprocessor_ints;
+ const reg_t delegable_ints = supervisor_ints | coprocessor_ints | lscof_int;
const reg_t all_ints = delegable_ints | hypervisor_ints | MIP_MSIP | MIP_MTIP | MIP_MEIP;
return all_ints;
}
@@ -796,8 +798,9 @@ void mideleg_csr_t::verify_permissions(insn_t insn, bool write) const {
bool mideleg_csr_t::unlogged_write(const reg_t val) noexcept {
const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | MIP_STIP | MIP_SEIP : 0;
+ const reg_t lscof_int = proc->extension_enabled(EXT_SSCOFPMF) ? MIP_LCOFIP : 0;
const reg_t coprocessor_ints = (reg_t)proc->any_custom_extensions() << IRQ_COP;
- const reg_t delegable_ints = supervisor_ints | coprocessor_ints;
+ const reg_t delegable_ints = supervisor_ints | coprocessor_ints | lscof_int;
return basic_csr_t::unlogged_write(val & delegable_ints);
}
@@ -1435,3 +1438,34 @@ void virtualized_stimecmp_csr_t::verify_permissions(insn_t insn, bool write) con
throw trap_virtual_instruction(insn.bits());
}
}
+
+scountovf_csr_t::scountovf_csr_t(processor_t* const proc, const reg_t addr):
+ csr_t(proc, addr) {
+}
+
+void scountovf_csr_t::verify_permissions(insn_t insn, bool write) const {
+ if (!proc->extension_enabled(EXT_SSCOFPMF))
+ throw trap_illegal_instruction(insn.bits());
+ csr_t::verify_permissions(insn, write);
+}
+
+reg_t scountovf_csr_t::read() const noexcept {
+ reg_t val = 0;
+ for (reg_t i = 3; i <= 31; ++i) {
+ bool of = state->mevent[i - 3]->read() & MHPMEVENT_OF;
+ val |= of << i;
+ }
+
+ /* In M and S modes, scountovf bit X is readable when mcounteren bit X is set, */
+ /* and otherwise reads as zero. Similarly, in VS mode, scountovf bit X is readable */
+ /* when mcounteren bit X and hcounteren bit X are both set, and otherwise reads as zero. */
+ val &= state->mcounteren->read();
+ if (state->v)
+ val &= state->hcounteren->read();
+ return val;
+}
+
+bool scountovf_csr_t::unlogged_write(const reg_t val) noexcept {
+ /* this function is unused */
+ return false;
+}
diff --git a/riscv/csrs.h b/riscv/csrs.h
index acd889c..5503255 100644
--- a/riscv/csrs.h
+++ b/riscv/csrs.h
@@ -744,4 +744,13 @@ class virtualized_stimecmp_csr_t: public virtualized_csr_t {
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
diff --git a/riscv/isa_parser.cc b/riscv/isa_parser.cc
index 6ac146b..ed1295e 100644
--- a/riscv/isa_parser.cc
+++ b/riscv/isa_parser.cc
@@ -168,6 +168,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_SMEPMP] = true;
} else if (ext_str == "smstateen") {
extension_table[EXT_SMSTATEEN] = true;
+ } else if (ext_str == "sscofpmf") {
+ extension_table[EXT_SSCOFPMF] = true;
} else if (ext_str == "svnapot") {
extension_table[EXT_SVNAPOT] = true;
} else if (ext_str == "svpbmt") {
diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h
index c57436e..6b5bb0a 100644
--- a/riscv/isa_parser.h
+++ b/riscv/isa_parser.h
@@ -33,6 +33,7 @@ typedef enum {
EXT_ZPSFOPERAND,
EXT_SMEPMP,
EXT_SMSTATEEN,
+ EXT_SSCOFPMF,
EXT_SVNAPOT,
EXT_SVPBMT,
EXT_SVINVAL,
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 0389707..7cac387 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -228,13 +228,15 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
}
for (reg_t i = 3; i <= 31; ++i) {
const reg_t which_mevent = CSR_MHPMEVENT3 + i - 3;
+ const reg_t which_meventh = CSR_MHPMEVENT3H + i - 3;
const reg_t which_mcounter = CSR_MHPMCOUNTER3 + i - 3;
const reg_t which_mcounterh = CSR_MHPMCOUNTER3H + i - 3;
const reg_t which_counter = CSR_HPMCOUNTER3 + i - 3;
const reg_t which_counterh = CSR_HPMCOUNTER3H + i - 3;
- auto mevent = std::make_shared<const_csr_t>(proc, which_mevent, 0);
+ const reg_t mevent_mask = proc->extension_enabled_const(EXT_SSCOFPMF) ? MHPMEVENT_VUINH | MHPMEVENT_VSINH | MHPMEVENTH_UINH |
+ MHPMEVENT_UINH | MHPMEVENT_MINH | MHPMEVENT_OF : 0;
+ mevent[i - 3] = std::make_shared<masked_csr_t>(proc, which_mevent, mevent_mask, 0);
auto mcounter = std::make_shared<const_csr_t>(proc, which_mcounter, 0);
- csrmap[which_mevent] = mevent;
csrmap[which_mcounter] = mcounter;
if (proc->extension_enabled_const(EXT_ZICNTR) && proc->extension_enabled_const(EXT_ZIHPM)) {
@@ -242,21 +244,30 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
csrmap[which_counter] = counter;
}
if (xlen == 32) {
+ csrmap[which_mevent] = std::make_shared<rv32_low_csr_t>(proc, which_mevent, mevent[i - 3]);;
auto mcounterh = std::make_shared<const_csr_t>(proc, which_mcounterh, 0);
csrmap[which_mcounterh] = mcounterh;
if (proc->extension_enabled_const(EXT_ZICNTR) && proc->extension_enabled_const(EXT_ZIHPM)) {
auto counterh = std::make_shared<counter_proxy_csr_t>(proc, which_counterh, mcounterh);
csrmap[which_counterh] = counterh;
}
+ if (proc->extension_enabled_const(EXT_SSCOFPMF)) {
+ auto meventh = std::make_shared<rv32_high_csr_t>(proc, which_meventh, mevent[i - 3]);
+ csrmap[which_meventh] = meventh;
+ }
+ } else {
+ csrmap[which_mevent] = mevent[i - 3];
}
}
csrmap[CSR_MCOUNTINHIBIT] = std::make_shared<const_csr_t>(proc, CSR_MCOUNTINHIBIT, 0);
+ if (proc->extension_enabled_const(EXT_SSCOFPMF))
+ csrmap[CSR_SCOUNTOVF] = std::make_shared<scountovf_csr_t>(proc, CSR_SCOUNTOVF);
csrmap[CSR_MIE] = mie = std::make_shared<mie_csr_t>(proc, CSR_MIE);
csrmap[CSR_MIP] = mip = std::make_shared<mip_csr_t>(proc, CSR_MIP);
auto sip_sie_accr = std::make_shared<generic_int_accessor_t>(
this,
~MIP_HS_MASK, // read_mask
- MIP_SSIP, // ip_write_mask
+ MIP_SSIP | MIP_LCOFIP, // ip_write_mask
~MIP_HS_MASK, // ie_write_mask
generic_int_accessor_t::mask_mode_t::MIDELEG,
0 // shiftamt
diff --git a/riscv/processor.h b/riscv/processor.h
index 88ddf70..9b821b3 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -145,6 +145,7 @@ struct state_t
csr_t_p medeleg;
csr_t_p mideleg;
csr_t_p mcounteren;
+ csr_t_p mevent[29];
csr_t_p scounteren;
csr_t_p sepc;
csr_t_p stval;