mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Remove legacy performance counters
This commit is contained in:
parent
d4b349766e
commit
a3b6c28ebd
3 changed files with 21 additions and 218 deletions
|
@ -25,13 +25,12 @@
|
|||
* Top level module of the ibex RISC-V core
|
||||
*/
|
||||
module ibex_core #(
|
||||
parameter int unsigned NumExtPerfCounters = 1,
|
||||
parameter int unsigned MHPMCounterNum = 8,
|
||||
parameter int unsigned MHPMCounterWidth = 40,
|
||||
parameter bit RV32E = 0,
|
||||
parameter bit RV32M = 1,
|
||||
parameter int unsigned DmHaltAddr = 32'h1A110800,
|
||||
parameter int unsigned DmExceptionAddr = 32'h1A110808
|
||||
parameter int unsigned MHPMCounterNum = 8,
|
||||
parameter int unsigned MHPMCounterWidth = 40,
|
||||
parameter bit RV32E = 0,
|
||||
parameter bit RV32M = 1,
|
||||
parameter int unsigned DmHaltAddr = 32'h1A110800,
|
||||
parameter int unsigned DmExceptionAddr = 32'h1A110808
|
||||
) (
|
||||
// Clock and Reset
|
||||
input logic clk_i,
|
||||
|
@ -72,9 +71,7 @@ module ibex_core #(
|
|||
input logic debug_req_i,
|
||||
|
||||
// CPU Control Signals
|
||||
input logic fetch_enable_i,
|
||||
|
||||
input logic [NumExtPerfCounters-1:0] ext_perf_counters_i
|
||||
input logic fetch_enable_i
|
||||
);
|
||||
|
||||
import ibex_defines::*;
|
||||
|
@ -482,11 +479,10 @@ module ibex_core #(
|
|||
assign insn_ret = if_valid & ~illegal_insn_id;
|
||||
|
||||
ibex_cs_registers #(
|
||||
.NumExtCounters ( NumExtPerfCounters ),
|
||||
.MHPMCounterNum ( MHPMCounterNum ),
|
||||
.MHPMCounterWidth ( MHPMCounterWidth ),
|
||||
.RV32E ( RV32E ),
|
||||
.RV32M ( RV32M )
|
||||
.MHPMCounterNum ( MHPMCounterNum ),
|
||||
.MHPMCounterWidth ( MHPMCounterWidth ),
|
||||
.RV32E ( RV32E ),
|
||||
.RV32M ( RV32M )
|
||||
) cs_registers_i (
|
||||
.clk_i ( clk ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
@ -527,7 +523,6 @@ module ibex_core #(
|
|||
|
||||
// performance counter related signals
|
||||
.insn_ret_i ( insn_ret ),
|
||||
.if_valid_i ( if_valid ),
|
||||
.id_valid_i ( id_valid ),
|
||||
.is_compressed_i ( is_compressed_id ),
|
||||
.is_decoding_i ( is_decoding ),
|
||||
|
@ -539,9 +534,7 @@ module ibex_core #(
|
|||
.branch_taken_i ( perf_tbranch ),
|
||||
.mem_load_i ( perf_load ),
|
||||
.mem_store_i ( perf_store ),
|
||||
.lsu_busy_i ( lsu_busy ),
|
||||
|
||||
.ext_counters_i ( ext_perf_counters_i )
|
||||
.lsu_busy_i ( lsu_busy )
|
||||
);
|
||||
|
||||
`ifndef VERILATOR
|
||||
|
|
|
@ -26,11 +26,10 @@
|
|||
* Specification, draft version 1.11
|
||||
*/
|
||||
module ibex_cs_registers #(
|
||||
parameter int unsigned NumExtCounters = 0,
|
||||
parameter int unsigned MHPMCounterNum = 8,
|
||||
parameter int unsigned MHPMCounterWidth = 40,
|
||||
parameter bit RV32E = 0,
|
||||
parameter bit RV32M = 0
|
||||
parameter int unsigned MHPMCounterNum = 8,
|
||||
parameter int unsigned MHPMCounterWidth = 40,
|
||||
parameter bit RV32E = 0,
|
||||
parameter bit RV32M = 0
|
||||
) (
|
||||
// Clock and Reset
|
||||
input logic clk_i,
|
||||
|
@ -76,7 +75,6 @@ module ibex_cs_registers #(
|
|||
// missing write permissions
|
||||
// Performance Counters
|
||||
input logic insn_ret_i, // instr retired in ID/EX stage
|
||||
input logic if_valid_i, // IF stage gives a new instr
|
||||
input logic id_valid_i, // ID stage is done
|
||||
input logic is_compressed_i, // compressed instr in ID
|
||||
input logic is_decoding_i, // controller is in DECODE state
|
||||
|
@ -88,8 +86,7 @@ module ibex_cs_registers #(
|
|||
input logic branch_taken_i, // branch was taken
|
||||
input logic mem_load_i, // load from memory in this cycle
|
||||
input logic mem_store_i, // store to memory in this cycle
|
||||
input logic lsu_busy_i,
|
||||
input logic [NumExtCounters-1:0] ext_counters_i
|
||||
input logic lsu_busy_i
|
||||
);
|
||||
|
||||
import ibex_defines::*;
|
||||
|
@ -110,14 +107,6 @@ module ibex_cs_registers #(
|
|||
| (0 << 23) // X - Non-standard extensions present
|
||||
| (MXL << 30); // M-XLEN
|
||||
|
||||
localparam int unsigned N_PERF_COUNTERS = 11 + NumExtCounters;
|
||||
|
||||
`ifdef ASIC_SYNTHESIS
|
||||
localparam N_PERF_REGS = 1;
|
||||
`else
|
||||
localparam N_PERF_REGS = N_PERF_COUNTERS;
|
||||
`endif
|
||||
|
||||
`define MSTATUS_UIE_BITS 0
|
||||
`define MSTATUS_SIE_BITS 1
|
||||
`define MSTATUS_MIE_BITS 3
|
||||
|
@ -172,22 +161,6 @@ module ibex_cs_registers #(
|
|||
logic [31:0] mhpmevent [32];
|
||||
logic [4:0] mhpmcounter_idx;
|
||||
|
||||
// Legacy Performance Counter Signals
|
||||
logic [N_PERF_COUNTERS-1:0] PCCR_in; // input signals for each counter category
|
||||
logic [N_PERF_COUNTERS-1:0] PCCR_inc, PCCR_inc_q; // should the counter be increased?
|
||||
|
||||
logic [N_PERF_REGS-1:0] [31:0] PCCR_q, PCCR_n; // performance counters counter register
|
||||
logic [1:0] PCMR_n, PCMR_q; // mode register, controls saturation and
|
||||
// global enable
|
||||
logic [N_PERF_COUNTERS-1:0] PCER_n, PCER_q; // selected counter input
|
||||
|
||||
logic [31:0] perf_rdata;
|
||||
logic [4:0] pccr_index;
|
||||
logic pccr_all_sel;
|
||||
logic is_pccr;
|
||||
logic is_pcer;
|
||||
logic is_pcmr;
|
||||
|
||||
// CSR update logic
|
||||
logic [31:0] csr_wdata_int;
|
||||
logic [31:0] csr_rdata_int;
|
||||
|
@ -200,7 +173,7 @@ module ibex_cs_registers #(
|
|||
logic [31:0] dscratch0_q, dscratch0_n;
|
||||
logic [31:0] dscratch1_q, dscratch1_n;
|
||||
logic [ 5:0] mcause_q, mcause_n;
|
||||
Status_t mstatus_q, mstatus_n;
|
||||
Status_t mstatus_q, mstatus_n;
|
||||
logic [31:0] exception_pc;
|
||||
|
||||
// Access violation signals
|
||||
|
@ -213,8 +186,8 @@ module ibex_cs_registers #(
|
|||
/////////////
|
||||
|
||||
logic [$bits(csr_num_e)-1:0] csr_addr;
|
||||
assign csr_addr = {csr_addr_i};
|
||||
assign mhpmcounter_idx = csr_addr[4:0];
|
||||
assign csr_addr = {csr_addr_i};
|
||||
assign mhpmcounter_idx = csr_addr[4:0];
|
||||
|
||||
assign illegal_csr_priv = 1'b0; // we only support M-mode
|
||||
assign illegal_csr_write = (csr_addr[11:10] == 2'b11) && csr_we_int;
|
||||
|
@ -474,8 +447,7 @@ module ibex_cs_registers #(
|
|||
endcase
|
||||
end
|
||||
|
||||
// output mux, possibly choose performance counters
|
||||
assign csr_rdata_o = (is_pccr || is_pcer || is_pcmr) ? perf_rdata : csr_rdata_int;
|
||||
assign csr_rdata_o = csr_rdata_int;
|
||||
|
||||
// directly output some registers
|
||||
assign m_irq_enable_o = mstatus_q.mie;
|
||||
|
@ -621,161 +593,4 @@ module ibex_cs_registers #(
|
|||
end
|
||||
end
|
||||
|
||||
/////////////////////////////////
|
||||
// Legacy Performance counters //
|
||||
/////////////////////////////////
|
||||
|
||||
assign PCCR_in[0] = 1'b1; // cycle counter
|
||||
assign PCCR_in[1] = if_valid_i; // instruction counter
|
||||
assign PCCR_in[2] = 1'b0; // Reserved
|
||||
assign PCCR_in[3] = 1'b0; // Reserved
|
||||
assign PCCR_in[4] = imiss_i & (~pc_set_i); // cycles waiting for instruction fetches,
|
||||
// excluding jumps and branches
|
||||
assign PCCR_in[5] = mem_load_i; // nr of loads
|
||||
assign PCCR_in[6] = mem_store_i; // nr of stores
|
||||
assign PCCR_in[7] = jump_i; // nr of jumps (unconditional)
|
||||
assign PCCR_in[8] = branch_i; // nr of branches (conditional)
|
||||
assign PCCR_in[9] = branch_taken_i; // nr of taken branches (conditional)
|
||||
assign PCCR_in[10] = id_valid_i & is_decoding_i & is_compressed_i; // compressed intr ctr
|
||||
|
||||
// assign external performance counters
|
||||
for (genvar i = 0; i < NumExtCounters; i++) begin : gen_ext_counters
|
||||
assign PCCR_in[N_PERF_COUNTERS - NumExtCounters + i] = ext_counters_i[i];
|
||||
end
|
||||
|
||||
// address decoder for performance counter registers
|
||||
always_comb begin
|
||||
is_pccr = 1'b0;
|
||||
is_pcmr = 1'b0;
|
||||
is_pcer = 1'b0;
|
||||
pccr_all_sel = 1'b0;
|
||||
pccr_index = '0;
|
||||
perf_rdata = '0;
|
||||
|
||||
// only perform csr access if we actually care about the read data
|
||||
if (csr_access_i) begin
|
||||
unique case (csr_addr_i)
|
||||
CSR_TSELECT: begin
|
||||
is_pcer = 1'b1;
|
||||
perf_rdata[N_PERF_COUNTERS-1:0] = PCER_q;
|
||||
end
|
||||
CSR_TDATA1: begin
|
||||
is_pcmr = 1'b1;
|
||||
perf_rdata[1:0] = PCMR_q;
|
||||
end
|
||||
CSR_PCCR31: begin
|
||||
is_pccr = 1'b1;
|
||||
pccr_all_sel = 1'b1;
|
||||
end
|
||||
default:;
|
||||
endcase
|
||||
|
||||
// look for 780 to 79F, Performance Counter Counter Registers
|
||||
if (csr_addr[11:5] == 7'b0111100) begin
|
||||
is_pccr = 1'b1;
|
||||
|
||||
pccr_index = csr_addr[4:0];
|
||||
`ifdef ASIC_SYNTHESIS
|
||||
perf_rdata = PCCR_q[0];
|
||||
`else
|
||||
perf_rdata = csr_addr[4:0] < N_PERF_COUNTERS ? PCCR_q[csr_addr[4:0]] : '0;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// performance counter counter update logic
|
||||
`ifdef ASIC_SYNTHESIS
|
||||
// for synthesis we just have one performance counter register
|
||||
assign PCCR_inc[0] = (|(PCCR_in & PCER_q)) & PCMR_q[0];
|
||||
|
||||
always_comb begin
|
||||
PCCR_n[0] = PCCR_q[0];
|
||||
|
||||
if ((PCCR_inc_q[0] == 1'b1) && ((PCCR_q[0] != 32'hFFFFFFFF) || (PCMR_q[1] == 1'b0))) begin
|
||||
PCCR_n[0] = PCCR_q[0] + 32'h1;
|
||||
end
|
||||
|
||||
if (is_pccr) begin
|
||||
unique case (csr_op_i)
|
||||
CSR_OP_NONE: ;
|
||||
CSR_OP_WRITE: PCCR_n[0] = csr_wdata_i;
|
||||
CSR_OP_SET: PCCR_n[0] = csr_wdata_i | PCCR_q[0];
|
||||
CSR_OP_CLEAR: PCCR_n[0] = ~csr_wdata_i & PCCR_q[0];
|
||||
default: PCCR_n[0] = 'X;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
`else
|
||||
always_comb begin
|
||||
for (int c = 0; c < N_PERF_COUNTERS; c++) begin : perf_counters_inc
|
||||
PCCR_inc[c] = PCCR_in[c] & PCER_q[c] & PCMR_q[0];
|
||||
|
||||
PCCR_n[c] = PCCR_q[c];
|
||||
|
||||
if ((PCCR_inc_q[c] == 1'b1) && ((PCCR_q[c] != 32'hFFFFFFFF) || (PCMR_q[1] == 1'b0))) begin
|
||||
PCCR_n[c] = PCCR_q[c] + 32'h1;
|
||||
end
|
||||
|
||||
if (is_pccr && (pccr_all_sel || pccr_index == c)) begin
|
||||
unique case (csr_op_i)
|
||||
CSR_OP_NONE: ;
|
||||
CSR_OP_WRITE: PCCR_n[c] = csr_wdata_i;
|
||||
CSR_OP_SET: PCCR_n[c] = csr_wdata_i | PCCR_q[c];
|
||||
CSR_OP_CLEAR: PCCR_n[c] = ~csr_wdata_i & PCCR_q[c];
|
||||
default: PCCR_n[c] = 'X;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
// update PCMR and PCER
|
||||
always_comb begin
|
||||
PCMR_n = PCMR_q;
|
||||
PCER_n = PCER_q;
|
||||
|
||||
if (is_pcmr) begin
|
||||
unique case (csr_op_i)
|
||||
CSR_OP_NONE: ;
|
||||
CSR_OP_WRITE: PCMR_n = csr_wdata_i[1:0];
|
||||
CSR_OP_SET: PCMR_n = csr_wdata_i[1:0] | PCMR_q;
|
||||
CSR_OP_CLEAR: PCMR_n = ~csr_wdata_i[1:0] & PCMR_q;
|
||||
default: PCMR_n = 'X;
|
||||
endcase
|
||||
end
|
||||
|
||||
if (is_pcer) begin
|
||||
unique case (csr_op_i)
|
||||
CSR_OP_NONE: ;
|
||||
CSR_OP_WRITE: PCER_n = csr_wdata_i[N_PERF_COUNTERS-1:0];
|
||||
CSR_OP_SET: PCER_n = csr_wdata_i[N_PERF_COUNTERS-1:0] | PCER_q;
|
||||
CSR_OP_CLEAR: PCER_n = ~csr_wdata_i[N_PERF_COUNTERS-1:0] & PCER_q;
|
||||
default: PCER_n = 'X;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// Performance Counter Registers
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
PCER_q <= '0;
|
||||
PCMR_q <= 2'h3;
|
||||
|
||||
for (int r = 0; r < N_PERF_REGS; r++) begin
|
||||
PCCR_q[r] <= '0;
|
||||
PCCR_inc_q[r] <= '0;
|
||||
end
|
||||
end else begin
|
||||
PCER_q <= PCER_n;
|
||||
PCMR_q <= PCMR_n;
|
||||
|
||||
for (int r = 0; r < N_PERF_REGS; r++) begin
|
||||
PCCR_q[r] <= PCCR_n[r];
|
||||
PCCR_inc_q[r] <= PCCR_inc[r];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -232,14 +232,9 @@ typedef enum logic[11:0] {
|
|||
CSR_MCAUSE = 12'h342,
|
||||
|
||||
// Debug/trace
|
||||
CSR_TSELECT = 12'h7a0,
|
||||
CSR_TDATA1 = 12'h7a1,
|
||||
CSR_DCSR = 12'h7b0,
|
||||
CSR_DPC = 12'h7b1,
|
||||
|
||||
// Performance counters
|
||||
CSR_PCCR31 = 12'h79F, // custom
|
||||
|
||||
// Debug
|
||||
CSR_DSCRATCH0 = 12'h7b2, // optional
|
||||
CSR_DSCRATCH1 = 12'h7b3, // optional
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue