litedram: Split L2 PLRU into storage and logic

As has been done for the L1 dcache and icache, this puts the L2 cache
PLRU state into a little RAM and has a single copy of the logic to
calculate the pseudo-LRU way and update the PLRU state.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/408/head
Paul Mackerras 2 years ago
parent a1f5867919
commit b8f9c833f8

@ -305,8 +305,7 @@ architecture behaviour of litedram_wrapper is
signal cache_out : cache_ram_out_t;

-- 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 plru_victim : way_t;

--
-- Helper functions to decode incoming requests
@ -565,39 +564,44 @@ begin
end generate;

-- Generate PLRUs
maybe_plrus: if NUM_WAYS > 1 generate
maybe_plrus : if NUM_WAYS > 1 generate
type plru_array is array(index_t) of std_ulogic_vector(NUM_WAYS - 2 downto 0);
signal plru_ram : plru_array;
signal plru_cur : std_ulogic_vector(NUM_WAYS - 2 downto 0);
signal plru_upd : std_ulogic_vector(NUM_WAYS - 2 downto 0);
signal plru_acc : std_ulogic_vector(WAY_BITS-1 downto 0);
signal plru_out : std_ulogic_vector(WAY_BITS-1 downto 0);
begin
plrus: for i in 0 to NUM_LINES-1 generate
plru : entity work.plrufn
generic map (
BITS => WAY_BITS
)
port map (
acc => plru_acc,
tree_in => plru_cur,
tree_out => plru_upd,
lru => plru_out
);

process(all)
begin
-- Read PLRU bits from array
plru_cur <= plru_ram(req_index);

-- PLRU interface
signal plru_acc : std_ulogic_vector(WAY_BITS-1 downto 0);
signal plru_acc_en : std_ulogic;
signal plru_out : std_ulogic_vector(WAY_BITS-1 downto 0);
plru_acc <= std_ulogic_vector(to_unsigned(req_hit_way, WAY_BITS));
plru_victim <= to_integer(unsigned(plru_out));
end process;

-- synchronous writes to PLRU array
process(system_clk)
begin
plru : entity work.plru
generic map (
BITS => WAY_BITS
)
port map (
clk => system_clk,
rst => system_reset,
acc => plru_acc,
acc_en => plru_acc_en,
lru => plru_out
);

process(req_index, req_op, req_hit_way, plru_out)
begin
-- PLRU interface
if (req_op = OP_LOAD_HIT or
req_op = OP_STORE_HIT) and req_index = i then
plru_acc_en <= '1';
else
plru_acc_en <= '0';
if rising_edge(system_clk) then
if (req_op = OP_LOAD_HIT or req_op = OP_STORE_HIT) then
plru_ram(req_index) <= plru_upd;
end if;
plru_acc <= std_ulogic_vector(to_unsigned(req_hit_way, WAY_BITS));
plru_victim(i) <= plru_out;
end process;
end generate;
end if;
end process;
end generate;

--
@ -1019,7 +1023,7 @@ begin
-- We need to read a cache line
if req_op = OP_LOAD_MISS and not wait_qdrain then
-- Grab way to replace
refill_way <= to_integer(unsigned(plru_victim(req_index)));
refill_way <= plru_victim;

-- Keep track of our index and way for subsequent stores
refill_index <= req_index;

Loading…
Cancel
Save