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.
110 lines
2.6 KiB
VHDL
110 lines
2.6 KiB
VHDL
5 years ago
|
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;
|