Skip to content

Commit

Permalink
Change: rework cache blocks to have fully independant port for
Browse files Browse the repository at this point in the history
concurrent r/w request in dCache
  • Loading branch information
dpretet committed Aug 20, 2023
1 parent 7e0287b commit 9d9e136
Show file tree
Hide file tree
Showing 6 changed files with 302 additions and 463 deletions.
422 changes: 55 additions & 367 deletions doc/friscv.drawio

Large diffs are not rendered by default.

32 changes: 21 additions & 11 deletions rtl/friscv_cache_blocks.sv
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,6 @@ module friscv_cache_blocks
localparam TAG_IX = INDEX_IX + INDEX_W;
localparam TAG_W = ADDR_W - INDEX_W - OFFSET_W - OFFSET_IX;

// Number of isntruction per block, used to parse the words to write
localparam NB_INST_PER_BLK = CACHE_BLOCK_W / WLEN;


//////////////////////////////////////////////////////////////////////////
// Logic declaration
Expand All @@ -87,9 +84,6 @@ module friscv_cache_blocks
logic [INDEX_W -1:0] p2_windex;
logic [TAG_W -1:0] p2_wtag;

logic [INDEX_W -1:0] p1_index;
logic [INDEX_W -1:0] p2_index;

// extracted from the read interface
logic [INDEX_W -1:0] p1_rindex;
logic [TAG_W -1:0] p1_rtag;
Expand All @@ -108,9 +102,10 @@ module friscv_cache_blocks
logic [CACHE_BLOCK_W -1:0] p2_rblock_data;
logic p2_rblock_set;

// To switch between read and write request on a port
logic [INDEX_W -1:0] p1_index;
logic [INDEX_W -1:0] p2_index;

genvar i;
genvar k;

// Tracer setup
`ifdef TRACE_CACHE
Expand Down Expand Up @@ -158,6 +153,7 @@ module friscv_cache_blocks
end
`endif


//////////////////////////////////////////////////////////////////////////
// Address parsing and cache line construction
//////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -201,7 +197,6 @@ module friscv_cache_blocks
.p2_data_out (p2_rblock_data)
);


friscv_dpram
#(
`ifdef CACHE_SIM_ENV
Expand All @@ -224,6 +219,21 @@ module friscv_cache_blocks
.p2_data_out ({p2_rblock_set, p2_rblock_tag})
);

//////////////////////////////////////////////////////////////////////////
// always @ (posedge aclk) begin
// if (aresetn) begin
// if (p1_wen && p2_ren && p1_waddr == p2_raddr) begin
// $display("p1 write while p2 read");
// $finish();
// end
// if (p2_wen && p1_ren && p2_waddr == p1_raddr) begin
// $display("p2 write while p1 read");
// $finish();
// end
// end
// end
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// Follow the block fetch, the data selection and the hit/miss generation.
// raddr is decomposed in three parts:
Expand All @@ -238,7 +248,7 @@ module friscv_cache_blocks
//
// The MSB of a cache block is the set bit, set to 1 once the block
// has been written and so valid. This bit is set back to 0 during flush.
//
//
// Generate hit/miss flags based on read_tag == block_tag:
// - hit indicates the cache line store the expected instruction
// - miss indicates the cache is not initialized or doesn't contain
Expand All @@ -247,7 +257,7 @@ module friscv_cache_blocks

// offset is used to select the correct instruction across the cache line
assign p1_roffset = p1_raddr[OFFSET_IX+:OFFSET_W];
assign p2_roffset = p1_raddr[OFFSET_IX+:OFFSET_W];
assign p2_roffset = p2_raddr[OFFSET_IX+:OFFSET_W];

// address's MSB to identify the memory address source
assign p1_rtag = p1_raddr[TAG_IX+:TAG_W];
Expand Down
135 changes: 88 additions & 47 deletions rtl/friscv_cache_pusher.sv
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ module friscv_cache_pusher
parameter AXI_ADDR_W = 8,
// AXI ID width, setup by default to 8 and unused
parameter AXI_ID_W = 8,
// AXI4 data width, independant of control unit width
parameter AXI_DATA_W = 8,
// ID Mask to apply to identify the instruction cache in the AXI4
// infrastructure
parameter AXI_ID_MASK = 'h20,
Expand Down Expand Up @@ -105,9 +103,11 @@ module friscv_cache_pusher
logic data_fifo_afull;
logic resp_fifo_full;
logic resp_fifo_empty;
logic [XLEN/8 -1:0] wstrb;
logic wrbf_fifo_full;
logic wrbf_fifo_afull;
logic wrbf_fifo_empty;

logic [AXI_ID_W -1:0] cache_rid;
// Write-through path signals
logic [AXI_ID_W -1:0] cpl_bid;
logic [2 -1:0] cpl_bresp;
logic push_addr_data;
Expand All @@ -117,8 +117,19 @@ module friscv_cache_pusher
logic [AXI_ID_W -1:0] cpl_id_m;
logic [AXI_ID_W -1:0] req_id_m;
logic to_cpl;
logic awready;
logic wready;
logic wt_awready;
logic wt_wready;

// Write path signals
logic [XLEN/8 -1:0] wstrb;
logic [XLEN -1:0] wdata;
logic [AXI_ID_W -1:0] cache_rid_r;
logic [AXI_ADDR_W -1:0] cache_waddr_r;
logic [XLEN -1:0] cache_wdata_r;
logic [XLEN/8 -1:0] cache_wstrb_r;
logic [AXI_ID_W -1:0] cache_rid;
logic pull_wrbf;
logic is_io_req;

// Tracer setup
`ifdef TRACE_CACHE
Expand All @@ -137,53 +148,87 @@ module friscv_cache_pusher
// the cache blocks
//
///////////////////////////////////////////////////////////////////////////

