|
|
@ -29,6 +29,9 @@ architecture behave of mmu is
|
|
|
|
type state_t is (IDLE,
|
|
|
|
type state_t is (IDLE,
|
|
|
|
DO_TLBIE,
|
|
|
|
DO_TLBIE,
|
|
|
|
TLB_WAIT,
|
|
|
|
TLB_WAIT,
|
|
|
|
|
|
|
|
PART_TBL_READ,
|
|
|
|
|
|
|
|
PART_TBL_WAIT,
|
|
|
|
|
|
|
|
PART_TBL_DONE,
|
|
|
|
PROC_TBL_READ,
|
|
|
|
PROC_TBL_READ,
|
|
|
|
PROC_TBL_WAIT,
|
|
|
|
PROC_TBL_WAIT,
|
|
|
|
SEGMENT_CHECK,
|
|
|
|
SEGMENT_CHECK,
|
|
|
@ -47,12 +50,14 @@ architecture behave of mmu is
|
|
|
|
addr : std_ulogic_vector(63 downto 0);
|
|
|
|
addr : std_ulogic_vector(63 downto 0);
|
|
|
|
inval_all : std_ulogic;
|
|
|
|
inval_all : std_ulogic;
|
|
|
|
-- config SPRs
|
|
|
|
-- config SPRs
|
|
|
|
prtbl : std_ulogic_vector(63 downto 0);
|
|
|
|
ptcr : std_ulogic_vector(63 downto 0);
|
|
|
|
pid : std_ulogic_vector(31 downto 0);
|
|
|
|
pid : std_ulogic_vector(31 downto 0);
|
|
|
|
-- internal state
|
|
|
|
-- internal state
|
|
|
|
state : state_t;
|
|
|
|
state : state_t;
|
|
|
|
done : std_ulogic;
|
|
|
|
done : std_ulogic;
|
|
|
|
err : std_ulogic;
|
|
|
|
err : std_ulogic;
|
|
|
|
|
|
|
|
prtbl : std_ulogic_vector(63 downto 0);
|
|
|
|
|
|
|
|
ptb_valid : std_ulogic;
|
|
|
|
pgtbl0 : std_ulogic_vector(63 downto 0);
|
|
|
|
pgtbl0 : std_ulogic_vector(63 downto 0);
|
|
|
|
pt0_valid : std_ulogic;
|
|
|
|
pt0_valid : std_ulogic;
|
|
|
|
pgtbl3 : std_ulogic_vector(63 downto 0);
|
|
|
|
pgtbl3 : std_ulogic_vector(63 downto 0);
|
|
|
@ -77,7 +82,7 @@ architecture behave of mmu is
|
|
|
|
begin
|
|
|
|
begin
|
|
|
|
-- Multiplex internal SPR values back to loadstore1, selected
|
|
|
|
-- Multiplex internal SPR values back to loadstore1, selected
|
|
|
|
-- by l_in.sprn.
|
|
|
|
-- by l_in.sprn.
|
|
|
|
l_out.sprval <= r.prtbl when l_in.sprn(9) = '1' else x"00000000" & r.pid;
|
|
|
|
l_out.sprval <= r.ptcr when l_in.sprn(8) = '1' else x"00000000" & r.pid;
|
|
|
|
|
|
|
|
|
|
|
|
mmu_0: process(clk)
|
|
|
|
mmu_0: process(clk)
|
|
|
|
begin
|
|
|
|
begin
|
|
|
@ -85,9 +90,10 @@ begin
|
|
|
|
if rst = '1' then
|
|
|
|
if rst = '1' then
|
|
|
|
r.state <= IDLE;
|
|
|
|
r.state <= IDLE;
|
|
|
|
r.valid <= '0';
|
|
|
|
r.valid <= '0';
|
|
|
|
|
|
|
|
r.ptb_valid <= '0';
|
|
|
|
r.pt0_valid <= '0';
|
|
|
|
r.pt0_valid <= '0';
|
|
|
|
r.pt3_valid <= '0';
|
|
|
|
r.pt3_valid <= '0';
|
|
|
|
r.prtbl <= (others => '0');
|
|
|
|
r.ptcr <= (others => '0');
|
|
|
|
r.pid <= (others => '0');
|
|
|
|
r.pid <= (others => '0');
|
|
|
|
else
|
|
|
|
else
|
|
|
|
if rin.valid = '1' then
|
|
|
|
if rin.valid = '1' then
|
|
|
@ -185,6 +191,7 @@ begin
|
|
|
|
variable tlb_load : std_ulogic;
|
|
|
|
variable tlb_load : std_ulogic;
|
|
|
|
variable itlb_load : std_ulogic;
|
|
|
|
variable itlb_load : std_ulogic;
|
|
|
|
variable tlbie_req : std_ulogic;
|
|
|
|
variable tlbie_req : std_ulogic;
|
|
|
|
|
|
|
|
variable ptbl_rd : std_ulogic;
|
|
|
|
variable prtbl_rd : std_ulogic;
|
|
|
|
variable prtbl_rd : std_ulogic;
|
|
|
|
variable pt_valid : std_ulogic;
|
|
|
|
variable pt_valid : std_ulogic;
|
|
|
|
variable effpid : std_ulogic_vector(31 downto 0);
|
|
|
|
variable effpid : std_ulogic_vector(31 downto 0);
|
|
|
@ -215,6 +222,7 @@ begin
|
|
|
|
itlb_load := '0';
|
|
|
|
itlb_load := '0';
|
|
|
|
tlbie_req := '0';
|
|
|
|
tlbie_req := '0';
|
|
|
|
v.inval_all := '0';
|
|
|
|
v.inval_all := '0';
|
|
|
|
|
|
|
|
ptbl_rd := '0';
|
|
|
|
prtbl_rd := '0';
|
|
|
|
prtbl_rd := '0';
|
|
|
|
|
|
|
|
|
|
|
|
-- Radix tree data structures in memory are big-endian,
|
|
|
|
-- Radix tree data structures in memory are big-endian,
|
|
|
@ -256,11 +264,15 @@ begin
|
|
|
|
if l_in.sprn(3) = '1' then
|
|
|
|
if l_in.sprn(3) = '1' then
|
|
|
|
v.pt0_valid := '0';
|
|
|
|
v.pt0_valid := '0';
|
|
|
|
v.pt3_valid := '0';
|
|
|
|
v.pt3_valid := '0';
|
|
|
|
|
|
|
|
v.ptb_valid := '0';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
v.state := DO_TLBIE;
|
|
|
|
v.state := DO_TLBIE;
|
|
|
|
else
|
|
|
|
else
|
|
|
|
v.valid := '1';
|
|
|
|
v.valid := '1';
|
|
|
|
if pt_valid = '0' then
|
|
|
|
if r.ptb_valid = '0' then
|
|
|
|
|
|
|
|
-- need to fetch process table base from partition table
|
|
|
|
|
|
|
|
v.state := PART_TBL_READ;
|
|
|
|
|
|
|
|
elsif pt_valid = '0' then
|
|
|
|
-- need to fetch process table entry
|
|
|
|
-- need to fetch process table entry
|
|
|
|
-- set v.shift so we can use finalmask for generating
|
|
|
|
-- set v.shift so we can use finalmask for generating
|
|
|
|
-- the process table entry address
|
|
|
|
-- the process table entry address
|
|
|
@ -277,13 +289,14 @@ begin
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
if l_in.mtspr = '1' then
|
|
|
|
if l_in.mtspr = '1' then
|
|
|
|
-- Move to PID needs to invalidate L1 TLBs and cached
|
|
|
|
-- Move to PID needs to invalidate L1 TLBs and cached
|
|
|
|
-- pgtbl0 value. Move to PRTBL does that plus
|
|
|
|
-- pgtbl0 value. Move to PTCR does that plus
|
|
|
|
-- invalidating the cached pgtbl3 value as well.
|
|
|
|
-- invalidating the cached pgtbl3 and prtbl values as well.
|
|
|
|
if l_in.sprn(9) = '0' then
|
|
|
|
if l_in.sprn(8) = '0' then
|
|
|
|
v.pid := l_in.rs(31 downto 0);
|
|
|
|
v.pid := l_in.rs(31 downto 0);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
v.prtbl := l_in.rs;
|
|
|
|
v.ptcr := l_in.rs;
|
|
|
|
v.pt3_valid := '0';
|
|
|
|
v.pt3_valid := '0';
|
|
|
|
|
|
|
|
v.ptb_valid := '0';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
v.pt0_valid := '0';
|
|
|
|
v.pt0_valid := '0';
|
|
|
|
v.inval_all := '1';
|
|
|
|
v.inval_all := '1';
|
|
|
@ -300,6 +313,22 @@ begin
|
|
|
|
v.state := RADIX_FINISH;
|
|
|
|
v.state := RADIX_FINISH;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when PART_TBL_READ =>
|
|
|
|
|
|
|
|
dcreq := '1';
|
|
|
|
|
|
|
|
ptbl_rd := '1';
|
|
|
|
|
|
|
|
v.state := PART_TBL_WAIT;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when PART_TBL_WAIT =>
|
|
|
|
|
|
|
|
if d_in.done = '1' then
|
|
|
|
|
|
|
|
v.prtbl := data;
|
|
|
|
|
|
|
|
v.ptb_valid := '1';
|
|
|
|
|
|
|
|
v.state := PART_TBL_DONE;
|
|
|
|
|
|
|
|
end if;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when PART_TBL_DONE =>
|
|
|
|
|
|
|
|
v.shift := unsigned('0' & r.prtbl(4 downto 0));
|
|
|
|
|
|
|
|
v.state := PROC_TBL_READ;
|
|
|
|
|
|
|
|
|
|
|
|
when PROC_TBL_READ =>
|
|
|
|
when PROC_TBL_READ =>
|
|
|
|
dcreq := '1';
|
|
|
|
dcreq := '1';
|
|
|
|
prtbl_rd := '1';
|
|
|
|
prtbl_rd := '1';
|
|
|
@ -449,6 +478,9 @@ begin
|
|
|
|
elsif tlb_load = '1' then
|
|
|
|
elsif tlb_load = '1' then
|
|
|
|
addr := r.addr(63 downto 12) & x"000";
|
|
|
|
addr := r.addr(63 downto 12) & x"000";
|
|
|
|
tlb_data := pte;
|
|
|
|
tlb_data := pte;
|
|
|
|
|
|
|
|
elsif ptbl_rd = '1' then
|
|
|
|
|
|
|
|
addr := x"00" & r.ptcr(55 downto 12) & x"008";
|
|
|
|
|
|
|
|
tlb_data := (others => '0');
|
|
|
|
elsif prtbl_rd = '1' then
|
|
|
|
elsif prtbl_rd = '1' then
|
|
|
|
addr := prtable_addr;
|
|
|
|
addr := prtable_addr;
|
|
|
|
tlb_data := (others => '0');
|
|
|
|
tlb_data := (others => '0');
|
|
|
|