Skip to content

Commit

Permalink
cva6_icache: Allow one outstanding killed miss
Browse files Browse the repository at this point in the history
  • Loading branch information
colluca committed Oct 6, 2023
1 parent 9d822f1 commit b63ee13
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 24 deletions.
54 changes: 30 additions & 24 deletions hw/vendor/openhwgroup_cva6/core/cache_subsystem/cva6_icache.sv
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ module cva6_icache import ariane_pkg::*; import wt_cache_pkg::*; #(
logic cache_wren; // triggers write to cacheline
logic cmp_en_d, cmp_en_q; // enable tag comparison in next cycle. used to cut long path due to NC signal.
logic flush_d, flush_q; // used to register and signal pending flushes
logic outst_miss_d, outst_miss_q; // tracks whether there are any outstanding misses

// replacement strategy
logic update_lfsr; // shift the LFSR
Expand Down Expand Up @@ -171,6 +172,7 @@ end else begin : gen_piton_offset
cache_wren = 1'b0;
inv_en = 1'b0;
flush_d = flush_q | flush_i; // register incoming flush
outst_miss_d = outst_miss_q;

// interfaces
dreq_o.ready = 1'b0;
Expand All @@ -189,6 +191,11 @@ end else begin : gen_piton_offset
inv_en = 1'b1;
end

// kill an outstanding miss
if (mem_rtrn_vld_i && mem_rtrn_i.rtype == ICACHE_IFILL_ACK && outst_miss_q) begin
outst_miss_d = 1'b0;
end

unique case (state_q)
//////////////////////////////////
// this clears all valid bits
Expand All @@ -213,7 +220,7 @@ end else begin : gen_piton_offset
// wait for incoming requests
end
else if (!stall_i) begin
// mem requests are for sure invals here
// mem requests are for sure invals or killed misses here
if (!mem_rtrn_vld_i) begin
dreq_o.ready = 1'b1;
// we have a new request
Expand Down Expand Up @@ -251,8 +258,8 @@ end else begin : gen_piton_offset

// we can accept another request
// and stay here, but only if no inval is coming in
// note: we are not expecting ifill return packets here...
if (!mem_rtrn_vld_i) begin
// note: ifill return packets may arrive here only if killed...
if (!mem_rtrn_vld_i || (mem_rtrn_i.rtype == ICACHE_IFILL_ACK)) begin
dreq_o.ready = 1'b1;
if (dreq_i.req) begin
state_d = READ;
Expand Down Expand Up @@ -287,19 +294,25 @@ end else begin : gen_piton_offset
// returns. do not write to memory
// if the nc bit is set.
MISS: begin
// note: this is mutually exclusive with ICACHE_INV_REQ,
// so we do not have to check for invals here
if (mem_rtrn_vld_i && mem_rtrn_i.rtype == ICACHE_IFILL_ACK) begin
state_d = IDLE;
// only return data if request is not being killed
if (!(dreq_i.kill_s2 || flush_d)) begin
dreq_o.valid = 1'b1;
// only write to cache if this address is cacheable
cache_wren = ~paddr_is_nc;
// if there is an outstanding miss we must wait that it is discarded
if (!outst_miss_q) begin
// note: this is mutually exclusive with ICACHE_INV_REQ,
// so we do not have to check for invals here
if (mem_rtrn_vld_i && mem_rtrn_i.rtype == ICACHE_IFILL_ACK) begin
state_d = IDLE;
// only return data if request is not being killed
if (!(dreq_i.kill_s2 || flush_d)) begin
dreq_o.valid = 1'b1;
// only write to cache if this address is cacheable
cache_wren = ~paddr_is_nc;
end
// bail out if this request is being killed
end else if (dreq_i.kill_s2 || flush_d) begin
state_d = IDLE;
// track if there is an outstanding miss,
// the next response from memory must be discarded
outst_miss_d = 1'b1;
end
// bail out if this request is being killed
end else if (dreq_i.kill_s2 || flush_d) begin
state_d = KILL_MISS;
end
end
//////////////////////////////////
Expand All @@ -312,15 +325,6 @@ end else begin : gen_piton_offset
state_d = IDLE;
end
end
//////////////////////////////////
// killed miss,
// wait until memory responds and
// go back to idle
KILL_MISS: begin
if (mem_rtrn_vld_i && mem_rtrn_i.rtype == ICACHE_IFILL_ACK) begin
state_d = IDLE;
end
end
default: begin
// we should never get here
state_d = FLUSH;
Expand Down Expand Up @@ -492,6 +496,7 @@ end else begin : gen_piton_offset
cl_offset_q <= '0;
repl_way_oh_q <= '0;
inv_q <= '0;
outst_miss_q <= '0;
end else begin
cl_tag_q <= cl_tag_d;
flush_cnt_q <= flush_cnt_d;
Expand All @@ -503,6 +508,7 @@ end else begin : gen_piton_offset
cl_offset_q <= cl_offset_d;
repl_way_oh_q <= repl_way_oh_d;
inv_q <= inv_d;
outst_miss_q <= outst_miss_d;
end
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
From d9902d6cfb889da4e302f531b9dd31c2987bcb0c Mon Sep 17 00:00:00 2001
From: Luca Colagrande <luca.colagrande3@gmail.com>
Date: Fri, 6 Oct 2023 15:59:08 +0200
Subject: [PATCH] cva6_icache: Allow one outstanding killed miss

