[rtl] Alter some CSR WARL behaviour to match spike

The following changes are made:

- For unimplemented counters corresponding bits in MCOUNTINHIBIT read as
0 not 1
- For MHPMEVENTx we start at x = 3 with the first bit set (0-2
MHPMEVENTx CSRs do not exist)
- When writing an invalid privilege mode to MSTATUS.MPP/DCSR.PRV default
to U rather than M mode.

These new behaviours remain spec compliant and match spike.
This commit is contained in:
Greg Chadwick 2022-08-05 11:22:11 +01:00 committed by Greg Chadwick
parent 19d12ee3a7
commit e53a02ab31
2 changed files with 13 additions and 10 deletions

View file

@ -33,11 +33,11 @@ RegisterModel::RegisterModel(SimCtrl *sc, CSRParams *params) : simctrl_(sc) {
}
}
// mcountinhibit
// - MSBs are always 1: unused counters cannot be enabled
// - MSBs are always 0: unused counters cannot be inhibited
// - Bit 1 is always 0: time cannot be disabled
uint32_t mcountinhibit_mask =
(~((0x1 << params->MHPMCounterNum) - 1) << 3) | 0x2;
uint32_t mcountinhibit_resval = ~((0x1 << params->MHPMCounterNum) - 1) << 3;
uint32_t mcountinhibit_resval = 0;
register_map_.push_back(std::make_unique<WARLRegister>(
0x320, &register_map_, mcountinhibit_mask, mcountinhibit_resval));
// Performance counter setup
@ -45,7 +45,7 @@ RegisterModel::RegisterModel(SimCtrl *sc, CSRParams *params) : simctrl_(sc) {
uint32_t reg_addr = 0x320 + i;
if (i < (params->MHPMCounterNum + 3)) {
register_map_.push_back(std::make_unique<WARLRegister>(
reg_addr, &register_map_, 0xFFFFFFFF, 0x1 << i));
reg_addr, &register_map_, 0xFFFFFFFF, 0x1 << (i - 3)));
} else {
register_map_.push_back(
std::make_unique<NonImpRegister>(reg_addr, &register_map_));

View file

@ -566,9 +566,9 @@ module ibex_cs_registers #(
mprv: csr_wdata_int[CSR_MSTATUS_MPRV_BIT],
tw: csr_wdata_int[CSR_MSTATUS_TW_BIT]
};
// Convert illegal values to M-mode
// Convert illegal values to U-mode
if ((mstatus_d.mpp != PRIV_LVL_M) && (mstatus_d.mpp != PRIV_LVL_U)) begin
mstatus_d.mpp = PRIV_LVL_M;
mstatus_d.mpp = PRIV_LVL_U;
end
end
@ -592,9 +592,9 @@ module ibex_cs_registers #(
CSR_DCSR: begin
dcsr_d = csr_wdata_int;
dcsr_d.xdebugver = XDEBUGVER_STD;
// Change to PRIV_LVL_M if software writes an unsupported value
// Change to PRIV_LVL_U if software writes an unsupported value
if ((dcsr_d.prv != PRIV_LVL_M) && (dcsr_d.prv != PRIV_LVL_U)) begin
dcsr_d.prv = PRIV_LVL_M;
dcsr_d.prv = PRIV_LVL_U;
end
// Read-only for SW
@ -1254,8 +1254,11 @@ module ibex_cs_registers #(
// activate all
for (int i = 0; i < 32; i++) begin : gen_mhpmevent_active
mhpmevent[i] = '0;
mhpmevent[i][i] = 1'b1;
mhpmevent[i] = '0;
if (i >= 3) begin
mhpmevent[i][i - 3] = 1'b1;
end
end
// deactivate
@ -1358,7 +1361,7 @@ module ibex_cs_registers #(
logic [29-MHPMCounterNum-1:0] unused_mhphcounterh_we;
logic [29-MHPMCounterNum-1:0] unused_mhphcounter_incr;
assign mcountinhibit = {{29 - MHPMCounterNum{1'b1}}, mcountinhibit_q};
assign mcountinhibit = {{29 - MHPMCounterNum{1'b0}}, mcountinhibit_q};
// Lint tieoffs for unused bits
assign unused_mhphcounter_we = mhpmcounter_we[31:MHPMCounterNum+3];
assign unused_mhphcounterh_we = mhpmcounterh_we[31:MHPMCounterNum+3];