FPU: Do masking after adder rather than on A input

The masking enabled by opsel_amask is only used when rounding, to trim
the rounded result to the required precision.  We now do the masking
after the adder rather than before (on the A input).  This gives the
same result and helps timing.  The path from r.shift through the mask
generator and adder to v.r was showing up as a critical path.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/245/head
Paul Mackerras 4 years ago
parent e1ca023bad
commit 73f819301b

@ -130,7 +130,7 @@ architecture behaviour of fpu is
signal opsel_r : std_ulogic_vector(1 downto 0); signal opsel_r : std_ulogic_vector(1 downto 0);
signal opsel_s : std_ulogic_vector(1 downto 0); signal opsel_s : std_ulogic_vector(1 downto 0);
signal opsel_ainv : std_ulogic; signal opsel_ainv : std_ulogic;
signal opsel_amask : std_ulogic; signal opsel_mask : std_ulogic;
signal opsel_binv : std_ulogic; signal opsel_binv : std_ulogic;
signal in_a : std_ulogic_vector(63 downto 0); signal in_a : std_ulogic_vector(63 downto 0);
signal in_b : std_ulogic_vector(63 downto 0); signal in_b : std_ulogic_vector(63 downto 0);
@ -631,6 +631,7 @@ begin
variable shiftin : std_ulogic; variable shiftin : std_ulogic;
variable mulexp : signed(EXP_BITS-1 downto 0); variable mulexp : signed(EXP_BITS-1 downto 0);
variable maddend : std_ulogic_vector(127 downto 0); variable maddend : std_ulogic_vector(127 downto 0);
variable sum : std_ulogic_vector(63 downto 0);
begin begin
v := r; v := r;
illegal := '0'; illegal := '0';
@ -733,7 +734,7 @@ begin
v.first := '0'; v.first := '0';
v.opsel_a := AIN_R; v.opsel_a := AIN_R;
opsel_ainv <= '0'; opsel_ainv <= '0';
opsel_amask <= '0'; opsel_mask <= '0';
opsel_b <= BIN_ZERO; opsel_b <= BIN_ZERO;
opsel_binv <= '0'; opsel_binv <= '0';
opsel_r <= RES_SUM; opsel_r <= RES_SUM;
@ -2176,7 +2177,7 @@ begin
end if; end if;


when ROUNDING => when ROUNDING =>
opsel_amask <= '1'; opsel_mask <= '1';
round := fp_rounding(r.r, r.x, r.single_prec, r.round_mode, r.result_sign); round := fp_rounding(r.r, r.x, r.single_prec, r.round_mode, r.result_sign);
v.fpscr(FPSCR_FR downto FPSCR_FI) := round; v.fpscr(FPSCR_FR downto FPSCR_FI) := round;
if round(1) = '1' then if round(1) = '1' then
@ -2398,9 +2399,6 @@ begin
if opsel_ainv = '1' then if opsel_ainv = '1' then
in_a0 := not in_a0; in_a0 := not in_a0;
end if; end if;
if opsel_amask = '1' then
in_a0 := in_a0 and not mask;
end if;
in_a <= in_a0; in_a <= in_a0;
case opsel_b is case opsel_b is
when BIN_ZERO => when BIN_ZERO =>
@ -2423,9 +2421,13 @@ begin
else else
shift_res := (others => '0'); shift_res := (others => '0');
end if; end if;
sum := std_ulogic_vector(unsigned(in_a) + unsigned(in_b) + carry_in);
if opsel_mask = '1' then
sum := sum and not mask;
end if;
case opsel_r is case opsel_r is
when RES_SUM => when RES_SUM =>
result <= std_ulogic_vector(unsigned(in_a) + unsigned(in_b) + carry_in); result <= sum;
when RES_SHIFT => when RES_SHIFT =>
result <= shift_res; result <= shift_res;
when RES_MULT => when RES_MULT =>

Loading…
Cancel
Save