mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-03 12:03:15 +00:00
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>
This commit is contained in:
27
fpu.vhdl
27
fpu.vhdl
@@ -157,7 +157,7 @@ architecture behaviour of fpu is
|
||||
|
||||
constant BIN_ZERO : std_ulogic_vector(1 downto 0) := "00";
|
||||
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 RES_SUM : std_ulogic_vector(1 downto 0) := "00";
|
||||
@@ -632,6 +632,7 @@ begin
|
||||
variable mulexp : signed(EXP_BITS-1 downto 0);
|
||||
variable maddend : std_ulogic_vector(127 downto 0);
|
||||
variable sum : std_ulogic_vector(63 downto 0);
|
||||
variable round_inc : std_ulogic_vector(63 downto 0);
|
||||
begin
|
||||
v := r;
|
||||
illegal := '0';
|
||||
@@ -1117,7 +1118,6 @@ begin
|
||||
elsif r.b.exponent > to_signed(127, EXP_BITS) then
|
||||
v.state := ROUND_OFLOW;
|
||||
else
|
||||
v.shift := to_signed(-2, EXP_BITS);
|
||||
v.state := ROUNDING;
|
||||
end if;
|
||||
else
|
||||
@@ -1619,7 +1619,6 @@ begin
|
||||
-- sum overflowed, shift right
|
||||
opsel_r <= RES_SHIFT;
|
||||
set_x := '1';
|
||||
v.shift := to_signed(-2, EXP_BITS);
|
||||
if exp_huge = '1' then
|
||||
v.state := ROUND_OFLOW;
|
||||
else
|
||||
@@ -1627,7 +1626,6 @@ begin
|
||||
end if;
|
||||
elsif r.r(54) = '1' then
|
||||
set_x := '1';
|
||||
v.shift := to_signed(-2, EXP_BITS);
|
||||
v.state := ROUNDING;
|
||||
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
|
||||
@@ -2085,7 +2083,6 @@ begin
|
||||
-- r.shift = b.exponent - 52
|
||||
opsel_r <= RES_SHIFT;
|
||||
set_x := '1';
|
||||
v.shift := to_signed(-2, EXP_BITS);
|
||||
v.state := ROUNDING;
|
||||
|
||||
when FINISH =>
|
||||
@@ -2103,7 +2100,6 @@ begin
|
||||
elsif exp_huge = '1' then
|
||||
v.state := ROUND_OFLOW;
|
||||
else
|
||||
v.shift := to_signed(-2, EXP_BITS);
|
||||
v.state := ROUNDING;
|
||||
end if;
|
||||
end if;
|
||||
@@ -2119,7 +2115,6 @@ begin
|
||||
elsif exp_huge = '1' then
|
||||
v.state := ROUND_OFLOW;
|
||||
else
|
||||
v.shift := to_signed(-2, EXP_BITS);
|
||||
v.state := ROUNDING;
|
||||
end if;
|
||||
|
||||
@@ -2131,7 +2126,6 @@ begin
|
||||
-- have to denormalize before rounding
|
||||
opsel_r <= RES_SHIFT;
|
||||
set_x := '1';
|
||||
v.shift := to_signed(-2, EXP_BITS);
|
||||
v.state := ROUNDING;
|
||||
else
|
||||
-- enabled underflow exception case
|
||||
@@ -2142,7 +2136,6 @@ begin
|
||||
renormalize := '1';
|
||||
v.state := NORMALIZE;
|
||||
else
|
||||
v.shift := to_signed(-2, EXP_BITS);
|
||||
v.state := ROUNDING;
|
||||
end if;
|
||||
end if;
|
||||
@@ -2169,7 +2162,6 @@ begin
|
||||
else
|
||||
-- enabled overflow exception
|
||||
v.result_exp := r.result_exp - bias_exp;
|
||||
v.shift := to_signed(-2, EXP_BITS);
|
||||
v.state := ROUNDING;
|
||||
end if;
|
||||
|
||||
@@ -2178,9 +2170,8 @@ begin
|
||||
round := fp_rounding(r.r, r.x, r.single_prec, r.round_mode, r.result_sign);
|
||||
v.fpscr(FPSCR_FR downto FPSCR_FI) := round;
|
||||
if round(1) = '1' then
|
||||
-- set mask to increment the LSB for the precision
|
||||
opsel_b <= BIN_MASK;
|
||||
carry_in <= '1';
|
||||
-- increment the LSB for the precision
|
||||
opsel_b <= BIN_RND;
|
||||
v.shift := to_signed(-1, EXP_BITS);
|
||||
v.state := ROUNDING_2;
|
||||
else
|
||||
@@ -2402,8 +2393,9 @@ begin
|
||||
in_b0 := (others => '0');
|
||||
when BIN_R =>
|
||||
in_b0 := r.r;
|
||||
when BIN_MASK =>
|
||||
in_b0 := mask;
|
||||
when BIN_RND =>
|
||||
round_inc := (31 => r.single_prec, 2 => not r.single_prec, others => '0');
|
||||
in_b0 := round_inc;
|
||||
when others =>
|
||||
-- BIN_PS6, 6 LSBs of P/4 sign-extended to 64
|
||||
in_b0 := std_ulogic_vector(resize(signed(r.p(7 downto 2)), 64));
|
||||
@@ -2420,7 +2412,10 @@ begin
|
||||
end if;
|
||||
sum := std_ulogic_vector(unsigned(in_a) + unsigned(in_b) + carry_in);
|
||||
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;
|
||||
case opsel_r is
|
||||
when RES_SUM =>
|
||||
|
||||
Reference in New Issue
Block a user