fixed redundnat cache fill with dirty block, fixed cache tag_store critical path
This commit is contained in:
18
hw/rtl/cache/VX_bank.v
vendored
18
hw/rtl/cache/VX_bank.v
vendored
@@ -328,7 +328,7 @@ module VX_bank #(
|
|||||||
|
|
||||||
assign writedata_st0 = dfpq_filldata_st0;
|
assign writedata_st0 = dfpq_filldata_st0;
|
||||||
|
|
||||||
assign inst_meta_st0 = msrq_pop_unqual ? {`REQ_TAG_WIDTH'(msrq_tag_st0) , msrq_rw_st0, msrq_byteen_st0, msrq_tid_st0} :
|
assign inst_meta_st0 = msrq_pop_unqual ? {`REQ_TAG_WIDTH'(msrq_tag_st0), msrq_rw_st0, msrq_byteen_st0, msrq_tid_st0} :
|
||||||
reqq_pop_unqual ? {`REQ_TAG_WIDTH'(reqq_tag_st0), reqq_rw_st0, reqq_byteen_st0, reqq_tid_st0} :
|
reqq_pop_unqual ? {`REQ_TAG_WIDTH'(reqq_tag_st0), reqq_rw_st0, reqq_byteen_st0, reqq_tid_st0} :
|
||||||
snrq_pop_unqual ? {`REQ_TAG_WIDTH'(snrq_tag_st0), 1'b0, WORD_SIZE'(0), `REQS_BITS'(0)} :
|
snrq_pop_unqual ? {`REQ_TAG_WIDTH'(snrq_tag_st0), 1'b0, WORD_SIZE'(0), `REQS_BITS'(0)} :
|
||||||
0;
|
0;
|
||||||
@@ -712,14 +712,14 @@ module VX_bank #(
|
|||||||
|
|
||||||
wire dwbq_empty, dwbq_full;
|
wire dwbq_empty, dwbq_full;
|
||||||
|
|
||||||
wire dwbq_is_dfl_in = valid_st3 && miss_st3 && (!force_miss_st3 || is_msrq_st3);
|
wire dwbq_is_fill = valid_st3 && miss_st3 && (!force_miss_st3 || is_msrq_st3);
|
||||||
wire dwbq_is_dwb_in = valid_st3 && dirty_st3 && (is_fill_st3 || (!force_miss_st3 && is_snp_st3));
|
wire dwbq_is_wb = valid_st3 && dirty_st3 && (is_fill_st3 || (!force_miss_st3 && is_snp_st3));
|
||||||
wire dwbq_push_unqual = dwbq_is_dfl_in || dwbq_is_dwb_in;
|
wire dwbq_push_unqual = dwbq_is_fill || dwbq_is_wb;
|
||||||
|
|
||||||
assign dwbq_push_stall = dwbq_push_unqual && dwbq_full;
|
assign dwbq_push_stall = dwbq_push_unqual && dwbq_full;
|
||||||
|
|
||||||
wire dwbq_push = dwbq_push_unqual
|
wire dwbq_push = dwbq_push_unqual
|
||||||
&& !(dwbq_is_dfl_in && incoming_fill) // not in 'dwbq_push_stall' to reduce clock delay
|
&& !(dwbq_is_fill && incoming_fill) // not in 'dwbq_push_stall' to reduce clock delay
|
||||||
&& !dwbq_full
|
&& !dwbq_full
|
||||||
&& !msrq_push_stall
|
&& !msrq_push_stall
|
||||||
&& !cwbq_push_stall
|
&& !cwbq_push_stall
|
||||||
@@ -727,10 +727,10 @@ module VX_bank #(
|
|||||||
|
|
||||||
wire dwbq_pop = dram_req_valid && dram_req_ready;
|
wire dwbq_pop = dram_req_valid && dram_req_ready;
|
||||||
|
|
||||||
wire [`LINE_ADDR_WIDTH-1:0] dwbq_addr = dwbq_is_dwb_in ? {readtag_st3, addr_st3[`LINE_SELECT_BITS-1:0]} :
|
wire [`LINE_ADDR_WIDTH-1:0] dwbq_addr = dwbq_is_wb ? {readtag_st3, addr_st3[`LINE_SELECT_BITS-1:0]} :
|
||||||
addr_st3;
|
addr_st3;
|
||||||
|
|
||||||
wire [BANK_LINE_SIZE-1:0] dwbq_byteen = dwbq_is_dwb_in ? dirtyb_st3 : {BANK_LINE_SIZE{1'b1}};
|
wire [BANK_LINE_SIZE-1:0] dwbq_byteen = dwbq_is_wb ? dirtyb_st3 : {BANK_LINE_SIZE{1'b1}};
|
||||||
|
|
||||||
if (DRAM_ENABLE) begin
|
if (DRAM_ENABLE) begin
|
||||||
VX_generic_queue #(
|
VX_generic_queue #(
|
||||||
@@ -741,7 +741,7 @@ module VX_bank #(
|
|||||||
.reset (reset),
|
.reset (reset),
|
||||||
.push (dwbq_push),
|
.push (dwbq_push),
|
||||||
.pop (dwbq_pop),
|
.pop (dwbq_pop),
|
||||||
.data_in ({dwbq_is_dwb_in, dwbq_byteen, dwbq_addr, readdata_st3}),
|
.data_in ({dwbq_is_wb, dwbq_byteen, dwbq_addr, readdata_st3}),
|
||||||
.data_out({dram_req_rw, dram_req_byteen, dram_req_addr, dram_req_data}),
|
.data_out({dram_req_rw, dram_req_byteen, dram_req_addr, dram_req_data}),
|
||||||
.empty (dwbq_empty),
|
.empty (dwbq_empty),
|
||||||
.full (dwbq_full),
|
.full (dwbq_full),
|
||||||
@@ -856,7 +856,7 @@ module VX_bank #(
|
|||||||
$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_st3, BANK_ID), cwbq_tag_st3, cwbq_tid_st3, cwbq_data_st3, debug_wid_st3, debug_pc_st3);
|
$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_st3, BANK_ID), cwbq_tag_st3, cwbq_tid_st3, cwbq_data_st3, debug_wid_st3, debug_pc_st3);
|
||||||
end
|
end
|
||||||
if (dwbq_push) begin
|
if (dwbq_push) begin
|
||||||
if (dwbq_is_dwb_in)
|
if (dwbq_is_wb)
|
||||||
$display("%t: cache%0d:%0d writeback: addr=%0h, data=%0h, byteen=%b, wid=%0d, PC=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(dwbq_addr, BANK_ID), readdata_st3, dirtyb_st3, debug_wid_st3, debug_pc_st3);
|
$display("%t: cache%0d:%0d writeback: addr=%0h, data=%0h, byteen=%b, wid=%0d, PC=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(dwbq_addr, BANK_ID), readdata_st3, dirtyb_st3, debug_wid_st3, debug_pc_st3);
|
||||||
else
|
else
|
||||||
$display("%t: cache%0d:%0d fill-req: addr=%0h, wid=%0d, PC=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(dwbq_addr, BANK_ID), debug_wid_st3, debug_pc_st3);
|
$display("%t: cache%0d:%0d fill-req: addr=%0h, wid=%0d, PC=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(dwbq_addr, BANK_ID), debug_wid_st3, debug_pc_st3);
|
||||||
|
|||||||
55
hw/rtl/cache/VX_tag_access.v
vendored
55
hw/rtl/cache/VX_tag_access.v
vendored
@@ -60,7 +60,8 @@ module VX_tag_access #(
|
|||||||
wire use_read_dirty;
|
wire use_read_dirty;
|
||||||
wire[`TAG_SELECT_BITS-1:0] use_read_tag;
|
wire[`TAG_SELECT_BITS-1:0] use_read_tag;
|
||||||
|
|
||||||
wire use_write_enable;
|
wire use_do_fill;
|
||||||
|
wire use_do_write;
|
||||||
wire use_invalidate;
|
wire use_invalidate;
|
||||||
|
|
||||||
wire[`TAG_SELECT_BITS-1:0] addrtag = addr_in[`TAG_LINE_ADDR_RNG];
|
wire[`TAG_SELECT_BITS-1:0] addrtag = addr_in[`TAG_LINE_ADDR_RNG];
|
||||||
@@ -80,9 +81,9 @@ module VX_tag_access #(
|
|||||||
.read_dirty (qual_read_dirty),
|
.read_dirty (qual_read_dirty),
|
||||||
.read_tag (qual_read_tag),
|
.read_tag (qual_read_tag),
|
||||||
|
|
||||||
|
.do_fill (use_do_fill),
|
||||||
|
.do_write (use_do_write),
|
||||||
.invalidate (use_invalidate),
|
.invalidate (use_invalidate),
|
||||||
.write_enable(use_write_enable),
|
|
||||||
.write_fill (is_fill_in),
|
|
||||||
.write_addr (addrline),
|
.write_addr (addrline),
|
||||||
.write_tag (addrtag)
|
.write_tag (addrtag)
|
||||||
);
|
);
|
||||||
@@ -94,50 +95,46 @@ module VX_tag_access #(
|
|||||||
// use "case equality" to handle uninitialized tag when block entry is not valid
|
// use "case equality" to handle uninitialized tag when block entry is not valid
|
||||||
wire tags_match = use_read_valid && (addrtag === use_read_tag);
|
wire tags_match = use_read_valid && (addrtag === use_read_tag);
|
||||||
|
|
||||||
wire normal_write = valid_in
|
wire core_req_miss = valid_in && !is_snp_in && !is_fill_in
|
||||||
|
&& !tags_match;
|
||||||
|
|
||||||
|
assign use_do_write = valid_in
|
||||||
&& is_write_in
|
&& is_write_in
|
||||||
&& use_read_valid
|
&& use_read_valid
|
||||||
&& !is_fill_in
|
&& !core_req_miss
|
||||||
&& !is_snp_in
|
&& !force_miss_in
|
||||||
&& !miss_out
|
|
||||||
&& !force_miss_in;
|
|
||||||
|
|
||||||
wire fill_write = valid_in && is_fill_in
|
|
||||||
&& !tags_match; // discard redundant fills because the block could be dirty
|
|
||||||
|
|
||||||
assign use_write_enable = (normal_write || fill_write)
|
|
||||||
&& !stall;
|
&& !stall;
|
||||||
|
|
||||||
assign use_invalidate = valid_in && is_snp_in
|
assign use_do_fill = valid_in
|
||||||
|
&& is_fill_in
|
||||||
|
&& !stall;
|
||||||
|
|
||||||
|
assign use_invalidate = valid_in
|
||||||
|
&& is_snp_in
|
||||||
&& tags_match
|
&& tags_match
|
||||||
&& (use_read_dirty || snp_invalidate_in) // block is dirty or should invalidate
|
&& (use_read_dirty || snp_invalidate_in) // block is dirty or should invalidate
|
||||||
&& !force_miss_in
|
&& !force_miss_in
|
||||||
&& !stall;
|
&& !stall;
|
||||||
|
|
||||||
wire core_req_miss = valid_in && !is_snp_in && !is_fill_in
|
|
||||||
&& !tags_match;
|
|
||||||
|
|
||||||
assign miss_out = core_req_miss;
|
assign miss_out = core_req_miss;
|
||||||
assign dirty_out = valid_in && use_read_valid && use_read_dirty;
|
assign dirty_out = valid_in && use_read_valid && use_read_dirty
|
||||||
|
&& !(is_fill_in && tags_match); // disable writeback for redundant fills
|
||||||
|
|
||||||
assign readtag_out = use_read_tag;
|
assign readtag_out = use_read_tag;
|
||||||
assign writeen_out = use_write_enable;
|
assign writeen_out = (use_do_write || use_do_fill);
|
||||||
|
|
||||||
`ifdef DBG_PRINT_CACHE_DATA
|
`ifdef DBG_PRINT_CACHE_DATA
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (valid_in && !stall) begin
|
if (valid_in && !stall) begin
|
||||||
if (is_fill_in && use_read_valid && tags_match) begin
|
if (use_do_fill && tags_match) begin
|
||||||
$display("%t: warning: redundant fill - addr=%0h", $time, `LINE_TO_BYTE_ADDR(addr_in, BANK_ID));
|
$display("%t: warning: redundant fill - addr=%0h", $time, `LINE_TO_BYTE_ADDR(addr_in, BANK_ID));
|
||||||
end
|
end
|
||||||
if (miss_out) begin
|
if (use_do_fill) begin
|
||||||
$display("%t: cache%0d:%0d tag-miss: addr=%0h, wid=%0d, PC=%0h, valid=%b, blk_tag_id=%0h, blk_addr=%0d, tag_id=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_in, BANK_ID), debug_wid, debug_pc, use_read_dirty, qual_read_tag, addrline, addrtag);
|
$display("%t: cache%0d:%0d tag-fill: addr=%0h, blk_addr=%0d, tag_id=%0h, old_tag_id=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_in, BANK_ID), addrline, addrtag, qual_read_tag);
|
||||||
end else if ((| use_write_enable)) begin
|
end else if (tags_match) begin
|
||||||
if (is_fill_in) begin
|
$display("%t: cache%0d:%0d tag-hit: addr=%0h, wid=%0d, PC=%0h, dirty=%b, blk_addr=%0d, tag_id=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_in, BANK_ID), debug_wid, debug_pc, use_read_dirty, addrline, addrtag);
|
||||||
$display("%t: cache%0d:%0d tag-fill: addr=%0h, blk_addr=%0d, tag_id=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_in, BANK_ID), addrline, addrtag);
|
|
||||||
end else begin
|
end else begin
|
||||||
$display("%t: cache%0d:%0d tag-write: addr=%0h, wid=%0d, PC=%0h, blk_addr=%0d, tag_id=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_in, BANK_ID), debug_wid, debug_pc, addrline, addrtag);
|
$display("%t: cache%0d:%0d tag-miss: addr=%0h, wid=%0d, PC=%0h, dirty=%b, blk_addr=%0d, tag_id=%0h, old_tag_id=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_in, BANK_ID), debug_wid, debug_pc, use_read_dirty, addrline, addrtag, qual_read_tag);
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
$display("%t: cache%0d:%0d tag-read: addr=%0h, wid=%0d, PC=%0h, blk_addr=%0d, tag_id=%0h", $time, CACHE_ID, BANK_ID, `LINE_TO_BYTE_ADDR(addr_in, BANK_ID), debug_wid, debug_pc, addrline, qual_read_tag);
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
15
hw/rtl/cache/VX_tag_store.v
vendored
15
hw/rtl/cache/VX_tag_store.v
vendored
@@ -13,11 +13,11 @@ module VX_tag_store #(
|
|||||||
input wire clk,
|
input wire clk,
|
||||||
input wire reset,
|
input wire reset,
|
||||||
|
|
||||||
input wire write_enable,
|
input wire do_fill,
|
||||||
input wire write_fill,
|
input wire do_write,
|
||||||
|
input wire invalidate,
|
||||||
input wire[`LINE_SELECT_BITS-1:0] write_addr,
|
input wire[`LINE_SELECT_BITS-1:0] write_addr,
|
||||||
input wire[`TAG_SELECT_BITS-1:0] write_tag,
|
input wire[`TAG_SELECT_BITS-1:0] write_tag,
|
||||||
input wire invalidate,
|
|
||||||
|
|
||||||
input wire[`LINE_SELECT_BITS-1:0] read_addr,
|
input wire[`LINE_SELECT_BITS-1:0] read_addr,
|
||||||
output wire[`TAG_SELECT_BITS-1:0] read_tag,
|
output wire[`TAG_SELECT_BITS-1:0] read_tag,
|
||||||
@@ -34,10 +34,11 @@ module VX_tag_store #(
|
|||||||
dirty[i] <= 0;
|
dirty[i] <= 0;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
if (write_enable) begin
|
if (do_fill) begin
|
||||||
assert(!invalidate);
|
|
||||||
dirty[write_addr] <= !write_fill;
|
|
||||||
valid[write_addr] <= 1;
|
valid[write_addr] <= 1;
|
||||||
|
dirty[write_addr] <= 0;
|
||||||
|
end else if (do_write) begin
|
||||||
|
dirty[write_addr] <= 1;
|
||||||
end else if (invalidate) begin
|
end else if (invalidate) begin
|
||||||
valid[write_addr] <= 0;
|
valid[write_addr] <= 0;
|
||||||
end
|
end
|
||||||
@@ -54,7 +55,7 @@ module VX_tag_store #(
|
|||||||
.clk(clk),
|
.clk(clk),
|
||||||
.waddr(write_addr),
|
.waddr(write_addr),
|
||||||
.raddr(read_addr),
|
.raddr(read_addr),
|
||||||
.wren(write_enable),
|
.wren(do_fill),
|
||||||
.byteen(1'b1),
|
.byteen(1'b1),
|
||||||
.rden(1'b1),
|
.rden(1'b1),
|
||||||
.din(write_tag),
|
.din(write_tag),
|
||||||
|
|||||||
Reference in New Issue
Block a user