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:
Florian Zaruba 2019-04-19 17:48:01 +02:00
parent 9acc57937b
commit 50b4a5d58b
4 changed files with 128 additions and 53 deletions

View file

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

View file

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

View file

@ -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

View file

@ -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