Add rudimentary test for partitioned add with carry
authorMichael Nolan <mtnolan2640@gmail.com>
Sun, 9 Feb 2020 00:55:34 +0000 (19:55 -0500)
committerMichael Nolan <mtnolan2640@gmail.com>
Sun, 9 Feb 2020 00:56:46 +0000 (19:56 -0500)
src/ieee754/part/partsig.py
src/ieee754/part/test/test_partsig.py
src/ieee754/part_mul_add/adder.py

index 5e34f60d6ad85b6af8bc183fd9feff70fae180f4..2c2da8a90a6e34e0b4a4996beefaf44f762e96db 100644 (file)
@@ -112,6 +112,19 @@ class PartitionedSignal:
     def __add__(self, other):
         return self.add_op(self, other)
 
+    def addc(self, other, carry):
+        shape = self.sig.shape()
+        pa = PartitionedAdder(shape[0], self.partpoints)
+        setattr(self.m.submodules, self.get_modname('add'), pa)
+        comb = self.m.d.comb
+        comb += pa.a.eq(self.sig)
+        comb += pa.carry_in.eq(carry)
+        if isinstance(other, PartitionedSignal):
+            comb += pa.b.eq(other.sig)
+        else:
+            comb += pa.b.eq(other)
+        return (pa.output, pa.carry_out)
+
     def __radd__(self, other):
         return self.add_op(other, self)
 
index bbb84b8065d34b3333daad64a1f16ef607ead89f..5e5f310b361ebb70fe015f2953cc779f84fc8e54 100644 (file)
@@ -44,6 +44,8 @@ class TestAddMod(Elaboratable):
         self.le_output = Signal(len(partpoints)+1)
         self.mux_sel = Signal(len(partpoints)+1)
         self.mux_out = Signal(width)
+        self.carry_in = Signal(len(partpoints)+1)
+        self.carry_out = Signal(len(partpoints)+1)
 
     def elaborate(self, platform):
         m = Module()
@@ -55,7 +57,9 @@ class TestAddMod(Elaboratable):
         m.d.comb += self.gt_output.eq(self.a > self.b)
         m.d.comb += self.eq_output.eq(self.a == self.b)
         m.d.comb += self.ge_output.eq(self.a >= self.b)
-        m.d.comb += self.add_output.eq(self.a + self.b)
+        add_out, add_carry = self.a.addc(self.b, self.carry_in)
+        m.d.comb += self.add_output.eq(add_out)
+        m.d.comb += self.carry_out.eq(add_carry)
         ppts = self.partpoints
         m.d.comb += self.mux_out.eq(PMux(m, ppts, self.mux_sel, self.a, self.b))
 
@@ -76,7 +80,7 @@ class TestPartitionPoints(unittest.TestCase):
                                module.eq_output],
                               "part_sig_add")
         def async_process():
-            def test_add(msg_prefix, *mask_list):
+            def test_add(msg_prefix, carry, *mask_list):
                 for a, b in [(0x0000, 0x0000),
                              (0x1234, 0x1234),
                              (0xABCD, 0xABCD),
@@ -86,20 +90,27 @@ class TestPartitionPoints(unittest.TestCase):
                              (0x0000, 0xFFFF)]:
                     yield module.a.eq(a)
                     yield module.b.eq(b)
+                    carry_sig = 0xf if carry else 0
+                    yield module.carry_in.eq(carry_sig)
                     yield Delay(0.1e-6)
                     y = 0
-                    for mask in mask_list:
-                        y |= mask & ((a & mask) + (b & mask))
+                    for i, mask in enumerate(mask_list):
+                        lsb = mask & ~(mask-1) if carry else 0
+                        y |= mask & ((a & mask) + (b & mask) + lsb)
                     outval = (yield module.add_output)
+                    print(a, b, outval, carry)
                     msg = f"{msg_prefix}: 0x{a:X} + 0x{b:X}" + \
                         f" => 0x{y:X} != 0x{outval:X}"
                     self.assertEqual(y, outval, msg)
             yield part_mask.eq(0)
-            yield from test_add("16-bit", 0xFFFF)
+            yield from test_add("16-bit", 1, 0xFFFF)
+            yield from test_add("16-bit", 0, 0xFFFF)
             yield part_mask.eq(0b10)
-            yield from test_add("8-bit", 0xFF00, 0x00FF)
+            yield from test_add("8-bit", 0, 0xFF00, 0x00FF)
+            yield from test_add("8-bit", 1, 0xFF00, 0x00FF)
             yield part_mask.eq(0b1111)
-            yield from test_add("4-bit", 0xF000, 0x0F00, 0x00F0, 0x000F)
+            yield from test_add("4-bit", 0, 0xF000, 0x0F00, 0x00F0, 0x000F)
+            yield from test_add("4-bit", 1, 0xF000, 0x0F00, 0x00F0, 0x000F)
 
             def test_ne_fn(a, b, mask):
                 return (a & mask) != (b & mask)
index 84d8d9108c6ddce8c31c2a92db6ec7f9a109d372..e07101ad851a2e00b79d043b873217e6a74b9e0f 100644 (file)
@@ -199,7 +199,8 @@ class PartitionedAdder(Elaboratable):
                 ea.append(expanded_a[expanded_index])
                 al.append(a_bit) # add extra bit in a
                 eb.append(expanded_b[expanded_index])
-                bl.append(self.carry_in[carry_bit]) # yes, add a zero
+                bl.append(self.carry_in[carry_bit] &
+                          self.partition_points[pi]) # yes, add a zero
                 co.append(expanded_o[expanded_index])
                 cl.append(self.carry_out[carry_bit-1])
                 expanded_index += 1 # skip the extra point.  NOT in the output