icache: Fix icbi potentially clobbering the icache (#192)

icbi currently just resets the icache. This has some nasty side
effects such as also clearing the TLB, but also the wishbone interface.

That means that any ongoing cycle will be dropped.

However, most of our slaves don't handle that well and will continue
sending acks for already issued requests.

Under some circumstances we can thus restart an icache load and get
spurious ack/data from the wishbone left over from the "cancelled"
sequence.

This has broken booting Linux for me.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
jtag-port
Benjamin Herrenschmidt 5 years ago committed by GitHub
parent 983f4fefe1
commit b863791e38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -159,7 +159,7 @@ begin
if rising_edge(clk) then if rising_edge(clk) then
rst_fetch1 <= core_rst; rst_fetch1 <= core_rst;
rst_fetch2 <= core_rst; rst_fetch2 <= core_rst;
rst_icache <= core_rst or dbg_icache_rst or ex1_icache_inval; rst_icache <= core_rst;
rst_dcache <= core_rst; rst_dcache <= core_rst;
rst_dec1 <= core_rst; rst_dec1 <= core_rst;
rst_dec2 <= core_rst; rst_dec2 <= core_rst;
@ -202,6 +202,7 @@ begin
i_out => icache_to_fetch2, i_out => icache_to_fetch2,
m_in => mmu_to_icache, m_in => mmu_to_icache,
flush_in => flush, flush_in => flush,
inval_in => dbg_icache_rst or ex1_icache_inval,
stall_out => icache_stall_out, stall_out => icache_stall_out,
wishbone_out => wishbone_insn_out, wishbone_out => wishbone_insn_out,
wishbone_in => wishbone_insn_in wishbone_in => wishbone_insn_in

@ -54,6 +54,7 @@ entity icache is


stall_out : out std_ulogic; stall_out : out std_ulogic;
flush_in : in std_ulogic; flush_in : in std_ulogic;
inval_in : in std_ulogic;


wishbone_out : out wishbone_master_out; wishbone_out : out wishbone_master_out;
wishbone_in : in wishbone_slave_out wishbone_in : in wishbone_slave_out
@ -173,6 +174,7 @@ architecture rtl of icache is
store_way : way_t; store_way : way_t;
store_index : index_t; store_index : index_t;
store_row : row_t; store_row : row_t;
store_valid : std_ulogic;


-- TLB miss state -- TLB miss state
fetch_failed : std_ulogic; fetch_failed : std_ulogic;
@ -570,6 +572,14 @@ begin
-- Not useful normally but helps avoiding tons of sim warnings -- Not useful normally but helps avoiding tons of sim warnings
r.wb.adr <= (others => '0'); r.wb.adr <= (others => '0');
else else
-- Process cache invalidations
if inval_in = '1' then
for i in index_t loop
cache_valids(i) <= (others => '0');
end loop;
r.store_valid <= '0';
end if;

-- Main state machine -- Main state machine
case r.state is case r.state is
when IDLE => when IDLE =>
@ -599,6 +609,7 @@ begin
r.store_index <= req_index; r.store_index <= req_index;
r.store_way <= replace_way; r.store_way <= replace_way;
r.store_row <= get_row(req_laddr); r.store_row <= get_row(req_laddr);
r.store_valid <= '1';


-- Prep for first wishbone read. We calculate the address of -- Prep for first wishbone read. We calculate the address of
-- the start of the cache line and start the WB cycle. -- the start of the cache line and start the WB cycle.
@ -638,7 +649,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) <= '1'; cache_valids(r.store_index)(r.store_way) <= r.store_valid and not inval_in;


-- We are done -- We are done
r.state <= IDLE; r.state <= IDLE;

@ -34,6 +34,7 @@ begin
i_out => i_in, i_out => i_in,
m_in => m_out, m_in => m_out,
flush_in => '0', flush_in => '0',
inval_in => '0',
wishbone_out => wb_bram_in, wishbone_out => wb_bram_in,
wishbone_in => wb_bram_out wishbone_in => wb_bram_out
); );

Loading…
Cancel
Save