|
|
|
@ -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); |
|
|
|
} |
|
|
|
|