RADIX_LOOKUP,
RADIX_READ_WAIT,
RADIX_LOAD_TLB,
- RADIX_ERROR
+ RADIX_FINISH
);
type reg_stage_t is record
pid : std_ulogic_vector(31 downto 0);
-- internal state
state : state_t;
+ done : std_ulogic;
pgtbl0 : std_ulogic_vector(63 downto 0);
pt0_valid : std_ulogic;
pgtbl3 : std_ulogic_vector(63 downto 0);
mmu_1: process(all)
variable v : reg_stage_t;
variable dcreq : std_ulogic;
- variable done : std_ulogic;
variable tlb_load : std_ulogic;
variable itlb_load : std_ulogic;
variable tlbie_req : std_ulogic;
v := r;
v.valid := '0';
dcreq := '0';
- done := '0';
+ v.done := '0';
v.invalid := '0';
v.badtree := '0';
v.segerror := '0';
v.state := PROC_TBL_READ;
elsif mbits = 0 then
-- Use RPDS = 0 to disable radix tree walks
- v.state := RADIX_ERROR;
+ v.state := RADIX_FINISH;
v.invalid := '1';
else
v.state := SEGMENT_CHECK;
when TLB_WAIT =>
if d_in.done = '1' then
- done := '1';
- v.state := IDLE;
+ v.state := RADIX_FINISH;
end if;
when PROC_TBL_READ =>
v.mask_size := mbits(4 downto 0);
v.pgbase := data(55 downto 8) & x"00";
if mbits = 0 then
- v.state := RADIX_ERROR;
+ v.state := RADIX_FINISH;
v.invalid := '1';
else
v.state := SEGMENT_CHECK;
end if;
else
- v.state := RADIX_ERROR;
+ v.state := RADIX_FINISH;
v.badtree := '1';
end if;
end if;
v.shift := r.shift + (31 - 12) - mbits;
nonzero := or(r.addr(61 downto 31) and not finalmask(30 downto 0));
if r.addr(63) /= r.addr(62) or nonzero = '1' then
- v.state := RADIX_ERROR;
+ v.state := RADIX_FINISH;
v.segerror := '1';
elsif mbits < 5 or mbits > 16 or mbits > (r.shift + (31 - 12)) then
- v.state := RADIX_ERROR;
+ v.state := RADIX_FINISH;
v.badtree := '1';
else
v.state := RADIX_LOOKUP;
if perm_ok = '1' and rc_ok = '1' then
v.state := RADIX_LOAD_TLB;
else
- v.state := RADIX_ERROR;
+ v.state := RADIX_FINISH;
v.perm_err := not perm_ok;
-- permission error takes precedence over RC error
v.rc_error := perm_ok;
else
mbits := unsigned('0' & data(4 downto 0));
if mbits < 5 or mbits > 16 or mbits > r.shift then
- v.state := RADIX_ERROR;
+ v.state := RADIX_FINISH;
v.badtree := '1';
else
v.shift := v.shift - mbits;
end if;
else
-- non-present PTE, generate a DSI
- v.state := RADIX_ERROR;
+ v.state := RADIX_FINISH;
v.invalid := '1';
end if;
else
- v.state := RADIX_ERROR;
+ v.state := RADIX_FINISH;
v.badtree := '1';
end if;
end if;
v.state := TLB_WAIT;
else
itlb_load := '1';
- done := '1';
v.state := IDLE;
end if;
- when RADIX_ERROR =>
- done := '1';
+ when RADIX_FINISH =>
v.state := IDLE;
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
effpid := x"00000000";
else
tlb_data := (others => '0');
end if;
- l_out.done <= done;
+ l_out.done <= r.done;
l_out.invalid <= r.invalid;
l_out.badtree <= r.badtree;
l_out.segerr <= r.segerror;