create a new "MaskedFullAdder" class, which performs the partition-carry mask
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 20 Aug 2019 05:43:07 +0000 (06:43 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 20 Aug 2019 05:43:07 +0000 (06:43 +0100)
the FullAdder is always masked, so a derivative class is created.
cleans up the graphviz output a lot

src/ieee754/part_mul_add/multiply.py

index 2dbe6338d18765f25eb5a210e09d7f6d059697fd..81c5a8ac0f3f3d535bcfe98a8a7431ba1c8df024 100644 (file)
@@ -140,6 +140,37 @@ class FullAdder(Elaboratable):
         return m
 
 
+class MaskedFullAdder(FullAdder):
+    """Masked Full Adder.
+
+    :attribute mask: the carry partition mask
+    :attribute in0: the first input
+    :attribute in1: the second input
+    :attribute in2: the third input
+    :attribute sum: the sum output
+    :attribute mcarry: the masked carry output
+
+    FullAdders are always used with a "mask" on the output.  To keep
+    the graphviz "clean", this class performs the masking here rather
+    than inside a large for-loop.
+    """
+
+    def __init__(self, width):
+        """Create a ``MaskedFullAdder``.
+
+        :param width: the bit width of the input and output
+        """
+        FullAdder.__init__(self, width)
+        self.mask = Signal(width)
+        self.mcarry = Signal(width)
+
+    def elaborate(self, platform):
+        """Elaborate this module."""
+        m = FullAdder.elaborate(self, platform)
+        m.d.comb += self.mcarry.eq((self.carry << 1) & self.mask)
+        return m
+
+
 class PartitionedAdder(Elaboratable):
     """Partitioned Adder.
 
@@ -350,15 +381,15 @@ class AddReduce(Elaboratable):
         # create full adders for this recursive level.
         # this shrinks N terms to 2 * (N // 3) plus the remainder
         for i in groups:
-            adder_i = FullAdder(len(self.output))
+            adder_i = MaskedFullAdder(len(self.output))
             setattr(m.submodules, f"adder_{i}", adder_i)
             m.d.comb += adder_i.in0.eq(self._resized_inputs[i])
             m.d.comb += adder_i.in1.eq(self._resized_inputs[i + 1])
             m.d.comb += adder_i.in2.eq(self._resized_inputs[i + 2])
+            m.d.comb += adder_i.mask.eq(part_mask)
             add_intermediate_term(adder_i.sum)
-            shifted_carry = adder_i.carry << 1
             # mask out carry bits to prevent carries between partitions
-            add_intermediate_term((adder_i.carry << 1) & part_mask)
+            add_intermediate_term(adder_i.mcarry)
         # handle the remaining inputs.
         if len(self.inputs) % FULL_ADDER_INPUT_COUNT == 1:
             add_intermediate_term(self._resized_inputs[-1])