data : std_ulogic_vector(63 downto 0);
byte_sel : std_ulogic_vector(7 downto 0);
hit_way : way_t;
- repl_way : way_t;
same_tag : std_ulogic;
end record;
-- Cache hit state
hit_way : way_t;
hit_load_valid : std_ulogic;
+ hit_index : index_t;
+ cache_hit : std_ulogic;
-- 2-stage data buffer for data forwarded from writes to reads
forward_data1 : std_ulogic_vector(63 downto 0);
lru => plru_out
);
- process(req_index, req_op, req_hit_way, plru_out)
+ process(all)
begin
-- PLRU interface
- if (req_op = OP_LOAD_HIT or
- req_op = OP_STORE_HIT) and req_index = i then
- plru_acc_en <= '1';
+ if r1.hit_index = i then
+ plru_acc_en <= r1.cache_hit;
else
plru_acc_en <= '0';
end if;
- plru_acc <= std_ulogic_vector(to_unsigned(req_hit_way, WAY_BITS));
+ plru_acc <= std_ulogic_vector(to_unsigned(r1.hit_way, WAY_BITS));
plru_victim(i) <= plru_out;
end process;
end generate;
-- since it will be by the time we perform the store.
-- For a load, check the appropriate row valid bit.
is_hit := not r0.req.load or r1.rows_valid(req_row mod ROW_PER_LINE);
- hit_way := r1.store_way;
+ hit_way := replace_way;
end if;
-- Whether to use forwarded data for a load or not
-- 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)));
+ -- The way to replace on a miss
+ if r1.write_tag = '1' then
+ replace_way <= to_integer(unsigned(plru_victim(r1.store_index)));
+ else
+ replace_way <= r1.store_way;
+ end if;
-- work out whether we have permission for this access
-- NB we don't yet implement AMR, thus no KUAP
wr_addr <= std_ulogic_vector(to_unsigned(r1.store_row, ROW_BITS));
wr_sel <= (others => '1');
- if r1.state = RELOAD_WAIT_ACK and wishbone_in.ack = '1' and r1.store_way = i then
+ if r1.state = RELOAD_WAIT_ACK and wishbone_in.ack = '1' and replace_way = i then
do_write <= '1';
end if;
end if;
end if;
-- Fast path for load/store hits. Set signals for the writeback controls.
+ r1.hit_way <= req_hit_way;
+ r1.hit_index <= req_index;
if req_op = OP_LOAD_HIT then
- r1.hit_way <= req_hit_way;
r1.hit_load_valid <= '1';
else
r1.hit_load_valid <= '0';
end if;
+ if req_op = OP_LOAD_HIT or req_op = OP_STORE_HIT then
+ r1.cache_hit <= '1';
+ else
+ r1.cache_hit <= '0';
+ end if;
if req_op = OP_BAD then
report "Signalling ld/st error valid_ra=" & std_ulogic'image(valid_ra) &
r1.forward_data1 <= wishbone_in.dat;
end if;
r1.forward_sel1 <= (others => '1');
- r1.forward_way1 <= r1.store_way;
+ r1.forward_way1 <= replace_way;
r1.forward_row1 <= r1.store_row;
r1.forward_valid1 <= '0';
end if;
if r1.write_tag = '1' then
-- Store new tag in selected way
for i in 0 to NUM_WAYS-1 loop
- if i = r1.store_way then
+ if i = replace_way then
cache_tags(r1.store_index)((i + 1) * TAG_WIDTH - 1 downto i * TAG_WIDTH) <=
(TAG_WIDTH - 1 downto TAG_BITS => '0') & r1.reload_tag;
end if;
end loop;
+ r1.store_way <= replace_way;
r1.write_tag <= '0';
end if;
req.data := r0.req.data;
req.byte_sel := r0.req.byte_sel;
req.hit_way := req_hit_way;
- req.repl_way := replace_way;
req.same_tag := req_same_tag;
-- Store the incoming request from r0, if it is a slow request
if req.op = OP_STORE_HIT then
r1.store_way <= req.hit_way;
- else
- r1.store_way <= req.repl_way;
end if;
-- Reset per-row valid bits, ready for handling OP_LOAD_MISS
--
report "cache miss real addr:" & to_hstring(req.real_addr) &
" idx:" & integer'image(get_index(req.real_addr)) &
- " way:" & integer'image(req.repl_way) &
" tag:" & to_hstring(get_tag(req.real_addr));
-- Start the wishbone cycle
-- Handle the rest like a load miss
r1.state <= RELOAD_WAIT_ACK;
- r1.write_tag <= '1';
+ if req.op = OP_STORE_MISS then
+ r1.write_tag <= '1';
+ end if;
r1.dcbz <= '1';
end if;
r1.wb.we <= '1';