add TestReplMod, under development
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 9 Oct 2021 16:14:56 +0000 (17:14 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 9 Oct 2021 16:14:56 +0000 (17:14 +0100)
src/ieee754/part/test/test_partsig.py

index dff2d6ec847a7b7538db3b61f087b23d80328247..a1f44fc6361eb8e53b2bb872724f1ea9bfcbb69c 100644 (file)
@@ -2,7 +2,7 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 # See Notices.txt for copyright information
 
-from nmigen import Signal, Module, Elaboratable, Mux, Cat, Shape
+from nmigen import Signal, Module, Elaboratable, Mux, Cat, Shape, Repl
 from nmigen.back.pysim import Simulator, Delay, Settle
 from nmigen.cli import rtlil
 
@@ -143,7 +143,6 @@ class TestCatMod(Elaboratable):
         self.partpoints = partpoints
         self.a = PartitionedSignal(partpoints, width)
         self.b = PartitionedSignal(partpoints, width*2)
-        self.cat_sel = Signal(len(partpoints)+1)
         self.cat_out = Signal(width*3)
 
     def elaborate(self, platform):
@@ -151,13 +150,29 @@ class TestCatMod(Elaboratable):
         comb = m.d.comb
         self.a.set_module(m)
         self.b.set_module(m)
-        #self.cat_sel.set_module(m)
 
         comb += self.cat_out.eq(Cat(self.a, self.b))
 
         return m
 
 
+class TestReplMod(Elaboratable):
+    def __init__(self, width, partpoints):
+        self.partpoints = partpoints
+        self.a = PartitionedSignal(partpoints, width)
+        self.repl_sel = Signal(len(partpoints)+1)
+        self.repl_out = Signal(width*2)
+
+    def elaborate(self, platform):
+        m = Module()
+        comb = m.d.comb
+        self.a.set_module(m)
+
+        comb += self.repl_out.eq(Repl(self.a, 2))
+
+        return m
+
+
 class TestAssMod(Elaboratable):
     def __init__(self, width, out_shape, partpoints, scalar):
         self.partpoints = partpoints
@@ -429,6 +444,101 @@ class TestCat(unittest.TestCase):
             sim.run()
 
 
+class TestRepl(unittest.TestCase):
+    def test(self):
+        width = 16
+        part_mask = Signal(3)  # divide into 4-bits
+        module = TestReplMod(width, part_mask)
+
+        test_name = "part_sig_repl"
+        traces = [part_mask,
+                  module.a.sig,
+                  module.repl_out]
+        sim = create_simulator(module, traces, test_name)
+
+        # annoying recursive import issue
+        from ieee754.part_repl.repl import get_runlengths
+
+        def async_process():
+
+            def test_replop(msg_prefix):
+                # define lengths of a/b test input
+                alen, blen = 16, 32
+                # pairs of test values a, b
+                for a, b in [(0x0000, 0x00000000),
+                             (0xDCBA, 0x12345678),
+                             (0xABCD, 0x01234567),
+                             (0xFFFF, 0x0000),
+                             (0x0000, 0x0000),
+                             (0x1F1F, 0xF1F1F1F1),
+                             (0x0000, 0xFFFFFFFF)]:
+
+                    # convert a and b to partitions
+                    apart, bpart = [], []
+                    ajump, bjump = alen // 4, blen // 4
+                    for i in range(4):
+                        apart.append((a >> (ajump*i) & ((1<<ajump)-1)))
+                        bpart.append((b >> (bjump*i) & ((1<<bjump)-1)))
+
+                    print ("apart bpart", hex(a), hex(b),
+                            list(map(hex, apart)), list(map(hex, bpart)))
+
+                    yield module.a.lower().eq(a)
+                    yield module.b.lower().eq(b)
+                    yield Delay(0.1e-6)
+
+                    y = 0
+                    # work out the runlengths for this mask.
+                    # 0b011 returns [1,1,2] (for a mask of length 3)
+                    mval = yield part_mask
+                    runlengths = get_runlengths(mval, 3)
+                    j = 0
+                    ai = 0
+                    bi = 0
+                    for i in runlengths:
+                        # a first
+                        for _ in range(i):
+                            print ("runlength", i,
+                                   "ai", ai,
+                                   "apart", hex(apart[ai]),
+                                   "j", j)
+                            y |= apart[ai] << j
+                            print ("    y", hex(y))
+                            j += ajump
+                            ai += 1
+                        # now b
+                        for _ in range(i):
+                            print ("runlength", i,
+                                   "bi", bi,
+                                   "bpart", hex(bpart[bi]),
+                                   "j", j)
+                            y |= bpart[bi] << j
+                            print ("    y", hex(y))
+                            j += bjump
+                            bi += 1
+
+                    # check the result
+                    outval = (yield module.repl_out)
+                    msg = f"{msg_prefix}: repl " + \
+                        f"0x{mval:X} 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_replop("16-bit")
+            yield part_mask.eq(0b10)
+            yield from test_replop("8-bit")
+            yield part_mask.eq(0b1111)
+            yield from test_replop("4-bit")
+
+        sim.add_process(async_process)
+        with sim.write_vcd(
+                vcd_file=open(test_name + ".vcd", "w"),
+                gtkw_file=open(test_name + ".gtkw", "w"),
+                traces=traces):
+            sim.run()
+
+
 class TestAssign(unittest.TestCase):
     def run_tst(self, in_width, out_width, out_signed, scalar):
         part_mask = Signal(3)  # divide into 4-bits