mirror of
https://github.com/vortexgpgpu/vortex.git
synced 2025-04-23 13:27:29 -04:00
fixed l2/l3 caches related bugs
This commit is contained in:
parent
5c83c594c1
commit
06945533cf
13 changed files with 354 additions and 274 deletions
|
@ -302,7 +302,7 @@
|
|||
`define DDRAM_BYTEEN_WIDTH `DCACHE_LINE_SIZE
|
||||
|
||||
// DRAM request tag bits
|
||||
`define DDRAM_TAG_WIDTH `LOG2UP(`DNUM_BANKS)
|
||||
`define DDRAM_TAG_WIDTH `DDRAM_ADDR_WIDTH
|
||||
|
||||
// Core request size
|
||||
`define DNUM_REQUESTS `NUM_THREADS
|
||||
|
@ -351,7 +351,7 @@
|
|||
`define L2DRAM_BYTEEN_WIDTH `L2CACHE_LINE_SIZE
|
||||
|
||||
// DRAM request tag bits
|
||||
`define L2DRAM_TAG_WIDTH (`L2_ENABLE ? `LOG2UP(`L2NUM_BANKS) : (`XDRAM_TAG_WIDTH+`CLOG2(`NUM_CORES)))
|
||||
`define L2DRAM_TAG_WIDTH (`L2_ENABLE ? `L2DRAM_ADDR_WIDTH : (`XDRAM_TAG_WIDTH+`CLOG2(`NUM_CORES)))
|
||||
|
||||
////////////////////////// L3cache Configurable Knobs /////////////////////////
|
||||
|
||||
|
@ -377,7 +377,7 @@
|
|||
`define L3DRAM_BYTEEN_WIDTH `L3CACHE_LINE_SIZE
|
||||
|
||||
// DRAM request tag bits
|
||||
`define L3DRAM_TAG_WIDTH (`L3_ENABLE ? `LOG2UP(`L3NUM_BANKS) : (`L2DRAM_TAG_WIDTH+`CLOG2(`NUM_CLUSTERS)))
|
||||
`define L3DRAM_TAG_WIDTH (`L3_ENABLE ? `L3DRAM_ADDR_WIDTH : (`L2DRAM_TAG_WIDTH+`CLOG2(`NUM_CLUSTERS)))
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -239,7 +239,7 @@ module VX_lsu_unit #(
|
|||
|
||||
`ifdef DBG_PRINT_CORE_DCACHE
|
||||
always @(posedge clk) begin
|
||||
if ((| dcache_req_if.valid) && (|dcache_req_if.ready)) begin
|
||||
if (| (dcache_req_if.valid & dcache_req_if.ready)) begin
|
||||
if (dcache_req_if.rw[0])
|
||||
$display("%t: D$%0d Wr Req: wid=%0d, PC=%0h, tmask=%b, addr=%0h, tag=%0h, byteen=%0h, data=%0h",
|
||||
$time, CORE_ID, req_wid, req_pc, (dcache_req_if.valid & dcache_req_if.ready), req_address, dcache_req_if.tag, dcache_req_if.byteen, dcache_req_if.data);
|
||||
|
|
|
@ -269,9 +269,9 @@ module VX_mem_unit # (
|
|||
.dram_req_ready (1'b0),
|
||||
|
||||
// DRAM response
|
||||
.dram_rsp_valid (1'b0),
|
||||
.dram_rsp_data ((`SCACHE_LINE_SIZE*8)'(0)),
|
||||
.dram_rsp_tag (`LOG2UP(`SNUM_BANKS)'(0)),
|
||||
.dram_rsp_valid (0),
|
||||
.dram_rsp_data (0),
|
||||
.dram_rsp_tag (0),
|
||||
`UNUSED_PIN (dram_rsp_ready)
|
||||
);
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ module VX_scoreboard #(
|
|||
stall_ctr <= 0;
|
||||
end else if (ibuf_deq_if.valid && ~ibuf_deq_if.ready) begin
|
||||
stall_ctr <= stall_ctr + 1;
|
||||
assert(stall_ctr < 100000) else $error("*** %t: core%0d-stalled: wid=%0d, PC=%0h, rd=%0d, wb=%0d, inuse=%b%b%b%b",
|
||||
assert(stall_ctr < 10000) else $error("*** %t: core%0d-stalled: wid=%0d, PC=%0h, rd=%0d, wb=%0d, inuse=%b%b%b%b",
|
||||
$time, CORE_ID, ibuf_deq_if.wid, ibuf_deq_if.PC, ibuf_deq_if.rd, ibuf_deq_if.wb,
|
||||
deq_real_inuse_regs[ibuf_deq_if.rd], deq_real_inuse_regs[ibuf_deq_if.rs1], deq_real_inuse_regs[ibuf_deq_if.rs2], deq_real_inuse_regs[ibuf_deq_if.rs3]);
|
||||
end else if (ibuf_deq_if.valid && ibuf_deq_if.ready) begin
|
||||
|
|
|
@ -52,25 +52,20 @@ module VX_avs_wrapper #(
|
|||
wire avs_rspq_pop = avs_reqq_pop;
|
||||
wire avs_rspq_empty;
|
||||
|
||||
reg [RD_QUEUE_ADDRW-1:0] avs_pending_reads;
|
||||
wire [RD_QUEUE_ADDRW-1:0] avs_pending_reads_n;
|
||||
|
||||
assign avs_pending_reads_n = avs_pending_reads
|
||||
+ RD_QUEUE_ADDRW'((avs_reqq_push && !avs_rspq_pop) ? 1 :
|
||||
(avs_rspq_pop && !avs_reqq_push) ? -1 : 0);
|
||||
|
||||
reg rsp_queue_ready;
|
||||
wire rsp_queue_going_full;
|
||||
VX_pending_size #(
|
||||
.SIZE (RD_QUEUE_SIZE)
|
||||
) pending_size (
|
||||
.clk (clk),
|
||||
.reset (reset),
|
||||
.push (avs_reqq_push),
|
||||
.pop (avs_rspq_pop),
|
||||
.full (rsp_queue_going_full)
|
||||
);
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
avs_burstcount_r <= 1;
|
||||
avs_bankselect_r <= 0;
|
||||
avs_pending_reads <= 0;
|
||||
rsp_queue_ready <= 1;
|
||||
end else begin
|
||||
avs_pending_reads <= avs_pending_reads_n;
|
||||
rsp_queue_ready <= (avs_pending_reads_n != RD_QUEUE_SIZE);
|
||||
end
|
||||
avs_burstcount_r <= 1;
|
||||
avs_bankselect_r <= 0;
|
||||
end
|
||||
|
||||
VX_fifo_queue #(
|
||||
|
@ -107,12 +102,12 @@ module VX_avs_wrapper #(
|
|||
`UNUSED_PIN (size)
|
||||
);
|
||||
|
||||
assign avs_read = dram_req_valid && !dram_req_rw && rsp_queue_ready;
|
||||
assign avs_write = dram_req_valid && dram_req_rw && rsp_queue_ready;
|
||||
assign avs_read = dram_req_valid && !dram_req_rw && !rsp_queue_going_full;
|
||||
assign avs_write = dram_req_valid && dram_req_rw && !rsp_queue_going_full;
|
||||
assign avs_address = dram_req_addr;
|
||||
assign avs_byteenable = dram_req_byteen;
|
||||
assign avs_writedata = dram_req_data;
|
||||
assign dram_req_ready = !avs_waitrequest && rsp_queue_ready;
|
||||
assign dram_req_ready = !avs_waitrequest && !rsp_queue_going_full;
|
||||
assign avs_burstcount = avs_burstcount_r;
|
||||
assign avs_bankselect = avs_bankselect_r;
|
||||
|
||||
|
@ -124,10 +119,10 @@ module VX_avs_wrapper #(
|
|||
if (dram_req_rw)
|
||||
$display("%t: AVS Wr Req: addr=%0h, byteen=%0h, tag=%0h, data=%0h", $time, `TO_FULL_ADDR(dram_req_addr), dram_req_byteen, dram_req_tag, dram_req_data);
|
||||
else
|
||||
$display("%t: AVS Rd Req: addr=%0h, byteen=%0h, tag=%0h, pending=%0d", $time, `TO_FULL_ADDR(dram_req_addr), dram_req_byteen, dram_req_tag, avs_pending_reads_n);
|
||||
$display("%t: AVS Rd Req: addr=%0h, byteen=%0h, tag=%0h", $time, `TO_FULL_ADDR(dram_req_addr), dram_req_byteen, dram_req_tag);
|
||||
end
|
||||
if (dram_rsp_valid && dram_rsp_ready) begin
|
||||
$display("%t: AVS Rd Rsp: tag=%0h, data=%0h, pending=%0d", $time, dram_rsp_tag, dram_rsp_data, avs_pending_reads_n);
|
||||
$display("%t: AVS Rd Rsp: tag=%0h, data=%0h", $time, dram_rsp_tag, dram_rsp_data);
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
|
231
hw/rtl/cache/VX_bank.v
vendored
231
hw/rtl/cache/VX_bank.v
vendored
|
@ -84,12 +84,11 @@ module VX_bank #(
|
|||
|
||||
// DRAM response
|
||||
input wire dram_rsp_valid,
|
||||
input wire [`LINE_ADDR_WIDTH-1:0] dram_rsp_addr,
|
||||
input wire [`CACHE_LINE_WIDTH-1:0] dram_rsp_data,
|
||||
output wire dram_rsp_ready
|
||||
);
|
||||
|
||||
localparam MSHR_SIZE_BITS = $clog2(MSHR_SIZE+1);
|
||||
|
||||
`ifdef DBG_CACHE_REQ_INFO
|
||||
/* verilator lint_off UNUSED */
|
||||
wire [31:0] debug_pc_st0, debug_pc_st1, debug_pc_st01;
|
||||
|
@ -98,9 +97,9 @@ module VX_bank #(
|
|||
`endif
|
||||
|
||||
wire drsq_pop;
|
||||
wire drsq_empty, drsp_empty_next;
|
||||
|
||||
wire [`CACHE_LINE_WIDTH-1:0] drsq_filldata;
|
||||
wire drsq_empty, drsq_empty_next;
|
||||
wire [`LINE_ADDR_WIDTH-1:0] drsq_addr_next;
|
||||
wire [`CACHE_LINE_WIDTH-1:0] drsq_filldata_next;
|
||||
|
||||
wire drsq_push = dram_rsp_valid && dram_rsp_ready;
|
||||
|
||||
|
@ -108,8 +107,8 @@ module VX_bank #(
|
|||
wire drsq_full;
|
||||
assign dram_rsp_ready = !drsq_full;
|
||||
|
||||
VX_input_queue #(
|
||||
.DATAW ($bits(dram_rsp_data)),
|
||||
VX_fifo_queue_xt #(
|
||||
.DATAW (`LINE_ADDR_WIDTH + $bits(dram_rsp_data)),
|
||||
.SIZE (DRSQ_SIZE),
|
||||
.FASTRAM (1)
|
||||
) dram_rsp_queue (
|
||||
|
@ -117,29 +116,31 @@ module VX_bank #(
|
|||
.reset (reset),
|
||||
.push (drsq_push),
|
||||
.pop (drsq_pop),
|
||||
.data_in (dram_rsp_data),
|
||||
.data_out(drsq_filldata),
|
||||
.data_in ({dram_rsp_addr, dram_rsp_data}),
|
||||
`UNUSED_PIN (data_out),
|
||||
.empty (drsq_empty),
|
||||
`UNUSED_PIN (data_out_next),
|
||||
.empty_next(drsp_empty_next),
|
||||
.data_out_next ({drsq_addr_next, drsq_filldata_next}),
|
||||
.empty_next (drsq_empty_next),
|
||||
.full (drsq_full),
|
||||
`UNUSED_PIN (almost_full),
|
||||
`UNUSED_PIN (size)
|
||||
);
|
||||
end else begin
|
||||
`UNUSED_VAR (dram_rsp_valid)
|
||||
`UNUSED_VAR (dram_rsp_addr)
|
||||
`UNUSED_VAR (dram_rsp_data)
|
||||
assign drsq_empty = 1;
|
||||
assign drsp_empty_next = 1;
|
||||
assign drsq_filldata = 0;
|
||||
assign dram_rsp_ready = 0;
|
||||
assign drsq_empty = 1;
|
||||
assign drsq_empty_next = 1;
|
||||
assign drsq_addr_next = 0;
|
||||
assign drsq_filldata_next = 0;
|
||||
assign dram_rsp_ready = 0;
|
||||
end
|
||||
|
||||
wire creq_pop;
|
||||
wire creq_full;
|
||||
wire creq_empty;
|
||||
wire [`REQS_BITS-1:0] creq_tid_next;
|
||||
wire creq_full, creq_empty;
|
||||
wire creq_rw_next;
|
||||
wire [WORD_SIZE-1:0] creq_byteen_next;
|
||||
wire [`REQS_BITS-1:0] creq_tid_next;
|
||||
`IGNORE_WARNINGS_BEGIN
|
||||
wire [`WORD_ADDR_WIDTH-1:0] creq_addr_next_unqual;
|
||||
`IGNORE_WARNINGS_END
|
||||
|
@ -163,7 +164,7 @@ module VX_bank #(
|
|||
assign creq_wsel_next = 0;
|
||||
end
|
||||
|
||||
VX_input_queue #(
|
||||
VX_fifo_queue_xt #(
|
||||
.DATAW (CORE_TAG_WIDTH + `REQS_BITS + 1 + WORD_SIZE + `WORD_ADDR_WIDTH + `WORD_WIDTH),
|
||||
.SIZE (CREQ_SIZE),
|
||||
.FASTRAM (1)
|
||||
|
@ -173,14 +174,18 @@ module VX_bank #(
|
|||
.push (creq_push),
|
||||
.pop (creq_pop),
|
||||
.data_in ({core_req_tag, core_req_tid, core_req_rw, core_req_byteen, core_req_addr, core_req_data}),
|
||||
.data_out_next({creq_tag_next, creq_tid_next, creq_rw_next, creq_byteen_next, creq_addr_next_unqual, creq_writeword_next}),
|
||||
`UNUSED_PIN (empty_next),
|
||||
`UNUSED_PIN (data_out),
|
||||
.empty (creq_empty),
|
||||
.data_out_next({creq_tag_next, creq_tid_next, creq_rw_next, creq_byteen_next, creq_addr_next_unqual, creq_writeword_next}),
|
||||
`UNUSED_PIN (empty_next),
|
||||
.full (creq_full),
|
||||
`UNUSED_PIN (almost_full),
|
||||
`UNUSED_PIN (size)
|
||||
);
|
||||
|
||||
wire mshr_pop;
|
||||
wire mshr_almost_full;
|
||||
wire mshr_pending_unqual_st0;
|
||||
wire mshr_valid;
|
||||
wire mshr_valid_next;
|
||||
wire [`REQS_BITS-1:0] mshr_tid_next;
|
||||
|
@ -190,48 +195,26 @@ module VX_bank #(
|
|||
wire [`REQ_TAG_WIDTH-1:0] mshr_tag_next;
|
||||
wire mshr_rw_next;
|
||||
wire [WORD_SIZE-1:0] mshr_byteen_next;
|
||||
|
||||
reg [`LINE_ADDR_WIDTH-1:0] creq_addr;
|
||||
reg [`UP(`WORD_SELECT_BITS)-1:0] creq_wsel;
|
||||
reg [`REQ_TAG_WIDTH-1:0] creq_tag;
|
||||
reg creq_mem_rw;
|
||||
reg [WORD_SIZE-1:0] creq_byteen;
|
||||
reg [`WORD_WIDTH-1:0] creq_writeword;
|
||||
reg [`REQS_BITS-1:0] creq_tid;
|
||||
|
||||
always @(posedge clk) begin
|
||||
creq_addr <= (mshr_valid_next || !drsp_empty_next) ? mshr_addr_next : creq_addr_next;
|
||||
creq_wsel <= mshr_valid_next ? mshr_wsel_next : creq_wsel_next;
|
||||
creq_mem_rw <= mshr_valid_next ? mshr_rw_next : creq_rw_next;
|
||||
creq_byteen <= mshr_valid_next ? mshr_byteen_next : creq_byteen_next;
|
||||
creq_writeword <= mshr_valid_next ? mshr_writeword_next : creq_writeword_next;
|
||||
creq_tid <= mshr_valid_next ? mshr_tid_next : creq_tid_next;
|
||||
creq_tag <= mshr_valid_next ? `REQ_TAG_WIDTH'(mshr_tag_next) : `REQ_TAG_WIDTH'(creq_tag_next);
|
||||
end
|
||||
wire dreq_almost_full;
|
||||
|
||||
wire mshr_pop;
|
||||
reg [MSHR_SIZE_BITS-1:0] mshr_pending_size;
|
||||
wire [MSHR_SIZE_BITS-1:0] mshr_pending_size_n;
|
||||
reg mshr_going_full;
|
||||
wire mshr_pending_hazard_unqual_st0;
|
||||
|
||||
wire valid_st0, valid_st1;
|
||||
wire is_fill_st0, is_fill_st1;
|
||||
wire is_mshr_st0, is_mshr_st1;
|
||||
wire [`LINE_ADDR_WIDTH-1:0] addr_st0, addr_st1;
|
||||
wire [`UP(`WORD_SELECT_BITS)-1:0] wsel_st0, wsel_st1;
|
||||
wire [`CACHE_LINE_WIDTH-1:0] readdata_st0, readdata_st1;
|
||||
wire mem_rw_st0, mem_rw_st1;
|
||||
wire [WORD_SIZE-1:0] byteen_st0, byteen_st1;
|
||||
wire [`WORD_WIDTH-1:0] writeword_st0, writeword_st1;
|
||||
wire [`CACHE_LINE_WIDTH-1:0] filldata_st0, filldata_st1;
|
||||
wire [`REQS_BITS-1:0] req_tid_st0, req_tid_st1;
|
||||
wire [`REQ_TAG_WIDTH-1:0] tag_st0, tag_st1;
|
||||
wire valid_st0, valid_st1;
|
||||
wire is_fill_st0, is_fill_st1;
|
||||
wire is_mshr_st0, is_mshr_st1;
|
||||
wire [`CACHE_LINE_WIDTH-1:0] readdata_st0, readdata_st1;
|
||||
wire [`TAG_SELECT_BITS-1:0] readtag_st0, readtag_st1;
|
||||
wire miss_st0, miss_st1;
|
||||
wire force_miss_st0, force_miss_st1;
|
||||
wire dirty_st0;
|
||||
wire [CACHE_LINE_SIZE-1:0] dirtyb_st0, dirtyb_st1;
|
||||
wire [`REQ_TAG_WIDTH-1:0] tag_st0, tag_st1;
|
||||
wire mem_rw_st0, mem_rw_st1;
|
||||
wire [WORD_SIZE-1:0] byteen_st0, byteen_st1;
|
||||
wire [`REQS_BITS-1:0] req_tid_st0, req_tid_st1;
|
||||
wire do_writeback_st0, do_writeback_st1;
|
||||
wire writeen_unqual_st0, writeen_unqual_st1;
|
||||
wire mshr_push_unqual_st0, mshr_push_unqual_st1;
|
||||
|
@ -254,44 +237,39 @@ module VX_bank #(
|
|||
|
||||
wire is_mshr_miss_st1 = valid_st1 && is_mshr_st1 && (miss_st1 || force_miss_st1);
|
||||
|
||||
wire creq_commit = valid_st1 && !is_fill_st1
|
||||
&& (core_req_hit_st1 || (WRITE_THROUGH && mem_rw_st1))
|
||||
&& !pipeline_stall;
|
||||
|
||||
// determine which queue to pop next in piority order
|
||||
wire mshr_pop_unqual = mshr_valid;
|
||||
wire drsq_pop_unqual = !mshr_pop_unqual && !drsq_empty;
|
||||
wire creq_pop_unqual = !mshr_pop_unqual && !drsq_pop_unqual && !creq_empty && !mshr_going_full;
|
||||
wire creq_pop_unqual = !mshr_pop_unqual && !drsq_pop_unqual && !creq_empty && !mshr_almost_full && !dreq_almost_full;
|
||||
|
||||
assign mshr_pop = mshr_pop_unqual && !pipeline_stall
|
||||
&& !is_mshr_miss_st1; // stop if previous request was a miss
|
||||
assign drsq_pop = drsq_pop_unqual && !pipeline_stall;
|
||||
assign creq_pop = creq_pop_unqual && !pipeline_stall;
|
||||
|
||||
// MSHR pending size
|
||||
assign mshr_pending_size_n = mshr_pending_size +
|
||||
((creq_pop && !creq_commit) ? 1 : ((creq_commit && !creq_pop) ? -1 : 0));
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
mshr_pending_size <= 0;
|
||||
mshr_going_full <= 0;
|
||||
end else begin
|
||||
mshr_pending_size <= mshr_pending_size_n;
|
||||
mshr_going_full <= (mshr_pending_size_n == MSHR_SIZE_BITS'(MSHR_SIZE));
|
||||
end
|
||||
end
|
||||
assign valid_st0 = mshr_pop || drsq_pop || creq_pop;
|
||||
assign is_mshr_st0 = mshr_pop_unqual;
|
||||
assign is_fill_st0 = drsq_pop_unqual;
|
||||
|
||||
assign valid_st0 = mshr_pop || drsq_pop || creq_pop;
|
||||
assign is_mshr_st0 = mshr_pop_unqual;
|
||||
assign is_fill_st0 = drsq_pop_unqual;
|
||||
assign addr_st0 = creq_addr;
|
||||
assign wsel_st0 = creq_wsel;
|
||||
assign mem_rw_st0 = creq_mem_rw;
|
||||
assign byteen_st0 = creq_byteen;
|
||||
assign writeword_st0 = creq_writeword;
|
||||
assign req_tid_st0 = creq_tid;
|
||||
assign tag_st0 = creq_tag;
|
||||
assign filldata_st0 = drsq_filldata;
|
||||
VX_pipe_register #(
|
||||
.DATAW (`LINE_ADDR_WIDTH + `UP(`WORD_SELECT_BITS) + 1 + WORD_SIZE + `WORD_WIDTH + `REQS_BITS + `REQ_TAG_WIDTH + `CACHE_LINE_WIDTH),
|
||||
.RESETW (0)
|
||||
) pipe_reg0 (
|
||||
.clk (clk),
|
||||
.reset (reset),
|
||||
.enable (1'b1),
|
||||
.data_in ({
|
||||
mshr_valid_next ? mshr_addr_next : (!drsq_empty_next ? drsq_addr_next : creq_addr_next),
|
||||
mshr_valid_next ? mshr_wsel_next : creq_wsel_next,
|
||||
mshr_valid_next ? mshr_rw_next : creq_rw_next,
|
||||
mshr_valid_next ? mshr_byteen_next : creq_byteen_next,
|
||||
mshr_valid_next ? mshr_writeword_next : creq_writeword_next,
|
||||
mshr_valid_next ? mshr_tid_next : creq_tid_next,
|
||||
mshr_valid_next ? `REQ_TAG_WIDTH'(mshr_tag_next) : `REQ_TAG_WIDTH'(creq_tag_next),
|
||||
drsq_filldata_next
|
||||
}),
|
||||
.data_out ({addr_st0, wsel_st0, mem_rw_st0, byteen_st0, writeword_st0, req_tid_st0, tag_st0, filldata_st0})
|
||||
);
|
||||
|
||||
`ifdef DBG_CACHE_REQ_INFO
|
||||
if (CORE_TAG_WIDTH != CORE_TAG_ID_BITS && CORE_TAG_ID_BITS != 0) begin
|
||||
|
@ -347,12 +325,12 @@ if (DRAM_ENABLE) begin
|
|||
// redundant fills
|
||||
wire is_redundant_fill = is_fill_st0 && !miss_st0;
|
||||
|
||||
// we have a miss in mshr for the current address
|
||||
wire mshr_pending_hazard_st0 = mshr_pending_hazard_unqual_st0
|
||||
|| (valid_st1 && (miss_st1 || force_miss_st1) && (addr_st0 == addr_st1));
|
||||
// we have a miss in mshr or going to it for the current address
|
||||
wire mshr_pending_st0 = mshr_pending_unqual_st0
|
||||
|| (valid_st1 && (miss_st1 || force_miss_st1) && (addr_st0 == addr_st1));
|
||||
|
||||
// force miss to ensure commit order when a new request has pending previous requests to same block
|
||||
assign force_miss_st0 = !is_mshr_st0 && !is_fill_st0 && mshr_pending_hazard_st0;
|
||||
assign force_miss_st0 = !is_mshr_st0 && !is_fill_st0 && mshr_pending_st0;
|
||||
|
||||
assign writeen_unqual_st0 = (!is_fill_st0 && !miss_st0 && mem_rw_st0)
|
||||
|| (is_fill_st0 && !is_redundant_fill);
|
||||
|
@ -369,7 +347,7 @@ if (DRAM_ENABLE) begin
|
|||
|
||||
end else begin
|
||||
|
||||
`UNUSED_VAR (mshr_pending_hazard_unqual_st0)
|
||||
`UNUSED_VAR (mshr_pending_unqual_st0)
|
||||
`UNUSED_VAR (drsq_push)
|
||||
`UNUSED_VAR (dirty_st0)
|
||||
`UNUSED_VAR (writeen_st1)
|
||||
|
@ -400,7 +378,7 @@ end
|
|||
VX_pipe_register #(
|
||||
.DATAW (1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + `LINE_ADDR_WIDTH + `UP(`WORD_SELECT_BITS) + CACHE_LINE_SIZE + `CACHE_LINE_WIDTH + `WORD_WIDTH + `TAG_SELECT_BITS + `CACHE_LINE_WIDTH + 1 + WORD_SIZE + `REQS_BITS + `REQ_TAG_WIDTH),
|
||||
.RESETW (1)
|
||||
) pipe_reg (
|
||||
) pipe_reg1 (
|
||||
.clk (clk),
|
||||
.reset (reset),
|
||||
.enable (!pipeline_stall),
|
||||
|
@ -482,7 +460,7 @@ end
|
|||
&& !crsq_push_stall
|
||||
&& !dreq_push_stall;
|
||||
|
||||
wire incoming_fill_st1 = (!drsq_empty && (addr_st1 == addr_st0));
|
||||
wire incoming_fill_st1 = valid_st0 && is_fill_st0 && (addr_st1 == addr_st0);
|
||||
|
||||
if (DRAM_ENABLE) begin
|
||||
|
||||
|
@ -501,6 +479,7 @@ end
|
|||
.WORD_SIZE (WORD_SIZE),
|
||||
.NUM_REQS (NUM_REQS),
|
||||
.MSHR_SIZE (MSHR_SIZE),
|
||||
.ALM_FULL (MSHR_SIZE-1),
|
||||
.CORE_TAG_WIDTH (CORE_TAG_WIDTH)
|
||||
) miss_resrv (
|
||||
.clk (clk),
|
||||
|
@ -518,21 +497,22 @@ end
|
|||
.enqueue_addr (addr_st1),
|
||||
.enqueue_data ({writeword_st1, req_tid_st1, tag_st1, mem_rw_st1, byteen_st1, wsel_st1}),
|
||||
.enqueue_is_mshr (is_mshr_st1),
|
||||
.enqueue_ready (mshr_init_ready_state_st1),
|
||||
.enqueue_as_ready (mshr_init_ready_state_st1),
|
||||
.enqueue_almfull (mshr_almost_full),
|
||||
|
||||
// lookup
|
||||
.lookup_ready (drsq_pop),
|
||||
.lookup_addr (addr_st0),
|
||||
.lookup_match (mshr_pending_hazard_unqual_st0),
|
||||
.lookup_match (mshr_pending_unqual_st0),
|
||||
|
||||
// schedule
|
||||
.schedule (mshr_pop),
|
||||
.schedule_valid (mshr_valid),
|
||||
.schedule_valid_next(mshr_valid_next),
|
||||
.schedule_addr_next (mshr_addr_next),
|
||||
.schedule_data_next ({mshr_writeword_next, mshr_tid_next, mshr_tag_next, mshr_rw_next, mshr_byteen_next, mshr_wsel_next}),
|
||||
`UNUSED_PIN (schedule_addr),
|
||||
`UNUSED_PIN (schedule_data),
|
||||
.schedule_valid_next(mshr_valid_next),
|
||||
.schedule_addr_next (mshr_addr_next),
|
||||
.schedule_data_next ({mshr_writeword_next, mshr_tid_next, mshr_tag_next, mshr_rw_next, mshr_byteen_next, mshr_wsel_next}),
|
||||
|
||||
// dequeue
|
||||
.dequeue (mshr_dequeue_st1)
|
||||
|
@ -545,15 +525,16 @@ end
|
|||
`UNUSED_VAR (mem_rw_st1)
|
||||
`UNUSED_VAR (byteen_st1)
|
||||
`UNUSED_VAR (incoming_fill_st1)
|
||||
assign mshr_pending_hazard_unqual_st0 = 0;
|
||||
assign mshr_valid = 0;
|
||||
assign mshr_valid_next = 0;
|
||||
assign mshr_addr_next = 0;
|
||||
assign mshr_wsel_next = 0;
|
||||
assign mshr_almost_full = 0;
|
||||
assign mshr_pending_unqual_st0 = 0;
|
||||
assign mshr_valid = 0;
|
||||
assign mshr_valid_next = 0;
|
||||
assign mshr_addr_next = 0;
|
||||
assign mshr_wsel_next = 0;
|
||||
assign mshr_writeword_next = 0;
|
||||
assign mshr_tid_next = 0;
|
||||
assign mshr_tag_next = 0;
|
||||
assign mshr_rw_next = 0;
|
||||
assign mshr_tid_next = 0;
|
||||
assign mshr_tag_next = 0;
|
||||
assign mshr_rw_next = 0;
|
||||
assign mshr_byteen_next = 0;
|
||||
end
|
||||
|
||||
|
@ -607,13 +588,13 @@ end
|
|||
|
||||
// Enqueue DRAM request
|
||||
|
||||
wire dreq_empty, dreq_full;
|
||||
wire dreq_empty;
|
||||
|
||||
wire dreq_push_unqual = valid_st1 && dreq_push_st1;
|
||||
assign dreq_push_stall = dreq_push_unqual && dreq_full;
|
||||
assign dreq_push_stall = 0;
|
||||
|
||||
wire dreq_push = dreq_push_unqual
|
||||
&& !dreq_full
|
||||
wire dreq_push = dreq_push_unqual
|
||||
&& (do_writeback_st1 || !incoming_fill_st1)
|
||||
&& !mshr_push_stall
|
||||
&& !crsq_push_stall;
|
||||
|
||||
|
@ -645,16 +626,11 @@ end
|
|||
|
||||
assign dreq_byteen = writeback ? dreq_byteen_unqual : {CACHE_LINE_SIZE{1'b1}};
|
||||
|
||||
if (DRAM_ENABLE) begin
|
||||
always @(posedge clk) begin
|
||||
assert (!(dreq_push && !do_writeback_st1 && incoming_fill_st1))
|
||||
else $error("%t: incoming fill - addr=%0h", $time, `LINE_TO_BYTE_ADDR(addr_st1, BANK_ID));
|
||||
end
|
||||
|
||||
VX_fifo_queue #(
|
||||
if (DRAM_ENABLE) begin
|
||||
VX_fifo_queue_xt #(
|
||||
.DATAW (1 + CACHE_LINE_SIZE + `LINE_ADDR_WIDTH + `CACHE_LINE_WIDTH),
|
||||
.SIZE (DREQ_SIZE),
|
||||
.BUFFERED (1),
|
||||
.ALM_FULL (DREQ_SIZE-1),
|
||||
.FASTRAM (1)
|
||||
) dram_req_queue (
|
||||
.clk (clk),
|
||||
|
@ -664,7 +640,10 @@ end
|
|||
.data_in ({writeback, dreq_byteen, dreq_addr, dreq_data}),
|
||||
.data_out({dram_req_rw, dram_req_byteen, dram_req_addr, dram_req_data}),
|
||||
.empty (dreq_empty),
|
||||
.full (dreq_full),
|
||||
.almost_full (dreq_almost_full),
|
||||
`UNUSED_PIN (full),
|
||||
`UNUSED_PIN (data_out_next),
|
||||
`UNUSED_PIN (empty_next),
|
||||
`UNUSED_PIN (size)
|
||||
);
|
||||
end else begin
|
||||
|
@ -678,9 +657,9 @@ end
|
|||
`UNUSED_VAR (readdata_st1)
|
||||
`UNUSED_VAR (writeback)
|
||||
`UNUSED_VAR (dram_req_ready)
|
||||
assign dreq_empty = 1;
|
||||
assign dreq_full = 0;
|
||||
assign dram_req_rw = 0;
|
||||
assign dreq_empty = 1;
|
||||
assign dreq_almost_full = 0;
|
||||
assign dram_req_rw = 0;
|
||||
assign dram_req_byteen = 0;
|
||||
assign dram_req_addr = 0;
|
||||
assign dram_req_data = 0;
|
||||
|
@ -689,9 +668,7 @@ end
|
|||
assign dram_req_valid = !dreq_empty;
|
||||
|
||||
// bank pipeline stall
|
||||
assign pipeline_stall = mshr_push_stall
|
||||
|| crsq_push_stall
|
||||
|| dreq_push_stall;
|
||||
assign pipeline_stall = crsq_push_stall;
|
||||
|
||||
`SCOPE_ASSIGN (valid_st0, valid_st0);
|
||||
`SCOPE_ASSIGN (valid_st1, valid_st1);
|
||||
|
@ -708,23 +685,27 @@ end
|
|||
`ifdef PERF_ENABLE
|
||||
assign perf_read_misses = !pipeline_stall && miss_st1 && !is_mshr_st1 && !mem_rw_st1;
|
||||
assign perf_write_misses = !pipeline_stall && miss_st1 && !is_mshr_st1 && mem_rw_st1;
|
||||
assign perf_mshr_stalls = mshr_going_full;
|
||||
assign perf_pipe_stalls = pipeline_stall || mshr_going_full;
|
||||
assign perf_pipe_stalls = pipeline_stall || mshr_almost_full || dreq_going_full;
|
||||
assign perf_mshr_stalls = mshr_almost_full;
|
||||
`endif
|
||||
|
||||
`ifdef DBG_PRINT_CACHE_BANK
|
||||
always @(posedge clk) begin
|
||||
if (valid_st1 && !is_fill_st1 && miss_st1 && incoming_fill_st1) begin
|
||||
$display("%t: miss with incoming fill - addr=%0h", $time, `LINE_TO_BYTE_ADDR(addr_st1, BANK_ID));
|
||||
assert(!is_mshr_st1);
|
||||
end
|
||||
if (pipeline_stall) begin
|
||||
$display("%t: cache%0d:%0d pipeline-stall: mshr=%b, cwbq=%b, dwbq=%b", $time, CACHE_ID, BANK_ID, mshr_push_stall, crsq_push_stall, dreq_push_stall);
|
||||
end
|
||||
if (drsq_pop) begin
|
||||
$display("%t: cache%0d:%0d fill-rsp: addr=%0h, data=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_st0, BANK_ID), drsq_filldata);
|
||||
$display("%t: cache%0d:%0d fill-rsp: addr=%0h, data=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_st0, BANK_ID), filldata_st0);
|
||||
end
|
||||
if (creq_pop || mshr_pop) begin
|
||||
if (creq_mem_rw)
|
||||
$display("%t: cache%0d:%0d core-wr-req: addr=%0h, is_mshr=%b, tag=%0h, tid=%0d, byteen=%b, data=%0h, wid=%0d, PC=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_st0, BANK_ID), is_mshr_st0, creq_tag, creq_tid, creq_byteen, creq_writeword, debug_wid_st0, debug_pc_st0);
|
||||
if (mem_rw_st0)
|
||||
$display("%t: cache%0d:%0d core-wr-req: addr=%0h, is_mshr=%b, tag=%0h, tid=%0d, byteen=%b, data=%0h, wid=%0d, PC=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_st0, BANK_ID), is_mshr_st0, tag_st0, req_tid_st0, byteen_st0, writeword_st0, debug_wid_st0, debug_pc_st0);
|
||||
else
|
||||
$display("%t: cache%0d:%0d core-rd-req: addr=%0h, is_mshr=%b, tag=%0h, tid=%0d, byteen=%b, wid=%0d, PC=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_st0, BANK_ID), is_mshr_st0, creq_tag, creq_tid, creq_byteen, debug_wid_st0, debug_pc_st0);
|
||||
$display("%t: cache%0d:%0d core-rd-req: addr=%0h, is_mshr=%b, tag=%0h, tid=%0d, byteen=%b, wid=%0d, PC=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_st0, BANK_ID), is_mshr_st0, tag_st0, req_tid_st0, byteen_st0, debug_wid_st0, debug_pc_st0);
|
||||
end
|
||||
if (crsq_push) begin
|
||||
$display("%t: cache%0d:%0d core-rsp: addr=%0h, tag=%0h, tid=%0d, data=%0h, wid=%0d, PC=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_st1, BANK_ID), crsq_tag_st1, crsq_tid_st1, crsq_data_st1, debug_wid_st1, debug_pc_st1);
|
||||
|
|
31
hw/rtl/cache/VX_cache.v
vendored
31
hw/rtl/cache/VX_cache.v
vendored
|
@ -42,7 +42,7 @@ module VX_cache #(
|
|||
parameter CORE_TAG_ID_BITS = CORE_TAG_WIDTH,
|
||||
|
||||
// dram request tag size
|
||||
parameter DRAM_TAG_WIDTH = `LOG2UP(NUM_BANKS),
|
||||
parameter DRAM_TAG_WIDTH = (32 - $clog2(CACHE_LINE_SIZE)),
|
||||
|
||||
// bank offset from beginning of index range
|
||||
parameter BANK_ADDR_OFFSET = 0
|
||||
|
@ -89,6 +89,7 @@ module VX_cache #(
|
|||
);
|
||||
|
||||
`STATIC_ASSERT(NUM_BANKS <= NUM_REQS, ("invalid value"))
|
||||
`UNUSED_VAR (dram_rsp_tag)
|
||||
|
||||
wire [NUM_BANKS-1:0] per_bank_core_req_valid;
|
||||
wire [NUM_BANKS-1:0][`REQS_BITS-1:0] per_bank_core_req_tid;
|
||||
|
@ -130,10 +131,10 @@ module VX_cache #(
|
|||
.BANK_ADDR_OFFSET(BANK_ADDR_OFFSET),
|
||||
.BUFFERED ((NUM_BANKS > 1) && DRAM_ENABLE)
|
||||
) cache_core_req_bank_sel (
|
||||
.clk (clk),
|
||||
.reset (reset),
|
||||
.clk (clk),
|
||||
.reset (reset),
|
||||
`ifdef PERF_ENABLE
|
||||
.bank_stalls (perf_cache_if.bank_stalls),
|
||||
.bank_stalls(perf_cache_if.bank_stalls),
|
||||
`else
|
||||
`UNUSED_PIN (bank_stalls),
|
||||
`endif
|
||||
|
@ -154,11 +155,12 @@ module VX_cache #(
|
|||
.per_bank_core_req_ready (per_bank_core_req_ready)
|
||||
);
|
||||
|
||||
assign dram_req_tag = dram_req_addr;
|
||||
if (NUM_BANKS == 1) begin
|
||||
`UNUSED_VAR (dram_rsp_tag)
|
||||
assign dram_rsp_ready = per_bank_dram_rsp_ready;
|
||||
end else begin
|
||||
assign dram_rsp_ready = per_bank_dram_rsp_ready[dram_rsp_tag];
|
||||
assign dram_rsp_ready = per_bank_dram_rsp_ready[`DRAM_ADDR_BANK(dram_rsp_tag)];
|
||||
end
|
||||
|
||||
for (genvar i = 0; i < NUM_BANKS; i++) begin
|
||||
|
@ -184,7 +186,8 @@ module VX_cache #(
|
|||
wire[`CACHE_LINE_WIDTH-1:0] curr_bank_dram_req_data;
|
||||
wire curr_bank_dram_req_ready;
|
||||
|
||||
wire curr_bank_dram_rsp_valid;
|
||||
wire curr_bank_dram_rsp_valid;
|
||||
wire [`LINE_ADDR_WIDTH-1:0] curr_bank_dram_rsp_addr;
|
||||
wire [`CACHE_LINE_WIDTH-1:0] curr_bank_dram_rsp_data;
|
||||
wire curr_bank_dram_rsp_ready;
|
||||
|
||||
|
@ -220,8 +223,10 @@ module VX_cache #(
|
|||
// DRAM response
|
||||
if (NUM_BANKS == 1) begin
|
||||
assign curr_bank_dram_rsp_valid = dram_rsp_valid;
|
||||
assign curr_bank_dram_rsp_addr = dram_rsp_tag;
|
||||
end else begin
|
||||
assign curr_bank_dram_rsp_valid = dram_rsp_valid && (dram_rsp_tag == i);
|
||||
assign curr_bank_dram_rsp_valid = dram_rsp_valid && (`DRAM_ADDR_BANK(dram_rsp_tag) == i);
|
||||
assign curr_bank_dram_rsp_addr = `DRAM_TO_LINE_ADDR(dram_rsp_tag);
|
||||
end
|
||||
assign curr_bank_dram_rsp_data = dram_rsp_data;
|
||||
assign per_bank_dram_rsp_ready[i] = curr_bank_dram_rsp_ready;
|
||||
|
@ -284,7 +289,8 @@ module VX_cache #(
|
|||
.dram_req_ready (curr_bank_dram_req_ready),
|
||||
|
||||
// DRAM response
|
||||
.dram_rsp_valid (curr_bank_dram_rsp_valid),
|
||||
.dram_rsp_valid (curr_bank_dram_rsp_valid),
|
||||
.dram_rsp_addr (curr_bank_dram_rsp_addr),
|
||||
.dram_rsp_data (curr_bank_dram_rsp_data),
|
||||
.dram_rsp_ready (curr_bank_dram_rsp_ready)
|
||||
);
|
||||
|
@ -311,14 +317,14 @@ module VX_cache #(
|
|||
);
|
||||
|
||||
if (DRAM_ENABLE) begin
|
||||
wire [NUM_BANKS-1:0][(DRAM_TAG_WIDTH + `DRAM_ADDR_WIDTH + 1 + CACHE_LINE_SIZE + `CACHE_LINE_WIDTH)-1:0] data_in;
|
||||
wire [NUM_BANKS-1:0][(`DRAM_ADDR_WIDTH + 1 + CACHE_LINE_SIZE + `CACHE_LINE_WIDTH)-1:0] data_in;
|
||||
for (genvar i = 0; i < NUM_BANKS; i++) begin
|
||||
assign data_in[i] = {DRAM_TAG_WIDTH'(i), per_bank_dram_req_addr[i], per_bank_dram_req_rw[i], per_bank_dram_req_byteen[i], per_bank_dram_req_data[i]};
|
||||
assign data_in[i] = {per_bank_dram_req_addr[i], per_bank_dram_req_rw[i], per_bank_dram_req_byteen[i], per_bank_dram_req_data[i]};
|
||||
end
|
||||
|
||||
VX_stream_arbiter #(
|
||||
.NUM_REQS (NUM_BANKS),
|
||||
.DATAW (DRAM_TAG_WIDTH + `DRAM_ADDR_WIDTH + 1 + CACHE_LINE_SIZE + `CACHE_LINE_WIDTH),
|
||||
.DATAW (`DRAM_ADDR_WIDTH + 1 + CACHE_LINE_SIZE + `CACHE_LINE_WIDTH),
|
||||
.BUFFERED (1)
|
||||
) dram_req_arb (
|
||||
.clk (clk),
|
||||
|
@ -327,7 +333,7 @@ module VX_cache #(
|
|||
.data_in (data_in),
|
||||
.ready_in (per_bank_dram_req_ready),
|
||||
.valid_out (dram_req_valid),
|
||||
.data_out ({dram_req_tag, dram_req_addr, dram_req_rw, dram_req_byteen, dram_req_data}),
|
||||
.data_out ({dram_req_addr, dram_req_rw, dram_req_byteen, dram_req_data}),
|
||||
.ready_out (dram_req_ready)
|
||||
);
|
||||
end else begin
|
||||
|
@ -342,7 +348,6 @@ module VX_cache #(
|
|||
assign dram_req_byteen = 0;
|
||||
assign dram_req_addr = 0;
|
||||
assign dram_req_data = 0;
|
||||
assign dram_req_tag = 0;
|
||||
`UNUSED_VAR (dram_req_ready)
|
||||
end
|
||||
|
||||
|
|
50
hw/rtl/cache/VX_data_access.v
vendored
50
hw/rtl/cache/VX_data_access.v
vendored
|
@ -77,7 +77,8 @@ module VX_data_access #(
|
|||
.CACHE_LINE_SIZE (CACHE_LINE_SIZE),
|
||||
.NUM_BANKS (NUM_BANKS),
|
||||
.WORD_SIZE (WORD_SIZE),
|
||||
.WRITE_ENABLE (WRITE_ENABLE)
|
||||
.WRITE_ENABLE (WRITE_ENABLE),
|
||||
.WRITE_THROUGH (WRITE_THROUGH)
|
||||
) data_store (
|
||||
.clk (clk),
|
||||
.reset (reset),
|
||||
|
@ -97,26 +98,51 @@ module VX_data_access #(
|
|||
wire [`WORDS_PER_LINE-1:0][`WORD_WIDTH-1:0] writedata_qual;
|
||||
|
||||
if (`WORD_SELECT_BITS != 0) begin
|
||||
for (genvar i = 0; i < `WORDS_PER_LINE; i++) begin
|
||||
assign wbyteen_qual[i] = (wwsel_in == `WORD_SELECT_BITS'(i)) ? wbyteen_in : {WORD_SIZE{1'b0}};
|
||||
assign writedata_qual[i] = (wwsel_in == `WORD_SELECT_BITS'(i)) ? writeword_in : readdata_in[i * `WORD_WIDTH +: `WORD_WIDTH];
|
||||
for (genvar i = 0; i < `WORDS_PER_LINE; i++) begin
|
||||
wire [`WORD_WIDTH-1:0] readdata_sel = readdata_in[i * `WORD_WIDTH +: `WORD_WIDTH];
|
||||
wire [`WORD_WIDTH-1:0] writeword_qual;
|
||||
for (genvar j = 0; j < WORD_SIZE; j++) begin
|
||||
assign writeword_qual[j * 8 +: 8] = wbyteen_in[j] ? writeword_in[j * 8 +: 8] : readdata_sel[j * 8 +: 8];
|
||||
end
|
||||
wire wenable = (wwsel_in == `WORD_SELECT_BITS'(i));
|
||||
assign wbyteen_qual[i] = wenable ? wbyteen_in : {WORD_SIZE{1'b0}};
|
||||
assign writedata_qual[i] = wenable ? writeword_qual : readdata_sel;
|
||||
end
|
||||
end else begin
|
||||
`UNUSED_VAR (wwsel_in)
|
||||
`UNUSED_VAR (readdata_in)
|
||||
wire [`WORD_WIDTH-1:0] writeword_qual;
|
||||
for (genvar i = 0; i < WORD_SIZE; i++) begin
|
||||
assign writeword_qual[i * 8 +: 8] = wbyteen_in[i] ? writeword_in[i * 8 +: 8] : readdata_in[i * 8 +: 8];
|
||||
end
|
||||
assign wbyteen_qual = wbyteen_in;
|
||||
assign writedata_qual = writeword_in;
|
||||
assign writedata_qual = writeword_qual;
|
||||
end
|
||||
|
||||
assign byte_enable = wfill_in ? {CACHE_LINE_SIZE{1'b1}} : wbyteen_qual;
|
||||
assign write_data = wfill_in ? filldata_in : writedata_qual;
|
||||
|
||||
assign write_enable = writeen_in && !stall;
|
||||
assign byte_enable = wfill_in ? {CACHE_LINE_SIZE{1'b1}} : wbyteen_qual;
|
||||
assign write_data = wfill_in ? filldata_in : writedata_qual;
|
||||
|
||||
wire rw_hazard = DRAM_ENABLE && (raddr == waddr) && writeen_in;
|
||||
for (genvar i = 0; i < CACHE_LINE_SIZE; i++) begin
|
||||
assign dirtyb_out[i] = rw_hazard ? byte_enable[i] : read_dirtyb[i];
|
||||
assign readdata_out[i * 8 +: 8] = (rw_hazard && byte_enable[i]) ? write_data[i * 8 +: 8] : read_data[i * 8 +: 8];
|
||||
|
||||
if (`WORD_SELECT_BITS != 0) begin
|
||||
for (genvar i = 0; i < `WORDS_PER_LINE; i++) begin
|
||||
wire [`WORD_WIDTH-1:0] readdata_sel = read_data[i * `WORD_WIDTH +: `WORD_WIDTH];
|
||||
wire [`WORD_WIDTH-1:0] writeword_qual;
|
||||
for (genvar j = 0; j < WORD_SIZE; j++) begin
|
||||
assign writeword_qual[j * 8 +: 8] = wbyteen_in[j] ? writeword_in[j * 8 +: 8] : readdata_sel[j * 8 +: 8];
|
||||
end
|
||||
wire wenable = (wwsel_in == `WORD_SELECT_BITS'(i));
|
||||
assign dirtyb_out[i * WORD_SIZE +: WORD_SIZE] = read_dirtyb[i * WORD_SIZE +: WORD_SIZE] | ({WORD_SIZE{rw_hazard && wenable}} & wbyteen_in);
|
||||
assign readdata_out[i * `WORD_WIDTH +: `WORD_WIDTH] = (rw_hazard && wfill_in) ? filldata_in[i * `WORD_WIDTH +: `WORD_WIDTH] :
|
||||
(rw_hazard && wenable) ? writeword_qual : readdata_sel;
|
||||
end
|
||||
end else begin
|
||||
wire [`WORD_WIDTH-1:0] writeword_qual;
|
||||
for (genvar i = 0; i < WORD_SIZE; i++) begin
|
||||
assign writeword_qual[i * 8 +: 8] = wbyteen_in[i] ? writeword_in[i * 8 +: 8] : read_data[i * 8 +: 8];
|
||||
end
|
||||
assign dirtyb_out = read_dirtyb | ({WORD_SIZE{rw_hazard}} & wbyteen_in);
|
||||
assign readdata_out = rw_hazard ? (wfill_in ? filldata_in : writeword_qual) : read_data;
|
||||
end
|
||||
|
||||
`ifdef DBG_PRINT_CACHE_DATA
|
||||
|
|
21
hw/rtl/cache/VX_data_store.v
vendored
21
hw/rtl/cache/VX_data_store.v
vendored
|
@ -2,33 +2,36 @@
|
|||
|
||||
module VX_data_store #(
|
||||
// Size of cache in bytes
|
||||
parameter CACHE_SIZE = 1,
|
||||
parameter CACHE_SIZE = 1,
|
||||
// Size of line inside a bank in bytes
|
||||
parameter CACHE_LINE_SIZE = 1,
|
||||
parameter CACHE_LINE_SIZE = 1,
|
||||
// Number of banks
|
||||
parameter NUM_BANKS = 1,
|
||||
parameter NUM_BANKS = 1,
|
||||
// Size of a word in bytes
|
||||
parameter WORD_SIZE = 1,
|
||||
parameter WORD_SIZE = 1,
|
||||
|
||||
// Enable cache writeable
|
||||
parameter WRITE_ENABLE = 0
|
||||
parameter WRITE_ENABLE = 1,
|
||||
|
||||
// Enable write-through
|
||||
parameter WRITE_THROUGH = 1
|
||||
) (
|
||||
input wire clk,
|
||||
input wire reset,
|
||||
|
||||
input wire write_enable,
|
||||
input wire write_fill,
|
||||
input wire[CACHE_LINE_SIZE-1:0] byte_enable,
|
||||
input wire[CACHE_LINE_SIZE-1:0] byte_enable,
|
||||
input wire[`LINE_SELECT_BITS-1:0] write_addr,
|
||||
input wire[`CACHE_LINE_WIDTH-1:0] write_data,
|
||||
input wire[`CACHE_LINE_WIDTH-1:0] write_data,
|
||||
|
||||
input wire[`LINE_SELECT_BITS-1:0] read_addr,
|
||||
output wire[`WORDS_PER_LINE-1:0][WORD_SIZE-1:0] read_dirtyb,
|
||||
output wire[`CACHE_LINE_WIDTH-1:0] read_data
|
||||
output wire[`CACHE_LINE_WIDTH-1:0] read_data
|
||||
);
|
||||
`UNUSED_VAR (reset)
|
||||
|
||||
if (WRITE_ENABLE) begin
|
||||
if (WRITE_ENABLE && !WRITE_THROUGH) begin
|
||||
reg [`WORDS_PER_LINE-1:0][WORD_SIZE-1:0] dirtyb[`LINES_PER_BANK-1:0];
|
||||
always @(posedge clk) begin
|
||||
if (write_enable) begin
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
`include "VX_platform.vh"
|
||||
|
||||
module VX_input_queue #(
|
||||
module VX_fifo_queue_xt #(
|
||||
parameter DATAW = 1,
|
||||
parameter SIZE = 2,
|
||||
parameter ALM_FULL = (SIZE - 1),
|
||||
parameter ADDRW = $clog2(SIZE),
|
||||
parameter SIZEW = $clog2(SIZE+1),
|
||||
parameter FASTRAM = 0
|
||||
|
@ -17,61 +18,41 @@ module VX_input_queue #(
|
|||
output wire [DATAW-1:0] data_out_next,
|
||||
output wire empty_next,
|
||||
output wire full,
|
||||
output wire almost_full,
|
||||
output wire [SIZEW-1:0] size
|
||||
);
|
||||
wire [DATAW-1:0] dout;
|
||||
reg [DATAW-1:0] dout_r, dout_n_r;
|
||||
reg [ADDRW-1:0] wr_ptr_r;
|
||||
reg [ADDRW-1:0] rd_ptr_r, rd_ptr_n_r;
|
||||
reg full_r;
|
||||
reg full_r, almost_full_r;
|
||||
reg empty_r, empty_n_r;
|
||||
reg [ADDRW-1:0] used_r;
|
||||
|
||||
always @(*) begin
|
||||
empty_n_r = empty_r;
|
||||
if (reset) begin
|
||||
empty_n_r = 1;
|
||||
end else begin
|
||||
if (push && !pop) begin
|
||||
empty_n_r = 0;
|
||||
end
|
||||
if (pop && !push) begin
|
||||
if (used_r == ADDRW'(1)) begin
|
||||
empty_n_r = 1;
|
||||
end;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
dout_n_r = dout_r;
|
||||
if (push && (empty_r || ((used_r == ADDRW'(1)) && pop))) begin
|
||||
dout_n_r = data_in;
|
||||
end else if (pop) begin
|
||||
dout_n_r = dout;
|
||||
end
|
||||
end
|
||||
reg [ADDRW-1:0] used_r;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
full_r <= 0;
|
||||
used_r <= 0;
|
||||
if (reset) begin
|
||||
used_r <= 0;
|
||||
full_r <= 0;
|
||||
almost_full_r <= 0;
|
||||
end else begin
|
||||
assert(!push || !full);
|
||||
assert(!pop || !empty_r);
|
||||
if (push && !pop) begin
|
||||
if (used_r == ADDRW'(SIZE-1)) begin
|
||||
full_r <= 1;
|
||||
if (push) begin
|
||||
if (!pop) begin
|
||||
if (used_r == ADDRW'(SIZE-1))
|
||||
full_r <= 1;
|
||||
if (used_r == ADDRW'(ALM_FULL-1))
|
||||
almost_full_r <= 1;
|
||||
end
|
||||
end
|
||||
if (pop && !push) begin
|
||||
end else if (pop) begin
|
||||
if (used_r == ADDRW'(ALM_FULL))
|
||||
almost_full_r <= 0;
|
||||
full_r <= 0;
|
||||
end
|
||||
|
||||
used_r <= used_r + ADDRW'($signed(2'(push) - 2'(pop)));
|
||||
end
|
||||
empty_r <= empty_n_r;
|
||||
dout_r <= dout_n_r;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
|
@ -108,13 +89,45 @@ module VX_input_queue #(
|
|||
.rden(1'b1),
|
||||
.din(data_in),
|
||||
.dout(dout)
|
||||
);
|
||||
);
|
||||
|
||||
always @(*) begin
|
||||
empty_n_r = empty_r;
|
||||
if (reset) begin
|
||||
empty_n_r = 1;
|
||||
end else begin
|
||||
if (push) begin
|
||||
if (!pop) begin
|
||||
empty_n_r = 0;
|
||||
end
|
||||
end else if (pop) begin
|
||||
if (used_r == ADDRW'(1)) begin
|
||||
empty_n_r = 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
dout_n_r = dout_r;
|
||||
if (push && (empty_r || ((used_r == ADDRW'(1)) && pop))) begin
|
||||
dout_n_r = data_in;
|
||||
end else if (pop) begin
|
||||
dout_n_r = dout;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
empty_r <= empty_n_r;
|
||||
dout_r <= dout_n_r;
|
||||
end
|
||||
|
||||
assign data_out = dout_r;
|
||||
assign data_out_next = dout_n_r;
|
||||
assign empty = empty_r;
|
||||
assign empty_next = empty_n_r;
|
||||
assign full = full_r;
|
||||
assign almost_full = almost_full_r;
|
||||
assign size = {full_r, used_r};
|
||||
|
||||
endmodule
|
87
hw/rtl/cache/VX_miss_resrv.v
vendored
87
hw/rtl/cache/VX_miss_resrv.v
vendored
|
@ -14,6 +14,7 @@ module VX_miss_resrv #(
|
|||
parameter NUM_REQS = 1,
|
||||
// Miss Reserv Queue Knob
|
||||
parameter MSHR_SIZE = 1,
|
||||
parameter ALM_FULL = (MSHR_SIZE-1),
|
||||
// core request tag size
|
||||
parameter CORE_TAG_WIDTH = 1,
|
||||
// size of tag id in core request tag
|
||||
|
@ -36,7 +37,8 @@ module VX_miss_resrv #(
|
|||
input wire [`LINE_ADDR_WIDTH-1:0] enqueue_addr,
|
||||
input wire [`MSHR_DATA_WIDTH-1:0] enqueue_data,
|
||||
input wire enqueue_is_mshr,
|
||||
input wire enqueue_ready,
|
||||
input wire enqueue_as_ready,
|
||||
output wire enqueue_almfull,
|
||||
|
||||
// lookup
|
||||
input wire lookup_ready,
|
||||
|
@ -55,19 +57,22 @@ module VX_miss_resrv #(
|
|||
// dequeue
|
||||
input wire dequeue
|
||||
);
|
||||
localparam ADDRW = $clog2(MSHR_SIZE);
|
||||
|
||||
reg [MSHR_SIZE-1:0][`LINE_ADDR_WIDTH-1:0] addr_table;
|
||||
|
||||
reg [MSHR_SIZE-1:0] valid_table;
|
||||
reg [MSHR_SIZE-1:0] ready_table;
|
||||
reg [`LOG2UP(MSHR_SIZE)-1:0] schedule_ptr, schedule_n_ptr;
|
||||
reg [`LOG2UP(MSHR_SIZE)-1:0] restore_ptr;
|
||||
reg [`LOG2UP(MSHR_SIZE)-1:0] head_ptr, tail_ptr;
|
||||
reg [`LOG2UP(MSHR_SIZE)-1:0] used_r;
|
||||
reg full_r;
|
||||
|
||||
reg [MSHR_SIZE-1:0] valid_table;
|
||||
reg [MSHR_SIZE-1:0] ready_table;
|
||||
reg [ADDRW-1:0] schedule_ptr, schedule_n_ptr;
|
||||
reg [ADDRW-1:0] restore_ptr;
|
||||
reg [ADDRW-1:0] head_ptr, tail_ptr;
|
||||
reg [ADDRW-1:0] used_r;
|
||||
reg full_r, almost_full_r;
|
||||
|
||||
reg schedule_valid_r, schedule_valid_n_r;
|
||||
reg [`LINE_ADDR_WIDTH-1:0] schedule_addr_r, schedule_addr_n_r;
|
||||
reg [`MSHR_DATA_WIDTH-1:0] dout_r, dout_n_r;
|
||||
wire [`MSHR_DATA_WIDTH-1:0] dout;
|
||||
|
||||
wire [MSHR_SIZE-1:0] valid_address_match;
|
||||
for (genvar i = 0; i < MSHR_SIZE; i++) begin
|
||||
|
@ -79,17 +84,20 @@ module VX_miss_resrv #(
|
|||
wire push_new = enqueue && !enqueue_is_mshr;
|
||||
wire restore = enqueue && enqueue_is_mshr;
|
||||
|
||||
wire [`LOG2UP(MSHR_SIZE)-1:0] head_ptr_n = head_ptr + $bits(head_ptr)'(1);
|
||||
wire [ADDRW-1:0] head_ptr_n = head_ptr + $bits(head_ptr)'(1);
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
valid_table <= 0;
|
||||
ready_table <= 0;
|
||||
schedule_ptr <= 0;
|
||||
schedule_n_ptr <= 1;
|
||||
restore_ptr <= 0;
|
||||
head_ptr <= 0;
|
||||
tail_ptr <= 0;
|
||||
valid_table <= 0;
|
||||
ready_table <= 0;
|
||||
schedule_ptr <= 0;
|
||||
schedule_n_ptr <= 1;
|
||||
restore_ptr <= 0;
|
||||
head_ptr <= 0;
|
||||
tail_ptr <= 0;
|
||||
used_r <= 0;
|
||||
full_r <= 0;
|
||||
almost_full_r <= 0;
|
||||
end else begin
|
||||
|
||||
// WARNING: lookup should happen enqueue for ready_table's correct update
|
||||
|
@ -102,7 +110,7 @@ module VX_miss_resrv #(
|
|||
if (enqueue_is_mshr) begin
|
||||
// restore schedule, returning missed msrq entry
|
||||
valid_table[restore_ptr] <= 1;
|
||||
ready_table[restore_ptr] <= enqueue_ready;
|
||||
ready_table[restore_ptr] <= enqueue_as_ready;
|
||||
restore_ptr <= restore_ptr + $bits(restore_ptr)'(1);
|
||||
schedule_ptr <= head_ptr;
|
||||
schedule_n_ptr <= head_ptr_n;
|
||||
|
@ -110,7 +118,7 @@ module VX_miss_resrv #(
|
|||
// push new entry
|
||||
assert(!full_r);
|
||||
valid_table[tail_ptr] <= 1;
|
||||
ready_table[tail_ptr] <= enqueue_ready;
|
||||
ready_table[tail_ptr] <= enqueue_as_ready;
|
||||
tail_ptr <= tail_ptr + $bits(tail_ptr)'(1);
|
||||
end
|
||||
end else if (dequeue) begin
|
||||
|
@ -129,10 +137,25 @@ module VX_miss_resrv #(
|
|||
schedule_ptr <= schedule_n_ptr;
|
||||
if (MSHR_SIZE > 2) begin
|
||||
schedule_n_ptr <= schedule_ptr + $bits(schedule_ptr)'(2);
|
||||
end else begin // (SIZE == 2);
|
||||
end else begin // (MSHR_SIZE == 2);
|
||||
schedule_n_ptr <= ~schedule_n_ptr;
|
||||
end
|
||||
end
|
||||
|
||||
if (push_new) begin
|
||||
if (!dequeue) begin
|
||||
if (used_r == ADDRW'(MSHR_SIZE-1))
|
||||
full_r <= 1;
|
||||
if (used_r == ADDRW'(ALM_FULL-1))
|
||||
almost_full_r <= 1;
|
||||
end
|
||||
end else if (dequeue) begin
|
||||
if (used_r == ADDRW'(ALM_FULL))
|
||||
almost_full_r <= 0;
|
||||
full_r <= 0;
|
||||
end
|
||||
|
||||
used_r <= used_r + ADDRW'($signed(2'(push_new) - 2'(dequeue)));
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -142,8 +165,6 @@ module VX_miss_resrv #(
|
|||
end
|
||||
end
|
||||
|
||||
wire [`MSHR_DATA_WIDTH-1:0] dout;
|
||||
|
||||
VX_dp_ram #(
|
||||
.DATAW(`MSHR_DATA_WIDTH),
|
||||
.SIZE(MSHR_SIZE),
|
||||
|
@ -165,8 +186,10 @@ module VX_miss_resrv #(
|
|||
if (reset) begin
|
||||
schedule_valid_n_r = 0;
|
||||
end else begin
|
||||
if (lookup_ready) begin
|
||||
schedule_valid_n_r = 1;
|
||||
if (restore) begin
|
||||
schedule_valid_n_r = enqueue_as_ready;
|
||||
end else if (lookup_ready) begin
|
||||
schedule_valid_n_r = schedule_valid_r || (schedule_addr_r == lookup_addr);
|
||||
end else if (schedule) begin
|
||||
schedule_valid_n_r = ready_table[schedule_n_ptr];
|
||||
end
|
||||
|
@ -176,7 +199,8 @@ module VX_miss_resrv #(
|
|||
always @(*) begin
|
||||
schedule_addr_n_r = schedule_addr_r;
|
||||
dout_n_r = dout_r;
|
||||
if ((push_new && (used_r == 0 || (used_r == 1 && schedule))) || restore) begin
|
||||
if (restore
|
||||
|| (push_new && (used_r == 0 || (used_r == 1 && schedule)))) begin
|
||||
schedule_addr_n_r = enqueue_addr;
|
||||
dout_n_r = enqueue_data;
|
||||
end else if (schedule) begin
|
||||
|
@ -186,13 +210,6 @@ module VX_miss_resrv #(
|
|||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
used_r <= 0;
|
||||
full_r <= 0;
|
||||
end else begin
|
||||
used_r <= used_r + $bits(used_r)'($signed(2'(enqueue) - 2'(schedule)));
|
||||
full_r <= (used_r == $bits(used_r)'(MSHR_SIZE-1)) && enqueue;
|
||||
end
|
||||
schedule_valid_r <= schedule_valid_n_r;
|
||||
schedule_addr_r <= schedule_addr_n_r;
|
||||
dout_r <= dout_n_r;
|
||||
|
@ -206,6 +223,8 @@ module VX_miss_resrv #(
|
|||
assign schedule_addr_next = schedule_addr_n_r;
|
||||
assign schedule_data_next = dout_n_r;
|
||||
|
||||
assign enqueue_almfull = almost_full_r;
|
||||
|
||||
`ifdef DBG_PRINT_CACHE_MSHR
|
||||
always @(posedge clk) begin
|
||||
if (lookup_ready || schedule || enqueue || dequeue) begin
|
||||
|
@ -213,9 +232,9 @@ module VX_miss_resrv #(
|
|||
$display("%t: cache%0d:%0d msrq-schedule: addr%0d=%0h, wid=%0d, PC=%0h", $time, CACHE_ID, BANK_ID, schedule_ptr, `LINE_TO_BYTE_ADDR(schedule_addr, BANK_ID), deq_debug_wid, deq_debug_pc);
|
||||
if (enqueue) begin
|
||||
if (enqueue_is_mshr)
|
||||
$display("%t: cache%0d:%0d msrq-restore: addr%0d=%0h, ready=%b", $time, CACHE_ID, BANK_ID, restore_ptr, `LINE_TO_BYTE_ADDR(enqueue_addr, BANK_ID), enqueue_ready);
|
||||
$display("%t: cache%0d:%0d msrq-restore: addr%0d=%0h, ready=%b", $time, CACHE_ID, BANK_ID, restore_ptr, `LINE_TO_BYTE_ADDR(enqueue_addr, BANK_ID), enqueue_as_ready);
|
||||
else
|
||||
$display("%t: cache%0d:%0d msrq-enq: addr%0d=%0h, ready=%b, wid=%0d, PC=%0h", $time, CACHE_ID, BANK_ID, tail_ptr, `LINE_TO_BYTE_ADDR(enqueue_addr, BANK_ID), enqueue_ready, enq_debug_wid, enq_debug_pc);
|
||||
$display("%t: cache%0d:%0d msrq-enq: addr%0d=%0h, ready=%b, wid=%0d, PC=%0h", $time, CACHE_ID, BANK_ID, tail_ptr, `LINE_TO_BYTE_ADDR(enqueue_addr, BANK_ID), enqueue_as_ready, enq_debug_wid, enq_debug_pc);
|
||||
end
|
||||
if (dequeue)
|
||||
$display("%t: cache%0d:%0d msrq-deq addr%0d, wid=%0d, PC=%0h", $time, CACHE_ID, BANK_ID, head_ptr, enq_debug_wid, enq_debug_pc);
|
||||
|
|
|
@ -30,11 +30,13 @@ module VX_fifo_queue #(
|
|||
head_r <= 0;
|
||||
size_r <= 0;
|
||||
end else begin
|
||||
if (push && !pop) begin
|
||||
assert(!full);
|
||||
size_r <= 1;
|
||||
end else if (pop && !push) begin
|
||||
assert(!empty);
|
||||
assert(!push || !full);
|
||||
assert(!pop || !empty);
|
||||
if (push) begin
|
||||
if (!pop) begin
|
||||
size_r <= 1;
|
||||
end
|
||||
end else if (pop) begin
|
||||
size_r <= 0;
|
||||
end
|
||||
if (push) begin
|
||||
|
@ -62,13 +64,14 @@ module VX_fifo_queue #(
|
|||
end else begin
|
||||
assert(!push || !full);
|
||||
assert(!pop || !empty);
|
||||
if (push && !pop) begin
|
||||
empty_r <= 0;
|
||||
if (used_r == ADDRW'(SIZE-1)) begin
|
||||
full_r <= 1;
|
||||
if (push) begin
|
||||
if (!pop) begin
|
||||
empty_r <= 0;
|
||||
if (used_r == ADDRW'(SIZE-1)) begin
|
||||
full_r <= 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
if (pop && !push) begin
|
||||
end else if (pop) begin
|
||||
full_r <= 0;
|
||||
if (used_r == ADDRW'(1)) begin
|
||||
empty_r <= 1;
|
||||
|
|
35
hw/rtl/libs/VX_pending_size.v
Normal file
35
hw/rtl/libs/VX_pending_size.v
Normal file
|
@ -0,0 +1,35 @@
|
|||
`include "VX_platform.vh"
|
||||
|
||||
module VX_pending_size #(
|
||||
parameter SIZE = 1
|
||||
) (
|
||||
input wire clk,
|
||||
input wire reset,
|
||||
input wire push,
|
||||
input wire pop,
|
||||
output wire full
|
||||
);
|
||||
localparam ADDRW = $clog2(SIZE);
|
||||
|
||||
reg [ADDRW-1:0] size_r;
|
||||
reg full_r;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
size_r <= 0;
|
||||
full_r <= 0;
|
||||
end else begin
|
||||
assert(!push || !full);
|
||||
if (push) begin
|
||||
if (!pop && (used_r == ADDRW'(SIZE-1)))
|
||||
full_r <= 1;
|
||||
end else if (pop) begin
|
||||
full_r <= 0;
|
||||
end
|
||||
size_r <= size_r + ADDRW'($signed(2'(push && !pop) - 2'(pop && !push)));
|
||||
end
|
||||
end
|
||||
|
||||
assign full = full_r;
|
||||
|
||||
endmodule
|
Loading…
Add table
Add a link
Reference in a new issue