From 8332f7de9dab91453d2379997dc23725c5b9b603 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 5 Jun 2020 17:34:23 +0100 Subject: [PATCH] [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 --- dv/uvm/core_ibex/ibex_dv.f | 2 +- formal/Makefile | 2 +- ibex_core.core | 2 +- rtl/ibex_counter.sv | 82 +++++++++++++++++++++++++++++++++++ rtl/ibex_counters.sv | 89 -------------------------------------- rtl/ibex_cs_registers.sv | 49 +++++++++++---------- 6 files changed, 112 insertions(+), 114 deletions(-) create mode 100644 rtl/ibex_counter.sv delete mode 100644 rtl/ibex_counters.sv diff --git a/dv/uvm/core_ibex/ibex_dv.f b/dv/uvm/core_ibex/ibex_dv.f index 5a9d7fc0..5096ec7e 100644 --- a/dv/uvm/core_ibex/ibex_dv.f +++ b/dv/uvm/core_ibex/ibex_dv.f @@ -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 diff --git a/formal/Makefile b/formal/Makefile index dc8e4761..97d7d8dd 100644 --- a/formal/Makefile +++ b/formal/Makefile @@ -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 \ diff --git a/ibex_core.core b/ibex_core.core index 882873ec..0c45f590 100644 --- a/ibex_core.core +++ b/ibex_core.core @@ -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 diff --git a/rtl/ibex_counter.sv b/rtl/ibex_counter.sv new file mode 100644 index 00000000..2c0722f3 --- /dev/null +++ b/rtl/ibex_counter.sv @@ -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 diff --git a/rtl/ibex_counters.sv b/rtl/ibex_counters.sv deleted file mode 100644 index 2d9a4ef4..00000000 --- a/rtl/ibex_counters.sv +++ /dev/null @@ -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 diff --git a/rtl/ibex_cs_registers.sv b/rtl/ibex_cs_registers.sv index 04126bae..b4df9bde 100644 --- a/rtl/ibex_cs_registers.sv +++ b/rtl/ibex_cs_registers.sv @@ -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