assign mst_awready = wt_awready & wt_wready & !wrbf_fifo_afull & !wrbf_fifo_full;
assign mst_wready = wt_awready & wt_wready & !wrbf_fifo_afull & !wrbf_fifo_full;

assign cache_ren = mst_awvalid && mst_awready && mst_wvalid && mst_wready && !mst_awcache[1];
assign cache_raddr = mst_awaddr;

// Monitor the write requests and drive the cache block updater. Acts as a pipeline
// of the incoming write request to check if the data needs to be updated in a cache block
always @ (posedge aclk or negedge aresetn) begin

if (!aresetn) begin
cache_waddr <= '0;
cache_rid <= '0;
cache_wdata <= '0;
cache_wstrb <= '0;
cache_waddr_r <= '0;
cache_rid_r <= '0;
cache_wdata_r <= '0;
cache_wstrb_r <= '0;
push_addr_data <= '0;
wstrb <= '0;
is_io_req <= '0;
end else if (srst) begin
cache_waddr <= '0;
cache_rid <= '0;
cache_wdata <= '0;
cache_wstrb <= '0;
cache_waddr_r <= '0;
cache_rid_r <= '0;
cache_wdata_r <= '0;
cache_wstrb_r <= '0;
push_addr_data <= '0;
wstrb <= '0;
is_io_req <= '0;
end else begin
push_addr_data <= mst_awvalid && mst_awready && mst_wvalid && mst_wready;
cache_waddr_r <= mst_awaddr;
cache_rid_r <= mst_awid;
cache_wdata_r <= mst_wdata;
cache_wstrb_r <= mst_wstrb;
is_io_req <= mst_awcache[1] & mst_awvalid && mst_awready && mst_wvalid && mst_wready;
end
end

