dcache: Simplify forwarding of load data while reloading a cache line

This removes a dependency of req_is_hit and similar signals on the
wishbone ack input, by removing use_forward_rl, and making idx_reload
not dependent on wr_row_match and wishbone_in.ack.  Previously if a
load in r0 hit the doubleword being supplied from memory, that was
treated as a hit and the data was forwarded via a multiplexer
associated with the cache RAM.  Now it is called a miss and completed
by the logic in the RELOAD_WAIT_ACK state of the state machine.

The only downside is that now the selection of data source in the
dcache_fast_hit process depends on req_is_hit rather than r1.full.
Overall this change seems to reduce the number of LUTs, and make
timing easier on the ECP-5.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/441/head
Paul Mackerras 2 weeks ago
parent c938246cc8
commit 1da8476cf9

@ -442,7 +442,6 @@ architecture rtl of dcache is
signal r0_stall : std_ulogic; signal r0_stall : std_ulogic;


signal use_forward_st : way_expand_t; signal use_forward_st : way_expand_t;
signal use_forward_rl : way_expand_t;
signal use_forward2 : way_expand_t; signal use_forward2 : way_expand_t;


-- Cache RAM interface -- Cache RAM interface
@ -950,7 +949,6 @@ begin
variable hit_reload : std_ulogic; variable hit_reload : std_ulogic;
variable dawr_match : std_ulogic; variable dawr_match : std_ulogic;
variable idx_reload : way_expand_t; variable idx_reload : way_expand_t;
variable maybe_fwd_rl : way_expand_t;
variable maybe_fwd_st : way_expand_t; variable maybe_fwd_st : way_expand_t;
variable maybe_fwd2 : way_expand_t; variable maybe_fwd2 : way_expand_t;
variable wr_row_match : std_ulogic; variable wr_row_match : std_ulogic;
@ -982,16 +980,13 @@ begin
wr_row_match := '1'; wr_row_match := '1';
end if; end if;
idx_reload := (others => '0'); idx_reload := (others => '0');
maybe_fwd_rl := (others => '0');
if go = '1' and r1.reloading = '1' and rindex = r1.store_index then if go = '1' and r1.reloading = '1' and rindex = r1.store_index then
-- Way r1.store_way at this index is currently being reloaded. -- Way r1.store_way at this index is currently being reloaded.
-- If we detect that this way is the one that hits below, -- If we detect that this way is the one that hits below,
-- and this is a load, then this is a hit only if r1.rows_valid() -- and this is a load, then this is a hit only if r1.rows_valid()
-- is true, or if the data currently arriving on the wishbone is -- is true, or if the data currently arriving on the wishbone is
-- the row we want. -- the row we want.
if wr_row_match = '1' and wishbone_in.ack = '1' then if r0.req.load = '1' and r0.req.touch = '0' and
maybe_fwd_rl := r1.store_ways;
elsif r0.req.load = '1' and r0.req.touch = '0' and
r1.rows_valid(to_integer(req_row(ROW_LINEBITS-1 downto 0))) = '0' then r1.rows_valid(to_integer(req_row(ROW_LINEBITS-1 downto 0))) = '0' then
idx_reload := r1.store_ways; idx_reload := r1.store_ways;
end if; end if;
@ -1076,14 +1071,8 @@ begin
end if; end if;


-- Whether to use forwarded data for a load or not -- Whether to use forwarded data for a load or not
if r1.dcbz = '0' then use_forward_st <= maybe_fwd_st;
use_forward_rl <= maybe_fwd_rl; use_forward2 <= maybe_fwd2;
use_forward_st <= maybe_fwd_st;
else
use_forward_rl <= (others => '0');
use_forward_st <= maybe_fwd_rl;
end if;
use_forward2 <= maybe_fwd2;


-- The way to replace on a miss -- The way to replace on a miss
replace_way <= to_unsigned(0, WAY_BITS); replace_way <= to_unsigned(0, WAY_BITS);
@ -1256,9 +1245,8 @@ begin
end process; end process;


