From c083b9507dafee86c5c0c14d6e1ef8c56a2b8a3f Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 31 Jul 2020 16:46:12 +1000 Subject: [PATCH] FPU: Implement ftdiv and ftsqrt Signed-off-by: Paul Mackerras --- decode1.vhdl | 2 ++ fpu.vhdl | 68 ++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/decode1.vhdl b/decode1.vhdl index e821469..bd7f0f3 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -441,6 +441,8 @@ architecture behaviour of decode1 is 2#000000000# => (FPU, OP_FPOP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- 0/0=fcmpu 2#000000001# => (FPU, OP_FPOP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- 1/0=fcmpo 2#000000010# => (FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- 2/0=mcrfs + 2#000000100# => (FPU, OP_FPOP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- 4/0=ftdiv + 2#000000101# => (FPU, OP_FPOP, NONE, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- 5/0=ftsqrt 2#011000001# => (FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 1/6=mtfsb1 2#011000010# => (FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 2/6=mtfsb0 2#011000100# => (FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 4/6=mtfsfi diff --git a/fpu.vhdl b/fpu.vhdl index 244454e..90670e9 100644 --- a/fpu.vhdl +++ b/fpu.vhdl @@ -37,7 +37,7 @@ architecture behaviour of fpu is type state_t is (IDLE, DO_MCRFS, DO_MTFSB, DO_MTFSFI, DO_MFFS, DO_MTFSF, - DO_FMR, DO_FMRG, DO_FCMP, + DO_FMR, DO_FMRG, DO_FCMP, DO_FTDIV, DO_FTSQRT, DO_FCFID, DO_FCTI, DO_FRSP, DO_FRI, DO_FADD, DO_FMUL, DO_FDIV, DO_FSQRT, @@ -51,6 +51,7 @@ architecture behaviour of fpu is DIV_2, DIV_3, DIV_4, DIV_5, DIV_6, FRE_1, RSQRT_1, + FTDIV_1, SQRT_1, SQRT_2, SQRT_3, SQRT_4, SQRT_5, SQRT_6, SQRT_7, SQRT_8, SQRT_9, SQRT_10, SQRT_11, SQRT_12, @@ -105,6 +106,7 @@ architecture behaviour of fpu is is_sqrt : std_ulogic; first : std_ulogic; count : unsigned(1 downto 0); + doing_ftdiv : std_ulogic_vector(1 downto 0); end record; type lookup_table is array(0 to 1023) of std_ulogic_vector(17 downto 0); @@ -642,6 +644,8 @@ begin v.is_multiply := '0'; v.is_sqrt := '0'; v.add_bsmall := '0'; + v.doing_ftdiv := "00"; + adec := decode_dp(e_in.fra, int_input); bdec := decode_dp(e_in.frb, int_input); cdec := decode_dp(e_in.frc, int_input); @@ -659,8 +663,16 @@ begin r_lo_nz <= or (r.r(30 downto 2)); if r.single_prec = '0' then - max_exp := to_signed(1023, EXP_BITS); - min_exp := to_signed(-1022, EXP_BITS); + if r.doing_ftdiv(1) = '0' then + max_exp := to_signed(1023, EXP_BITS); + else + max_exp := to_signed(1020, EXP_BITS); + end if; + if r.doing_ftdiv(0) = '0' then + min_exp := to_signed(-1022, EXP_BITS); + else + min_exp := to_signed(-1021, EXP_BITS); + end if; bias_exp := to_signed(1536, EXP_BITS); else max_exp := to_signed(127, EXP_BITS); @@ -728,7 +740,13 @@ begin if e_in.valid = '1' then case e_in.insn(5 downto 1) is when "00000" => - if e_in.insn(7) = '1' then + if e_in.insn(8) = '1' then + if e_in.insn(6) = '0' then + v.state := DO_FTDIV; + else + v.state := DO_FTSQRT; + end if; + elsif e_in.insn(7) = '1' then v.state := DO_MCRFS; else v.state := DO_FCMP; @@ -804,6 +822,38 @@ begin v.instr_done := '1'; v.state := IDLE; + when DO_FTDIV => + v.instr_done := '1'; + v.state := IDLE; + v.cr_result := "0000"; + if r.a.class = INFINITY or r.b.class = ZERO or r.b.class = INFINITY or + (r.b.class = FINITE and r.b.mantissa(53) = '0') then + v.cr_result(2) := '1'; + end if; + if r.a.class = NAN or r.a.class = INFINITY or + r.b.class = NAN or r.b.class = ZERO or r.b.class = INFINITY or + (r.a.class = FINITE and r.a.exponent <= to_signed(-970, EXP_BITS)) then + v.cr_result(1) := '1'; + else + v.doing_ftdiv := "11"; + v.first := '1'; + v.state := FTDIV_1; + v.instr_done := '0'; + end if; + + when DO_FTSQRT => + v.instr_done := '1'; + v.state := IDLE; + v.cr_result := "0000"; + if r.b.class = ZERO or r.b.class = INFINITY or + (r.b.class = FINITE and r.b.mantissa(53) = '0') then + v.cr_result(2) := '1'; + end if; + if r.b.class = NAN or r.b.class = INFINITY or r.b.class = ZERO + or r.b.negative = '1' or r.b.exponent <= to_signed(-970, EXP_BITS) then + v.cr_result(1) := '0'; + end if; + when DO_FCMP => -- fcmp[uo] v.instr_done := '1'; @@ -1587,6 +1637,16 @@ begin v.shift := to_signed(1, EXP_BITS); v.state := NORMALIZE; + when FTDIV_1 => + v.cr_result(1) := exp_tiny or exp_huge; + if exp_tiny = '1' or exp_huge = '1' or r.a.class = ZERO or r.first = '0' then + v.instr_done := '1'; + v.state := IDLE; + else + v.shift := r.a.exponent; + v.doing_ftdiv := "10"; + end if; + when RSQRT_1 => opsel_r <= RES_MISC; misc_sel <= "0111";