mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-12 14:53:10 +00:00
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>
This commit is contained in:
committed by
GitHub
parent
983f4fefe1
commit
b863791e38
@@ -159,7 +159,7 @@ begin
|
||||
if rising_edge(clk) then
|
||||
rst_fetch1 <= 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_dec1 <= core_rst;
|
||||
rst_dec2 <= core_rst;
|
||||
@@ -202,6 +202,7 @@ begin
|
||||
i_out => icache_to_fetch2,
|
||||
m_in => mmu_to_icache,
|
||||
flush_in => flush,
|
||||
inval_in => dbg_icache_rst or ex1_icache_inval,
|
||||
stall_out => icache_stall_out,
|
||||
wishbone_out => wishbone_insn_out,
|
||||
wishbone_in => wishbone_insn_in
|
||||
|
||||
13
icache.vhdl
13
icache.vhdl
@@ -54,6 +54,7 @@ entity icache is
|
||||
|
||||
stall_out : out std_ulogic;
|
||||
flush_in : in std_ulogic;
|
||||
inval_in : in std_ulogic;
|
||||
|
||||
wishbone_out : out wishbone_master_out;
|
||||
wishbone_in : in wishbone_slave_out
|
||||
@@ -173,6 +174,7 @@ architecture rtl of icache is
|
||||
store_way : way_t;
|
||||
store_index : index_t;
|
||||
store_row : row_t;
|
||||
store_valid : std_ulogic;
|
||||
|
||||
-- TLB miss state
|
||||
fetch_failed : std_ulogic;
|
||||
@@ -570,6 +572,14 @@ begin
|
||||
-- Not useful normally but helps avoiding tons of sim warnings
|
||||
r.wb.adr <= (others => '0');
|
||||
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
|
||||
case r.state is
|
||||
when IDLE =>
|
||||
@@ -599,6 +609,7 @@ begin
|
||||
r.store_index <= req_index;
|
||||
r.store_way <= replace_way;
|
||||
r.store_row <= get_row(req_laddr);
|
||||
r.store_valid <= '1';
|
||||
|
||||
-- Prep for first wishbone read. We calculate the address of
|
||||
-- the start of the cache line and start the WB cycle.
|
||||
@@ -638,7 +649,7 @@ begin
|
||||
r.wb.cyc <= '0';
|
||||
|
||||
-- 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
|
||||
r.state <= IDLE;
|
||||
|
||||
@@ -34,6 +34,7 @@ begin
|
||||
i_out => i_in,
|
||||
m_in => m_out,
|
||||
flush_in => '0',
|
||||
inval_in => '0',
|
||||
wishbone_out => wb_bram_in,
|
||||
wishbone_in => wb_bram_out
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user