diff --git a/config/rv32e/config.vh b/config/rv32e/config.vh index 4ec0123d1..71f41df2b 100644 --- a/config/rv32e/config.vh +++ b/config/rv32e/config.vh @@ -116,6 +116,9 @@ localparam logic VIRTMEM_SUPPORTED = 0; localparam logic VECTORED_INTERRUPTS_SUPPORTED = 0; localparam logic BIGENDIAN_SUPPORTED = 0; +// Fetch buffer configuration +localparam FETCHBUFFER_ENTRIES =32'd0; + // TLB configuration. Entries should be a power of 2 localparam ITLB_ENTRIES = 32'd0; localparam DTLB_ENTRIES = 32'd0; diff --git a/config/rv32gc/config.vh b/config/rv32gc/config.vh index c861759d9..1c6c3b8c0 100644 --- a/config/rv32gc/config.vh +++ b/config/rv32gc/config.vh @@ -116,6 +116,9 @@ localparam logic VIRTMEM_SUPPORTED = 1; localparam logic VECTORED_INTERRUPTS_SUPPORTED = 1; localparam logic BIGENDIAN_SUPPORTED = 1; +// Fetch buffer configuration +localparam FETCHBUFFER_ENTRIES = 32'd3; + // TLB configuration. Entries should be a power of 2 localparam ITLB_ENTRIES = 32'd32; localparam DTLB_ENTRIES = 32'd32; diff --git a/config/rv32i/config.vh b/config/rv32i/config.vh index 01818afc2..c87a903c4 100644 --- a/config/rv32i/config.vh +++ b/config/rv32i/config.vh @@ -116,6 +116,9 @@ localparam logic VIRTMEM_SUPPORTED = 0; localparam logic VECTORED_INTERRUPTS_SUPPORTED = 1; localparam logic BIGENDIAN_SUPPORTED = 0; +// Fetch buffer configuration +localparam FETCHBUFFER_ENTRIES = 32'd3; + // TLB configuration. Entries should be a power of 2 localparam ITLB_ENTRIES = 32'd32; localparam DTLB_ENTRIES = 32'd32; diff --git a/config/rv32imc/config.vh b/config/rv32imc/config.vh index 05a8fd242..abd6a595a 100644 --- a/config/rv32imc/config.vh +++ b/config/rv32imc/config.vh @@ -116,6 +116,9 @@ localparam logic VIRTMEM_SUPPORTED = 0; localparam logic VECTORED_INTERRUPTS_SUPPORTED = 1; localparam logic BIGENDIAN_SUPPORTED = 0; +// Fetch buffer configuration +localparam FETCHBUFFER_ENTRIES = 32'd3; + // TLB configuration. Entries should be a power of 2 localparam ITLB_ENTRIES = 32'd0; localparam DTLB_ENTRIES = 32'd0; diff --git a/config/rv64gc/config.vh b/config/rv64gc/config.vh index b8ed8dc47..4208512d4 100644 --- a/config/rv64gc/config.vh +++ b/config/rv64gc/config.vh @@ -116,6 +116,9 @@ localparam logic VIRTMEM_SUPPORTED = 1; localparam logic VECTORED_INTERRUPTS_SUPPORTED = 1; localparam logic BIGENDIAN_SUPPORTED = 1; +// Fetch buffer configuration +localparam FETCHBUFFER_ENTRIES = 32'd3; + // TLB configuration. Entries should be a power of 2 localparam ITLB_ENTRIES = 32'd32; localparam DTLB_ENTRIES = 32'd32; diff --git a/config/rv64i/config.vh b/config/rv64i/config.vh index 94360877f..bf2c94bca 100644 --- a/config/rv64i/config.vh +++ b/config/rv64i/config.vh @@ -116,6 +116,9 @@ localparam logic VIRTMEM_SUPPORTED = 0; localparam logic VECTORED_INTERRUPTS_SUPPORTED = 1; localparam logic BIGENDIAN_SUPPORTED = 0; +// Fetch buffer configuration +localparam FETCHBUFFER_ENTRIES = 32'd3; + // TLB configuration. Entries should be a power of 2 localparam ITLB_ENTRIES = 32'd0; localparam DTLB_ENTRIES = 32'd0; diff --git a/config/shared/parameter-defs.vh b/config/shared/parameter-defs.vh index c80b00232..5d30710c1 100644 --- a/config/shared/parameter-defs.vh +++ b/config/shared/parameter-defs.vh @@ -45,6 +45,7 @@ localparam cvw_t P = '{ ICACHE_WAYSIZEINBYTES : ICACHE_WAYSIZEINBYTES, ICACHE_LINELENINBITS : ICACHE_LINELENINBITS, CACHE_SRAMLEN : CACHE_SRAMLEN, + FETCHBUFFER_ENTRIES : FETCHBUFFER_ENTRIES, IDIV_BITSPERCYCLE : IDIV_BITSPERCYCLE, IDIV_ON_FPU : IDIV_ON_FPU, PMP_ENTRIES : PMP_ENTRIES, diff --git a/src/cvw.sv b/src/cvw.sv index ed0493484..c6030ff31 100644 --- a/src/cvw.sv +++ b/src/cvw.sv @@ -74,6 +74,9 @@ typedef struct packed { logic DCACHE_SUPPORTED; logic ICACHE_SUPPORTED; + // Fetch Buffer Configuration + int FETCHBUFFER_ENTRIES; + // TLB configuration. Entries should be a power of 2 int ITLB_ENTRIES; int DTLB_ENTRIES; diff --git a/src/ifu/fetchbuffer.sv b/src/ifu/fetchbuffer.sv index 2efd2a6c0..c68ddbdad 100644 --- a/src/ifu/fetchbuffer.sv +++ b/src/ifu/fetchbuffer.sv @@ -34,38 +34,35 @@ module fetchbuffer import cvw::*; #(parameter cvw_t P) ( output logic FetchBufferStallF ); localparam [31:0] nop = 32'h00000013; - logic [31:0] Readf0, Readf1, Readf2, ReadFetchBuffer; - logic [2:0] ReadPtr, WritePtr; + logic [31:0] ReadReg [P.FETCHBUFFER_ENTRIES-1:0]; + logic [31:0] ReadFetchBuffer; + logic [P.FETCHBUFFER_ENTRIES-1:0] ReadPtr, WritePtr; logic Empty, Full; assign Empty = |(ReadPtr & WritePtr); // Bitwise and the read&write ptr, and or the bits of the result together - assign Full = |({WritePtr[1:0], WritePtr[2]} & ReadPtr); // Same as above but left rotate WritePtr to "add 1" + assign Full = |({WritePtr[P.FETCHBUFFER_ENTRIES-2:0], WritePtr[P.FETCHBUFFER_ENTRIES-1]} & ReadPtr); // Same as above but left rotate WritePtr to "add 1" assign FetchBufferStallF = Full; - // will go in a generate block once this is parameterized - flopenl #(32) f0 (.clk, .load(reset | FlushD), .en(WritePtr[0]), .d(WriteData), .val(nop), .q(Readf0)); - flopenl #(32) f1 (.clk, .load(reset | FlushD), .en(WritePtr[1]), .d(WriteData), .val(nop), .q(Readf1)); - flopenl #(32) f2 (.clk, .load(reset | FlushD), .en(WritePtr[2]), .d(WriteData), .val(nop), .q(Readf2)); + flopenl #(32) fbEntries[P.FETCHBUFFER_ENTRIES-1:0] (.clk, .load(reset | FlushD), .en(WritePtr), .d(WriteData), .val(nop), .q(ReadReg)); // Fetch buffer entries anded with read ptr for AO Muxing - logic [31:0] DaoArr [2:0]; - // ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Make parameterizable - assign DaoArr[0] = ReadPtr[0] ? Readf0 : '0; - assign DaoArr[1] = ReadPtr[1] ? Readf1 : '0; - assign DaoArr[2] = ReadPtr[2] ? Readf2 : '0; + logic [31:0] DaoArr [P.FETCHBUFFER_ENTRIES-1:0]; - or_rows #(3, 32) ReadFBAOMux(.a(DaoArr), .y(ReadFetchBuffer)); - // ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Make parameterizable + for (genvar i = 0; i < P.FETCHBUFFER_ENTRIES; i++) begin + assign DaoArr[i] = ReadPtr[i] ? ReadReg[i] : '0; + end + + or_rows #(P.FETCHBUFFER_ENTRIES, 32) ReadFBAOMux(.a(DaoArr), .y(ReadFetchBuffer)); assign ReadData = Empty ? nop : ReadFetchBuffer; always_ff @(posedge clk) begin : shiftRegister if (reset) begin - WritePtr <= 3'b001; - ReadPtr <= 3'b001; + WritePtr <= {{P.FETCHBUFFER_ENTRIES-1{1'b0}}, 1'b1}; + ReadPtr <= {{P.FETCHBUFFER_ENTRIES-1{1'b0}}, 1'b1}; end else begin - WritePtr <= ~(Full | StallF) ? {WritePtr[1:0], WritePtr[2]} : WritePtr; - ReadPtr <= ~(StallD | Empty) ? {ReadPtr[1:0], ReadPtr[2]} : ReadPtr; + WritePtr <= ~(Full | StallF) ? {WritePtr[P.FETCHBUFFER_ENTRIES-2:0], WritePtr[P.FETCHBUFFER_ENTRIES-1]} : WritePtr; + ReadPtr <= ~(StallD | Empty) ? {ReadPtr[P.FETCHBUFFER_ENTRIES-2:0], ReadPtr[P.FETCHBUFFER_ENTRIES-1]} : ReadPtr; end end endmodule diff --git a/src/ifu/ifu.sv b/src/ifu/ifu.sv index e91f9123b..9759bb79a 100644 --- a/src/ifu/ifu.sv +++ b/src/ifu/ifu.sv @@ -303,8 +303,12 @@ module ifu import cvw::*; #(parameter cvw_t P) ( assign IFUStallF = IFUCacheBusStallF | SelSpillNextF; assign GatedStallD = StallD & ~SelSpillNextF; - // flopenl #(32) AlignedInstrRawDFlop(clk, reset | FlushD, ~StallD, PostSpillInstrRawF, nop, InstrRawD); - fetchbuffer #(P) fetchbuff(.clk, .reset, .StallF, .StallD, .FlushD, .WriteData(PostSpillInstrRawF), .ReadData(InstrRawD), .FetchBufferStallF); + if (P.FETCHBUFFER_ENTRIES != 0) begin : fetchbuffer + fetchbuffer #(P) fetchbuff(.clk, .reset, .StallF, .StallD, .FlushD, .WriteData(PostSpillInstrRawF), .ReadData(InstrRawD), .FetchBufferStallF); + end else begin + flopenl #(32) AlignedInstrRawDFlop(clk, reset | FlushD, ~StallD, PostSpillInstrRawF, nop, InstrRawD); + assign FetchBufferStallF = '0; + end //////////////////////////////////////////////////////////////////////////////////////////////// // PCNextF logic diff --git a/testbench/common/riscvassertions.sv b/testbench/common/riscvassertions.sv index c0f13d8ff..951d5d86b 100644 --- a/testbench/common/riscvassertions.sv +++ b/testbench/common/riscvassertions.sv @@ -67,6 +67,7 @@ module riscvassertions import cvw::*; #(parameter cvw_t P); assert ((P.ZCD_SUPPORTED == 0) | (P.D_SUPPORTED == 1)) else $fatal(1, "ZCD requires D"); assert ((P.LLEN == P.XLEN) | (P.DCACHE_SUPPORTED & P.DTIM_SUPPORTED == 0)) else $fatal(1, "LLEN > XLEN (D on RV32 or Q on RV64) requires data cache"); assert ((P.ZICCLSM_SUPPORTED == 0) | (P.DCACHE_SUPPORTED == 1)) else $fatal(1, "ZICCLSM requires DCACHE_SUPPORTED"); + assert ((P.FETCHBUFFER_ENTRIES == 0) | (P.FETCHBUFFER_ENTRIES >= 3)) else $fatal(1, "FETCHBUFFER_ENTRIES must be 0 (disabled) or at least 3"); end endmodule