mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 21:57:11 -04:00
perf_counters: Fix bug in address encoding
The performance counters were accessible in user mode although `mcounteren` or `scounteren` are not implemented. This commit moves the writeable performance counters to machine mode. Access from user/supervisor-space will trap as this is not implemented in Ariane.
This commit is contained in:
parent
9acc57937b
commit
50b4a5d58b
4 changed files with 128 additions and 53 deletions
|
@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
|
||||
### Changed
|
||||
|
||||
- Fix privilege bug in performance counters. The counters have always been accessible in user mode.
|
||||
- Re-work interrupt and debug subsystem to associate requests during decode. This improves stability on for non-idempotent loads.
|
||||
- Fix RISC-V PK simulation bug caused due to insufficient time to init the `a0` and `a1` registers via the bootrom
|
||||
- Fix bug in wt_axi_adapter (only appeared when dcache lines were wider than icache lines)
|
||||
|
|
|
@ -354,26 +354,55 @@ package riscv;
|
|||
CSR_MHARTID = 12'hF14,
|
||||
CSR_MCYCLE = 12'hB00,
|
||||
CSR_MINSTRET = 12'hB02,
|
||||
// Performance counters (Machine Mode)
|
||||
CSR_ML1_ICACHE_MISS = 12'hB03, // L1 Instr Cache Miss
|
||||
CSR_ML1_DCACHE_MISS = 12'hB04, // L1 Data Cache Miss
|
||||
CSR_MITLB_MISS = 12'hB05, // ITLB Miss
|
||||
CSR_MDTLB_MISS = 12'hB06, // DTLB Miss
|
||||
CSR_MLOAD = 12'hB07, // Loads
|
||||
CSR_MSTORE = 12'hB08, // Stores
|
||||
CSR_MEXCEPTION = 12'hB09, // Taken exceptions
|
||||
CSR_MEXCEPTION_RET = 12'hB0A, // Exception return
|
||||
CSR_MBRANCH_JUMP = 12'hB0B, // Software change of PC
|
||||
CSR_MCALL = 12'hB0C, // Procedure call
|
||||
CSR_MRET = 12'hB0D, // Procedure Return
|
||||
CSR_MMIS_PREDICT = 12'hB0E, // Branch mis-predicted
|
||||
CSR_MSB_FULL = 12'hB0F, // Scoreboard full
|
||||
CSR_MIF_EMPTY = 12'hB10, // instruction fetch queue empty
|
||||
CSR_MHPM_COUNTER_17 = 12'hB11, // reserved
|
||||
CSR_MHPM_COUNTER_18 = 12'hB12, // reserved
|
||||
CSR_MHPM_COUNTER_19 = 12'hB13, // reserved
|
||||
CSR_MHPM_COUNTER_20 = 12'hB14, // reserved
|
||||
CSR_MHPM_COUNTER_21 = 12'hB15, // reserved
|
||||
CSR_MHPM_COUNTER_22 = 12'hB16, // reserved
|
||||
CSR_MHPM_COUNTER_23 = 12'hB17, // reserved
|
||||
CSR_MHPM_COUNTER_24 = 12'hB18, // reserved
|
||||
CSR_MHPM_COUNTER_25 = 12'hB19, // reserved
|
||||
CSR_MHPM_COUNTER_26 = 12'hB1A, // reserved
|
||||
CSR_MHPM_COUNTER_27 = 12'hB1B, // reserved
|
||||
CSR_MHPM_COUNTER_28 = 12'hB1C, // reserved
|
||||
CSR_MHPM_COUNTER_29 = 12'hB1D, // reserved
|
||||
CSR_MHPM_COUNTER_30 = 12'hB1E, // reserved
|
||||
CSR_MHPM_COUNTER_31 = 12'hB1F, // reserved
|
||||
// Cache Control (platform specifc)
|
||||
CSR_DCACHE = 12'h701,
|
||||
CSR_ICACHE = 12'h700,
|
||||
|
||||
// Triggers
|
||||
CSR_TSELECT = 12'h7A0,
|
||||
CSR_TDATA1 = 12'h7A1,
|
||||
CSR_TDATA2 = 12'h7A2,
|
||||
CSR_TDATA3 = 12'h7A3,
|
||||
CSR_TINFO = 12'h7A4,
|
||||
|
||||
// Debug CSR
|
||||
CSR_DCSR = 12'h7b0,
|
||||
CSR_DPC = 12'h7b1,
|
||||
CSR_DSCRATCH0 = 12'h7b2, // optional
|
||||
CSR_DSCRATCH1 = 12'h7b3, // optional
|
||||
|
||||
// Counters and Timers
|
||||
// Counters and Timers (User Mode - R/O Shadows)
|
||||
CSR_CYCLE = 12'hC00,
|
||||
CSR_TIME = 12'hC01,
|
||||
CSR_INSTRET = 12'hC02,
|
||||
// Performance counters
|
||||
// Performance counters (User Mode - R/O Shadows)
|
||||
CSR_L1_ICACHE_MISS = 12'hC03, // L1 Instr Cache Miss
|
||||
CSR_L1_DCACHE_MISS = 12'hC04, // L1 Data Cache Miss
|
||||
CSR_ITLB_MISS = 12'hC05, // ITLB Miss
|
||||
|
@ -387,7 +416,22 @@ package riscv;
|
|||
CSR_RET = 12'hC0D, // Procedure Return
|
||||
CSR_MIS_PREDICT = 12'hC0E, // Branch mis-predicted
|
||||
CSR_SB_FULL = 12'hC0F, // Scoreboard full
|
||||
CSR_IF_EMPTY = 12'hC10 // instruction fetch queue empty
|
||||
CSR_IF_EMPTY = 12'hC10, // instruction fetch queue empty
|
||||
CSR_HPM_COUNTER_17 = 12'hC11, // reserved
|
||||
CSR_HPM_COUNTER_18 = 12'hC12, // reserved
|
||||
CSR_HPM_COUNTER_19 = 12'hC13, // reserved
|
||||
CSR_HPM_COUNTER_20 = 12'hC14, // reserved
|
||||
CSR_HPM_COUNTER_21 = 12'hC15, // reserved
|
||||
CSR_HPM_COUNTER_22 = 12'hC16, // reserved
|
||||
CSR_HPM_COUNTER_23 = 12'hC17, // reserved
|
||||
CSR_HPM_COUNTER_24 = 12'hC18, // reserved
|
||||
CSR_HPM_COUNTER_25 = 12'hC19, // reserved
|
||||
CSR_HPM_COUNTER_26 = 12'hC1A, // reserved
|
||||
CSR_HPM_COUNTER_27 = 12'hC1B, // reserved
|
||||
CSR_HPM_COUNTER_28 = 12'hC1C, // reserved
|
||||
CSR_HPM_COUNTER_29 = 12'hC1D, // reserved
|
||||
CSR_HPM_COUNTER_30 = 12'hC1E, // reserved
|
||||
CSR_HPM_COUNTER_31 = 12'hC1F // reserved
|
||||
} csr_reg_t;
|
||||
|
||||
localparam logic [63:0] SSTATUS_UIE = 64'h00000001;
|
||||
|
|
|
@ -234,26 +234,39 @@ module csr_regfile #(
|
|||
riscv::CSR_MHARTID: csr_rdata = hart_id_i;
|
||||
riscv::CSR_MCYCLE: csr_rdata = cycle_q;
|
||||
riscv::CSR_MINSTRET: csr_rdata = instret_q;
|
||||
// Counters and Timers
|
||||
riscv::CSR_ML1_ICACHE_MISS,
|
||||
riscv::CSR_ML1_DCACHE_MISS,
|
||||
riscv::CSR_MITLB_MISS,
|
||||
riscv::CSR_MDTLB_MISS,
|
||||
riscv::CSR_MLOAD,
|
||||
riscv::CSR_MSTORE,
|
||||
riscv::CSR_MEXCEPTION,
|
||||
riscv::CSR_MEXCEPTION_RET,
|
||||
riscv::CSR_MBRANCH_JUMP,
|
||||
riscv::CSR_MCALL,
|
||||
riscv::CSR_MRET,
|
||||
riscv::CSR_MMIS_PREDICT,
|
||||
riscv::CSR_MSB_FULL,
|
||||
riscv::CSR_MIF_EMPTY,
|
||||
riscv::CSR_MHPM_COUNTER_17,
|
||||
riscv::CSR_MHPM_COUNTER_18,
|
||||
riscv::CSR_MHPM_COUNTER_19,
|
||||
riscv::CSR_MHPM_COUNTER_20,
|
||||
riscv::CSR_MHPM_COUNTER_21,
|
||||
riscv::CSR_MHPM_COUNTER_22,
|
||||
riscv::CSR_MHPM_COUNTER_23,
|
||||
riscv::CSR_MHPM_COUNTER_24,
|
||||
riscv::CSR_MHPM_COUNTER_25,
|
||||
riscv::CSR_MHPM_COUNTER_26,
|
||||
riscv::CSR_MHPM_COUNTER_27,
|
||||
riscv::CSR_MHPM_COUNTER_28,
|
||||
riscv::CSR_MHPM_COUNTER_29,
|
||||
riscv::CSR_MHPM_COUNTER_30,
|
||||
riscv::CSR_MHPM_COUNTER_31: csr_rdata = perf_data_i;
|
||||
// custom (non RISC-V) cache control
|
||||
riscv::CSR_DCACHE: csr_rdata = dcache_q;
|
||||
riscv::CSR_ICACHE: csr_rdata = icache_q;
|
||||
// Counters and Timers
|
||||
riscv::CSR_CYCLE: csr_rdata = cycle_q;
|
||||
riscv::CSR_INSTRET: csr_rdata = instret_q;
|
||||
riscv::CSR_L1_ICACHE_MISS,
|
||||
riscv::CSR_L1_DCACHE_MISS,
|
||||
riscv::CSR_ITLB_MISS,
|
||||
riscv::CSR_DTLB_MISS,
|
||||
riscv::CSR_LOAD,
|
||||
riscv::CSR_STORE,
|
||||
riscv::CSR_EXCEPTION,
|
||||
riscv::CSR_EXCEPTION_RET,
|
||||
riscv::CSR_BRANCH_JUMP,
|
||||
riscv::CSR_CALL,
|
||||
riscv::CSR_RET,
|
||||
riscv::CSR_MIS_PREDICT,
|
||||
riscv::CSR_SB_FULL,
|
||||
riscv::CSR_IF_EMPTY: csr_rdata = perf_data_i;
|
||||
default: read_access_exception = 1'b1;
|
||||
endcase
|
||||
end
|
||||
|
@ -508,23 +521,41 @@ module csr_regfile #(
|
|||
// performance counters
|
||||
riscv::CSR_MCYCLE: cycle_d = csr_wdata;
|
||||
riscv::CSR_MINSTRET: instret = csr_wdata;
|
||||
riscv::CSR_DCACHE: dcache_d = csr_wdata[0]; // enable bit
|
||||
riscv::CSR_ICACHE: icache_d = csr_wdata[0]; // enable bit
|
||||
riscv::CSR_L1_ICACHE_MISS,
|
||||
riscv::CSR_L1_DCACHE_MISS,
|
||||
riscv::CSR_ITLB_MISS,
|
||||
riscv::CSR_DTLB_MISS,
|
||||
riscv::CSR_LOAD,
|
||||
riscv::CSR_STORE,
|
||||
riscv::CSR_EXCEPTION,
|
||||
riscv::CSR_EXCEPTION_RET,
|
||||
riscv::CSR_BRANCH_JUMP,
|
||||
riscv::CSR_CALL,
|
||||
riscv::CSR_RET,
|
||||
riscv::CSR_MIS_PREDICT: begin
|
||||
riscv::CSR_ML1_ICACHE_MISS,
|
||||
riscv::CSR_ML1_DCACHE_MISS,
|
||||
riscv::CSR_MITLB_MISS,
|
||||
riscv::CSR_MDTLB_MISS,
|
||||
riscv::CSR_MLOAD,
|
||||
riscv::CSR_MSTORE,
|
||||
riscv::CSR_MEXCEPTION,
|
||||
riscv::CSR_MEXCEPTION_RET,
|
||||
riscv::CSR_MBRANCH_JUMP,
|
||||
riscv::CSR_MCALL,
|
||||
riscv::CSR_MRET,
|
||||
riscv::CSR_MMIS_PREDICT,
|
||||
riscv::CSR_MSB_FULL,
|
||||
riscv::CSR_MIF_EMPTY,
|
||||
riscv::CSR_MHPM_COUNTER_17,
|
||||
riscv::CSR_MHPM_COUNTER_18,
|
||||
riscv::CSR_MHPM_COUNTER_19,
|
||||
riscv::CSR_MHPM_COUNTER_20,
|
||||
riscv::CSR_MHPM_COUNTER_21,
|
||||
riscv::CSR_MHPM_COUNTER_22,
|
||||
riscv::CSR_MHPM_COUNTER_23,
|
||||
riscv::CSR_MHPM_COUNTER_24,
|
||||
riscv::CSR_MHPM_COUNTER_25,
|
||||
riscv::CSR_MHPM_COUNTER_26,
|
||||
riscv::CSR_MHPM_COUNTER_27,
|
||||
riscv::CSR_MHPM_COUNTER_28,
|
||||
riscv::CSR_MHPM_COUNTER_29,
|
||||
riscv::CSR_MHPM_COUNTER_30,
|
||||
riscv::CSR_MHPM_COUNTER_31: begin
|
||||
perf_data_o = csr_wdata;
|
||||
perf_we_o = 1'b1;
|
||||
end
|
||||
|
||||
riscv::CSR_DCACHE: dcache_d = csr_wdata[0]; // enable bit
|
||||
riscv::CSR_ICACHE: icache_d = csr_wdata[0]; // enable bit
|
||||
default: update_access_exception = 1'b1;
|
||||
endcase
|
||||
end
|
||||
|
|
|
@ -44,8 +44,7 @@ module perf_counters #(
|
|||
input logic eret_i,
|
||||
input branchpredict_t resolved_branch_i
|
||||
);
|
||||
|
||||
logic [riscv::CSR_IF_EMPTY[4:0] : riscv::CSR_L1_ICACHE_MISS[4:0]][63:0] perf_counter_d, perf_counter_q;
|
||||
logic [riscv::CSR_MIF_EMPTY[4:0] : riscv::CSR_ML1_ICACHE_MISS[4:0]][63:0] perf_counter_d, perf_counter_q;
|
||||
|
||||
always_comb begin : perf_counters
|
||||
perf_counter_d = perf_counter_q;
|
||||
|
@ -57,56 +56,56 @@ module perf_counters #(
|
|||
// Update Performance Counters
|
||||
// ------------------------------
|
||||
if (l1_icache_miss_i)
|
||||
perf_counter_d[riscv::CSR_L1_ICACHE_MISS[4:0]] = perf_counter_q[riscv::CSR_L1_ICACHE_MISS[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_ML1_ICACHE_MISS[4:0]] = perf_counter_q[riscv::CSR_ML1_ICACHE_MISS[4:0]] + 1'b1;
|
||||
|
||||
if (l1_dcache_miss_i)
|
||||
perf_counter_d[riscv::CSR_L1_DCACHE_MISS[4:0]] = perf_counter_q[riscv::CSR_L1_DCACHE_MISS[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_ML1_DCACHE_MISS[4:0]] = perf_counter_q[riscv::CSR_ML1_DCACHE_MISS[4:0]] + 1'b1;
|
||||
|
||||
if (itlb_miss_i)
|
||||
perf_counter_d[riscv::CSR_ITLB_MISS[4:0]] = perf_counter_q[riscv::CSR_ITLB_MISS[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_MITLB_MISS[4:0]] = perf_counter_q[riscv::CSR_MITLB_MISS[4:0]] + 1'b1;
|
||||
|
||||
if (dtlb_miss_i)
|
||||
perf_counter_d[riscv::CSR_DTLB_MISS[4:0]] = perf_counter_q[riscv::CSR_DTLB_MISS[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_MDTLB_MISS[4:0]] = perf_counter_q[riscv::CSR_MDTLB_MISS[4:0]] + 1'b1;
|
||||
|
||||
// instruction related perf counters
|
||||
for (int unsigned i = 0; i < NR_COMMIT_PORTS-1; i++) begin
|
||||
if (commit_ack_i[i]) begin
|
||||
if (commit_instr_i[i].fu == LOAD)
|
||||
perf_counter_d[riscv::CSR_LOAD[4:0]] = perf_counter_q[riscv::CSR_LOAD[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_MLOAD[4:0]] = perf_counter_q[riscv::CSR_MLOAD[4:0]] + 1'b1;
|
||||
|
||||
if (commit_instr_i[i].fu == STORE)
|
||||
perf_counter_d[riscv::CSR_STORE[4:0]] = perf_counter_q[riscv::CSR_STORE[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_MSTORE[4:0]] = perf_counter_q[riscv::CSR_MSTORE[4:0]] + 1'b1;
|
||||
|
||||
if (commit_instr_i[i].fu == CTRL_FLOW)
|
||||
perf_counter_d[riscv::CSR_BRANCH_JUMP[4:0]] = perf_counter_q[riscv::CSR_BRANCH_JUMP[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_MBRANCH_JUMP[4:0]] = perf_counter_q[riscv::CSR_MBRANCH_JUMP[4:0]] + 1'b1;
|
||||
|
||||
// The standard software calling convention uses register x1 to hold the return address on a call
|
||||
// the unconditional jump is decoded as ADD op
|
||||
if (commit_instr_i[i].fu == CTRL_FLOW && commit_instr_i[i].op == '0
|
||||
&& (commit_instr_i[i].rd == 'd1 || commit_instr_i[i].rd == 'd1))
|
||||
perf_counter_d[riscv::CSR_CALL[4:0]] = perf_counter_q[riscv::CSR_CALL[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_MCALL[4:0]] = perf_counter_q[riscv::CSR_MCALL[4:0]] + 1'b1;
|
||||
|
||||
// Return from call
|
||||
if (commit_instr_i[i].op == JALR && (commit_instr_i[i].rd == 'd1 || commit_instr_i[i].rd == 'd1))
|
||||
perf_counter_d[riscv::CSR_RET[4:0]] = perf_counter_q[riscv::CSR_RET[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_MRET[4:0]] = perf_counter_q[riscv::CSR_MRET[4:0]] + 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
if (ex_i.valid)
|
||||
perf_counter_d[riscv::CSR_EXCEPTION[4:0]] = perf_counter_q[riscv::CSR_EXCEPTION[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_MEXCEPTION[4:0]] = perf_counter_q[riscv::CSR_MEXCEPTION[4:0]] + 1'b1;
|
||||
|
||||
if (eret_i)
|
||||
perf_counter_d[riscv::CSR_EXCEPTION_RET[4:0]] = perf_counter_q[riscv::CSR_EXCEPTION_RET[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_MEXCEPTION_RET[4:0]] = perf_counter_q[riscv::CSR_MEXCEPTION_RET[4:0]] + 1'b1;
|
||||
|
||||
if (resolved_branch_i.valid && resolved_branch_i.is_mispredict)
|
||||
perf_counter_d[riscv::CSR_MIS_PREDICT[4:0]] = perf_counter_q[riscv::CSR_MIS_PREDICT[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_MMIS_PREDICT[4:0]] = perf_counter_q[riscv::CSR_MMIS_PREDICT[4:0]] + 1'b1;
|
||||
|
||||
if (sb_full_i) begin
|
||||
perf_counter_d[riscv::CSR_SB_FULL[4:0]] = perf_counter_q[riscv::CSR_SB_FULL[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_MSB_FULL[4:0]] = perf_counter_q[riscv::CSR_MSB_FULL[4:0]] + 1'b1;
|
||||
end
|
||||
|
||||
if (if_empty_i) begin
|
||||
perf_counter_d[riscv::CSR_IF_EMPTY[4:0]] = perf_counter_q[riscv::CSR_IF_EMPTY[4:0]] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_MIF_EMPTY[4:0]] = perf_counter_q[riscv::CSR_MIF_EMPTY[4:0]] + 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue