Skip to content

Commit

Permalink
Merge pull request #425 from paulusmack/fixes
Browse files Browse the repository at this point in the history
Fixes to the FPU and the run_test script
  • Loading branch information
paulusmack authored Feb 7, 2024
2 parents fdcb6ec + 7b86bf8 commit af2d6e2
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 25 deletions.
57 changes: 33 additions & 24 deletions fpu.vhdl
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,7 @@ architecture behaviour of fpu is
oe : std_ulogic;
xerc : xer_common_t;
xerc_result : xer_common_t;
res_negate : std_ulogic;
res_subtract : std_ulogic;
res_rmode : std_ulogic_vector(2 downto 0);
res_sign : std_ulogic;
end record;

type lookup_table is array(0 to 1023) of std_ulogic_vector(17 downto 0);
Expand Down Expand Up @@ -609,20 +607,13 @@ architecture behaviour of fpu is

-- Construct a DP floating-point result from components
function pack_dp(negative: 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;
negate: std_ulogic; is_subtract: std_ulogic; round_mode: std_ulogic_vector)
mantissa: std_ulogic_vector; single_prec: std_ulogic; quieten_nan: std_ulogic)
return std_ulogic_vector is
variable dp_result : std_ulogic_vector(63 downto 0);
variable sign : std_ulogic;
begin
dp_result := (others => '0');
sign := negative;
case class is
when ZERO =>
if is_subtract = '1' then
-- set result sign depending on rounding mode
sign := round_mode(0) and round_mode(1);
end if;
when FINITE =>
if mantissa(UNIT_BIT) = '1' then
-- normalized number
Expand All @@ -642,7 +633,7 @@ architecture behaviour of fpu is
dp_result(28 downto 0) := mantissa(SP_LSB - 1 downto DP_LSB);
end if;
end case;
dp_result(63) := sign xor negate;
dp_result(63) := negative;
return dp_result;
end;

Expand Down Expand Up @@ -860,6 +851,7 @@ begin
variable opcbits : std_ulogic_vector(4 downto 0);
variable int_result : std_ulogic;
variable illegal : std_ulogic;
variable rsign : std_ulogic;
begin
v := r;
v.complete := '0';
Expand Down Expand Up @@ -1825,8 +1817,17 @@ begin

when RENORM_B2 =>
set_b := '1';
re_sel2 <= REXP2_NE;
re_set_result <= '1';
-- For fdiv, we need to increase result_exp by shift rather
-- than decreasing it as for fre/frsqrte and fsqrt.
-- We do that by negating r.shift in this cycle and then
-- setting result_exp to new_exp in the next cycle
if r.use_a = '1' then
rs_sel1 <= RSH1_S;
rs_neg1 <= '1';
else
re_sel2 <= REXP2_NE;
re_set_result <= '1';
end if;
v.opsel_a := AIN_B;
v.state := LOOKUP;

Expand Down Expand Up @@ -2046,6 +2047,12 @@ begin
when LOOKUP =>
-- r.opsel_a = AIN_B
-- wait one cycle for inverse_table[B] lookup
-- if this is a division, compute exponent
-- (see comment on RENORM_B2 above)
if r.use_a = '1' then
re_sel2 <= REXP2_NE;
re_set_result <= '1';
end if;
v.first := '1';
if r.insn(4) = '0' then
if r.insn(3) = '0' then
Expand Down Expand Up @@ -2590,7 +2597,6 @@ begin
arith_done := '1';

when NAN_RESULT =>
v.negate := '0';
if (r.use_a = '1' and r.a.class = NAN and r.a.mantissa(QNAN_BIT) = '0') or
(r.use_b = '1' and r.b.class = NAN and r.b.mantissa(QNAN_BIT) = '0') or
(r.use_c = '1' and r.c.class = NAN and r.c.mantissa(QNAN_BIT) = '0') then
Expand Down Expand Up @@ -3158,14 +3164,14 @@ begin

end case;

rsign := v.result_sign;
if zero_divide = '1' then
v.fpscr(FPSCR_ZX) := '1';
end if;
if qnan_result = '1' then
invalid := '1';
v.result_class := NAN;
v.result_sign := '0';
v.negate := '0';
rsign := '0';
misc_sel <= "0001";
opsel_r <= RES_MISC;
arith_done := '1';
Expand All @@ -3181,6 +3187,12 @@ begin
v.writing_fpr := '1';
v.update_fprf := '1';
end if;
if v.is_subtract = '1' and v.result_class = ZERO then
rsign := r.round_mode(0) and r.round_mode(1);
end if;
if v.negate = '1' and v.result_class /= NAN then
rsign := not rsign;
end if;
v.instr_done := '1';
update_fx := '1';
end if;
Expand Down Expand Up @@ -3516,7 +3528,7 @@ begin
end if;

if r.update_fprf = '1' then
v.fpscr(FPSCR_C downto FPSCR_FU) := result_flags(r.result_sign, r.result_class,
v.fpscr(FPSCR_C downto FPSCR_FU) := result_flags(r.res_sign, r.result_class,
r.r(UNIT_BIT) and not r.denorm);
end if;

Expand All @@ -3541,9 +3553,7 @@ begin
v.int_result := int_result;
v.illegal := illegal;
v.nsnan_result := v.quieten_nan;
v.res_negate := v.negate;
v.res_subtract := v.is_subtract;
v.res_rmode := r.round_mode;
v.res_sign := rsign;
if r.integer_op = '1' then
v.cr_mask := num_to_fxm(0);
elsif r.is_cmp = '0' then
Expand Down Expand Up @@ -3574,9 +3584,8 @@ begin
if r.int_result = '1' then
fp_result <= r.r;
else
fp_result <= pack_dp(r.result_sign, r.result_class, r.result_exp, r.r,
r.sp_result, r.nsnan_result,
r.res_negate, r.res_subtract, r.res_rmode);
fp_result <= pack_dp(r.res_sign, r.result_class, r.result_exp, r.r,
r.sp_result, r.nsnan_result);
end if;

rin <= v;
Expand Down
2 changes: 1 addition & 1 deletion scripts/run_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ cd $TMPDIR

cp ${MICROWATT_DIR}/tests/${TEST}.bin main_ram.bin

${MICROWATT_DIR}/core_tb | sed 's/.*: //' | egrep '^(GPR[0-9]|LR |CTR |XER |CR [0-9])' | sort | grep -v GPR31 > test.out || true
${MICROWATT_DIR}/core_tb | sed 's/.*: //' | grep -E '^(GPR[0-9]|LR |CTR |XER |CR [0-9])' | sort | grep -v GPR31 > test.out || true

grep -v "^$" ${MICROWATT_DIR}/tests/${TEST}.out | sort | grep -v GPR31 > exp.out

Expand Down
Loading

0 comments on commit af2d6e2

Please sign in to comment.