Skip to content

Commit

Permalink
Merge pull request #1381 from rivosinc/smcntrpmf_feature
Browse files Browse the repository at this point in the history
Add Smcntrpmf support
  • Loading branch information
aswaterman authored Jul 26, 2023
2 parents 60c08b1 + c927773 commit c59e80e
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 24 deletions.
2 changes: 2 additions & 0 deletions disasm/isa_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
47 changes: 43 additions & 4 deletions riscv/csrs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -999,17 +999,22 @@ 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 {
return val;
}

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 {
Expand All @@ -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;
}

Expand All @@ -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),
Expand Down Expand Up @@ -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);
}
22 changes: 21 additions & 1 deletion riscv/csrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
// For access_type:
#include "memtracer.h"
#include <cassert>
// For std::optional
#include <optional>

class processor_t;
struct state_t;
Expand Down Expand Up @@ -516,20 +518,26 @@ 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;
protected:
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;
Expand Down Expand Up @@ -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
57 changes: 40 additions & 17 deletions riscv/encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions riscv/execute.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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))) { \
Expand Down
1 change: 1 addition & 0 deletions riscv/isa_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ typedef enum {
EXT_INTERNAL_ZFH_MOVE,
EXT_SMCSRIND,
EXT_SSCSRIND,
EXT_SMCNTRPMF,
NUM_ISA_EXTENSIONS
} isa_extension_t;

Expand Down
27 changes: 25 additions & 2 deletions riscv/processor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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()
Expand Down
2 changes: 2 additions & 0 deletions riscv/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit c59e80e

Please sign in to comment.