add PartitionedSignal XOR partsig test
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 30 Sep 2021 22:24:29 +0000 (23:24 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 30 Sep 2021 22:24:29 +0000 (23:24 +0100)
src/ieee754/part/test/test_partsig.py

index 379282e6bd8c8abb59f010fe3310eff2668a20fc..a1eb452e10f95b9905cfb6fdcef92155874655ef 100644 (file)
@@ -202,6 +202,7 @@ class TestAddMod(Elaboratable):
         self.add_carry_out = Signal(len(partpoints)+1)
         self.sub_carry_out = Signal(len(partpoints)+1)
         self.neg_output = Signal(width)
+        self.xor_output = Signal(len(partpoints)+1)
 
     def elaborate(self, platform):
         m = Module()
@@ -228,6 +229,8 @@ class TestAddMod(Elaboratable):
         comb += self.sub_carry_out.eq(sub_carry)
         # neg
         comb += self.neg_output.eq((-self.a).sig)
+        # horizontal operators
+        comb += self.xor_output.eq(self.a.xor())
         # left shift
         comb += self.ls_output.eq(self.a << self.b)
         # right shift
@@ -565,6 +568,61 @@ class TestPartitionedSignal(unittest.TestCase):
 
         def async_process():
 
+            def test_xor_fn(a, mask):
+                test = (a & mask)
+                result = 0
+                while test != 0:
+                    bit = (test & 1)
+                    result ^= bit
+                    test >>= 1
+                return result
+
+            def test_horizop(msg_prefix, test_fn, mod_attr, *maskbit_list):
+                randomvals = []
+                for i in range(10):
+                    randomvals.append(randint(0, 65535))
+                for a in [0x0000,
+                             0x1234,
+                             0xABCD,
+                             0xFFFF,
+                             0x8000,
+                             0xBEEF, 0xFEED,
+                                ]+randomvals:
+                    yield module.a.lower().eq(a)
+                    yield Delay(0.1e-6)
+                    # convert to mask_list
+                    mask_list = []
+                    for mb in maskbit_list:
+                        v = 0
+                        for i in range(4):
+                            if mb & (1 << i):
+                                v |= 0xf << (i*4)
+                        mask_list.append(v)
+                    y = 0
+                    # do the partitioned tests
+                    for i, mask in enumerate(mask_list):
+                        if test_fn(a, mask):
+                            # OR y with the lowest set bit in the mask
+                            y |= maskbit_list[i]
+                    # check the result
+                    outval = (yield getattr(module, "%s_output" % mod_attr))
+                    msg = f"{msg_prefix}: {mod_attr} 0x{a:X} " + \
+                        f" => 0x{y:X} != 0x{outval:X}, masklist %s"
+                    print((msg % str(maskbit_list)).format(locals()))
+                    self.assertEqual(y, outval, msg % str(maskbit_list))
+
+            for (test_fn, mod_attr) in ((test_xor_fn, "xor"),
+                                        #(test_ne_fn, "ne"),
+                                        ):
+                yield part_mask.eq(0)
+                yield from test_horizop("16-bit", test_fn, mod_attr, 0b1111)
+                yield part_mask.eq(0b10)
+                yield from test_horizop("8-bit", test_fn, mod_attr,
+                                      0b1100, 0b0011)
+                yield part_mask.eq(0b1111)
+                yield from test_horizop("4-bit", test_fn, mod_attr,
+                                      0b1000, 0b0100, 0b0010, 0b0001)
+
             def test_ls_scal_fn(carry_in, a, b, mask):
                 # reduce range of b
                 bits = count_bits(mask)