Skip to content

Commit c59e80e

Browse files
authored
Merge pull request #1381 from rivosinc/smcntrpmf_feature
Add Smcntrpmf support
2 parents 60c08b1 + c927773 commit c59e80e

File tree

8 files changed

+136
-24
lines changed

8 files changed

+136
-24
lines changed

disasm/isa_parser.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
290290
extension_table[EXT_SMCSRIND] = true;
291291
} else if (ext_str == "sscsrind") {
292292
extension_table[EXT_SSCSRIND] = true;
293+
} else if (ext_str == "smcntrpmf") {
294+
extension_table[EXT_SMCNTRPMF] = true;
293295
} else if (ext_str[0] == 'x') {
294296
extension_table['X'] = true;
295297
if (ext_str.size() == 1) {

riscv/csrs.cc

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -999,17 +999,22 @@ bool virtualized_satp_csr_t::unlogged_write(const reg_t val) noexcept {
999999
}
10001000

10011001
// implement class wide_counter_csr_t
1002-
wide_counter_csr_t::wide_counter_csr_t(processor_t* const proc, const reg_t addr):
1002+
wide_counter_csr_t::wide_counter_csr_t(processor_t* const proc, const reg_t addr, smcntrpmf_csr_t_p config_csr):
10031003
csr_t(proc, addr),
1004-
val(0) {
1004+
val(0),
1005+
config_csr(config_csr) {
10051006
}
10061007

10071008
reg_t wide_counter_csr_t::read() const noexcept {
10081009
return val;
10091010
}
10101011

10111012
void wide_counter_csr_t::bump(const reg_t howmuch) noexcept {
1012-
val += howmuch; // to keep log reasonable size, don't log every bump
1013+
if (is_counting_enabled()) {
1014+
val += howmuch; // to keep log reasonable size, don't log every bump
1015+
}
1016+
// Clear cached value
1017+
config_csr->reset_prev();
10131018
}
10141019

10151020
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 {
10181023
// takes precedence over the increment to instret. However, Spike
10191024
// unconditionally increments instret after executing an instruction.
10201025
// Correct for this artifact by decrementing instret here.
1021-
this->val--;
1026+
// Ensure that Smctrpmf hasn't disabled counting.
1027+
if (is_counting_enabled()) {
1028+
this->val--;
1029+
}
10221030
return true;
10231031
}
10241032

@@ -1027,6 +1035,20 @@ reg_t wide_counter_csr_t::written_value() const noexcept {
10271035
return this->val + 1;
10281036
}
10291037

1038+
// Returns true if counting is not inhibited by Smcntrpmf.
1039+
// Note that minstretcfg / mcyclecfg / mhpmevent* share the same inhibit bits.
1040+
bool wide_counter_csr_t::is_counting_enabled() const noexcept {
1041+
auto prv = state->prv_changed ? state->prev_prv : state->prv;
1042+
auto v = state->v_changed ? state->v : state->prev_v;
1043+
auto mask = MHPMEVENT_MINH;
1044+
if (prv == PRV_S) {
1045+
mask = v ? MHPMEVENT_VSINH : MHPMEVENT_SINH;
1046+
} else if (prv == PRV_U) {
1047+
mask = v ? MHPMEVENT_VUINH : MHPMEVENT_UINH;
1048+
}
1049+
return (config_csr->read_prev() & mask) == 0;
1050+
}
1051+
10301052
// implement class time_counter_csr_t
10311053
time_counter_csr_t::time_counter_csr_t(processor_t* const proc, const reg_t addr):
10321054
csr_t(proc, addr),
@@ -1649,3 +1671,20 @@ csr_t_p sscsrind_reg_csr_t::get_reg() const noexcept {
16491671
void sscsrind_reg_csr_t::add_ireg_proxy(const reg_t iselect_value, csr_t_p csr) {
16501672
ireg_proxy[iselect_value] = csr;
16511673
}
1674+
1675+
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) {
1676+
}
1677+
1678+
reg_t smcntrpmf_csr_t::read_prev() const noexcept {
1679+
reg_t val = prev_val.value_or(read());
1680+
return val;
1681+
}
1682+
1683+
void smcntrpmf_csr_t::reset_prev() noexcept {
1684+
prev_val.reset();
1685+
}
1686+
1687+
bool smcntrpmf_csr_t::unlogged_write(const reg_t val) noexcept {
1688+
prev_val = read();
1689+
return masked_csr_t::unlogged_write(val);
1690+
}

riscv/csrs.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
// For access_type:
1616
#include "memtracer.h"
1717
#include <cassert>
18+
// For std::optional
19+
#include <optional>
1820

1921
class processor_t;
2022
struct state_t;
@@ -516,20 +518,26 @@ class virtualized_satp_csr_t: public virtualized_csr_t {
516518
satp_csr_t_p orig_satp;
517519
};
518520

521+
// Forward declaration
522+
class smcntrpmf_csr_t;
523+
typedef std::shared_ptr<smcntrpmf_csr_t> smcntrpmf_csr_t_p;
524+
519525
// For minstret and mcycle, which are always 64 bits, but in RV32 are
520526
// split into high and low halves. The first class always holds the
521527
// full 64-bit value.
522528
class wide_counter_csr_t: public csr_t {
523529
public:
524-
wide_counter_csr_t(processor_t* const proc, const reg_t addr);
530+
wide_counter_csr_t(processor_t* const proc, const reg_t addr, smcntrpmf_csr_t_p config_csr);
525531
// Always returns full 64-bit value
526532
virtual reg_t read() const noexcept override;
527533
void bump(const reg_t howmuch) noexcept;
528534
protected:
529535
virtual bool unlogged_write(const reg_t val) noexcept override;
530536
virtual reg_t written_value() const noexcept override;
531537
private:
538+
bool is_counting_enabled() const noexcept;
532539
reg_t val;
540+
smcntrpmf_csr_t_p config_csr;
533541
};
534542

535543
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 {
822830
csr_t_p get_reg() const noexcept;
823831
};
824832

833+
// smcntrpmf_csr_t caches the previous state of the CSR in case a CSRW instruction
834+
// modifies the state that should not be immediately visible to bump()
835+
class smcntrpmf_csr_t : public masked_csr_t {
836+
public:
837+
smcntrpmf_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init);
838+
reg_t read_prev() const noexcept;
839+
void reset_prev() noexcept;
840+
protected:
841+
virtual bool unlogged_write(const reg_t val) noexcept override;
842+
private:
843+
std::optional<reg_t> prev_val;
844+
};
825845
#endif

riscv/encoding.h

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
/*
66
* This file is auto-generated by running 'make' in
7-
* https://github.com/riscv/riscv-opcodes (be53d24)
7+
* https://github.com/riscv/riscv-opcodes (6790b30)
88
*/
99

1010
#ifndef RISCV_CSR_ENCODING_H
@@ -172,6 +172,7 @@
172172
#define MSTATEEN0_FCSR 0x00000002
173173
#define MSTATEEN0_JVT 0x00000004
174174
#define MSTATEEN0_HCONTEXT 0x0200000000000000
175+
#define MSTATEEN0_CD 0x0100000000000000
175176
#define MSTATEEN0_HENVCFG 0x4000000000000000
176177
#define MSTATEEN_HSTATEEN 0x8000000000000000
177178

@@ -205,6 +206,18 @@
205206
#define HENVCFGH_PBMTE 0x40000000
206207
#define HENVCFGH_STCE 0x80000000
207208

209+
#define SISELECT_SMCDELEG_START 0x40
210+
#define SISELECT_SMCDELEG_UNUSED 0x41
211+
#define SISELECT_SMCDELEG_INSTRET 0x42
212+
#define SISELECT_SMCDELEG_INSTRETCFG 0x42
213+
/*
214+
* ?iselect values for hpmcounters4..31 and hpmevent4..31
215+
* can easily computed, and were elided for brevity.
216+
*/
217+
#define SISELECT_SMCDELEG_HPMCOUNTER_3 0x43
218+
#define SISELECT_SMCDELEG_HPMEVENT_3 0x43
219+
#define SISELECT_SMCDELEG_END 0x5f
220+
208221
#define HSTATEEN0_CS 0x00000001
209222
#define HSTATEEN0_FCSR 0x00000002
210223
#define HSTATEEN0_JVT 0x00000004
@@ -2477,10 +2490,10 @@
24772490
#define MASK_VMADD_VV 0xfc00707f
24782491
#define MATCH_VMADD_VX 0xa4006057
24792492
#define MASK_VMADD_VX 0xfc00707f
2480-
#define MATCH_VMAND_MM 0x64002057
2481-
#define MASK_VMAND_MM 0xfc00707f
2482-
#define MATCH_VMANDN_MM 0x60002057
2483-
#define MASK_VMANDN_MM 0xfc00707f
2493+
#define MATCH_VMAND_MM 0x66002057
2494+
#define MASK_VMAND_MM 0xfe00707f
2495+
#define MATCH_VMANDN_MM 0x62002057
2496+
#define MASK_VMANDN_MM 0xfe00707f
24842497
#define MATCH_VMAX_VV 0x1c000057
24852498
#define MASK_VMAX_VV 0xfc00707f
24862499
#define MATCH_VMAX_VX 0x1c004057
@@ -2523,14 +2536,14 @@
25232536
#define MASK_VMINU_VV 0xfc00707f
25242537
#define MATCH_VMINU_VX 0x10004057
25252538
#define MASK_VMINU_VX 0xfc00707f
2526-
#define MATCH_VMNAND_MM 0x74002057
2527-
#define MASK_VMNAND_MM 0xfc00707f
2528-
#define MATCH_VMNOR_MM 0x78002057
2529-
#define MASK_VMNOR_MM 0xfc00707f
2530-
#define MATCH_VMOR_MM 0x68002057
2531-
#define MASK_VMOR_MM 0xfc00707f
2532-
#define MATCH_VMORN_MM 0x70002057
2533-
#define MASK_VMORN_MM 0xfc00707f
2539+
#define MATCH_VMNAND_MM 0x76002057
2540+
#define MASK_VMNAND_MM 0xfe00707f
2541+
#define MATCH_VMNOR_MM 0x7a002057
2542+
#define MASK_VMNOR_MM 0xfe00707f
2543+
#define MATCH_VMOR_MM 0x6a002057
2544+
#define MASK_VMOR_MM 0xfe00707f
2545+
#define MATCH_VMORN_MM 0x72002057
2546+
#define MASK_VMORN_MM 0xfe00707f
25342547
#define MATCH_VMSBC_VV 0x4e000057
25352548
#define MASK_VMSBC_VV 0xfe00707f
25362549
#define MATCH_VMSBC_VVM 0x4c000057
@@ -2619,10 +2632,10 @@
26192632
#define MASK_VMV_V_X 0xfff0707f
26202633
#define MATCH_VMV_X_S 0x42002057
26212634
#define MASK_VMV_X_S 0xfe0ff07f
2622-
#define MATCH_VMXNOR_MM 0x7c002057
2623-
#define MASK_VMXNOR_MM 0xfc00707f
2624-
#define MATCH_VMXOR_MM 0x6c002057
2625-
#define MASK_VMXOR_MM 0xfc00707f
2635+
#define MATCH_VMXNOR_MM 0x7e002057
2636+
#define MASK_VMXNOR_MM 0xfe00707f
2637+
#define MATCH_VMXOR_MM 0x6e002057
2638+
#define MASK_VMXOR_MM 0xfe00707f
26262639
#define MATCH_VNCLIP_WI 0xbc003057
26272640
#define MASK_VNCLIP_WI 0xfc00707f
26282641
#define MATCH_VNCLIP_WV 0xbc000057
@@ -3051,6 +3064,7 @@
30513064
#define CSR_SSTATEEN1 0x10d
30523065
#define CSR_SSTATEEN2 0x10e
30533066
#define CSR_SSTATEEN3 0x10f
3067+
#define CSR_SCOUNTINHIBIT 0x120
30543068
#define CSR_SSCRATCH 0x140
30553069
#define CSR_SEPC 0x141
30563070
#define CSR_SCAUSE 0x142
@@ -3280,6 +3294,8 @@
32803294
#define CSR_MHPMCOUNTER29 0xb1d
32813295
#define CSR_MHPMCOUNTER30 0xb1e
32823296
#define CSR_MHPMCOUNTER31 0xb1f
3297+
#define CSR_MCYCLECFG 0x321
3298+
#define CSR_MINSTRETCFG 0x322
32833299
#define CSR_MHPMEVENT3 0x323
32843300
#define CSR_MHPMEVENT4 0x324
32853301
#define CSR_MHPMEVENT5 0x325
@@ -3375,6 +3391,8 @@
33753391
#define CSR_MSTATEEN2H 0x31e
33763392
#define CSR_MSTATEEN3H 0x31f
33773393
#define CSR_MIPH 0x354
3394+
#define CSR_MCYCLECFGH 0x721
3395+
#define CSR_MINSTRETCFGH 0x722
33783396
#define CSR_MHPMEVENT3H 0x723
33793397
#define CSR_MHPMEVENT4H 0x724
33803398
#define CSR_MHPMEVENT5H 0x725
@@ -4933,6 +4951,7 @@ DECLARE_CSR(sstateen0, CSR_SSTATEEN0)
49334951
DECLARE_CSR(sstateen1, CSR_SSTATEEN1)
49344952
DECLARE_CSR(sstateen2, CSR_SSTATEEN2)
49354953
DECLARE_CSR(sstateen3, CSR_SSTATEEN3)
4954+
DECLARE_CSR(scountinhibit, CSR_SCOUNTINHIBIT)
49364955
DECLARE_CSR(sscratch, CSR_SSCRATCH)
49374956
DECLARE_CSR(sepc, CSR_SEPC)
49384957
DECLARE_CSR(scause, CSR_SCAUSE)
@@ -5162,6 +5181,8 @@ DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28)
51625181
DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29)
51635182
DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30)
51645183
DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31)
5184+
DECLARE_CSR(mcyclecfg, CSR_MCYCLECFG)
5185+
DECLARE_CSR(minstretcfg, CSR_MINSTRETCFG)
51655186
DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3)
51665187
DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4)
51675188
DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5)
@@ -5257,6 +5278,8 @@ DECLARE_CSR(mstateen1h, CSR_MSTATEEN1H)
52575278
DECLARE_CSR(mstateen2h, CSR_MSTATEEN2H)
52585279
DECLARE_CSR(mstateen3h, CSR_MSTATEEN3H)
52595280
DECLARE_CSR(miph, CSR_MIPH)
5281+
DECLARE_CSR(mcyclecfgh, CSR_MCYCLECFGH)
5282+
DECLARE_CSR(minstretcfgh, CSR_MINSTRETCFGH)
52605283
DECLARE_CSR(mhpmevent3h, CSR_MHPMEVENT3H)
52615284
DECLARE_CSR(mhpmevent4h, CSR_MHPMEVENT4H)
52625285
DECLARE_CSR(mhpmevent5h, CSR_MHPMEVENT5H)

riscv/execute.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ void processor_t::step(size_t n)
226226
size_t instret = 0;
227227
reg_t pc = state.pc;
228228
mmu_t* _mmu = mmu;
229+
state.prv_changed = false;
230+
state.v_changed = false;
229231

230232
#define advance_pc() \
231233
if (unlikely(invalid_pc(pc))) { \

riscv/isa_parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ typedef enum {
7979
EXT_INTERNAL_ZFH_MOVE,
8080
EXT_SMCSRIND,
8181
EXT_SSCSRIND,
82+
EXT_SMCNTRPMF,
8283
NUM_ISA_EXTENSIONS
8384
} isa_extension_t;
8485

riscv/processor.cc

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
203203

204204
prv = prev_prv = PRV_M;
205205
v = prev_v = false;
206+
prv_changed = false;
207+
v_changed = false;
206208
csrmap[CSR_MISA] = misa = std::make_shared<misa_csr_t>(proc, CSR_MISA, max_isa);
207209
mstatus = std::make_shared<mstatus_csr_t>(proc, CSR_MSTATUS);
208210

@@ -217,8 +219,15 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
217219
csrmap[CSR_MSCRATCH] = std::make_shared<basic_csr_t>(proc, CSR_MSCRATCH, 0);
218220
csrmap[CSR_MTVEC] = mtvec = std::make_shared<tvec_csr_t>(proc, CSR_MTVEC);
219221
csrmap[CSR_MCAUSE] = mcause = std::make_shared<cause_csr_t>(proc, CSR_MCAUSE);
220-
minstret = std::make_shared<wide_counter_csr_t>(proc, CSR_MINSTRET);
221-
mcycle = std::make_shared<wide_counter_csr_t>(proc, CSR_MCYCLE);
222+
223+
auto smcntrpmf_enabled = proc->extension_enabled_const(EXT_SMCNTRPMF);
224+
const reg_t mask = smcntrpmf_enabled ? MHPMEVENT_MINH | MHPMEVENT_SINH |
225+
MHPMEVENT_UINH | MHPMEVENT_VSINH | MHPMEVENT_VUINH : 0;
226+
auto minstretcfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MINSTRETCFG, mask, 0);
227+
auto mcyclecfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MCYCLECFG, mask, 0);
228+
229+
minstret = std::make_shared<wide_counter_csr_t>(proc, CSR_MINSTRET, minstretcfg);
230+
mcycle = std::make_shared<wide_counter_csr_t>(proc, CSR_MCYCLE, mcyclecfg);
222231
time = std::make_shared<time_counter_csr_t>(proc, CSR_TIME);
223232
if (proc->extension_enabled_const(EXT_ZICNTR)) {
224233
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)
564573
}
565574
}
566575

576+
if (smcntrpmf_enabled) {
577+
if (xlen == 32) {
578+
csrmap[CSR_MCYCLECFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_MCYCLECFG, mcyclecfg);
579+
csrmap[CSR_MCYCLECFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_MCYCLECFGH, mcyclecfg);
580+
csrmap[CSR_MINSTRETCFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_MINSTRETCFG, minstretcfg);
581+
csrmap[CSR_MINSTRETCFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_MINSTRETCFGH, minstretcfg);
582+
} else {
583+
csrmap[CSR_MCYCLECFG] = mcyclecfg;
584+
csrmap[CSR_MINSTRETCFG] = minstretcfg;
585+
}
586+
}
587+
567588
serialized = false;
568589

569590
log_reg_write.clear();
@@ -766,6 +787,8 @@ void processor_t::set_privilege(reg_t prv, bool virt)
766787
state.prev_v = state.v;
767788
state.prv = legalize_privilege(prv);
768789
state.v = virt && state.prv != PRV_M;
790+
state.prv_changed = state.prv != state.prev_prv;
791+
state.v_changed = state.v != state.prev_v;
769792
}
770793

771794
const char* processor_t::get_privilege_string()

riscv/processor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ struct state_t
8484
std::unordered_map<reg_t, csr_t_p> csrmap;
8585
reg_t prv; // TODO: Can this be an enum instead?
8686
reg_t prev_prv;
87+
bool prv_changed;
88+
bool v_changed;
8789
bool v;
8890
bool prev_v;
8991
misa_csr_t_p misa;

0 commit comments

Comments
 (0)