mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-27 20:58:39 +00:00
This adds a new module to implement an MMU. At the moment it doesn't do very much. Tlbie instructions now get sent by loadstore1 to mmu, which sends them to dcache, rather than loadstore1 sending them directly to dcache. TLB misses from dcache now get sent by loadstore1 to mmu, which currently just returns an error. Loadstore1 then generates a DSI in response to the error return from mmu. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
141 lines
3.4 KiB
VHDL
141 lines
3.4 KiB
VHDL
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
library work;
|
|
use work.common.all;
|
|
use work.wishbone_types.all;
|
|
|
|
entity dcache_tb is
|
|
end dcache_tb;
|
|
|
|
architecture behave of dcache_tb is
|
|
signal clk : std_ulogic;
|
|
signal rst : std_ulogic;
|
|
|
|
signal d_in : Loadstore1ToDcacheType;
|
|
signal d_out : DcacheToLoadstore1Type;
|
|
|
|
signal m_in : MmuToDcacheType;
|
|
signal m_out : DcacheToMmuType;
|
|
|
|
signal wb_bram_in : wishbone_master_out;
|
|
signal wb_bram_out : wishbone_slave_out;
|
|
|
|
constant clk_period : time := 10 ns;
|
|
begin
|
|
dcache0: entity work.dcache
|
|
generic map(
|
|
LINE_SIZE => 64,
|
|
NUM_LINES => 4
|
|
)
|
|
port map(
|
|
clk => clk,
|
|
rst => rst,
|
|
d_in => d_in,
|
|
d_out => d_out,
|
|
m_in => m_in,
|
|
m_out => m_out,
|
|
wishbone_out => wb_bram_in,
|
|
wishbone_in => wb_bram_out
|
|
);
|
|
|
|
-- BRAM Memory slave
|
|
bram0: entity work.wishbone_bram_wrapper
|
|
generic map(
|
|
MEMORY_SIZE => 1024,
|
|
RAM_INIT_FILE => "icache_test.bin"
|
|
)
|
|
port map(
|
|
clk => clk,
|
|
rst => rst,
|
|
wishbone_in => wb_bram_in,
|
|
wishbone_out => wb_bram_out
|
|
);
|
|
|
|
clk_process: process
|
|
begin
|
|
clk <= '0';
|
|
wait for clk_period/2;
|
|
clk <= '1';
|
|
wait for clk_period/2;
|
|
end process;
|
|
|
|
rst_process: process
|
|
begin
|
|
rst <= '1';
|
|
wait for 2*clk_period;
|
|
rst <= '0';
|
|
wait;
|
|
end process;
|
|
|
|
stim: process
|
|
begin
|
|
-- Clear stuff
|
|
d_in.valid <= '0';
|
|
d_in.load <= '0';
|
|
d_in.nc <= '0';
|
|
d_in.addr <= (others => '0');
|
|
d_in.data <= (others => '0');
|
|
m_in.valid <= '0';
|
|
m_in.addr <= (others => '0');
|
|
m_in.pte <= (others => '0');
|
|
|
|
wait for 4*clk_period;
|
|
wait until rising_edge(clk);
|
|
|
|
-- Cacheable read of address 4
|
|
d_in.load <= '1';
|
|
d_in.nc <= '0';
|
|
d_in.addr <= x"0000000000000004";
|
|
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"0000000100000000"
|
|
report "data @" & to_hstring(d_in.addr) &
|
|
"=" & to_hstring(d_out.data) &
|
|
" expected 0000000100000000"
|
|
severity failure;
|
|
-- wait for clk_period;
|
|
|
|
-- Cacheable read of address 30
|
|
d_in.load <= '1';
|
|
d_in.nc <= '0';
|
|
d_in.addr <= x"0000000000000030";
|
|
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"0000000D0000000C"
|
|
report "data @" & to_hstring(d_in.addr) &
|
|
"=" & to_hstring(d_out.data) &
|
|
" expected 0000000D0000000C"
|
|
severity failure;
|
|
|
|
-- Non-cacheable read of address 100
|
|
d_in.load <= '1';
|
|
d_in.nc <= '1';
|
|
d_in.addr <= x"0000000000000100";
|
|
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"0000004100000040"
|
|
report "data @" & to_hstring(d_in.addr) &
|
|
"=" & to_hstring(d_out.data) &
|
|
" expected 0000004100000040"
|
|
severity failure;
|
|
|
|
wait until rising_edge(clk);
|
|
wait until rising_edge(clk);
|
|
wait until rising_edge(clk);
|
|
wait until rising_edge(clk);
|
|
|
|
assert false report "end of test" severity failure;
|
|
wait;
|
|
|
|
end process;
|
|
end;
|