-- RAM write data and select multiplexers -- RAM write data and select multiplexers
ram_wr_data <= r1.req.data when r1.write_bram = '1' else ram_wr_data <= r1.req.data when r1.write_bram = '1' or r1.dcbz = '1' else
wishbone_in.dat when r1.dcbz = '0' else wishbone_in.dat;
(others => '0');
ram_wr_select <= r1.req.byte_sel when r1.write_bram = '1' else ram_wr_select <= r1.req.byte_sel when r1.write_bram = '1' else
(others => '1'); (others => '1');


@ -1308,9 +1296,7 @@ begin
dword := (others => '0'); dword := (others => '0');
for b in 0 to ROW_SIZE - 1 loop for b in 0 to ROW_SIZE - 1 loop
j := b * 8; j := b * 8;
if use_forward_rl(i) = '1' then if use_forward_st(i) = '1' and r1.req.byte_sel(b) = '1' then
dword(j + 7 downto j) := wishbone_in.dat(j + 7 downto j);
elsif use_forward_st(i) = '1' and r1.req.byte_sel(b) = '1' then
dword(j + 7 downto j) := r1.req.data(j + 7 downto j); dword(j + 7 downto j) := r1.req.data(j + 7 downto j);
elsif use_forward2(i) = '1' and r1.forward_sel(b) = '1' then elsif use_forward2(i) = '1' and r1.forward_sel(b) = '1' then
dword(j + 7 downto j) := r1.forward_data(j + 7 downto j); dword(j + 7 downto j) := r1.forward_data(j + 7 downto j);
@ -1356,7 +1342,7 @@ begin
end if; end if;


data_out := (others => '0'); data_out := (others => '0');
if r1.full = '1' then if req_is_hit = '0' then
data_out := wishbone_in.dat; data_out := wishbone_in.dat;
else else
for w in 0 to NUM_WAYS-1 loop for w in 0 to NUM_WAYS-1 loop
@ -1551,7 +1537,7 @@ begin
req.hit_way := req_hit_way; req.hit_way := req_hit_way;
req.hit_ways := req_hit_ways; req.hit_ways := req_hit_ways;
req.is_hit := req_is_hit; req.is_hit := req_is_hit;
req.hit_reload := req_hit_reload; req.hit_reload := req_hit_reload and req_op_load_miss;
req.same_page := req_same_page; req.same_page := req_same_page;


-- Store the incoming request from r0, if it is a slow request -- Store the incoming request from r0, if it is a slow request
@ -1604,7 +1590,7 @@ begin
r1.wb.adr <= addr_to_wb(req.real_addr); r1.wb.adr <= addr_to_wb(req.real_addr);
r1.wb.sel <= req.byte_sel; r1.wb.sel <= req.byte_sel;
r1.wb.dat <= req.data; r1.wb.dat <= req.data;
r1.dcbz <= req.dcbz; r1.dcbz <= req.dcbz and req.valid;
r1.atomic_more <= not req.last_dw; r1.atomic_more <= not req.last_dw;


-- Keep track of our index and way for subsequent stores. -- Keep track of our index and way for subsequent stores.
@ -1741,9 +1727,8 @@ begin
-- r1.req.hit_reload is always 1 for the request that -- r1.req.hit_reload is always 1 for the request that
-- started this reload, and otherwise always 0 for dcbz -- started this reload, and otherwise always 0 for dcbz
-- (since it is considered a store). -- (since it is considered a store).
if r1.full = '1' and r1.req.hit_reload = '1' and if req.hit_reload = '1' and
get_row_of_line(r1.store_row) = get_row_of_line(r1.store_row) = get_row_of_line(get_row(req.real_addr)) then
get_row_of_line(get_row(r1.req.real_addr)) then
r1.full <= '0'; r1.full <= '0';
r1.slow_valid <= '1'; r1.slow_valid <= '1';
if r1.mmu_req = '0' then if r1.mmu_req = '0' then

Loading…
Cancel
Save