@ -35,7 +35,7 @@ architecture behave of mmu is
RADIX_LOOKUP,
RADIX_LOOKUP,
RADIX_READ_WAIT,
RADIX_READ_WAIT,
RADIX_LOAD_TLB,
RADIX_LOAD_TLB,
RADIX_ERROR
RADIX_FINISH
);
);
type reg_stage_t is record
type reg_stage_t is record
@ -51,6 +51,7 @@ architecture behave of mmu is
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;
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);
@ -176,7 +177,6 @@ begin
mmu_1: process(all)
mmu_1: process(all)
variable v : reg_stage_t;
variable v : reg_stage_t;
variable dcreq : std_ulogic;
variable dcreq : std_ulogic;
variable done : std_ulogic;
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;
@ -199,7 +199,7 @@ begin
v := r;
v := r;
v.valid := '0';
v.valid := '0';
dcreq := '0';
dcreq := '0';
done := '0';
v.done := '0';
v.invalid := '0';
v.invalid := '0';
v.badtree := '0';
v.badtree := '0';
v.segerror := '0';
v.segerror := '0';
@ -262,7 +262,7 @@ begin
v.state := PROC_TBL_READ;
v.state := PROC_TBL_READ;
elsif mbits = 0 then
elsif mbits = 0 then
-- Use RPDS = 0 to disable radix tree walks
-- Use RPDS = 0 to disable radix tree walks
v.state := RADIX_ERROR;
v.state := RADIX_FINISH;
v.invalid := '1';
v.invalid := '1';
else
else
v.state := SEGMENT_CHECK;
v.state := SEGMENT_CHECK;
@ -291,8 +291,7 @@ begin
when TLB_WAIT =>
when TLB_WAIT =>
if d_in.done = '1' then
if d_in.done = '1' then
done := '1';
v.state := RADIX_FINISH;
v.state := IDLE;
end if;
end if;
when PROC_TBL_READ =>
when PROC_TBL_READ =>
@ -319,13 +318,13 @@ begin
v.mask_size := mbits(4 downto 0);
v.mask_size := mbits(4 downto 0);
v.pgbase := data(55 downto 8) & x"00";
v.pgbase := data(55 downto 8) & x"00";
if mbits = 0 then
if mbits = 0 then
v.state := RADIX_ERROR;
v.state := RADIX_FINISH;
v.invalid := '1';
v.invalid := '1';
else
else
v.state := SEGMENT_CHECK;
v.state := SEGMENT_CHECK;
end if;
end if;
else
else
v.state := RADIX_ERROR;
v.state := RADIX_FINISH;
v.badtree := '1';
v.badtree := '1';
end if;
end if;
end if;
end if;
@ -335,10 +334,10 @@ begin
v.shift := r.shift + (31 - 12) - mbits;
v.shift := r.shift + (31 - 12) - mbits;
nonzero := or(r.addr(61 downto 31) and not finalmask(30 downto 0));
nonzero := or(r.addr(61 downto 31) and not finalmask(30 downto 0));
if r.addr(63) /= r.addr(62) or nonzero = '1' then
if r.addr(63) /= r.addr(62) or nonzero = '1' then
v.state := RADIX_ERROR;
v.state := RADIX_FINISH;
v.segerror := '1';
v.segerror := '1';
elsif mbits < 5 or mbits > 16 or mbits > (r.shift + (31 - 12)) then
elsif mbits < 5 or mbits > 16 or mbits > (r.shift + (31 - 12)) then
v.state := RADIX_ERROR;
v.state := RADIX_FINISH;
v.badtree := '1';
v.badtree := '1';
else
else
v.state := RADIX_LOOKUP;
v.state := RADIX_LOOKUP;
@ -371,7 +370,7 @@ begin
if perm_ok = '1' and rc_ok = '1' then
if perm_ok = '1' and rc_ok = '1' then
v.state := RADIX_LOAD_TLB;
v.state := RADIX_LOAD_TLB;
else
else
v.state := RADIX_ERROR;
v.state := RADIX_FINISH;
v.perm_err := not perm_ok;
v.perm_err := not perm_ok;
-- permission error takes precedence over RC error
-- permission error takes precedence over RC error
v.rc_error := perm_ok;
v.rc_error := perm_ok;
@ -379,7 +378,7 @@ begin
else
else
mbits := unsigned('0' & data(4 downto 0));
mbits := unsigned('0' & data(4 downto 0));
if mbits < 5 or mbits > 16 or mbits > r.shift then
if mbits < 5 or mbits > 16 or mbits > r.shift then
v.state := RADIX_ERROR;
v.state := RADIX_FINISH;
v.badtree := '1';
v.badtree := '1';
else
else
v.shift := v.shift - mbits;
v.shift := v.shift - mbits;
@ -390,11 +389,11 @@ begin
end if;
end if;
else
else
-- non-present PTE, generate a DSI
-- non-present PTE, generate a DSI
v.state := RADIX_ERROR;
v.state := RADIX_FINISH;
v.invalid := '1';
v.invalid := '1';
end if;
end if;
else
else
v.state := RADIX_ERROR;
v.state := RADIX_FINISH;
v.badtree := '1';
v.badtree := '1';
end if;
end if;
end if;
end if;
@ -406,16 +405,18 @@ begin
v.state := TLB_WAIT;
v.state := TLB_WAIT;
else
else
itlb_load := '1';
itlb_load := '1';
done := '1';
v.state := IDLE;
v.state := IDLE;
end if;
end if;
when RADIX_ERROR =>
when RADIX_FINISH =>
done := '1';
v.state := IDLE;
v.state := IDLE;
end case;
end case;
if v.state = RADIX_FINISH or (v.state = RADIX_LOAD_TLB and r.iside = '1') then
v.done := '1';
end if;
if r.addr(63) = '1' then
if r.addr(63) = '1' then
effpid := x"00000000";
effpid := x"00000000";
else
else
@ -451,7 +452,7 @@ begin
tlb_data := (others => '0');
tlb_data := (others => '0');
end if;
end if;
l_out.done <= done;
l_out.done <= r.done;
l_out.invalid <= r.invalid;
l_out.invalid <= r.invalid;
l_out.badtree <= r.badtree;
l_out.badtree <= r.badtree;
l_out.segerr <= r.segerror;
l_out.segerr <= r.segerror;