split out adder code (PartitionedAdder) into module, PartitionPoints too
[ieee754fpu.git] / src / ieee754 / fclass / fclass.py
index e1b034e6eb1ff7203642a70189cc071b05ad4b9f..8d5de09ecfb3147844c90255ab046b2ecbaea93c 100644 (file)
@@ -1,39 +1,31 @@
 # IEEE754 FCLASS Module
 # Copyright (C) 2019 Luke Kenneth Casson Leighon <lkcl@lkcl.net>
 
-from nmigen import Module, Signal, Cat, Elaboratable
+from nmigen import Module, Signal, Cat
 
-from ieee754.fpcommon.getop import FPADDBaseData
+from nmutil.pipemodbase import PipeModBase
+from ieee754.fpcommon.basedata import FPBaseData
 from ieee754.fpcommon.pack import FPPackData
 from ieee754.fpcommon.fpbase import FPNumDecode, FPNumBaseRecord
 
 
-class FPClassMod(Elaboratable):
+class FPClassMod(PipeModBase):
     """ obtains floating point information (zero, nan, inf etc.)
     """
     def __init__(self, in_pspec, out_pspec):
         self.in_pspec = in_pspec
         self.out_pspec = out_pspec
-        self.i = self.ispec()
-        self.o = self.ospec()
+        super().__init__(in_pspec, "fclass")
 
     def ispec(self):
-        return FPADDBaseData(self.in_pspec)
+        return FPBaseData(self.in_pspec)
 
     def ospec(self):
         return FPPackData(self.out_pspec)
 
-    def setup(self, m, i):
-        """ links module to inputs and outputs
-        """
-        m.submodules.fclass = self
-        m.d.comb += self.i.eq(i)
-
-    def process(self, i):
-        return self.o
-
     def elaborate(self, platform):
         m = Module()
+        comb = m.d.comb
 
         # decode incoming FP number
         print("in_width out", self.in_pspec.width,
@@ -41,20 +33,24 @@ class FPClassMod(Elaboratable):
         a1 = FPNumBaseRecord(self.in_pspec.width, False)
         print("a1", a1.width, a1.rmw, a1.e_width, a1.e_start, a1.e_end)
         m.submodules.sc_decode_a = a1 = FPNumDecode(None, a1)
-        m.d.comb += a1.v.eq(self.i.a)
+        comb += a1.v.eq(self.i.a)
 
         # FCLASS: work out the "type" of the FP number
 
         finite_nzero = Signal(reset_less=True)
         msbzero = Signal(reset_less=True)
         is_sig_nan = Signal(reset_less=True)
-        # XXX use *REAL* mantissa width to detect msb
-        m.d.comb += msbzero.eq(a1.m[a1.rmw-1] == 0) # sigh, 1 extra msb bit
-        m.d.comb += finite_nzero.eq(~a1.is_nan & ~a1.is_inf & ~a1.is_zero)
-        m.d.comb += is_sig_nan.eq(a1.exp_128 & (msbzero) & (~a1.m_zero))
+        # XXX use *REAL* mantissa width to detect msb.
+        # XXX do NOT use a1.m_msbzero because it has extra bitspace
+        comb += msbzero.eq(a1.m[a1.rmw-1] == 0) # sigh, 1 extra msb bit
+        comb += finite_nzero.eq(~a1.is_nan & ~a1.is_inf & ~a1.is_zero)
+        comb += is_sig_nan.eq(a1.exp_128 & (msbzero) & (~a1.m_zero))
         subnormal = a1.exp_n127
 
-        m.d.comb += self.o.z.eq(Cat(
+        # this is hardware-optimal but very hard to understand.
+        # see unit test test_fclass_pipe.py fclass() for what's
+        # going on.
+        comb += self.o.z.eq(Cat(
                     a1.s   & a1.is_inf,                 # | −inf.
                     a1.s   & finite_nzero & ~subnormal, # | -normal number.
                     a1.s   & finite_nzero &  subnormal, # | -subnormal number.
@@ -66,6 +62,6 @@ class FPClassMod(Elaboratable):
                     is_sig_nan,                         # | a signaling NaN.
                     a1.is_nan & ~is_sig_nan))           # | a quiet NaN
 
-        m.d.comb += self.o.ctx.eq(self.i.ctx)
+        comb += self.o.ctx.eq(self.i.ctx)
 
         return m