|
|
|
@ -389,7 +389,7 @@ architecture behaviour of fpu is
@@ -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
@@ -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
@@ -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), |
|
|
|
|
UNIT_BIT - 52)); |
|
|
|
|
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 |
|
|
|
|