You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
microwatt/mmu.vhdl

110 lines
2.6 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.common.all;
-- Radix MMU
-- Supports 4-level trees as in arch 3.0B, but not the two-step translation for
-- guests under a hypervisor (i.e. there is no gRA -> hRA translation).
entity mmu is
port (
clk : in std_ulogic;
rst : in std_ulogic;
l_in : in Loadstore1ToMmuType;
l_out : out MmuToLoadstore1Type;
d_out : out MmuToDcacheType;
d_in : in DcacheToMmuType
);
end mmu;
architecture behave of mmu is
type state_t is (IDLE,
TLBIE_WAIT,
RADIX_LOOKUP_0
);
type reg_stage_t is record
-- latched request from loadstore1
valid : std_ulogic;
addr : std_ulogic_vector(63 downto 0);
state : state_t;
end record;
signal r, rin : reg_stage_t;
begin
mmu_0: process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
r.state <= IDLE;
r.valid <= '0';
else
if rin.valid = '1' then
report "MMU got tlb miss for " & to_hstring(rin.addr);
end if;
if l_out.done = '1' then
report "MMU completing miss with error=" & std_ulogic'image(l_out.error);
end if;
r <= rin;
end if;
end if;
end process;
mmu_1: process(all)
variable v : reg_stage_t;
variable dcreq : std_ulogic;
variable done : std_ulogic;
variable err : std_ulogic;
begin
v.valid := l_in.valid;
v.addr := l_in.addr;
v.state := r.state;
dcreq := '0';
done := '0';
err := '0';
case r.state is
when IDLE =>
if l_in.valid = '1' then
if l_in.tlbie = '1' then
dcreq := '1';
v.state := TLBIE_WAIT;
else
v.state := RADIX_LOOKUP_0;
end if;
end if;
when TLBIE_WAIT =>
if d_in.done = '1' then
done := '1';
v.state := IDLE;
end if;
when RADIX_LOOKUP_0 =>
done := '1';
err := '1';
v.state := IDLE;
end case;
-- update registers
rin <= v;
-- drive outputs
l_out.done <= done;
l_out.error <= err;
d_out.valid <= dcreq;
d_out.tlbie <= l_in.tlbie;
d_out.addr <= l_in.addr;
d_out.pte <= l_in.rs;
end process;
end;