use Mux instead of m.If/Else in int2float fcvt
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 25 Aug 2019 20:33:20 +0000 (21:33 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 25 Aug 2019 20:33:20 +0000 (21:33 +0100)
src/ieee754/fcvt/int2float.py
src/ieee754/fcvt/test/test_fcvt_int_pipe.py

index 2004abc296a9144189305e4f7c76a4ce18dbd4c6..232ab7fa00803ad6694b466e70de240146dd9160 100644 (file)
@@ -1,7 +1,7 @@
 # IEEE Floating Point Conversion
 # Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
 
-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
index 857432b09cae9d77eaec09720dfbdacac877c878..7cea1dff8d2fa654f3e2edfed3a9b1d17efa1cc3 100644 (file)
@@ -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()