icache: Do PLRU update one cycle later

This does the PLRU update based on r.hit_valid and r.hit_way rather
than req_is_hit and req_hit_way, which means there is now a register
between the TLB and cache tag lookup and the PLRU update, which
should help with timing.

As a result, the PLRU victim way selection becomes valid one cycle
later, in the cycle when r.state = CLR_TAG.  So we have to use the
PLRU output directly in the CLR_TAG state and r.store_way in the
WAIT_ACK state.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
jtag-port
Paul Mackerras 4 years ago
parent 2081bdaa27
commit 144d8e3c61

@ -379,7 +379,7 @@ begin
begin begin
do_read <= not (stall_in or use_previous); do_read <= not (stall_in or use_previous);
do_write <= '0'; do_write <= '0';
if wishbone_in.ack = '1' and r.store_way = i then if wishbone_in.ack = '1' and replace_way = i then
do_write <= '1'; do_write <= '1';
end if; end if;
cache_out(i) <= dout; cache_out(i) <= dout;
@ -413,15 +413,15 @@ begin
lru => plru_out lru => plru_out
); );


process(req_index, req_is_hit, req_hit_way, req_is_hit, plru_out) process(all)
begin begin
-- PLRU interface -- PLRU interface
if req_is_hit = '1' and req_index = i then if get_index(r.hit_nia) = i then
plru_acc_en <= req_is_hit; plru_acc_en <= r.hit_valid;
else else
plru_acc_en <= '0'; plru_acc_en <= '0';
end if; end if;
plru_acc <= std_ulogic_vector(to_unsigned(req_hit_way, WAY_BITS)); plru_acc <= std_ulogic_vector(to_unsigned(r.hit_way, WAY_BITS));
plru_victim(i) <= plru_out; plru_victim(i) <= plru_out;
end process; end process;
end generate; end generate;
@ -532,7 +532,11 @@ begin
req_hit_way <= hit_way; req_hit_way <= hit_way;


-- The way to replace on a miss -- The way to replace on a miss
replace_way <= to_integer(unsigned(plru_victim(req_index))); if r.state = CLR_TAG then
replace_way <= to_integer(unsigned(plru_victim(r.store_index)));
else
replace_way <= r.store_way;
end if;


-- Output instruction from current cache row -- Output instruction from current cache row
-- --
@ -642,7 +646,6 @@ begin


-- Keep track of our index and way for subsequent stores -- Keep track of our index and way for subsequent stores
r.store_index <= req_index; r.store_index <= req_index;
r.store_way <= replace_way;
r.store_row <= get_row(req_laddr); r.store_row <= get_row(req_laddr);
r.store_tag <= req_tag; r.store_tag <= req_tag;
r.store_valid <= '1'; r.store_valid <= '1';
@ -661,12 +664,15 @@ begin


when CLR_TAG | WAIT_ACK => when CLR_TAG | WAIT_ACK =>
if r.state = CLR_TAG then if r.state = CLR_TAG then
-- Get victim way from plru
r.store_way <= replace_way;

-- Force misses on that way while reloading that line -- Force misses on that way while reloading that line
cache_valids(req_index)(r.store_way) <= '0'; cache_valids(req_index)(replace_way) <= '0';


-- Store new tag in selected way -- Store new tag in selected way
for i in 0 to NUM_WAYS-1 loop for i in 0 to NUM_WAYS-1 loop
if i = r.store_way then if i = replace_way then
tagset := cache_tags(r.store_index); tagset := cache_tags(r.store_index);
write_tag(i, tagset, r.store_tag); write_tag(i, tagset, r.store_tag);
cache_tags(r.store_index) <= tagset; cache_tags(r.store_index) <= tagset;
@ -702,7 +708,7 @@ begin
r.wb.cyc <= '0'; r.wb.cyc <= '0';


-- Cache line is now valid -- Cache line is now valid
cache_valids(r.store_index)(r.store_way) <= r.store_valid and not inval_in; cache_valids(r.store_index)(replace_way) <= r.store_valid and not inval_in;


-- We are done -- We are done
r.state <= IDLE; r.state <= IDLE;
@ -728,11 +734,7 @@ begin
variable wstate: std_ulogic; variable wstate: std_ulogic;
begin begin
if rising_edge(clk) then if rising_edge(clk) then
if req_is_hit then
lway := req_hit_way; lway := req_hit_way;
else
lway := replace_way;
end if;
wstate := '0'; wstate := '0';
if r.state /= IDLE then if r.state /= IDLE then
wstate := '1'; wstate := '1';

Loading…
Cancel
Save