fixed redundnat cache fill with dirty block, fixed cache tag_store critical path

This commit is contained in:
Blaise Tine
2020-11-10 08:32:34 -08:00
parent 725322807e
commit c1f23cf3ad
3 changed files with 52 additions and 54 deletions

View File

@@ -328,9 +328,9 @@ 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;
assign is_snp_st0 = msrq_pop_unqual ? msrq_is_snp_st0 : assign is_snp_st0 = msrq_pop_unqual ? msrq_is_snp_st0 :
@@ -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,8 +741,8 @@ 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),
`UNUSED_PIN (size) `UNUSED_PIN (size)
@@ -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);

View File

@@ -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
&& is_write_in && !tags_match;
&& use_read_valid
&& !is_fill_in
&& !is_snp_in
&& !miss_out
&& !force_miss_in;
wire fill_write = valid_in && is_fill_in assign use_do_write = valid_in
&& !tags_match; // discard redundant fills because the block could be dirty && is_write_in
&& use_read_valid
&& !core_req_miss
&& !force_miss_in
&& !stall;
assign use_write_enable = (normal_write || fill_write) assign use_do_fill = valid_in
&& !stall; && is_fill_in
&& !stall;
assign use_invalidate = valid_in && is_snp_in 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
$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);
end
end else begin 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); $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
end end
end end

View File

@@ -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),