mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-14 15:34:56 +00:00
FPU: Provide a separate path for transferring A/B/C to R
The timing path from r.a.class to result showed up as a critical path on the Artix-7, apparently because of transfers of A, B or C to R in special cases (e.g. NaN inputs) and the fsel instruction. To alleviate this, we provide a path via the miscellaneous value multiplexer from A, B and C to R, selected via opsel_R = RES_MISC and misc_sel = 111. A new selector opsel_sel selects which of A, B or C to transfer, using the same encoding as opsel_a. This new selector is now also used for the result class when rcls_op = RCLS_SEL and for the result sign when rsgn_op = RSGN_SEL. This reduces the number of things that opsel_a depends on and eases timing in the main adder path. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
37
fpu.vhdl
37
fpu.vhdl
@@ -201,6 +201,7 @@ architecture behaviour of fpu is
|
||||
signal opsel_aneg : std_ulogic;
|
||||
signal opsel_aabs : std_ulogic;
|
||||
signal opsel_mask : std_ulogic;
|
||||
signal opsel_sel : std_ulogic_vector(2 downto 0);
|
||||
signal in_a : std_ulogic_vector(63 downto 0);
|
||||
signal in_b : std_ulogic_vector(63 downto 0);
|
||||
signal result : std_ulogic_vector(63 downto 0);
|
||||
@@ -1320,6 +1321,7 @@ begin
|
||||
opsel_r <= RES_SUM;
|
||||
opsel_s <= S_ZERO;
|
||||
misc_sel <= "000";
|
||||
opsel_sel <= AIN_ZERO;
|
||||
fpscr_mask := (others => '1');
|
||||
cr_op := CROP_NONE;
|
||||
update_fx := '0';
|
||||
@@ -1566,8 +1568,9 @@ begin
|
||||
v.instr_done := '1';
|
||||
|
||||
when DO_FMR =>
|
||||
opsel_a <= AIN_B;
|
||||
opsel_b <= BIN_ZERO;
|
||||
opsel_r <= RES_MISC;
|
||||
misc_sel <= "111";
|
||||
opsel_sel <= AIN_B;
|
||||
set_r := '1';
|
||||
rcls_op <= RCLS_SEL;
|
||||
re_sel2 <= REXP2_B;
|
||||
@@ -1652,6 +1655,7 @@ begin
|
||||
opsel_aabs <= '1';
|
||||
opsel_b <= BIN_ZERO;
|
||||
set_r := '1';
|
||||
opsel_sel <= AIN_B;
|
||||
rcls_op <= RCLS_SEL;
|
||||
re_con2 <= RECON2_UNIT;
|
||||
re_set_result <= '1';
|
||||
@@ -1710,13 +1714,14 @@ begin
|
||||
rsgn_op := RSGN_SEL;
|
||||
rcls_op <= RCLS_SEL;
|
||||
if r.a.class = ZERO or (r.a.negative = '0' and r.a.class /= NAN) then
|
||||
opsel_a <= AIN_C;
|
||||
opsel_sel <= AIN_C;
|
||||
re_sel2 <= REXP2_C;
|
||||
else
|
||||
opsel_a <= AIN_B;
|
||||
opsel_sel <= AIN_B;
|
||||
re_sel2 <= REXP2_B;
|
||||
end if;
|
||||
opsel_b <= BIN_ZERO;
|
||||
opsel_r <= RES_MISC;
|
||||
misc_sel <= "111";
|
||||
set_r := '1';
|
||||
re_set_result <= '1';
|
||||
arith_done := '1';
|
||||
@@ -3083,15 +3088,16 @@ begin
|
||||
-- state machine is in the DO_SPECIAL or DO_FSQRT state here
|
||||
arith_done := '1';
|
||||
set_r := '1';
|
||||
opsel_a <= scinfo.result_sel;
|
||||
opsel_b <= BIN_ZERO;
|
||||
opsel_r <= RES_MISC;
|
||||
opsel_sel <= scinfo.result_sel;
|
||||
if scinfo.qnan_result = '1' then
|
||||
opsel_r <= RES_MISC;
|
||||
if r.int_result = '0' then
|
||||
misc_sel <= "001";
|
||||
else
|
||||
misc_sel <= "110";
|
||||
end if;
|
||||
else
|
||||
misc_sel <= "111";
|
||||
end if;
|
||||
rsgn_op := scinfo.rsgn_op;
|
||||
v.result_class := scinfo.result_class;
|
||||
@@ -3107,7 +3113,7 @@ begin
|
||||
rsign := r.result_sign;
|
||||
case rsgn_op is
|
||||
when RSGN_SEL =>
|
||||
case opsel_a is
|
||||
case opsel_sel is
|
||||
when AIN_A =>
|
||||
rsign := r.a.negative;
|
||||
when AIN_B =>
|
||||
@@ -3128,7 +3134,7 @@ begin
|
||||
|
||||
case rcls_op is
|
||||
when RCLS_SEL =>
|
||||
case opsel_a is
|
||||
case opsel_sel is
|
||||
when AIN_A =>
|
||||
v.result_class := r.a.class;
|
||||
when AIN_B =>
|
||||
@@ -3366,6 +3372,7 @@ begin
|
||||
misc := r.a.mantissa(63 downto 32) & r.b.mantissa(63 downto 32);
|
||||
end if;
|
||||
when "101" =>
|
||||
-- LUT value
|
||||
misc := std_ulogic_vector(shift_left(resize(unsigned(inverse_est), 64),
|
||||
UNIT_BIT - 19));
|
||||
when "110" =>
|
||||
@@ -3382,6 +3389,16 @@ begin
|
||||
end if;
|
||||
end if;
|
||||
when others =>
|
||||
-- A, B or C, according to opsel_sel
|
||||
case opsel_sel is
|
||||
when AIN_A =>
|
||||
misc := r.a.mantissa;
|
||||
when AIN_B =>
|
||||
misc := r.b.mantissa;
|
||||
when AIN_C =>
|
||||
misc := r.c.mantissa;
|
||||
when others =>
|
||||
end case;
|
||||
end case;
|
||||
result <= misc;
|
||||
end case;
|
||||
|
||||
Reference in New Issue
Block a user