mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-23 13:27:10 -04:00
[rtl] Rewrite perf counters to be Yosys compatible
- Yosys doesn't like unpacked array partial slicing - Instantiate counters individually instead Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
This commit is contained in:
parent
33ad42debb
commit
8332f7de9d
6 changed files with 112 additions and 114 deletions
|
@ -35,7 +35,7 @@ ${PRJ_DIR}/ibex/rtl/ibex_alu.sv
|
|||
${PRJ_DIR}/ibex/rtl/ibex_compressed_decoder.sv
|
||||
${PRJ_DIR}/ibex/rtl/ibex_controller.sv
|
||||
${PRJ_DIR}/ibex/rtl/ibex_cs_registers.sv
|
||||
${PRJ_DIR}/ibex/rtl/ibex_counters.sv
|
||||
${PRJ_DIR}/ibex/rtl/ibex_counter.sv
|
||||
${PRJ_DIR}/ibex/rtl/ibex_decoder.sv
|
||||
${PRJ_DIR}/ibex/rtl/ibex_dummy_instr.sv
|
||||
${PRJ_DIR}/ibex/rtl/ibex_ex_block.sv
|
||||
|
|
|
@ -20,7 +20,7 @@ INC_DIR := ../shared/rtl
|
|||
SRCS_SV ?= $(SRC_DIR)/ibex_alu.sv \
|
||||
$(SRC_DIR)/ibex_compressed_decoder.sv \
|
||||
$(SRC_DIR)/ibex_controller.sv \
|
||||
$(SRC_DIR)/ibex_counters.sv \
|
||||
$(SRC_DIR)/ibex_counter.sv \
|
||||
$(SRC_DIR)/ibex_cs_registers.sv \
|
||||
$(SRC_DIR)/ibex_decoder.sv \
|
||||
$(SRC_DIR)/ibex_ex_block.sv \
|
||||
|
|
|
@ -19,7 +19,7 @@ filesets:
|
|||
- rtl/ibex_compressed_decoder.sv
|
||||
- rtl/ibex_controller.sv
|
||||
- rtl/ibex_cs_registers.sv
|
||||
- rtl/ibex_counters.sv
|
||||
- rtl/ibex_counter.sv
|
||||
- rtl/ibex_decoder.sv
|
||||
- rtl/ibex_ex_block.sv
|
||||
- rtl/ibex_fetch_fifo.sv
|
||||
|
|
82
rtl/ibex_counter.sv
Normal file
82
rtl/ibex_counter.sv
Normal file
|
@ -0,0 +1,82 @@
|
|||
module ibex_counter #(
|
||||
parameter int CounterWidth = 32
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
input logic counter_inc_i,
|
||||
input logic counterh_we_i,
|
||||
input logic counter_we_i,
|
||||
input logic [31:0] counter_val_i,
|
||||
output logic [63:0] counter_val_o
|
||||
);
|
||||
|
||||
logic [63:0] counter;
|
||||
logic [CounterWidth-1:0] counter_upd;
|
||||
logic [63:0] counter_load;
|
||||
logic we;
|
||||
logic [CounterWidth-1:0] counter_d;
|
||||
|
||||
// Update
|
||||
always_comb begin
|
||||
|
||||
// Write
|
||||
we = counter_we_i | counterh_we_i;
|
||||
counter_load[63:32] = counter[63:32];
|
||||
counter_load[31:0] = counter_val_i;
|
||||
if (counterh_we_i) begin
|
||||
counter_load[63:32] = counter_val_i;
|
||||
counter_load[31:0] = counter[31:0];
|
||||
end
|
||||
|
||||
// Increment
|
||||
counter_upd = counter[CounterWidth-1:0] + {{CounterWidth-1{1'b0}},1'b1};
|
||||
|
||||
// Next value logic
|
||||
if (we) begin
|
||||
counter_d = counter_load[CounterWidth-1:0];
|
||||
end else if (counter_inc_i)begin
|
||||
counter_d = counter_upd[CounterWidth-1:0];
|
||||
end else begin
|
||||
counter_d = counter[CounterWidth-1:0];
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef FPGA_XILINX
|
||||
// Set DSP pragma for supported xilinx FPGAs
|
||||
localparam dsp_pragma = CounterWidth < 49 ? "yes" : "no";
|
||||
(* use_dsp = dsp_pragma *) logic [CounterWidth-1:0] counter_q;
|
||||
|
||||
// DSP output register requires synchronous reset.
|
||||
`define COUNTER_FLOP_RST posedge clk_i
|
||||
`else
|
||||
logic [CounterWidth-1:0] counter_q;
|
||||
|
||||
`define COUNTER_FLOP_RST posedge clk_i or negedge rst_ni
|
||||
`endif
|
||||
|
||||
// Counter flop
|
||||
always @(`COUNTER_FLOP_RST) begin
|
||||
if (!rst_ni) begin
|
||||
counter_q <= '0;
|
||||
end else begin
|
||||
counter_q <= counter_d;
|
||||
end
|
||||
end
|
||||
|
||||
if (CounterWidth < 64) begin : g_counter_narrow
|
||||
logic [63:CounterWidth] unused_counter_load;
|
||||
|
||||
assign counter[CounterWidth-1:0] = counter_q;
|
||||
assign counter[63:CounterWidth] = '0;
|
||||
assign unused_counter_load = counter_load[63:CounterWidth];
|
||||
end else begin : g_counter_full
|
||||
assign counter = counter_q;
|
||||
end
|
||||
|
||||
assign counter_val_o = counter;
|
||||
|
||||
endmodule
|
||||
|
||||
// Keep helper defines file-local.
|
||||
`undef COUNTER_FLOP_RST
|
|
@ -1,89 +0,0 @@
|
|||
module ibex_counters #(
|
||||
parameter int MaxNumCounters = 29,
|
||||
parameter int NumCounters = 0,
|
||||
parameter int CounterWidth = 32
|
||||
) (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
|
||||
input logic [MaxNumCounters-1:0] counter_inc_i,
|
||||
input logic [MaxNumCounters-1:0] counterh_we_i,
|
||||
input logic [MaxNumCounters-1:0] counter_we_i,
|
||||
input logic [31:0] counter_val_i,
|
||||
output logic [63:0] counter_val_o [MaxNumCounters]
|
||||
);
|
||||
logic [63:0] counter [MaxNumCounters];
|
||||
|
||||
assign counter_val_o = counter;
|
||||
|
||||
for (genvar i = 0; i < MaxNumCounters; i++) begin : g_counter
|
||||
// Only elaborate flops that are needed from the given CounterWidth and NumCounters.
|
||||
if (i < NumCounters) begin : g_counter_exists
|
||||
|
||||
logic [63:0] counter_upd;
|
||||
logic [63:0] counter_load;
|
||||
logic we;
|
||||
logic [CounterWidth-1:0] counter_d;
|
||||
|
||||
// Update
|
||||
always_comb begin
|
||||
|
||||
// Write
|
||||
we = counter_we_i[i] | counterh_we_i[i];
|
||||
counter_load[63:32] = counter[i][63:32];
|
||||
counter_load[31:0] = counter_val_i;
|
||||
if (counterh_we_i[i]) begin
|
||||
counter_load[63:32] = counter_val_i;
|
||||
counter_load[31:0] = counter[i][31:0];
|
||||
end
|
||||
|
||||
// Increment
|
||||
counter_upd = counter[i] + 64'h1;
|
||||
|
||||
// Next value logic
|
||||
if (we) begin
|
||||
counter_d = counter_load[CounterWidth-1:0];
|
||||
end else if (counter_inc_i[i])begin
|
||||
counter_d = counter_upd[CounterWidth-1:0];
|
||||
end else begin
|
||||
counter_d = counter[i][CounterWidth-1:0];
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef FPGA_XILINX
|
||||
// Set DSP pragma for supported xilinx FPGAs
|
||||
localparam dsp_pragma = CounterWidth < 49 ? "yes" : "no";
|
||||
(* use_dsp = dsp_pragma *) logic [CounterWidth-1:0] counter_q;
|
||||
|
||||
// DSP output register requires synchronous reset.
|
||||
`define COUNTER_FLOP_RST posedge clk_i
|
||||
`else
|
||||
logic [CounterWidth-1:0] counter_q;
|
||||
|
||||
`define COUNTER_FLOP_RST posedge clk_i or negedge rst_ni
|
||||
`endif
|
||||
|
||||
// Counter flop
|
||||
always @(`COUNTER_FLOP_RST) begin
|
||||
if (!rst_ni) begin
|
||||
counter_q <= '0;
|
||||
end else begin
|
||||
counter_q <= counter_d;
|
||||
end
|
||||
end
|
||||
|
||||
if (CounterWidth < 64) begin : g_counter_narrow
|
||||
assign counter[i][CounterWidth-1:0] = counter_q;
|
||||
assign counter[i][63:CounterWidth] = '0;
|
||||
end else begin : g_counter_full
|
||||
assign counter[i] = counter_q;
|
||||
end
|
||||
end else begin : g_no_counter
|
||||
assign counter[i] = '0;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
// Keep helper defines file-local.
|
||||
`undef COUNTER_FLOP_RST
|
|
@ -912,10 +912,8 @@ module ibex_cs_registers #(
|
|||
end
|
||||
end
|
||||
|
||||
// mcycle and minstret
|
||||
ibex_counters #(
|
||||
.MaxNumCounters(1),
|
||||
.NumCounters(1),
|
||||
// mcycle
|
||||
ibex_counter #(
|
||||
.CounterWidth(64)
|
||||
) mcycle_counter_i (
|
||||
.clk_i(clk_i),
|
||||
|
@ -924,12 +922,11 @@ module ibex_cs_registers #(
|
|||
.counterh_we_i(mhpmcounterh_we[0]),
|
||||
.counter_we_i(mhpmcounter_we[0]),
|
||||
.counter_val_i(csr_wdata_int),
|
||||
.counter_val_o(mhpmcounter[0:0])
|
||||
.counter_val_o(mhpmcounter[0])
|
||||
);
|
||||
|
||||
ibex_counters #(
|
||||
.MaxNumCounters(1),
|
||||
.NumCounters(1),
|
||||
// minstret
|
||||
ibex_counter #(
|
||||
.CounterWidth(64)
|
||||
) minstret_counter_i (
|
||||
.clk_i(clk_i),
|
||||
|
@ -938,28 +935,36 @@ module ibex_cs_registers #(
|
|||
.counterh_we_i(mhpmcounterh_we[2]),
|
||||
.counter_we_i(mhpmcounter_we[2]),
|
||||
.counter_val_i(csr_wdata_int),
|
||||
.counter_val_o(mhpmcounter[2:2])
|
||||
.counter_val_o(mhpmcounter[2])
|
||||
);
|
||||
|
||||
// reserved:
|
||||
assign mhpmcounter[1] = '0;
|
||||
|
||||
ibex_counters #(
|
||||
.MaxNumCounters(29),
|
||||
.NumCounters(MHPMCounterNum),
|
||||
.CounterWidth(MHPMCounterWidth)
|
||||
) mcounters_variable_i (
|
||||
.clk_i(clk_i),
|
||||
.rst_ni(rst_ni),
|
||||
.counter_inc_i(mhpmcounter_incr[31:3] & ~mcountinhibit[31:3]),
|
||||
.counterh_we_i(mhpmcounterh_we[31:3]),
|
||||
.counter_we_i(mhpmcounter_we[31:3]),
|
||||
.counter_val_i(csr_wdata_int),
|
||||
.counter_val_o(mhpmcounter[3:31])
|
||||
);
|
||||
for (genvar cnt=0; cnt < MHPMCounterNum; cnt++) begin : gen_cntrs
|
||||
ibex_counter #(
|
||||
.CounterWidth(MHPMCounterWidth)
|
||||
) mcounters_variable_i (
|
||||
.clk_i(clk_i),
|
||||
.rst_ni(rst_ni),
|
||||
.counter_inc_i(mhpmcounter_incr[cnt+3] & ~mcountinhibit[cnt+3]),
|
||||
.counterh_we_i(mhpmcounterh_we[cnt+3]),
|
||||
.counter_we_i(mhpmcounter_we[cnt+3]),
|
||||
.counter_val_i(csr_wdata_int),
|
||||
.counter_val_o(mhpmcounter[cnt+3])
|
||||
);
|
||||
end
|
||||
|
||||
if(MHPMCounterNum < 29) begin : g_mcountinhibit_reduced
|
||||
logic [29-MHPMCounterNum-1:0] unused_mhphcounter_we;
|
||||
logic [29-MHPMCounterNum-1:0] unused_mhphcounterh_we;
|
||||
logic [29-MHPMCounterNum-1:0] unused_mhphcounter_incr;
|
||||
|
||||
assign mcountinhibit = {{29-MHPMCounterNum{1'b1}}, 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];
|
||||
assign unused_mhphcounter_incr = mhpmcounter_incr[31:MHPMCounterNum+3];
|
||||
end else begin : g_mcountinhibit_full
|
||||
assign mcountinhibit = mcountinhibit_q;
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue