From 6e0ee0b0db81fbe190653e3903c87c2287d05946 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 17 Oct 2019 16:41:19 +1100 Subject: [PATCH] icache & dcache: Fix store way variable We used the variable "way" in the wrong state in the cache when updating a line valid bit after the end of the wishbone transactions, we need to use the latched "store_way". Signed-off-by: Benjamin Herrenschmidt --- dcache.vhdl | 19 +++++++++---------- icache.vhdl | 17 +++++++++-------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/dcache.vhdl b/dcache.vhdl index 1e2a86c..087e71d 100644 --- a/dcache.vhdl +++ b/dcache.vhdl @@ -221,6 +221,7 @@ architecture rtl of dcache is -- PLRU output interface type plru_out_t is array(index_t) of std_ulogic_vector(WAY_BITS-1 downto 0); signal plru_victim : plru_out_t; + signal replace_way : way_t; -- Wishbone read/write/cache write formatting signals signal bus_sel : wishbone_sel_type; @@ -395,6 +396,9 @@ begin -- The way that matched on a hit req_hit_way <= hit_way; + -- The way to replace on a miss + replace_way <= to_integer(unsigned(plru_victim(req_index))); + -- Combine the request and cache his status to decide what -- operation needs to be done -- @@ -666,7 +670,6 @@ begin -- operates at stage 1. -- dcache_slow : process(clk) - variable way : integer range 0 to NUM_WAYS-1; variable tagset : cache_tags_set_t; begin if rising_edge(clk) then @@ -706,21 +709,17 @@ begin when OP_LOAD_MISS => -- Normal load cache miss, start the reload machine -- - -- First find a victim way from the PLRU - -- - way := to_integer(unsigned(plru_victim(req_index))); - report "cache miss addr:" & to_hstring(d_in.addr) & " idx:" & integer'image(req_index) & - " way:" & integer'image(way) & + " way:" & integer'image(replace_way) & " tag:" & to_hstring(req_tag); -- Force misses on that way while reloading that line - cache_valids(req_index)(way) <= '0'; + cache_valids(req_index)(replace_way) <= '0'; -- Store new tag in selected way for i in 0 to NUM_WAYS-1 loop - if i = way then + if i = replace_way then tagset := cache_tags(req_index); write_tag(i, tagset, req_tag); cache_tags(req_index) <= tagset; @@ -729,7 +728,7 @@ begin -- Keep track of our index and way for subsequent stores. r1.store_index <= req_index; - r1.store_way <= way; + r1.store_way <= replace_way; -- Prep for first wishbone read. We calculate the address of -- the start of the cache line @@ -785,7 +784,7 @@ begin -- That was the last word ? We are done if is_last_row(r1.wb.adr) then - cache_valids(r1.store_index)(way) <= '1'; + cache_valids(r1.store_index)(r1.store_way) <= '1'; r1.wb.cyc <= '0'; r1.wb.stb <= '0'; diff --git a/icache.vhdl b/icache.vhdl index 75695e1..95e37af 100644 --- a/icache.vhdl +++ b/icache.vhdl @@ -178,6 +178,7 @@ architecture rtl of icache is -- PLRU output interface type plru_out_t is array(index_t) of std_ulogic_vector(WAY_BITS-1 downto 0); signal plru_victim : plru_out_t; + signal replace_way : way_t; -- Return the cache line index (tag index) for an address function get_index(addr: std_ulogic_vector(63 downto 0)) return index_t is @@ -371,6 +372,9 @@ begin req_is_miss <= i_in.req and not is_hit and not flush_in; req_hit_way <= hit_way; + -- The way to replace on a miss + replace_way <= to_integer(unsigned(plru_victim(req_index))); + -- Output instruction from current cache row -- -- Note: This is a mild violation of our design principle of having pipeline @@ -420,7 +424,6 @@ begin -- Cache miss/reload synchronous machine icache_miss : process(clk) - variable way : integer range 0 to NUM_WAYS-1; variable tagset : cache_tags_set_t; begin if rising_edge(clk) then @@ -446,20 +449,18 @@ begin when IDLE => -- We need to read a cache line if req_is_miss = '1' then - way := to_integer(unsigned(plru_victim(req_index))); - report "cache miss nia:" & to_hstring(i_in.nia) & " SM:" & std_ulogic'image(i_in.stop_mark) & " idx:" & integer'image(req_index) & - " way:" & integer'image(way) & + " way:" & integer'image(replace_way) & " tag:" & to_hstring(req_tag); -- Force misses on that way while reloading that line - cache_valids(req_index)(way) <= '0'; + cache_valids(req_index)(replace_way) <= '0'; -- Store new tag in selected way for i in 0 to NUM_WAYS-1 loop - if i = way then + if i = replace_way then tagset := cache_tags(req_index); write_tag(i, tagset, req_tag); cache_tags(req_index) <= tagset; @@ -468,7 +469,7 @@ begin -- Keep track of our index and way for subsequent stores r.store_index <= req_index; - r.store_way <= way; + r.store_way <= replace_way; -- Prep for first wishbone read. We calculate the address of -- the start of the cache line @@ -484,7 +485,7 @@ begin if wishbone_in.ack = '1' then -- That was the last word ? We are done if is_last_row(r.wb.adr) then - cache_valids(r.store_index)(way) <= '1'; + cache_valids(r.store_index)(r.store_way) <= '1'; r.wb.cyc <= '0'; r.wb.stb <= '0'; r.state <= IDLE;