friscv_scfifo
#(
.PASS_THRU (0),
.ADDR_WIDTH ($clog2(OSTDREQ_NUM)),
.DATA_WIDTH (AXI_ADDR_W+AXI_ID_W+XLEN+XLEN/8)
)
wr_buffer
(
.aclk (aclk),
.aresetn (aresetn),
.srst (srst),
.flush (1'b0),
.data_in ({cache_wstrb_r, cache_wdata_r, cache_rid_r, cache_waddr_r}),
.push (cache_hit),
.full (wrbf_fifo_full),
.afull (wrbf_fifo_afull),
.data_out ({wstrb, wdata, cache_rid, cache_waddr}),
.pull (pull_wrbf),
.empty (wrbf_fifo_empty),
.aempty ()
);

always @ (*) begin

push_addr_data <= mst_awvalid && awready && mst_wvalid && wready;
cache_waddr <= mst_awaddr;
cache_rid <= mst_awid;
cache_wdata <= {SCALE{mst_wdata}};
wstrb <= mst_wstrb;

for (int i=0;i<SCALE;i=i+1) begin
if (mst_awaddr[2+:SCALE_W]==i[SCALE_W-1:0])
cache_wstrb[i*XLEN/8+:XLEN/8] <= mst_wstrb;
else
cache_wstrb[i*XLEN/8+:XLEN/8] <= {XLEN/8{1'b0}};
for (int i=0;i<SCALE;i=i+1) begin
if (cache_waddr[2+:SCALE_W]==i[SCALE_W-1:0]) begin
cache_wstrb[i*XLEN/8+:XLEN/8] = wstrb;
end else begin
cache_wstrb[i*XLEN/8+:XLEN/8] = {XLEN/8{1'b0}};
end
end
end

assign cache_ren = mst_awvalid && mst_awready && mst_wvalid && mst_wready && !mst_awcache[1];
assign cache_raddr = mst_awaddr;
assign cache_wen = cache_hit;
pull_wrbf = !cache_ren;
cache_wen = !wrbf_fifo_empty & !cache_ren;
cache_wdata = {SCALE{wdata}};

end

`ifdef TRACE_CACHE
always @ (posedge aclk or negedge aresetn) begin
if (aresetn && cache_hit) begin
if (aresetn && cache_wen) begin
$fwrite(f, "@ %0t: Update block\n", $realtime);
$fwrite(f, " - addr 0x%x\n", cache_waddr);
$fwrite(f, " - data 0x%x\n", cache_wdata);
$fwrite(f, " - strb 0x%x\n", cache_wstrb);
$fwrite(f, " - addr: 0x%x\n", cache_waddr);
$fwrite(f, " - data: 0x%x\n", cache_wdata);
$fwrite(f, " - strb: 0x%x\n", cache_wstrb);
$fwrite(f, " - id: 0x%x\n", cache_rid);
end
end
`endif
Expand All @@ -209,7 +254,7 @@ module friscv_cache_pusher
.aresetn (aresetn),
.srst (srst),
.flush (1'b0),
.data_in ({cache_rid, cache_waddr}),
.data_in ({cache_rid_r, cache_waddr_r}),
.push (push_addr_data),
.full (addr_fifo_full),
.afull (addr_fifo_afull),
Expand All @@ -219,7 +264,7 @@ module friscv_cache_pusher
.aempty ()
);

assign awready = !addr_fifo_full && !addr_fifo_afull;
assign wt_awready = !addr_fifo_full && !addr_fifo_afull;
assign memctrl_awvalid = !addr_fifo_empty;

friscv_scfifo
Expand All @@ -234,7 +279,7 @@ module friscv_cache_pusher
.aresetn (aresetn),
.srst (srst),
.flush (1'b0),
.data_in ({wstrb, cache_wdata[0+:XLEN]}),
.data_in ({cache_wstrb_r, cache_wdata_r}),
.push (push_addr_data),
.full (data_fifo_full),
.afull (data_fifo_afull),
Expand All @@ -244,12 +289,10 @@ module friscv_cache_pusher
.aempty ()
);

assign wready = !data_fifo_full & !data_fifo_afull;
assign wt_wready = !data_fifo_full & !data_fifo_afull;
assign memctrl_wvalid = !data_fifo_empty;

assign memctrl_awprot = 3'b0;

assign mst_awready = awready & wready;
assign mst_wready = awready & wready;

/////////////////////////////////////////////////////////////////////////////////
//
Expand Down Expand Up @@ -287,13 +330,12 @@ module friscv_cache_pusher

// Used to address the RAM storing the flag indicating a completion needs to
// be driven back the application to complete a request
assign req_id_m = (cache_miss) ? cache_rid ^ AXI_ID_MASK : mst_awid ^ AXI_ID_MASK;
assign req_id_m = cache_rid_r ^ AXI_ID_MASK;
// Used to check if the completion needs to be stored and then driven back
assign cpl_id_m = memctrl_bid ^ AXI_ID_MASK;
assign to_cpl = id_ram[cpl_id_m[OSTDREQ_W-1:0]];

// Track the outstanding request to drive back completion to the application
// FIXME: can't track a cache miss and an IO req in the same cycle
for (genvar i=0; i<OSTDREQ_NUM; i=i+1) begin : ID_TRACKER

always @ (posedge aclk or negedge aresetn) begin
Expand All @@ -302,8 +344,7 @@ module friscv_cache_pusher
end else if (srst) begin
id_ram[i] <= '0;
end else begin
if ((cache_miss || mst_awvalid && mst_awready && mst_wvalid && mst_wready && mst_awcache[1]) &&
req_id_m[OSTDREQ_W-1:0]==i[OSTDREQ_W-1:0])
if ((cache_miss || is_io_req) && req_id_m[OSTDREQ_W-1:0]==i[OSTDREQ_W-1:0])
begin
id_ram[i] <= 1'b1;
end else if (memctrl_bvalid && memctrl_bready && cpl_id_m[OSTDREQ_W-1:0]==i[OSTDREQ_W-1:0]) begin
Expand All @@ -316,7 +357,7 @@ module friscv_cache_pusher
// TODO: manage back-pressure of completion channel readiness
// Today OoO or memfy are always ready
always @ (*) begin
if (cache_hit) begin
if (cache_wen) begin
mst_bvalid = 1'b1;
mst_bresp = 2'b0;
mst_bid = cache_rid;
Expand Down
2 changes: 1 addition & 1 deletion rtl/friscv_control_h.sv
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

`ifndef CONTROL_VERBOSITY
`define CONTROL_VERBOSITY `SVL_VERBOSE_DEBUG
`define CONTROL_ROUTE `SVL_ROUTE_ALL
`define CONTROL_ROUTE `SVL_ROUTE_FILE
`endif

`endif
Expand Down
1 change: 0 additions & 1 deletion rtl/friscv_dcache.sv
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,6 @@ module friscv_dcache
.OSTDREQ_NUM (OSTDREQ_NUM),
.AXI_ADDR_W (AXI_ADDR_W),
.AXI_ID_W (AXI_ID_W),
.AXI_DATA_W (AXI_DATA_W),
.AXI_ID_MASK (AXI_ID_MASK),
.CACHE_BLOCK_W (CACHE_BLOCK_W)
)
Expand Down
Loading

0 comments on commit 9d9e136

Please sign in to comment.