|
|
|
@ -389,7 +389,7 @@ architecture behaviour of fpu is
|
|
|
|
|
return std_ulogic_vector is
|
|
|
|
|
variable s1 : std_ulogic_vector(94 downto 0);
|
|
|
|
|
variable s2 : std_ulogic_vector(70 downto 0);
|
|
|
|
|
variable result : std_ulogic_vector(63 downto 0);
|
|
|
|
|
variable shift_result : std_ulogic_vector(63 downto 0);
|
|
|
|
|
begin
|
|
|
|
|
case shift(6 downto 5) is
|
|
|
|
|
when "00" =>
|
|
|
|
@ -413,23 +413,23 @@ architecture behaviour of fpu is
|
|
|
|
|
end case;
|
|
|
|
|
case shift(2 downto 0) is
|
|
|
|
|
when "000" =>
|
|
|
|
|
result := s2(70 downto 7);
|
|
|
|
|
shift_result := s2(70 downto 7);
|
|
|
|
|
when "001" =>
|
|
|
|
|
result := s2(69 downto 6);
|
|
|
|
|
shift_result := s2(69 downto 6);
|
|
|
|
|
when "010" =>
|
|
|
|
|
result := s2(68 downto 5);
|
|
|
|
|
shift_result := s2(68 downto 5);
|
|
|
|
|
when "011" =>
|
|
|
|
|
result := s2(67 downto 4);
|
|
|
|
|
shift_result := s2(67 downto 4);
|
|
|
|
|
when "100" =>
|
|
|
|
|
result := s2(66 downto 3);
|
|
|
|
|
shift_result := s2(66 downto 3);
|
|
|
|
|
when "101" =>
|
|
|
|
|
result := s2(65 downto 2);
|
|
|
|
|
shift_result := s2(65 downto 2);
|
|
|
|
|
when "110" =>
|
|
|
|
|
result := s2(64 downto 1);
|
|
|
|
|
shift_result := s2(64 downto 1);
|
|
|
|
|
when others =>
|
|
|
|
|
result := s2(63 downto 0);
|
|
|
|
|
shift_result := s2(63 downto 0);
|
|
|
|
|
end case;
|
|
|
|
|
return result;
|
|
|
|
|
return shift_result;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
-- Generate a mask with 0-bits on the left and 1-bits on the right which
|
|
|
|
@ -437,105 +437,105 @@ architecture behaviour of fpu is
|
|
|
|
|
-- parameter is the bottom 6 bits of a negative shift count,
|
|
|
|
|
-- indicating a right shift.
|
|
|
|
|
function right_mask(shift: unsigned(5 downto 0)) return std_ulogic_vector is
|
|
|
|
|
variable result: std_ulogic_vector(63 downto 0);
|
|
|
|
|
variable mask_result: std_ulogic_vector(63 downto 0);
|
|
|
|
|
begin
|
|
|
|
|
result := (others => '0');
|
|
|
|
|
mask_result := (others => '0');
|
|
|
|
|
if is_X(shift) then
|
|
|
|
|
result := (others => 'X');
|
|
|
|
|
return result;
|
|
|
|
|
mask_result := (others => 'X');
|
|
|
|
|
return mask_result;
|
|
|
|
|
end if;
|
|
|
|
|
for i in 0 to 63 loop
|
|
|
|
|
if i >= shift then
|
|
|
|
|
result(63 - i) := '1';
|
|
|
|
|
mask_result(63 - i) := '1';
|
|
|
|
|
end if;
|
|
|
|
|
end loop;
|
|
|
|
|
return result;
|
|
|
|
|
return mask_result;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
-- Split a DP floating-point number into components and work out its class.
|
|
|
|
|
-- If is_int = 1, the input is considered an integer
|
|
|
|
|
function decode_dp(fpr: std_ulogic_vector(63 downto 0); is_int: std_ulogic;
|
|
|
|
|
is_32bint: std_ulogic; is_signed: std_ulogic) return fpu_reg_type is
|
|
|
|
|
variable r : fpu_reg_type;
|
|
|
|
|
variable reg : fpu_reg_type;
|
|
|
|
|
variable exp_nz : std_ulogic;
|
|
|
|
|
variable exp_ao : std_ulogic;
|
|
|
|
|
variable frac_nz : std_ulogic;
|
|
|
|
|
variable low_nz : std_ulogic;
|
|
|
|
|
variable cls : std_ulogic_vector(2 downto 0);
|
|
|
|
|
begin
|
|
|
|
|
r.negative := fpr(63);
|
|
|
|
|
reg.negative := fpr(63);
|
|
|
|
|
exp_nz := or (fpr(62 downto 52));
|
|
|
|
|
exp_ao := and (fpr(62 downto 52));
|
|
|
|
|
frac_nz := or (fpr(51 downto 0));
|
|
|
|
|
low_nz := or (fpr(31 downto 0));
|
|
|
|
|
if is_int = '0' then
|
|
|
|
|
r.exponent := signed(resize(unsigned(fpr(62 downto 52)), EXP_BITS)) - to_signed(1023, EXP_BITS);
|
|
|
|
|
reg.exponent := signed(resize(unsigned(fpr(62 downto 52)), EXP_BITS)) - to_signed(1023, EXP_BITS);
|
|
|
|
|
if exp_nz = '0' then
|
|
|
|
|
r.exponent := to_signed(-1022, EXP_BITS);
|
|
|
|
|
reg.exponent := to_signed(-1022, EXP_BITS);
|
|
|
|
|
end if;
|
|
|
|
|
r.mantissa := std_ulogic_vector(shift_left(resize(unsigned(exp_nz & fpr(51 downto 0)), 64),
|
|
|
|
|
reg.mantissa := std_ulogic_vector(shift_left(resize(unsigned(exp_nz & fpr(51 downto 0)), 64),
|
|
|
|
|
UNIT_BIT - 52));
|
|
|
|
|
cls := exp_ao & exp_nz & frac_nz;
|
|
|
|
|
case cls is
|
|
|
|
|
when "000" => r.class := ZERO;
|
|
|
|
|
when "001" => r.class := FINITE; -- denormalized
|
|
|
|
|
when "010" => r.class := FINITE;
|
|
|
|
|
when "011" => r.class := FINITE;
|
|
|
|
|
when "110" => r.class := INFINITY;
|
|
|
|
|
when others => r.class := NAN;
|
|
|
|
|
when "000" => reg.class := ZERO;
|
|
|
|
|
when "001" => reg.class := FINITE; -- denormalized
|
|
|
|
|
when "010" => reg.class := FINITE;
|
|
|
|
|
when "011" => reg.class := FINITE;
|
|
|
|
|
when "110" => reg.class := INFINITY;
|
|
|
|
|
when others => reg.class := NAN;
|
|
|
|
|
end case;
|
|
|
|
|
elsif is_32bint = '1' then
|
|
|
|
|
r.negative := fpr(31);
|
|
|
|
|
r.mantissa(31 downto 0) := fpr(31 downto 0);
|
|
|
|
|
r.mantissa(63 downto 32) := (others => (is_signed and fpr(31)));
|
|
|
|
|
r.exponent := (others => '0');
|
|
|
|
|
reg.negative := fpr(31);
|
|
|
|
|
reg.mantissa(31 downto 0) := fpr(31 downto 0);
|
|
|
|
|
reg.mantissa(63 downto 32) := (others => (is_signed and fpr(31)));
|
|
|
|
|
reg.exponent := (others => '0');
|
|
|
|
|
if low_nz = '1' then
|
|
|
|
|
r.class := FINITE;
|
|
|
|
|
reg.class := FINITE;
|
|
|
|
|
else
|
|
|
|
|
r.class := ZERO;
|
|
|
|
|
reg.class := ZERO;
|
|
|
|
|
end if;
|
|
|
|
|
else
|
|
|
|
|
r.mantissa := fpr;
|
|
|
|
|
r.exponent := (others => '0');
|
|
|
|
|
reg.mantissa := fpr;
|
|
|
|
|
reg.exponent := (others => '0');
|
|
|
|
|
if (fpr(63) or exp_nz or frac_nz) = '1' then
|
|
|
|
|
r.class := FINITE;
|
|
|
|
|
reg.class := FINITE;
|
|
|
|
|
else
|
|
|
|
|
r.class := ZERO;
|
|
|
|
|
reg.class := ZERO;
|
|
|
|
|
end if;
|
|
|
|
|
end if;
|
|
|
|
|
return r;
|
|
|
|
|
return reg;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
-- Construct a DP floating-point result from components
|
|
|
|
|
function pack_dp(sign: std_ulogic; class: fp_number_class; exp: signed(EXP_BITS-1 downto 0);
|
|
|
|
|
mantissa: std_ulogic_vector; single_prec: std_ulogic; quieten_nan: std_ulogic)
|
|
|
|
|
return std_ulogic_vector is
|
|
|
|
|
variable result : std_ulogic_vector(63 downto 0);
|
|
|
|
|
variable dp_result : std_ulogic_vector(63 downto 0);
|
|
|
|
|
begin
|
|
|
|
|
result := (others => '0');
|
|
|
|
|
result(63) := sign;
|
|
|
|
|
dp_result := (others => '0');
|
|
|
|
|
dp_result(63) := sign;
|
|
|
|
|
case class is
|
|
|
|
|
when ZERO =>
|
|
|
|
|
when FINITE =>
|
|
|
|
|
if mantissa(UNIT_BIT) = '1' then
|
|
|
|
|
-- normalized number
|
|
|
|
|
result(62 downto 52) := std_ulogic_vector(resize(exp, 11) + 1023);
|
|
|
|
|
dp_result(62 downto 52) := std_ulogic_vector(resize(exp, 11) + 1023);
|
|
|
|
|
end if;
|
|
|
|
|
result(51 downto 29) := mantissa(UNIT_BIT - 1 downto SP_LSB);
|
|
|
|
|
dp_result(51 downto 29) := mantissa(UNIT_BIT - 1 downto SP_LSB);
|
|
|
|
|
if single_prec = '0' then
|
|
|
|
|
result(28 downto 0) := mantissa(SP_LSB - 1 downto DP_LSB);
|
|
|
|
|
dp_result(28 downto 0) := mantissa(SP_LSB - 1 downto DP_LSB);
|
|
|
|
|
end if;
|
|
|
|
|
when INFINITY =>
|
|
|
|
|
result(62 downto 52) := "11111111111";
|
|
|
|
|
dp_result(62 downto 52) := "11111111111";
|
|
|
|
|
when NAN =>
|
|
|
|
|
result(62 downto 52) := "11111111111";
|
|
|
|
|
result(51) := quieten_nan or mantissa(QNAN_BIT);
|
|
|
|
|
result(50 downto 29) := mantissa(QNAN_BIT - 1 downto SP_LSB);
|
|
|
|
|
dp_result(62 downto 52) := "11111111111";
|
|
|
|
|
dp_result(51) := quieten_nan or mantissa(QNAN_BIT);
|
|
|
|
|
dp_result(50 downto 29) := mantissa(QNAN_BIT - 1 downto SP_LSB);
|
|
|
|
|
if single_prec = '0' then
|
|
|
|
|
result(28 downto 0) := mantissa(SP_LSB - 1 downto DP_LSB);
|
|
|
|
|
dp_result(28 downto 0) := mantissa(SP_LSB - 1 downto DP_LSB);
|
|
|
|
|
end if;
|
|
|
|
|
end case;
|
|
|
|
|
return result;
|
|
|
|
|
return dp_result;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
-- Determine whether to increment when rounding
|
|
|
|
|