add partition test add unit test
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 22 Jan 2020 14:21:24 +0000 (14:21 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 22 Jan 2020 14:21:24 +0000 (14:21 +0000)
src/ieee754/part/partsig.py
src/ieee754/part/test/test_partsig.py [new file with mode: 0644]
src/ieee754/part_mul_add/partpoints.py

index 47a7625c8f14754f87872a36b9c8fe92473a7ed5..949bebc2e148c27e5213df848db79ef5a35fbfc4 100644 (file)
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# See Notices.txt for copyright information
+
 """
 Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
 
@@ -13,23 +16,24 @@ from nmigen import (Module, Signal, Elaboratable,
 from ieee754.part_mul_add.adder import PartitionedAdder
 
 class PartitionedSignal(Elaboratable):
-    def __init__(self, partition_points, *args, **kwargs)
-                 reset=0, reset_less=False,
-                 attrs=None, decoder=None, src_loc_at=0):
+    def __init__(self, partition_points, *args, **kwargs):
         self.partpoints = partition_points
         self.sig = Signal(*args, **kwargs)
         self.modnames = {}
         for name in ['add']:
             self.modnames[name] = 0
+        self.m = Module()
 
-    def elaboratable(self, platform):
-        self.m = m = Module()
-        return m
+    def elaborate(self, platform):
+        return self.m
 
     def get_modname(self, category):
         self.modnames[category] += 1
         return "%s%d" % (category, self.modnames[category])
 
+    def eq(self, val):
+        return self.sig.eq(val)
+
     def __xor__(self, other):
         if isinstance(other, PartitionedSignal):
             return self.sig ^ other.sig
diff --git a/src/ieee754/part/test/test_partsig.py b/src/ieee754/part/test/test_partsig.py
new file mode 100644 (file)
index 0000000..cae067d
--- /dev/null
@@ -0,0 +1,91 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# See Notices.txt for copyright information
+
+from ieee754.part.partsig import PartitionedSignal
+from nmigen import Signal, Module, Elaboratable
+from nmigen.back.pysim import Simulator, Delay, Tick, Passive
+from nmigen.cli import verilog, rtlil
+
+import unittest
+
+def create_ilang(dut, traces, test_name):
+    vl = rtlil.convert(dut, ports=traces)
+    with open("%s.il" % test_name, "w") as f:
+        f.write(vl)
+
+
+def create_simulator(module, traces, test_name):
+    create_ilang(module, traces, test_name)
+    return Simulator(module,
+                     vcd_file=open(test_name + ".vcd", "w"),
+                     gtkw_file=open(test_name + ".gtkw", "w"),
+                     traces=traces)
+
+class TestAddMod(Elaboratable):
+    def __init__(self, width, partpoints):
+        self.a = PartitionedSignal(partpoints, width)
+        self.b = PartitionedSignal(partpoints, width)
+        self.add_output = Signal(width)
+
+    def elaborate(self, platform):
+        m = Module()
+        m.submodules.a = self.a
+        m.submodules.b = self.b
+        m.d.comb += self.add_output.eq(self.a + self.b)
+
+        return m
+
+
+class TestPartitionPoints(unittest.TestCase):
+    def test(self):
+        width = 16
+        partition_nibbles = Signal() # divide into 4-bits
+        partition_bytes = Signal()   # divide on 8-bits
+        partpoints = {0x4: partition_nibbles,
+                      0x8: partition_bytes | partition_nibbles,
+                      0xC: partition_nibbles}
+        module = TestAddMod(width, partpoints)
+
+        sim = create_simulator(module,
+                              [partition_nibbles,
+                               partition_bytes,
+                               module.a.sig,
+                               module.b.sig,
+                               module.add_output],
+                              "part_sig_add")
+        def async_process():
+            def test_add(msg_prefix, *mask_list):
+                for a, b in [(0x0000, 0x0000),
+                             (0x1234, 0x1234),
+                             (0xABCD, 0xABCD),
+                             (0xFFFF, 0x0000),
+                             (0x0000, 0x0000),
+                             (0xFFFF, 0xFFFF),
+                             (0x0000, 0xFFFF)]:
+                    yield module.a.eq(a)
+                    yield module.b.eq(b)
+                    yield Delay(0.1e-6)
+                    y = 0
+                    for mask in mask_list:
+                        y |= mask & ((a & mask) + (b & mask))
+                    outval = (yield module.add_output)
+                    msg = f"{msg_prefix}: 0x{a:X} + 0x{b:X}" + \
+                        f" => 0x{y:X} != 0x{outval:X}"
+                    self.assertEqual(y, outval, msg)
+            yield partition_nibbles.eq(0)
+            yield partition_bytes.eq(0)
+            yield from test_add("16-bit", 0xFFFF)
+            yield partition_nibbles.eq(0)
+            yield partition_bytes.eq(1)
+            yield from test_add("8-bit", 0xFF00, 0x00FF)
+            yield partition_nibbles.eq(1)
+            yield partition_bytes.eq(0)
+            yield from test_add("4-bit", 0xF000, 0x0F00, 0x00F0, 0x000F)
+
+        sim.add_process(async_process)
+        sim.run()
+
+if __name__ == '__main__':
+    unittest.main()
+
index 0ea3668f2da262b7789dc249e2a6d3fc26a72989..13ea5647e6b1c61b0e67010f4cdd67b74eb217a8 100644 (file)
@@ -43,7 +43,7 @@ class PartitionPoints(dict):
                     raise TypeError("point must be a non-negative integer")
                 if point < 0:
                     raise ValueError("point must be a non-negative integer")
-                self[point] = Value.wrap(enabled)
+                self[point] = Value.cast(enabled)
 
     def like(self, name=None, src_loc_at=0, mul=1):
         """Create a new ``PartitionPoints`` with ``Signal``s for all values.