constant MULADD_A : std_ulogic_vector(1 downto 0) := "10";
constant MULADD_RS : std_ulogic_vector(1 downto 0) := "11";
+ -- control signals and values for exponent data path
+ constant REXP1_ZERO : std_ulogic_vector(1 downto 0) := "00";
+ constant REXP1_R : std_ulogic_vector(1 downto 0) := "01";
+ constant REXP1_A : std_ulogic_vector(1 downto 0) := "10";
+ constant REXP1_BHALF : std_ulogic_vector(1 downto 0) := "11";
+
+ constant REXP2_CON : std_ulogic_vector(1 downto 0) := "00";
+ constant REXP2_NE : std_ulogic_vector(1 downto 0) := "01";
+ constant REXP2_C : std_ulogic_vector(1 downto 0) := "10";
+ constant REXP2_B : std_ulogic_vector(1 downto 0) := "11";
+
+ constant RECON2_ZERO : std_ulogic_vector(1 downto 0) := "00";
+ constant RECON2_UNIT : std_ulogic_vector(1 downto 0) := "01";
+ constant RECON2_BIAS : std_ulogic_vector(1 downto 0) := "10";
+ constant RECON2_MAX : std_ulogic_vector(1 downto 0) := "11";
+
+ signal re_sel1 : std_ulogic_vector(1 downto 0);
+ signal re_sel2 : std_ulogic_vector(1 downto 0);
+ signal re_con2 : std_ulogic_vector(1 downto 0);
+ signal re_neg1 : std_ulogic;
+ signal re_neg2 : std_ulogic;
+ signal re_set_result : std_ulogic;
+
+ constant RSH1_ZERO : std_ulogic_vector(1 downto 0) := "00";
+ constant RSH1_B : std_ulogic_vector(1 downto 0) := "01";
+ constant RSH1_NE : std_ulogic_vector(1 downto 0) := "10";
+ constant RSH1_S : std_ulogic_vector(1 downto 0) := "11";
+
+ constant RSH2_CON : std_ulogic := '0';
+ constant RSH2_A : std_ulogic := '1';
+
+ constant RSCON2_ZERO : std_ulogic_vector(3 downto 0) := "0000";
+ constant RSCON2_1 : std_ulogic_vector(3 downto 0) := "0001";
+ constant RSCON2_UNIT_52 : std_ulogic_vector(3 downto 0) := "0010";
+ constant RSCON2_64_UNIT : std_ulogic_vector(3 downto 0) := "0011";
+ constant RSCON2_32 : std_ulogic_vector(3 downto 0) := "0100";
+ constant RSCON2_52 : std_ulogic_vector(3 downto 0) := "0101";
+ constant RSCON2_UNIT : std_ulogic_vector(3 downto 0) := "0110";
+ constant RSCON2_63 : std_ulogic_vector(3 downto 0) := "0111";
+ constant RSCON2_64 : std_ulogic_vector(3 downto 0) := "1000";
+ constant RSCON2_MINEXP : std_ulogic_vector(3 downto 0) := "1001";
+
+ signal rs_sel1 : std_ulogic_vector(1 downto 0);
+ signal rs_sel2 : std_ulogic;
+ signal rs_con2 : std_ulogic_vector(3 downto 0);
+ signal rs_neg1 : std_ulogic;
+ signal rs_neg2 : std_ulogic;
+ signal rs_norm : std_ulogic;
+
-- Inverse lookup table, indexed by the top 8 fraction bits
-- The first 256 entries are the reciprocal (1/x) lookup table,
-- and the remaining 768 entries are the reciprocal square root table.
variable new_exp : signed(EXP_BITS-1 downto 0);
variable exp_tiny : std_ulogic;
variable exp_huge : std_ulogic;
- variable renormalize : std_ulogic;
variable clz : std_ulogic_vector(5 downto 0);
variable set_x : std_ulogic;
variable mshift : signed(EXP_BITS-1 downto 0);
variable mult_mask : std_ulogic;
variable sign_bit : std_ulogic;
variable rnd_b32 : std_ulogic;
+ variable rexp_in1 : signed(EXP_BITS-1 downto 0);
+ variable rexp_in2 : signed(EXP_BITS-1 downto 0);
+ variable rexp_cin : std_ulogic;
+ variable rexp_sum : signed(EXP_BITS-1 downto 0);
+ variable rsh_in1 : signed(EXP_BITS-1 downto 0);
+ variable rsh_in2 : signed(EXP_BITS-1 downto 0);
variable int_result : std_ulogic;
variable illegal : std_ulogic;
begin
end if;
v.update_fprf := '0';
- v.shift := to_signed(0, EXP_BITS);
v.first := '0';
v.opsel_a := AIN_R;
opsel_ainv <= '0';
arith_done := '0';
invalid := '0';
zero_divide := '0';
- renormalize := '0';
set_x := '0';
qnan_result := '0';
set_a := '0';
rnd_b32 := '0';
int_result := '0';
illegal := '0';
+
+ re_sel1 <= REXP1_ZERO;
+ re_sel2 <= REXP2_CON;
+ re_con2 <= RECON2_ZERO;
+ re_neg1 <= '0';
+ re_neg2 <= '0';
+ re_set_result <= '0';
+ rs_sel1 <= RSH1_ZERO;
+ rs_sel2 <= RSH2_CON;
+ rs_con2 <= RSCON2_ZERO;
+ rs_neg1 <= '0';
+ rs_neg2 <= '0';
+ rs_norm <= '0';
+
case r.state is
when IDLE =>
v.use_a := '0';
-- r.opsel_a = AIN_B
v.instr_done := '1';
update_fx := '1';
- v.result_exp := r.b.exponent;
+ re_sel2 <= REXP2_B;
+ re_set_result <= '1';
if (r.a.class = NAN and r.a.mantissa(QNAN_BIT) = '0') or
(r.b.class = NAN and r.b.mantissa(QNAN_BIT) = '0') then
-- Signalling NAN
when DO_FMR =>
-- r.opsel_a = AIN_B
v.result_class := r.b.class;
- v.result_exp := r.b.exponent;
+ re_sel2 <= REXP2_B;
+ re_set_result <= '1';
v.quieten_nan := '0';
if r.insn(9) = '1' then
v.result_sign := '0'; -- fabs
-- r.opsel_a = AIN_B
v.result_class := r.b.class;
v.result_sign := r.b.negative;
- v.result_exp := r.b.exponent;
+ re_sel2 <= REXP2_B;
+ re_set_result <= '1';
+ -- set shift to exponent - 52
+ rs_sel1 <= RSH1_B;
+ rs_con2 <= RSCON2_52;
+ rs_neg2 <= '1';
v.fpscr(FPSCR_FR) := '0';
v.fpscr(FPSCR_FI) := '0';
if r.b.class = NAN and r.b.mantissa(QNAN_BIT) = '0' then
-- integer already, no rounding required
arith_done := '1';
else
- v.shift := r.b.exponent - to_signed(52, EXP_BITS);
v.state := FRI_1;
v.round_mode := '1' & r.insn(7 downto 6);
end if;
-- r.opsel_a = AIN_B, r.shift = 0
v.result_class := r.b.class;
v.result_sign := r.b.negative;
- v.result_exp := r.b.exponent;
+ re_sel2 <= REXP2_B;
+ re_set_result <= '1';
+ -- set shift to exponent - -126
+ rs_sel1 <= RSH1_B;
+ rs_con2 <= RSCON2_MINEXP;
+ rs_neg2 <= '1';
v.fpscr(FPSCR_FR) := '0';
v.fpscr(FPSCR_FI) := '0';
if r.b.class = NAN and r.b.mantissa(53) = '0' then
set_x := '1';
if r.b.class = FINITE then
if r.b.exponent < to_signed(-126, EXP_BITS) then
- v.shift := r.b.exponent - to_signed(-126, EXP_BITS);
v.state := ROUND_UFLOW;
elsif r.b.exponent > to_signed(127, EXP_BITS) then
v.state := ROUND_OFLOW;
-- r.opsel_a = AIN_B
v.result_class := r.b.class;
v.result_sign := r.b.negative;
- v.result_exp := r.b.exponent;
+ re_sel2 <= REXP2_B;
+ re_set_result <= '1';
+ rs_sel1 <= RSH1_B;
+ rs_neg2 <= '1';
v.fpscr(FPSCR_FR) := '0';
v.fpscr(FPSCR_FI) := '0';
if r.b.class = NAN and r.b.mantissa(53) = '0' then
end if;
int_result := '1';
+
case r.b.class is
when ZERO =>
arith_done := '1';
elsif r.b.exponent >= to_signed(52, EXP_BITS) then
-- integer already, no rounding required,
-- shift into final position
- v.shift := r.b.exponent - to_signed(UNIT_BIT, EXP_BITS);
+ -- set shift to exponent - 56
+ rs_con2 <= RSCON2_UNIT;
if r.insn(8) = '1' and r.b.negative = '1' then
v.state := INT_OFLOW;
else
v.state := INT_ISHIFT;
end if;
else
- v.shift := r.b.exponent - to_signed(52, EXP_BITS);
+ -- set shift to exponent - 52
+ rs_con2 <= RSCON2_52;
v.state := INT_SHIFT;
end if;
when INFINITY | NAN =>
v.result_sign := '1';
end if;
v.result_class := r.b.class;
- v.result_exp := to_signed(UNIT_BIT, EXP_BITS);
+ re_con2 <= RECON2_UNIT;
+ re_set_result <= '1';
v.fpscr(FPSCR_FR) := '0';
v.fpscr(FPSCR_FI) := '0';
if r.b.class = ZERO then
-- r.opsel_a = AIN_A
v.result_sign := r.a.negative;
v.result_class := r.a.class;
- v.result_exp := r.a.exponent;
+ re_sel1 <= REXP1_A;
+ re_set_result <= '1';
+ -- set shift to a.exp - b.exp
+ rs_sel1 <= RSH1_B;
+ rs_neg1 <= '1';
+ rs_sel2 <= RSH2_A;
v.fpscr(FPSCR_FR) := '0';
v.fpscr(FPSCR_FI) := '0';
v.use_a := '1';
v.add_bsmall := r.exp_cmp;
v.opsel_a := AIN_B;
if r.exp_cmp = '0' then
- v.shift := r.a.exponent - r.b.exponent;
v.result_sign := r.b.negative xnor r.insn(1);
if r.a.exponent = r.b.exponent then
v.state := ADD_2;
v.fpscr(FPSCR_FI) := '0';
v.use_a := '1';
v.use_c := '1';
+ re_sel1 <= REXP1_A;
+ re_sel2 <= REXP2_C;
+ re_set_result <= '1';
if r.a.class = FINITE and r.c.class = FINITE then
- v.result_exp := r.a.exponent + r.c.exponent;
-- Renormalize denorm operands
if r.a.mantissa(UNIT_BIT) = '0' then
v.state := RENORM_A;
v.use_a := '1';
v.use_b := '1';
v.result_sign := r.a.negative xor r.b.negative;
- v.result_exp := r.a.exponent - r.b.exponent;
+ re_sel1 <= REXP1_A;
+ re_sel2 <= REXP2_B;
+ re_neg2 <= '1';
+ re_set_result <= '1';
v.count := "00";
if r.a.class = FINITE and r.b.class = FINITE then
-- Renormalize denorm operands
v.fpscr(FPSCR_FR) := '0';
v.fpscr(FPSCR_FI) := '0';
v.use_b := '1';
+ re_sel2 <= REXP2_B;
+ re_set_result <= '1';
case r.b.class is
when FINITE =>
- v.result_exp := r.b.exponent;
if r.b.negative = '1' then
v.fpscr(FPSCR_VXSQRT) := '1';
qnan_result := '1';
elsif r.b.exponent(0) = '0' then
v.state := SQRT_1;
else
- v.shift := to_signed(1, EXP_BITS);
+ -- set shift to 1
+ rs_con2 <= RSCON2_1;
v.state := RENORM_B2;
end if;
when NAN =>
v.fpscr(FPSCR_FR) := '0';
v.fpscr(FPSCR_FI) := '0';
v.use_b := '1';
- v.result_exp := r.b.exponent;
+ re_sel2 <= REXP2_B;
+ re_set_result <= '1';
case r.b.class is
when FINITE =>
if r.b.mantissa(UNIT_BIT) = '0' then
v.fpscr(FPSCR_FR) := '0';
v.fpscr(FPSCR_FI) := '0';
v.use_b := '1';
- v.shift := to_signed(1, EXP_BITS);
+ re_sel2 <= REXP2_B;
+ re_set_result <= '1';
+ -- set shift to 1
+ rs_con2 <= RSCON2_1;
case r.b.class is
when FINITE =>
- v.result_exp := r.b.exponent;
if r.b.negative = '1' then
v.fpscr(FPSCR_VXSQRT) := '1';
qnan_result := '1';
-- else AIN_B
v.result_sign := r.a.negative;
v.result_class := r.a.class;
- v.result_exp := r.a.exponent + r.c.exponent;
+ -- put a.exp + c.exp into result_exp
+ re_sel1 <= REXP1_A;
+ re_sel2 <= REXP2_C;
+ re_set_result <= '1';
+ -- put b.exp into shift
+ rs_sel1 <= RSH1_B;
v.fpscr(FPSCR_FR) := '0';
v.fpscr(FPSCR_FI) := '0';
v.use_a := '1';
-- addend is bigger, do multiply first
v.result_sign := not (r.b.negative xor r.insn(1) xor r.insn(2));
f_to_multiply.valid <= '1';
+ v.first := '1';
v.state := FMADD_0;
else
-- product is bigger, shift B first
end if;
when RENORM_A =>
- renormalize := '1';
+ rs_norm <= '1';
v.state := RENORM_A2;
if r.insn(4) = '1' then
v.opsel_a := AIN_C;
when RENORM_A2 =>
-- r.opsel_a = AIN_C for fmul/fmadd, AIN_B for fdiv
set_a := '1';
- v.result_exp := new_exp;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
if r.insn(4) = '1' then
if r.c.mantissa(UNIT_BIT) = '1' then
if r.insn(3) = '0' or r.b.class = ZERO then
end if;
when RENORM_B =>
- renormalize := '1';
+ rs_norm <= '1';
renorm_sqrt := r.is_sqrt;
v.state := RENORM_B2;
when RENORM_B2 =>
set_b := '1';
- v.result_exp := new_exp;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
v.opsel_a := AIN_B;
v.state := LOOKUP;
when RENORM_C =>
- renormalize := '1';
+ rs_norm <= '1';
v.state := RENORM_C2;
when RENORM_C2 =>
set_c := '1';
- v.result_exp := new_exp;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
if r.insn(3) = '0' or r.b.class = ZERO then
v.first := '1';
v.state := MULT_1;
when ADD_1 =>
-- transferring B to R
- v.shift := r.b.exponent - r.a.exponent;
- v.result_exp := r.b.exponent;
+ re_sel2 <= REXP2_B;
+ re_set_result <= '1';
+ -- set shift to b.exp - a.exp
+ rs_sel1 <= RSH1_B;
+ rs_sel2 <= RSH2_A;
+ rs_neg2 <= '1';
v.longmask := '0';
v.state := ADD_SHIFT;
when ADD_SHIFT =>
-- r.shift = - exponent difference, r.longmask = 0
opsel_r <= RES_SHIFT;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
v.x := s_nz;
set_x := '1';
v.longmask := r.single_prec;
opsel_b <= BIN_R;
opsel_binv <= r.is_subtract;
carry_in <= r.is_subtract and not r.x;
- v.shift := to_signed(-1, EXP_BITS);
+ -- set shift to -1
+ rs_con2 <= RSCON2_1;
+ rs_neg2 <= '1';
v.state := ADD_3;
when ADD_3 =>
-- check for overflow or negative result (can't get both)
-- r.shift = -1
+ re_sel2 <= REXP2_NE;
if r.r(63) = '1' then
-- result is opposite sign to expected
v.result_sign := not r.result_sign;
elsif r.r(UNIT_BIT + 1) = '1' then
-- sum overflowed, shift right
opsel_r <= RES_SHIFT;
+ re_set_result <= '1';
set_x := '1';
if exp_huge = '1' then
v.state := ROUND_OFLOW;
end if;
arith_done := '1';
else
- renormalize := '1';
+ rs_norm <= '1';
v.state := NORMALIZE;
end if;
end if;
when FMADD_0 =>
+ -- r.shift is b.exp, so new_exp is a.exp + c.exp - b.exp
+ -- (first time through; subsequent times we preserve v.shift)
-- Addend is bigger here
- v.result_sign := not (r.b.negative xor r.insn(1) xor r.insn(2));
+ -- set shift to a.exp + c.exp - b.exp
-- note v.shift is at most -2 here
- v.shift := r.result_exp - r.b.exponent;
+ if r.first = '1' then
+ rs_sel1 <= RSH1_NE;
+ else
+ rs_sel1 <= RSH1_S;
+ end if;
opsel_r <= RES_MULT;
opsel_s <= S_MULT;
set_s := '1';
- f_to_multiply.valid <= r.first;
if multiply_to_f.valid = '1' then
v.longmask := '0';
v.state := ADD_SHIFT;
end if;
when FMADD_1 =>
+ -- shift is b.exp, so new_exp is a.exp + c.exp - b.exp
-- product is bigger here
-- shift B right and use it as the addend to the multiplier
- v.shift := r.b.exponent - r.result_exp + to_signed(64, EXP_BITS);
-- for subtract, multiplier does B - A * C
v.result_sign := r.a.negative xor r.c.negative xor r.insn(2) xor r.is_subtract;
- v.result_exp := r.b.exponent;
+ re_sel2 <= REXP2_B;
+ re_set_result <= '1';
+ -- set shift to b.exp - result_exp + 64
+ rs_sel1 <= RSH1_NE;
+ rs_neg1 <= '1';
+ rs_con2 <= RSCON2_64;
v.state := FMADD_2;
when FMADD_2 =>
-- r.shift = addend exp - product exp + 64, r.r = r.b.mantissa
set_s := '1';
opsel_s <= S_SHIFT;
- v.shift := r.shift - to_signed(64, EXP_BITS);
+ -- set shift to r.shift - 64
+ rs_sel1 <= RSH1_S;
+ rs_con2 <= RSCON2_64;
+ rs_neg2 <= '1';
v.state := FMADD_3;
when FMADD_3 =>
-- r.shift = addend exp - product exp
opsel_r <= RES_SHIFT;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
v.first := '1';
v.state := FMADD_4;
opsel_s <= S_NEG;
set_s := '1';
end if;
- v.shift := to_signed(UNIT_BIT, EXP_BITS);
+ -- set shift to UNIT_BIT
+ rs_con2 <= RSCON2_UNIT;
v.state := FMADD_6;
when FMADD_6 =>
-- r.shift = UNIT_BIT (or 0, but only if r is now nonzero)
+ re_sel2 <= REXP2_NE;
+ rs_norm <= '1';
if (r.r(UNIT_BIT + 2) or r_hi_nz or r_lo_nz or (or (r.r(DP_LSB - 1 downto 0)))) = '0' then
if s_nz = '0' then
-- must be a subtraction, and r.x must be zero
-- R is all zeroes but there are non-zero bits in S
-- so shift them into R and set S to 0
opsel_r <= RES_SHIFT;
+ re_set_result <= '1';
set_s := '1';
- -- stay in state FMADD_6
+ v.state := FINISH;
end if;
elsif r.r(UNIT_BIT + 2 downto UNIT_BIT) = "001" then
v.state := FINISH;
else
- renormalize := '1';
v.state := NORMALIZE;
end if;
v.state := FINISH;
when FRE_1 =>
- v.result_exp := - r.result_exp;
+ re_sel1 <= REXP1_R;
+ re_neg1 <= '1';
+ re_set_result <= '1';
opsel_r <= RES_MISC;
misc_sel <= "0111";
- v.shift := to_signed(1, EXP_BITS);
+ -- set shift to 1
+ rs_con2 <= RSCON2_1;
v.state := NORMALIZE;
when FTDIV_1 =>
v.cr_result(1) := exp_tiny or exp_huge;
+ -- set shift to a.exp
+ rs_sel2 <= RSH2_A;
if exp_tiny = '1' or exp_huge = '1' or r.a.class = ZERO or r.first = '0' then
v.instr_done := '1';
else
- v.shift := r.a.exponent;
v.doing_ftdiv := "10";
end if;
when RSQRT_1 =>
opsel_r <= RES_MISC;
misc_sel <= "0111";
- sqrt_exp := r.b.exponent(EXP_BITS-1) & r.b.exponent(EXP_BITS-1 downto 1);
- v.result_exp := - sqrt_exp;
- v.shift := to_signed(1, EXP_BITS);
+ re_sel1 <= REXP1_BHALF;
+ re_neg1 <= '1';
+ re_set_result <= '1';
+ -- set shift to 1
+ rs_con2 <= RSCON2_1;
v.state := NORMALIZE;
when SQRT_1 =>
msel_1 <= MUL1_B;
msel_2 <= MUL2_LUT;
f_to_multiply.valid <= '1';
- v.shift := to_signed(-1, EXP_BITS);
+ -- set shift to -1
+ rs_con2 <= RSCON2_1;
+ rs_neg2 <= '1';
v.count := "00";
v.state := SQRT_2;
-- not expecting multiplier result yet
-- r.shift = -1
opsel_r <= RES_SHIFT;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
v.first := '1';
v.state := SQRT_3;
when SQRT_10 =>
-- Add the bottom 8 bits of P, sign-extended, onto R.
opsel_b <= BIN_PS8;
- sqrt_exp := r.b.exponent(EXP_BITS-1) & r.b.exponent(EXP_BITS-1 downto 1);
- v.result_exp := sqrt_exp;
- v.shift := to_signed(1, EXP_BITS);
+ re_sel1 <= REXP1_BHALF;
+ re_set_result <= '1';
+ -- set shift to 1
+ rs_con2 <= RSCON2_1;
v.first := '1';
v.state := SQRT_11;
when INT_SHIFT =>
-- r.shift = b.exponent - 52
opsel_r <= RES_SHIFT;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
set_x := '1';
v.state := INT_ROUND;
- v.shift := to_signed(52 - UNIT_BIT, EXP_BITS);
+ -- set shift to -4 (== 52 - UNIT_BIT)
+ rs_con2 <= RSCON2_UNIT_52;
+ rs_neg2 <= '1';
when INT_ROUND =>
-- r.shift = -4 (== 52 - UNIT_BIT)
opsel_r <= RES_SHIFT;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
round := fp_rounding(r.r, r.x, '0', r.round_mode, r.result_sign);
v.fpscr(FPSCR_FR downto FPSCR_FI) := round;
-- Check for negative values that don't round to 0 for fcti*u*
when INT_ISHIFT =>
-- r.shift = b.exponent - UNIT_BIT;
opsel_r <= RES_SHIFT;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
v.state := INT_FINAL;
when INT_FINAL =>
when FRI_1 =>
-- r.shift = b.exponent - 52
opsel_r <= RES_SHIFT;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
set_x := '1';
v.state := ROUNDING;
if r.is_multiply = '1' and px_nz = '1' then
v.x := '1';
end if;
+ -- set shift to new_exp - min_exp (N.B. rs_norm overrides this)
+ rs_sel1 <= RSH1_NE;
+ rs_con2 <= RSCON2_MINEXP;
+ rs_neg2 <= '1';
if r.r(63 downto UNIT_BIT) /= std_ulogic_vector(to_unsigned(1, 64 - UNIT_BIT)) then
- renormalize := '1';
+ rs_norm <= '1';
v.state := NORMALIZE;
else
set_x := '1';
if exp_tiny = '1' then
- v.shift := new_exp - min_exp;
v.state := ROUND_UFLOW;
elsif exp_huge = '1' then
v.state := ROUND_OFLOW;
when NORMALIZE =>
-- Shift so we have 9 leading zeroes (we know R is non-zero)
- -- r.shift = clz(r.r) - 9
+ -- r.shift = clz(r.r) - 7
opsel_r <= RES_SHIFT;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
+ -- set shift to new_exp - min_exp
+ rs_sel1 <= RSH1_NE;
+ rs_con2 <= RSCON2_MINEXP;
+ rs_neg2 <= '1';
set_x := '1';
if exp_tiny = '1' then
- v.shift := new_exp - min_exp;
v.state := ROUND_UFLOW;
elsif exp_huge = '1' then
v.state := ROUND_OFLOW;
-- disabled underflow exception case
-- have to denormalize before rounding
opsel_r <= RES_SHIFT;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
set_x := '1';
v.state := ROUNDING;
else
-- enabled underflow exception case
-- if denormalized, have to normalize before rounding
v.fpscr(FPSCR_UX) := '1';
- v.result_exp := r.result_exp + bias_exp;
+ re_sel1 <= REXP1_R;
+ re_con2 <= RECON2_BIAS;
+ re_set_result <= '1';
if r.r(UNIT_BIT) = '0' then
- renormalize := '1';
+ rs_norm <= '1';
v.state := NORMALIZE;
else
v.state := ROUNDING;
v.fpscr(FPSCR_FR) := '0';
end if;
-- construct largest representable number
- v.result_exp := max_exp;
+ re_con2 <= RECON2_MAX;
+ re_set_result <= '1';
opsel_r <= RES_MISC;
misc_sel <= "001" & r.single_prec;
arith_done := '1';
else
-- enabled overflow exception
- v.result_exp := r.result_exp - bias_exp;
+ re_sel1 <= REXP1_R;
+ re_con2 <= RECON2_BIAS;
+ re_neg2 <= '1';
+ re_set_result <= '1';
v.state := ROUNDING;
end if;
if round(1) = '1' then
-- increment the LSB for the precision
opsel_b <= BIN_RND;
- v.shift := to_signed(-1, EXP_BITS);
+ -- set shift to -1
+ rs_con2 <= RSCON2_1;
+ rs_neg2 <= '1';
v.state := ROUNDING_2;
else
if r.r(UNIT_BIT) = '0' then
-- result after masking could be zero, or could be a
-- denormalized result that needs to be renormalized
- renormalize := '1';
+ rs_norm <= '1';
v.state := ROUNDING_3;
else
arith_done := '1';
-- Check for overflow during rounding
-- r.shift = -1
v.x := '0';
+ re_sel2 <= REXP2_NE;
if r.r(UNIT_BIT + 1) = '1' then
opsel_r <= RES_SHIFT;
+ re_set_result <= '1';
if exp_huge = '1' then
v.state := ROUND_OFLOW;
else
end if;
elsif r.r(UNIT_BIT) = '0' then
-- Do CLZ so we can renormalize the result
- renormalize := '1';
+ rs_norm <= '1';
v.state := ROUNDING_3;
else
arith_done := '1';
when ROUNDING_3 =>
-- r.shift = clz(r.r) - 9
mant_nz := r_hi_nz or (r_lo_nz and not r.single_prec);
+ re_sel2 <= REXP2_NE;
+ -- set shift to new_exp - min_exp (== -1022)
+ rs_sel1 <= RSH1_NE;
+ rs_con2 <= RSCON2_MINEXP;
+ rs_neg2 <= '1';
if mant_nz = '0' then
v.result_class := ZERO;
if r.is_subtract = '1' then
else
-- Renormalize result after rounding
opsel_r <= RES_SHIFT;
+ re_set_result <= '1';
v.denorm := exp_tiny;
- v.shift := new_exp - to_signed(-1022, EXP_BITS);
if new_exp < to_signed(-1022, EXP_BITS) then
v.state := DENORM;
else
when DENORM =>
-- r.shift = result_exp - -1022
opsel_r <= RES_SHIFT;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
arith_done := '1';
when NAN_RESULT =>
case r.opsel_a is
when AIN_B =>
v.result_sign := r.b.negative xor r.negate;
- v.result_exp := r.b.exponent;
+ re_sel2 <= REXP2_B;
v.result_class := r.b.class;
when AIN_C =>
v.result_sign := r.c.negative xor r.negate;
- v.result_exp := r.c.exponent;
+ re_sel2 <= REXP2_C;
v.result_class := r.c.class;
when others =>
v.result_sign := r.a.negative xor r.negate;
- v.result_exp := r.a.exponent;
+ re_sel1 <= REXP1_A;
v.result_class := r.a.class;
end case;
+ re_set_result <= '1';
arith_done := '1';
when DO_IDIVMOD =>
carry_in <= '1';
end if;
v.result_class := FINITE;
- v.result_exp := to_signed(UNIT_BIT, EXP_BITS);
+ re_con2 <= RECON2_UNIT;
+ re_set_result <= '1';
v.state := IDIV_NORMB;
end if;
when IDIV_NORMB =>
-- do count-leading-zeroes on B (now in R)
- renormalize := '1';
+ rs_norm <= '1';
-- save the original value of B or |B| in C
set_c := '1';
v.state := IDIV_NORMB2;
-- get B into the range [1, 2) in 8.56 format
set_x := '1'; -- record if any 1 bits shifted out
opsel_r <= RES_SHIFT;
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
v.state := IDIV_NORMB3;
when IDIV_NORMB3 =>
-- add the X bit onto R to round up B
opsel_ainv <= '1';
carry_in <= '1';
end if;
- v.result_exp := to_signed(UNIT_BIT, EXP_BITS);
+ re_con2 <= RECON2_UNIT;
+ re_set_result <= '1';
v.opsel_a := AIN_C;
v.state := IDIV_CLZA2;
when IDIV_CLZA2 =>
-- r.opsel_a = AIN_C
- renormalize := '1';
+ rs_norm <= '1';
-- write the dividend back into A in case we negated it
set_a_mant := '1';
-- while doing the count-leading-zeroes on A,
v.state := IDIV_CLZA3;
when IDIV_CLZA3 =>
-- save the exponent of A (but don't overwrite the mantissa)
- v.a.exponent := new_exp;
+ set_a_exp := '1';
+ re_sel2 <= REXP2_NE;
+ re_set_result <= '1';
v.div_close := '0';
if new_exp = r.b.exponent then
v.div_close := '1';
end if;
when IDIV_NR0 =>
-- reduce number of Newton-Raphson iterations for small A
- if r.divext = '1' or new_exp >= to_signed(32, EXP_BITS) then
+ if r.divext = '1' or r.result_exp >= to_signed(32, EXP_BITS) then
v.count := "00";
- elsif new_exp >= to_signed(16, EXP_BITS) then
+ elsif r.result_exp >= to_signed(16, EXP_BITS) then
v.count := "01";
else
v.count := "10";
f_to_multiply.valid <= r.first;
pshift := '1';
v.opsel_a := AIN_A;
- v.shift := to_signed(64, EXP_BITS);
+ -- set shift to 64
+ rs_con2 <= RSCON2_64;
-- Get 0.5 into R in case the inverse estimate turns out to be
-- less than 0.5, in which case we want to use 0.5, to avoid
-- infinite loops in some cases.
opsel_r <= RES_MISC;
misc_sel <= "0001";
v.opsel_a := AIN_A;
- v.shift := to_signed(64, EXP_BITS);
+ -- set shift to 64
+ rs_con2 <= RSCON2_64;
v.state := IDIV_DODIV;
when IDIV_DODIV =>
-- r.opsel_a = AIN_A
-- put that into B, which now holds the quotient
set_b_mant := '1';
if r.divext = '0' then
- v.shift := to_signed(-UNIT_BIT, EXP_BITS);
+ -- set shift to -56
+ rs_con2 <= RSCON2_UNIT;
+ rs_neg2 <= '1';
v.first := '1';
v.state := IDIV_DIV;
elsif r.single_prec = '1' then
-- divwe[u][o], shift A left 32 bits
- v.shift := to_signed(32, EXP_BITS);
+ -- set shift to 32
+ rs_con2 <= RSCON2_32;
v.state := IDIV_SH32;
elsif r.div_close = '0' then
- v.shift := to_signed(64 - UNIT_BIT, EXP_BITS);
+ -- set shift to 64 - UNIT_BIT (== 8)
+ rs_con2 <= RSCON2_64_UNIT;
v.state := IDIV_EXTDIV;
else
-- handle top bit of quotient specially
when IDIV_SH32 =>
-- r.shift = 32, R contains the dividend
opsel_r <= RES_SHIFT;
- v.shift := to_signed(-UNIT_BIT, EXP_BITS);
+ -- set shift to -UNIT_BIT (== -56)
+ rs_con2 <= RSCON2_UNIT;
+ rs_neg2 <= '1';
v.first := '1';
v.state := IDIV_DIV;
when IDIV_DIV =>
f_to_multiply.valid <= r.first;
pshift := '1';
opsel_r <= RES_MULT;
- v.shift := - r.b.exponent;
+ -- set shift to - b.exp
+ rs_sel1 <= RSH1_B;
+ rs_neg1 <= '1';
if multiply_to_f.valid = '1' then
v.state := IDIV_DIV2;
end if;
if r.divmod = '0' then
v.opsel_a := AIN_B;
end if;
- v.shift := to_signed(UNIT_BIT, EXP_BITS);
+ -- set shift to UNIT_BIT (== 56)
+ rs_con2 <= RSCON2_UNIT;
if pcmpc_lt = '1' or pcmpc_eq = '1' then
if r.divmod = '0' then
v.state := IDIV_DIVADJ;
when IDIV_DIV5 =>
pshift := '1';
opsel_r <= RES_MULT;
- v.shift := - r.b.exponent;
+ -- set shift to - b.exp
+ rs_sel1 <= RSH1_B;
+ rs_neg1 <= '1';
if multiply_to_f.valid = '1' then
v.state := IDIV_DIV6;
end if;
if r.divmod = '0' then
v.opsel_a := AIN_B;
end if;
- v.shift := to_signed(UNIT_BIT, EXP_BITS);
+ -- set shift to UNIT_BIT (== 56)
+ rs_con2 <= RSCON2_UNIT;
if r.divmod = '0' then
v.state := IDIV_DIVADJ;
elsif pcmpc_eq = '1' then
end if;
when IDIV_EXT_TBH =>
-- r.opsel_a = AIN_C; get divisor into R and prepare to shift left
- v.shift := to_signed(63, EXP_BITS) - r.b.exponent;
+ -- set shift to 63 - b.exp
+ rs_sel1 <= RSH1_B;
+ rs_neg1 <= '1';
+ rs_con2 <= RSCON2_63;
v.opsel_a := AIN_A;
v.state := IDIV_EXT_TBH2;
when IDIV_EXT_TBH2 =>
-- r.opsel_a = AIN_A; divisor is in R
-- r.shift = 63 - b.exponent; shift and put into B
set_b_mant := '1';
- v.shift := to_signed(64 - UNIT_BIT, EXP_BITS);
+ -- set shift to 64 - UNIT_BIT (== 8)
+ rs_con2 <= RSCON2_64_UNIT;
v.state := IDIV_EXT_TBH3;
when IDIV_EXT_TBH3 =>
-- Dividing (A << 64) by C
-- Put A in the top 64 bits of Ahi/A/Alo
set_a_hi := '1';
set_a_mant := '1';
- v.shift := to_signed(64, EXP_BITS) - r.b.exponent;
+ -- set shift to 64 - b.exp
+ rs_sel1 <= RSH1_B;
+ rs_neg1 <= '1';
+ rs_con2 <= RSCON2_64;
v.state := IDIV_EXT_TBH4;
when IDIV_EXT_TBH4 =>
-- dividend (A) is in R
opsel_r <= RES_SHIFT;
-- top bit of A gets lost in the shift, so handle it specially
v.opsel_a := AIN_B;
- v.shift := to_signed(63, EXP_BITS);
+ -- set shift to 63
+ rs_con2 <= RSCON2_63;
v.state := IDIV_EXT_TBH5;
when IDIV_EXT_TBH5 =>
-- r.opsel_a = AIN_B, r.shift = 63
-- Put A in the top 64 bits of Ahi/A/Alo
set_a_hi := '1';
set_a_mant := '1';
- v.shift := to_signed(64, EXP_BITS) - r.b.exponent;
+ -- set shift to 64 - b.exp
+ rs_sel1 <= RSH1_B;
+ rs_neg1 <= '1';
+ rs_con2 <= RSCON2_64;
v.state := IDIV_EXTDIV1;
when IDIV_EXTDIV1 =>
-- dividend is in R
opsel_r <= RES_MULT;
opsel_s <= S_MULT;
set_s := '1';
- v.shift := to_signed(UNIT_BIT, EXP_BITS) - r.b.exponent;
+ -- set shift to UNIT_BIT - b.exp
+ rs_sel1 <= RSH1_B;
+ rs_neg1 <= '1';
+ rs_con2 <= RSCON2_UNIT;
if multiply_to_f.valid = '1' then
v.state := IDIV_EXTDIV5;
end if;
v.c.mantissa := shift_res;
end if;
- if opsel_r = RES_SHIFT then
- v.result_exp := new_exp;
+ -- exponent data path
+ case re_sel1 is
+ when REXP1_R =>
+ rexp_in1 := r.result_exp;
+ when REXP1_A =>
+ rexp_in1 := r.a.exponent;
+ when REXP1_BHALF =>
+ rexp_in1 := r.b.exponent(EXP_BITS-1) & r.b.exponent(EXP_BITS-1 downto 1);
+ when others =>
+ rexp_in1 := to_signed(0, EXP_BITS);
+ end case;
+ if re_neg1 = '1' then
+ rexp_in1 := not rexp_in1;
end if;
-
- if renormalize = '1' then
+ case re_sel2 is
+ when REXP2_NE =>
+ rexp_in2 := new_exp;
+ when REXP2_C =>
+ rexp_in2 := r.c.exponent;
+ when REXP2_B =>
+ rexp_in2 := r.b.exponent;
+ when others =>
+ case re_con2 is
+ when RECON2_UNIT =>
+ rexp_in2 := to_signed(UNIT_BIT, EXP_BITS);
+ when RECON2_MAX =>
+ rexp_in2 := max_exp;
+ when RECON2_BIAS =>
+ rexp_in2 := bias_exp;
+ when others =>
+ rexp_in2 := to_signed(0, EXP_BITS);
+ end case;
+ end case;
+ if re_neg2 = '1' then
+ rexp_in2 := not rexp_in2;
+ end if;
+ rexp_cin := re_neg1 or re_neg2;
+ rexp_sum := rexp_in1 + rexp_in2 + rexp_cin;
+ if re_set_result = '1' then
+ v.result_exp := rexp_sum;
+ end if;
+ case rs_sel1 is
+ when RSH1_B =>
+ rsh_in1 := r.b.exponent;
+ when RSH1_NE =>
+ rsh_in1 := new_exp;
+ when RSH1_S =>
+ rsh_in1 := r.shift;
+ when others =>
+ rsh_in1 := to_signed(0, EXP_BITS);
+ end case;
+ if rs_neg1 = '1' then
+ rsh_in1 := not rsh_in1;
+ end if;
+ case rs_sel2 is
+ when RSH2_A =>
+ rsh_in2 := r.a.exponent;
+ when others =>
+ case rs_con2 is
+ when RSCON2_1 =>
+ rsh_in2 := to_signed(1, EXP_BITS);
+ when RSCON2_UNIT_52 =>
+ rsh_in2 := to_signed(UNIT_BIT - 52, EXP_BITS);
+ when RSCON2_64_UNIT =>
+ rsh_in2 := to_signed(64 - UNIT_BIT, EXP_BITS);
+ when RSCON2_32 =>
+ rsh_in2 := to_signed(32, EXP_BITS);
+ when RSCON2_52 =>
+ rsh_in2 := to_signed(52, EXP_BITS);
+ when RSCON2_UNIT =>
+ rsh_in2 := to_signed(UNIT_BIT, EXP_BITS);
+ when RSCON2_63 =>
+ rsh_in2 := to_signed(63, EXP_BITS);
+ when RSCON2_64 =>
+ rsh_in2 := to_signed(64, EXP_BITS);
+ when RSCON2_MINEXP =>
+ rsh_in2 := min_exp;
+ when others =>
+ rsh_in2 := to_signed(0, EXP_BITS);
+ end case;
+ end case;
+ if rs_neg2 = '1' then
+ rsh_in2 := not rsh_in2;
+ end if;
+ if rs_norm = '1' then
clz := count_left_zeroes(r.r);
if renorm_sqrt = '1' then
-- make denormalized value end up with even exponent
clz(0) := '1';
end if;
+ -- do this as a separate dedicated 7-bit adder for timing reasons
v.shift := resize(signed('0' & clz) - (63 - UNIT_BIT), EXP_BITS);
+ else
+ v.shift := rsh_in1 + rsh_in2 + (rs_neg1 or rs_neg2);
end if;
if r.update_fprf = '1' then