diff --git a/dcache.vhdl b/dcache.vhdl index 75c2ce0..f24e9ec 100644 --- a/dcache.vhdl +++ b/dcache.vhdl @@ -1496,6 +1496,7 @@ begin -- Record victim way in the cycle after we see a load or dcbz miss if r1.choose_victim = '1' then r1.victim_way <= plru_victim; + report "victim way:" & to_hstring(plru_victim); end if; if req_op = OP_LOAD_MISS or (req_op = OP_STORE_MISS and r0.req.dcbz = '1') then r1.choose_victim <= '1'; diff --git a/dcache_tb.vhdl b/dcache_tb.vhdl index 35f727a..b39ad39 100644 --- a/dcache_tb.vhdl +++ b/dcache_tb.vhdl @@ -22,6 +22,8 @@ architecture behave of dcache_tb is signal wb_bram_out : wishbone_slave_out; constant clk_period : time := 10 ns; + + signal stall : std_ulogic; begin dcache0: entity work.dcache generic map( @@ -33,6 +35,7 @@ begin rst => rst, d_in => d_in, d_out => d_out, + stall_out => stall, m_in => m_in, m_out => m_out, wishbone_out => wb_bram_in, @@ -74,21 +77,31 @@ begin d_in.valid <= '0'; d_in.load <= '0'; d_in.nc <= '0'; + d_in.hold <= '0'; + d_in.dcbz <= '0'; + d_in.reserve <= '0'; + d_in.virt_mode <= '0'; + d_in.priv_mode <= '1'; d_in.addr <= (others => '0'); d_in.data <= (others => '0'); + d_in.byte_sel <= (others => '1'); m_in.valid <= '0'; m_in.addr <= (others => '0'); m_in.pte <= (others => '0'); + m_in.tlbie <= '0'; + m_in.doall <= '0'; + m_in.tlbld <= '0'; wait for 4*clk_period; wait until rising_edge(clk); -- Cacheable read of address 4 + report "cache read address 4..."; d_in.load <= '1'; d_in.nc <= '0'; d_in.addr <= x"0000000000000004"; d_in.valid <= '1'; - wait until rising_edge(clk); + wait until rising_edge(clk) and stall = '0'; d_in.valid <= '0'; wait until rising_edge(clk) and d_out.valid = '1'; @@ -97,14 +110,14 @@ begin "=" & to_hstring(d_out.data) & " expected 0000000100000000" severity failure; --- wait for clk_period; - -- Cacheable read of address 30 + -- Cacheable read of address 30 (hit after hit forward from reload) + report "cache read address 30..."; d_in.load <= '1'; d_in.nc <= '0'; d_in.addr <= x"0000000000000030"; d_in.valid <= '1'; - wait until rising_edge(clk); + wait until rising_edge(clk) and stall = '0'; d_in.valid <= '0'; wait until rising_edge(clk) and d_out.valid = '1'; @@ -114,18 +127,110 @@ begin " expected 0000000D0000000C" severity failure; - -- Non-cacheable read of address 100 + -- Ensure reload completes + wait for 100*clk_period; + wait until rising_edge(clk); + + -- Cacheable read of address 38 (hit on idle cache) + report "cache read address 38..."; d_in.load <= '1'; - d_in.nc <= '1'; - d_in.addr <= x"0000000000000100"; + d_in.nc <= '0'; + d_in.addr <= x"0000000000000038"; + d_in.valid <= '1'; + wait until rising_edge(clk) and stall = '0'; + d_in.valid <= '0'; + + wait until rising_edge(clk) and d_out.valid = '1'; + assert d_out.data = x"0000000F0000000E" + report "data @" & to_hstring(d_in.addr) & + "=" & to_hstring(d_out.data) & + " expected 0000000F0000000E" + severity failure; + + -- Cacheable read of address 130 (miss after hit, same index) + -- This will use way 2 + report "cache read address 130..."; + d_in.load <= '1'; + d_in.nc <= '0'; + d_in.addr <= x"0000000000000130"; d_in.valid <= '1'; + wait until rising_edge(clk) and stall = '0'; + d_in.valid <= '0'; + + wait until rising_edge(clk) and d_out.valid = '1'; + assert d_out.data = x"0000004d0000004c" + report "data @" & to_hstring(d_in.addr) & + "=" & to_hstring(d_out.data) & + " expected 0000004d0000004c" + severity failure; + + -- Ensure reload completes + wait for 100*clk_period; wait until rising_edge(clk); + + -- Cacheable read again of address 130 (hit in idle cache) + -- This should feed from way 2 + report "cache read address 130..."; + d_in.load <= '1'; + d_in.nc <= '0'; + d_in.addr <= x"0000000000000130"; + d_in.valid <= '1'; + wait until rising_edge(clk) and stall = '0'; + d_in.valid <= '0'; + + wait until rising_edge(clk) and d_out.valid = '1'; + assert d_out.data = x"0000004d0000004c" + report "data @" & to_hstring(d_in.addr) & + "=" & to_hstring(d_out.data) & + " expected 0000004d0000004c" + severity failure; + + -- Cacheable read of address 40 + report "cache read address 40..."; + d_in.load <= '1'; + d_in.nc <= '0'; + d_in.addr <= x"0000000000000040"; + d_in.valid <= '1'; + wait until rising_edge(clk); + d_in.valid <= '0'; + + wait until rising_edge(clk) and d_out.valid = '1'; + assert d_out.data = x"0000001100000010" + report "data @" & to_hstring(d_in.addr) & + "=" & to_hstring(d_out.data) & + " expected 0000001100000010" + severity failure; + + -- Cacheable read of address 140 (miss after miss, same index) + -- This should use way 2 + report "cache read address 140..."; + d_in.load <= '1'; + d_in.nc <= '0'; + d_in.addr <= x"0000000000000140"; + d_in.valid <= '1'; + wait until rising_edge(clk) and stall = '0'; + d_in.valid <= '0'; + + wait until rising_edge(clk) and d_out.valid = '1'; + assert d_out.data = x"0000005100000050" + report "data @" & to_hstring(d_in.addr) & + "=" & to_hstring(d_out.data) & + " expected 0000005100000050" + severity failure; + + -- Non-cacheable read of address 200 + report "non-cache read address 200..."; + d_in.load <= '1'; + d_in.nc <= '1'; + d_in.addr <= x"0000000000000200"; + d_in.valid <= '1'; + wait until rising_edge(clk) and stall = '0'; d_in.valid <= '0'; wait until rising_edge(clk) and d_out.valid = '1'; - assert d_out.data = x"0000004100000040" + assert d_out.data = x"0000008100000080" report "data @" & to_hstring(d_in.addr) & "=" & to_hstring(d_out.data) & - " expected 0000004100000040" + " expected 0000008100000080" severity failure; wait until rising_edge(clk);