From: Luke Kenneth Casson Leighton Date: Sun, 25 Aug 2019 20:33:20 +0000 (+0100) Subject: use Mux instead of m.If/Else in int2float fcvt X-Git-Tag: ls180-24jan2020~373 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d45a2e1d34683cb75c2766613faaaa4eb3f3f485;p=ieee754fpu.git use Mux instead of m.If/Else in int2float fcvt --- diff --git a/src/ieee754/fcvt/int2float.py b/src/ieee754/fcvt/int2float.py index 2004abc2..232ab7fa 100644 --- a/src/ieee754/fcvt/int2float.py +++ b/src/ieee754/fcvt/int2float.py @@ -1,7 +1,7 @@ # IEEE Floating Point Conversion # Copyright (C) 2019 Luke Kenneth Casson Leighton -from nmigen import Module, Signal, Cat +from nmigen import Module, Signal, Cat, Mux from nmigen.cli import main, verilog from nmutil.pipemodbase import PipeModBase @@ -9,7 +9,7 @@ from ieee754.fpcommon.basedata import FPBaseData from ieee754.fpcommon.postcalc import FPPostCalcData from ieee754.fpcommon.msbhigh import FPMSBHigh -from ieee754.fpcommon.fpbase import FPNumDecode, FPNumBaseRecord +from ieee754.fpcommon.fpbase import FPNumBaseRecord class FPCVTIntToFloatMod(PipeModBase): @@ -40,10 +40,11 @@ class FPCVTIntToFloatMod(PipeModBase): self.out_pspec.width) print("a1", self.in_pspec.width) z1 = self.o.z + a = self.i.a print("z1", z1.width, z1.rmw, z1.e_width, z1.e_start, z1.e_end) me = self.in_pspec.width - mz = self.o.z.rmw + mz = z1.rmw ms = mz - me print("ms-me", ms, me, mz) @@ -55,20 +56,17 @@ class FPCVTIntToFloatMod(PipeModBase): signed = Signal(reset_less=True) comb += signed.eq(self.i.ctx.op[0]) - # copy of mantissa (one less bit if signed) + # mantissa (one less bit if signed), and sign mantissa = Signal(me, reset_less=True) + sign = Signal(reset_less=True) # detect signed/unsigned. key case: -ve numbers need inversion # to +ve because the FP sign says if it's -ve or not. - with m.If(signed): - comb += z1.s.eq(self.i.a[-1]) # sign in top bit of a - with m.If(z1.s): - comb += mantissa.eq(-self.i.a) # invert input if sign -ve - with m.Else(): - comb += mantissa.eq(self.i.a) # leave as-is - with m.Else(): - comb += mantissa.eq(self.i.a) # unsigned, use full a - comb += z1.s.eq(0) + comb += sign.eq(Mux(signed, a[-1], 0)) # sign in top bit of a + comb += mantissa.eq(Mux(signed, + Mux(sign, -a, # invert input if sign -ve + a), # leave as-is + a)) # unsigned, use full a # set input from full INT comb += msb.m_in.eq(Cat(0, 0, 0, mantissa)) # g/r/s + input @@ -89,7 +87,8 @@ class FPCVTIntToFloatMod(PipeModBase): # smaller int to larger FP comb += z1.e.eq(msb.e_out) comb += z1.m[ms:].eq(msb.m_out[3:]) - comb += z1.create(z1.s, z1.e, z1.m) # ... here + comb += z1.s.eq(sign) + comb += z1.create(sign, z1.e, z1.m) # ... here # note: post-normalisation actually appears to be capable of # detecting overflow to infinity (FPPackMod). so it's ok to @@ -115,17 +114,20 @@ class FPCVTIntToFloatMod(PipeModBase): comb += self.o.of.sticky.eq(msb.m_out[:1].bool()) comb += self.o.of.m0.eq(msb.m_out[3]) - # special cases active by default - comb += self.o.out_do_z.eq(1) + a_nonzero = Signal(reset_less=True) + comb += a_nonzero.eq(~a.bool()) + + # prepare zero + z_zero = FPNumBaseRecord(z1.width, False, name="z_zero") + comb += z_zero.zero(0) + + # special cases? + comb += self.o.out_do_z.eq(a_nonzero) # detect zero - with m.If(~self.i.a.bool()): - comb += self.o.z.zero(0) - with m.Else(): - comb += self.o.out_do_z.eq(0) # activate normalisation + comb += self.o.oz.eq(Mux(a_nonzero, z1.v, z_zero.v)) # copy the context (muxid, operator) - comb += self.o.oz.eq(self.o.z.v) comb += self.o.ctx.eq(self.i.ctx) return m diff --git a/src/ieee754/fcvt/test/test_fcvt_int_pipe.py b/src/ieee754/fcvt/test/test_fcvt_int_pipe.py index 857432b0..7cea1dff 100644 --- a/src/ieee754/fcvt/test/test_fcvt_int_pipe.py +++ b/src/ieee754/fcvt/test/test_fcvt_int_pipe.py @@ -65,17 +65,17 @@ def test_int_pipe_i16_f32(): # should be fine. dut = FPCVTIntMuxInOut(16, 32, 4, op_wid=1) runfp(dut, 16, "test_fcvt_int_pipe_i16_f32", to_int16, fcvt_i16_f32, True, - n_vals=100, opcode=0x1) + n_vals=20, opcode=0x1) def test_int_pipe_i32_f64(): dut = FPCVTIntMuxInOut(32, 64, 4, op_wid=1) runfp(dut, 32, "test_fcvt_int_pipe_i32_f64", to_int32, fcvt_i32_f64, True, - n_vals=100, opcode=0x1) + n_vals=20, opcode=0x1) def test_int_pipe_i32_f32(): dut = FPCVTIntMuxInOut(32, 32, 4, op_wid=1) runfp(dut, 32, "test_fcvt_int_pipe_i32_f32", to_int32, fcvt_i32_f32, True, - n_vals=100, opcode=0x1) + n_vals=20, opcode=0x1) ###################### # unsigned int to fp @@ -86,22 +86,22 @@ def test_int_pipe_ui16_f32(): # should be fine. dut = FPCVTIntMuxInOut(16, 32, 4, op_wid=1) runfp(dut, 16, "test_fcvt_int_pipe_ui16_f32", to_uint16, fcvt_32, True, - n_vals=100) + n_vals=20) def test_int_pipe_ui16_f64(): dut = FPCVTIntMuxInOut(16, 64, 4, op_wid=1) runfp(dut, 16, "test_fcvt_int_pipe_ui16_f64", to_uint16, fcvt_64, True, - n_vals=100) + n_vals=20) def test_int_pipe_ui32_f32(): dut = FPCVTIntMuxInOut(32, 32, 4, op_wid=1) runfp(dut, 32, "test_fcvt_int_pipe_ui32_32", to_uint32, fcvt_32, True, - n_vals=100) + n_vals=20) def test_int_pipe_ui32_f64(): dut = FPCVTIntMuxInOut(32, 64, 4, op_wid=1) runfp(dut, 32, "test_fcvt_int_pipe_ui32_64", to_uint32, fcvt_64, True, - n_vals=100) + n_vals=20) def test_int_pipe_ui64_f32(): # ok, doing 33 bits here because it's pretty pointless (not entirely) @@ -109,7 +109,7 @@ def test_int_pipe_ui64_f32(): # converted to Inf dut = FPCVTIntMuxInOut(64, 32, 4, op_wid=1) runfp(dut, 33, "test_fcvt_int_pipe_ui64_32", to_uint64, fcvt_64_to_32, True, - n_vals=100) + n_vals=20) def test_int_pipe_ui64_f16(): # ok, doing 17 bits here because it's pretty pointless (not entirely) @@ -117,7 +117,7 @@ def test_int_pipe_ui64_f16(): # converted to Inf dut = FPCVTIntMuxInOut(64, 16, 4, op_wid=1) runfp(dut, 17, "test_fcvt_int_pipe_ui64_16", to_uint64, fcvt_16, True, - n_vals=100) + n_vals=20) def test_int_pipe_ui32_f16(): # ok, doing 17 bits here because it's pretty pointless (not entirely) @@ -125,16 +125,14 @@ def test_int_pipe_ui32_f16(): # converted to Inf dut = FPCVTIntMuxInOut(32, 16, 4, op_wid=1) runfp(dut, 17, "test_fcvt_int_pipe_ui32_16", to_uint32, fcvt_16, True, - n_vals=100) + n_vals=20) if __name__ == '__main__': for i in range(200): - test_int_pipe_ui32_f32() - test_int_pipe_i32_f32() - continue test_int_pipe_i16_f32() test_int_pipe_i32_f64() - continue + test_int_pipe_ui32_f32() + test_int_pipe_i32_f32() test_int_pipe_ui16_f32() test_int_pipe_ui64_f32() test_int_pipe_ui32_f16()