add docstring Mul8_16_32_64 only for testing
[ieee754fpu.git] / src / ieee754 / part_mul_add / multiply.py
index 51f994d25c4359cec5a246fe81c0f719b8411a86..215d18c6a1aacce049dd74c6331437c2e74e5853 100644 (file)
@@ -310,7 +310,7 @@ class AddReduceData:
     def __init__(self, part_pts, n_inputs, output_width, n_parts):
         self.part_ops = [Signal(2, name=f"part_ops_{i}", reset_less=True)
                           for i in range(n_parts)]
-        self.terms = [Signal(output_width, name=f"inputs_{i}",
+        self.terms = [Signal(output_width, name=f"terms_{i}",
                               reset_less=True)
                         for i in range(n_inputs)]
         self.part_pts = part_pts.like()
@@ -344,23 +344,22 @@ class FinalReduceData:
         return self.eq_from(rhs.part_pts, rhs.output, rhs.part_ops)
 
 
-class FinalAdd(Elaboratable):
+class FinalAdd(PipeModBase):
     """ Final stage of add reduce
     """
 
-    def __init__(self, lidx, n_inputs, output_width, n_parts, partition_points,
+    def __init__(self, pspec, lidx, n_inputs, partition_points,
                        partition_step=1):
         self.lidx = lidx
         self.partition_step = partition_step
-        self.output_width = output_width
+        self.output_width = pspec.width * 2
         self.n_inputs = n_inputs
-        self.n_parts = n_parts
+        self.n_parts = pspec.n_parts
         self.partition_points = PartitionPoints(partition_points)
-        if not self.partition_points.fits_in_width(output_width):
+        if not self.partition_points.fits_in_width(self.output_width):
             raise ValueError("partition_points doesn't fit in output_width")
 
-        self.i = self.ispec()
-        self.o = self.ospec()
+        super().__init__(pspec, "finaladd")
 
     def ispec(self):
         return AddReduceData(self.partition_points, self.n_inputs,
@@ -370,13 +369,6 @@ class FinalAdd(Elaboratable):
         return FinalReduceData(self.partition_points,
                                  self.output_width, self.n_parts)
 
-    def setup(self, m, i):
-        m.submodules.finaladd = self
-        m.d.comb += self.i.eq(i)
-
-    def process(self, i):
-        return self.o
-
     def elaborate(self, platform):
         """Elaborate this module."""
         m = Module()
@@ -547,7 +539,7 @@ class AddReduceSingle(PipeModBase):
 
 
 class AddReduceInternal:
-    """Recursively Add list of numbers together.
+    """Iteratively Add list of numbers together.
 
     :attribute inputs: input ``Signal``s to be summed. Modification not
         supported, except for by ``Signal.eq``.
@@ -558,19 +550,17 @@ class AddReduceInternal:
         supported, except for by ``Signal.eq``.
     """
 
-    def __init__(self, i, pspec, partition_step=1):
+    def __init__(self, pspec, n_inputs, part_pts, partition_step=1):
         """Create an ``AddReduce``.
 
         :param inputs: input ``Signal``s to be summed.
         :param output_width: bit-width of ``output``.
         :param partition_points: the input partition points.
         """
-        self.i = i
         self.pspec = pspec
-        self.inputs = i.terms
-        self.part_ops = i.part_ops
+        self.n_inputs = n_inputs
         self.output_width = pspec.width * 2
-        self.partition_points = i.part_pts
+        self.partition_points = part_pts
         self.partition_step = partition_step
 
         self.create_levels()
@@ -580,12 +570,9 @@ class AddReduceInternal:
 
         mods = []
         partition_points = self.partition_points
-        part_ops = self.part_ops
-        n_parts = len(part_ops)
-        inputs = self.inputs
-        ilen = len(inputs)
+        ilen = self.n_inputs
         while True:
-            groups = AddReduceSingle.full_adder_groups(len(inputs))
+            groups = AddReduceSingle.full_adder_groups(ilen)
             if len(groups) == 0:
                 break
             lidx = len(mods)
@@ -594,12 +581,10 @@ class AddReduceInternal:
                                          self.partition_step)
             mods.append(next_level)
             partition_points = next_level.i.part_pts
-            inputs = next_level.o.terms
-            ilen = len(inputs)
-            part_ops = next_level.i.part_ops
+            ilen = len(next_level.o.terms)
 
         lidx = len(mods)
-        next_level = FinalAdd(lidx, ilen, self.output_width, n_parts,
+        next_level = FinalAdd(self.pspec, lidx, ilen,
                               partition_points, self.partition_step)
         mods.append(next_level)
 
@@ -634,7 +619,8 @@ class AddReduce(AddReduceInternal, Elaboratable):
         n_parts = len(part_ops)
         self.i = AddReduceData(part_pts, len(inputs),
                              output_width, n_parts)
-        AddReduceInternal.__init__(self, self.i, output_width, partition_step)
+        AddReduceInternal.__init__(self, pspec, n_inputs, part_pts,
+                                   partition_step)
         self.o = FinalReduceData(part_pts, output_width, n_parts)
         self.register_levels = register_levels
 
@@ -986,21 +972,21 @@ class IntermediateOut(Elaboratable):
         return m
 
 
-class FinalOut(Elaboratable):
+class FinalOut(PipeModBase):
     """ selects the final output based on the partitioning.
 
         each byte is selectable independently, i.e. it is possible
         that some partitions requested 8-bit computation whilst others
         requested 16 or 32 bit.
     """
-    def __init__(self, output_width, n_parts, part_pts):
+    def __init__(self, pspec, part_pts):
+
         self.part_pts = part_pts
-        self.output_width = output_width
-        self.n_parts = n_parts
-        self.out_wid = output_width//2
+        self.output_width = pspec.width * 2
+        self.n_parts = pspec.n_parts
+        self.out_wid = pspec.width
 
-        self.i = self.ispec()
-        self.o = self.ospec()
+        super().__init__(pspec, "finalout")
 
     def ispec(self):
         return IntermediateData(self.part_pts, self.output_width, self.n_parts)
@@ -1008,13 +994,6 @@ class FinalOut(Elaboratable):
     def ospec(self):
         return OutputData()
 
-    def setup(self, m, i):
-        m.submodules.finalout = self
-        m.d.comb += self.i.eq(i)
-
-    def process(self, i):
-        return self.o
-
     def elaborate(self, platform):
         m = Module()
 
@@ -1271,17 +1250,16 @@ class AllTerms(PipeModBase):
         return m
 
 
-class Intermediates(Elaboratable):
+class Intermediates(PipeModBase):
     """ Intermediate output modules
     """
 
-    def __init__(self, output_width, n_parts, part_pts):
+    def __init__(self, pspec, part_pts):
         self.part_pts = part_pts
-        self.output_width = output_width
-        self.n_parts = n_parts
+        self.output_width = pspec.width * 2
+        self.n_parts = pspec.n_parts
 
-        self.i = self.ispec()
-        self.o = self.ospec()
+        super().__init__(pspec, "intermediates")
 
     def ispec(self):
         return FinalReduceData(self.part_pts, self.output_width, self.n_parts)
@@ -1289,13 +1267,6 @@ class Intermediates(Elaboratable):
     def ospec(self):
         return IntermediateData(self.part_pts, self.output_width, self.n_parts)
 
-    def setup(self, m, i):
-        m.submodules.intermediates = self
-        m.d.comb += self.i.eq(i)
-
-    def process(self, i):
-        return self.o
-
     def elaborate(self, platform):
         m = Module()
 
@@ -1341,6 +1312,8 @@ class Intermediates(Elaboratable):
 class Mul8_16_32_64(Elaboratable):
     """Signed/Unsigned 8/16/32/64-bit partitioned integer multiplier.
 
+    XXX NOTE: this class is intended for unit test purposes ONLY.
+
     Supports partitioning into any combination of 8, 16, 32, and 64-bit
     partitions on naturally-aligned boundaries. Supports the operation being
     set for each partition independently.
@@ -1403,17 +1376,15 @@ class Mul8_16_32_64(Elaboratable):
 
         part_pts = self.part_pts
 
-        n_parts = self.pspec.n_parts
         n_inputs = 64 + 4
-        output_width = self.pspec.width * 2
         t = AllTerms(self.pspec, n_inputs)
         t.setup(m, self.i)
 
         terms = t.o.terms
 
-        at = AddReduceInternal(t.process(self.i), self.pspec, partition_step=2)
+        at = AddReduceInternal(self.pspec, n_inputs, part_pts, partition_step=2)
 
-        i = at.i
+        i = t.o
         for idx in range(len(at.levels)):
             mcur = at.levels[idx]
             mcur.setup(m, i)
@@ -1424,12 +1395,12 @@ class Mul8_16_32_64(Elaboratable):
                 m.d.comb += o.eq(mcur.process(i))
             i = o # for next loop
 
-        interm = Intermediates(128, 8, part_pts)
+        interm = Intermediates(self.pspec, part_pts)
         interm.setup(m, i)
         o = interm.process(interm.i)
 
         # final output
-        finalout = FinalOut(128, 8, part_pts)
+        finalout = FinalOut(self.pspec, part_pts)
         finalout.setup(m, o)
         m.d.comb += self.o.eq(finalout.process(o))