---
core/cache_subsystem/cva6_icache.sv | 54 ++++++++++++++++-------------
1 file changed, 30 insertions(+), 24 deletions(-)

diff --git a/core/cache_subsystem/cva6_icache.sv b/core/cache_subsystem/cva6_icache.sv
index 6dd677d8..9c081426 100644
--- a/core/cache_subsystem/cva6_icache.sv
+++ b/core/cache_subsystem/cva6_icache.sv
@@ -66,6 +66,7 @@ module cva6_icache import ariane_pkg::*; import wt_cache_pkg::*; #(
logic cache_wren; // triggers write to cacheline
logic cmp_en_d, cmp_en_q; // enable tag comparison in next cycle. used to cut long path due to NC signal.
logic flush_d, flush_q; // used to register and signal pending flushes
+ logic outst_miss_d, outst_miss_q; // tracks whether there are any outstanding misses

// replacement strategy
logic update_lfsr; // shift the LFSR
@@ -171,6 +172,7 @@ end else begin : gen_piton_offset
cache_wren = 1'b0;
inv_en = 1'b0;
flush_d = flush_q | flush_i; // register incoming flush
+ outst_miss_d = outst_miss_q;

// interfaces
dreq_o.ready = 1'b0;
@@ -189,6 +191,11 @@ end else begin : gen_piton_offset
inv_en = 1'b1;
end

+ // kill an outstanding miss
+ if (mem_rtrn_vld_i && mem_rtrn_i.rtype == ICACHE_IFILL_ACK && outst_miss_q) begin
+ outst_miss_d = 1'b0;
+ end
+
unique case (state_q)
//////////////////////////////////
// this clears all valid bits
@@ -213,7 +220,7 @@ end else begin : gen_piton_offset
// wait for incoming requests
end
else if (!stall_i) begin
- // mem requests are for sure invals here
+ // mem requests are for sure invals or killed misses here
if (!mem_rtrn_vld_i) begin
dreq_o.ready = 1'b1;
// we have a new request
@@ -251,8 +258,8 @@ end else begin : gen_piton_offset

// we can accept another request
// and stay here, but only if no inval is coming in
- // note: we are not expecting ifill return packets here...
- if (!mem_rtrn_vld_i) begin
+ // note: ifill return packets may arrive here only if killed...
+ if (!mem_rtrn_vld_i || (mem_rtrn_i.rtype == ICACHE_IFILL_ACK)) begin
dreq_o.ready = 1'b1;
if (dreq_i.req) begin
state_d = READ;
@@ -287,19 +294,25 @@ end else begin : gen_piton_offset
// returns. do not write to memory
// if the nc bit is set.
MISS: begin
- // note: this is mutually exclusive with ICACHE_INV_REQ,
- // so we do not have to check for invals here
- if (mem_rtrn_vld_i && mem_rtrn_i.rtype == ICACHE_IFILL_ACK) begin
- state_d = IDLE;
- // only return data if request is not being killed
- if (!(dreq_i.kill_s2 || flush_d)) begin
- dreq_o.valid = 1'b1;
- // only write to cache if this address is cacheable
- cache_wren = ~paddr_is_nc;
+ // if there is an outstanding miss we must wait that it is discarded
+ if (!outst_miss_q) begin
+ // note: this is mutually exclusive with ICACHE_INV_REQ,
+ // so we do not have to check for invals here
+ if (mem_rtrn_vld_i && mem_rtrn_i.rtype == ICACHE_IFILL_ACK) begin
+ state_d = IDLE;
+ // only return data if request is not being killed
+ if (!(dreq_i.kill_s2 || flush_d)) begin
+ dreq_o.valid = 1'b1;
+ // only write to cache if this address is cacheable
+ cache_wren = ~paddr_is_nc;
+ end
+ // bail out if this request is being killed
+ end else if (dreq_i.kill_s2 || flush_d) begin
+ state_d = IDLE;
+ // track if there is an outstanding miss,
+ // the next response from memory must be discarded
+ outst_miss_d = 1'b1;
end
- // bail out if this request is being killed
- end else if (dreq_i.kill_s2 || flush_d) begin
- state_d = KILL_MISS;
end
end
//////////////////////////////////
@@ -312,15 +325,6 @@ end else begin : gen_piton_offset
state_d = IDLE;
end
end
- //////////////////////////////////
- // killed miss,
- // wait until memory responds and
- // go back to idle
- KILL_MISS: begin
- if (mem_rtrn_vld_i && mem_rtrn_i.rtype == ICACHE_IFILL_ACK) begin
- state_d = IDLE;
- end
- end
default: begin
// we should never get here
state_d = FLUSH;
@@ -492,6 +496,7 @@ end else begin : gen_piton_offset
cl_offset_q <= '0;
repl_way_oh_q <= '0;
inv_q <= '0;
+ outst_miss_q <= '0;
end else begin
cl_tag_q <= cl_tag_d;
flush_cnt_q <= flush_cnt_d;
@@ -503,6 +508,7 @@ end else begin : gen_piton_offset
cl_offset_q <= cl_offset_d;
repl_way_oh_q <= repl_way_oh_d;
inv_q <= inv_d;
+ outst_miss_q <= outst_miss_d;
end
end

--
2.28.0

0 comments on commit b63ee13

Please sign in to comment.