FPU: Don't use mask generator for rounding

Instead of using the mask generator in the rounding process, this uses
simpler logic to add in a 1 at the appropriate position (bit 2 or bit
31, depending on precision) and mask off the low-order bits.  Since
there are only two positions at which the masking and incrementing
need to be done, we don't need the full generality of the mask
generator.  This reduces the amount of logic and improves timing.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/267/head
Paul Mackerras 4 years ago
parent 45c5236700
commit 5535257c71

@ -157,7 +157,7 @@ architecture behaviour of fpu is


constant BIN_ZERO : std_ulogic_vector(1 downto 0) := "00"; constant BIN_ZERO : std_ulogic_vector(1 downto 0) := "00";
constant BIN_R : std_ulogic_vector(1 downto 0) := "01"; constant BIN_R : std_ulogic_vector(1 downto 0) := "01";
constant BIN_MASK : std_ulogic_vector(1 downto 0) := "10"; constant BIN_RND : std_ulogic_vector(1 downto 0) := "10";
constant BIN_PS6 : std_ulogic_vector(1 downto 0) := "11"; constant BIN_PS6 : std_ulogic_vector(1 downto 0) := "11";


constant RES_SUM : std_ulogic_vector(1 downto 0) := "00"; constant RES_SUM : std_ulogic_vector(1 downto 0) := "00";
@ -632,6 +632,7 @@ begin
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); variable sum : std_ulogic_vector(63 downto 0);
variable round_inc : std_ulogic_vector(63 downto 0);
begin begin
v := r; v := r;
illegal := '0'; illegal := '0';
@ -1117,7 +1118,6 @@ begin
elsif r.b.exponent > to_signed(127, EXP_BITS) then elsif r.b.exponent > to_signed(127, EXP_BITS) then
v.state := ROUND_OFLOW; v.state := ROUND_OFLOW;
else else
v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING; v.state := ROUNDING;
end if; end if;
else else
@ -1619,7 +1619,6 @@ begin
-- sum overflowed, shift right -- sum overflowed, shift right
opsel_r <= RES_SHIFT; opsel_r <= RES_SHIFT;
set_x := '1'; set_x := '1';
v.shift := to_signed(-2, EXP_BITS);
if exp_huge = '1' then if exp_huge = '1' then
v.state := ROUND_OFLOW; v.state := ROUND_OFLOW;
else else
@ -1627,7 +1626,6 @@ begin
end if; end if;
elsif r.r(54) = '1' then elsif r.r(54) = '1' then
set_x := '1'; set_x := '1';
v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING; v.state := ROUNDING;
elsif (r_hi_nz or r_lo_nz or r.r(1) or r.r(0)) = '0' then elsif (r_hi_nz or r_lo_nz or r.r(1) or r.r(0)) = '0' then
-- r.x must be zero at this point -- r.x must be zero at this point
@ -2085,7 +2083,6 @@ begin
-- r.shift = b.exponent - 52 -- r.shift = b.exponent - 52
opsel_r <= RES_SHIFT; opsel_r <= RES_SHIFT;
set_x := '1'; set_x := '1';
v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING; v.state := ROUNDING;


when FINISH => when FINISH =>
@ -2103,7 +2100,6 @@ begin
elsif exp_huge = '1' then elsif exp_huge = '1' then
v.state := ROUND_OFLOW; v.state := ROUND_OFLOW;
else else
v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING; v.state := ROUNDING;
end if; end if;
end if; end if;
@ -2119,7 +2115,6 @@ begin
elsif exp_huge = '1' then elsif exp_huge = '1' then
v.state := ROUND_OFLOW; v.state := ROUND_OFLOW;
else else
v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING; v.state := ROUNDING;
end if; end if;


@ -2131,7 +2126,6 @@ begin
-- have to denormalize before rounding -- have to denormalize before rounding
opsel_r <= RES_SHIFT; opsel_r <= RES_SHIFT;
set_x := '1'; set_x := '1';
v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING; v.state := ROUNDING;
else else
-- enabled underflow exception case -- enabled underflow exception case
@ -2142,7 +2136,6 @@ begin
renormalize := '1'; renormalize := '1';
v.state := NORMALIZE; v.state := NORMALIZE;
else else
v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING; v.state := ROUNDING;
end if; end if;
end if; end if;
@ -2169,7 +2162,6 @@ begin
else else
-- enabled overflow exception -- enabled overflow exception
v.result_exp := r.result_exp - bias_exp; v.result_exp := r.result_exp - bias_exp;
v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING; v.state := ROUNDING;
end if; end if;


@ -2178,9 +2170,8 @@ begin
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
-- set mask to increment the LSB for the precision -- increment the LSB for the precision
opsel_b <= BIN_MASK; opsel_b <= BIN_RND;
carry_in <= '1';
v.shift := to_signed(-1, EXP_BITS); v.shift := to_signed(-1, EXP_BITS);
v.state := ROUNDING_2; v.state := ROUNDING_2;
else else
@ -2402,8 +2393,9 @@ begin
in_b0 := (others => '0'); in_b0 := (others => '0');
when BIN_R => when BIN_R =>
in_b0 := r.r; in_b0 := r.r;
when BIN_MASK => when BIN_RND =>
in_b0 := mask; round_inc := (31 => r.single_prec, 2 => not r.single_prec, others => '0');
in_b0 := round_inc;
when others => when others =>
-- BIN_PS6, 6 LSBs of P/4 sign-extended to 64 -- BIN_PS6, 6 LSBs of P/4 sign-extended to 64
in_b0 := std_ulogic_vector(resize(signed(r.p(7 downto 2)), 64)); in_b0 := std_ulogic_vector(resize(signed(r.p(7 downto 2)), 64));
@ -2420,7 +2412,10 @@ begin
end if; end if;
sum := std_ulogic_vector(unsigned(in_a) + unsigned(in_b) + carry_in); sum := std_ulogic_vector(unsigned(in_a) + unsigned(in_b) + carry_in);
if opsel_mask = '1' then if opsel_mask = '1' then
sum := sum and not mask; sum(1 downto 0) := "00";
if r.single_prec = '1' then
sum(30 downto 2) := (others => '0');
end if;
end if; end if;
case opsel_r is case opsel_r is
when RES_SUM => when RES_SUM =>

Loading…
Cancel
Save