MMU: Improve timing of done signal back to loadstore1

This makes the l_out.done signal come from a clean latch, which
improves timing.  The cost is that TLB load and invalidation
operations to the dcache now signal done back to loadstore1 one
cycle later than before, but that doesn't seem to affect overall
performance noticeably.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/233/head
Paul Mackerras 4 years ago
parent 1be6fbac33
commit 1f2058a0ed

@ -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;

Loading…
Cancel
Save