mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-11 23:43:15 +00:00
dcache: Fix bug causing load to return incorrect data
If a touch is immediately followed by a load to a different address which has the same index as the touch address, and both are cache misses, it is possible for the load to be treated as if it is to the same cache line as the touch, and thus return data from the line being touched rather than the line being loaded from. For example, if the touch is to 0x1c20 and the load is to 0x2c20, and the state left in r1.store_ways by an earlier operation happens to match the PLRU victim way, the load will return data from 0x1c20. This happens because the touch completes immediately, meaning that the load gets processed before r1.store_ways and the cache tag for the line being touched have been set correctly, leading to a chance that the load can match when it shouldn't (or not match when it should). To fix this, complete the touch after one cycle, in RELOAD_WAIT_ACK state, rather than immediately. Also, for touches, consider hit_reload = 1 equivalent to a cache hit. If the line is being reloaded then the touch doesn't need to do anything. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
parent
c78d9b32ef
commit
a7420c2a4d
18
dcache.vhdl
18
dcache.vhdl
@ -1121,9 +1121,9 @@ begin
|
||||
if r0.req.sync = '1' then
|
||||
req_op_sync <= '1';
|
||||
elsif r0.req.touch = '1' then
|
||||
if access_ok = '1' and is_hit = '0' and nc = '0' then
|
||||
if access_ok = '1' and (is_hit or hit_reload) = '0' and nc = '0' then
|
||||
req_op_load_miss <= '1';
|
||||
elsif access_ok = '1' and is_hit = '1' and nc = '0' then
|
||||
elsif access_ok = '1' and (is_hit or hit_reload) = '1' and nc = '0' then
|
||||
-- Make this OP_LOAD_HIT so the PLRU gets updated
|
||||
req_op_load_hit <= '1';
|
||||
else
|
||||
@ -1632,13 +1632,6 @@ begin
|
||||
r1.reloading <= '1';
|
||||
r1.write_tag <= '1';
|
||||
ev.load_miss <= '1';
|
||||
|
||||
-- If this is a touch, complete the instruction
|
||||
if req.touch = '1' then
|
||||
r1.full <= '0';
|
||||
r1.slow_valid <= '1';
|
||||
r1.ls_valid <= '1';
|
||||
end if;
|
||||
else
|
||||
r1.state <= NC_LOAD_WAIT_ACK;
|
||||
end if;
|
||||
@ -1710,6 +1703,13 @@ begin
|
||||
r1.wb.adr <= next_row_wb_addr(r1.wb.adr);
|
||||
end if;
|
||||
|
||||
-- If this is a touch, complete the instruction
|
||||
if r1.full = '1' and r1.req.touch = '1' then
|
||||
r1.full <= '0';
|
||||
r1.slow_valid <= '1';
|
||||
r1.ls_valid <= '1';
|
||||
end if;
|
||||
|
||||
-- Incoming acks processing
|
||||
if wishbone_in.ack = '1' then
|
||||
r1.rows_valid(to_integer(r1.store_row(ROW_LINEBITS-1 downto 0))) <= '1';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user