rewrite test_clz.py to actually test both CLZ and clz.
[nmutil.git] / src / nmutil / test / test_clz.py
index e9b893b62df9be8cb086fa9b0496e8416d2eba8f..9e34379cc1d6b17d815657ab3e3357a8cc25bd8f 100644 (file)
@@ -1,43 +1,77 @@
-from nmigen import Module, Signal
-from nmigen.back.pysim import Simulator, Delay
-
-from nmutil.clz import CLZ
+from nmigen.sim import Delay
+from nmutil.clz import CLZ, clz
+from nmutil.sim_util import do_sim
 import unittest
-import math
-import random
-
 
-class CLZTestCase(unittest.TestCase):
-    def run_tst(self, inputs, width=8):
 
-        m = Module()
+def reference_clz(v, width):
+    assert isinstance(width, int) and 0 <= width
+    assert isinstance(v, int) and 0 <= v < 1 << width
+    msb = 1 << (width - 1)
+    retval = 0
+    while retval < width:
+        if v & msb:
+            break
+        v <<= 1
+        retval += 1
+    return retval
 
-        m.submodules.dut = dut = CLZ(width)
-        sig_in = Signal.like(dut.sig_in)
-        count = Signal.like(dut.lz)
 
-        m.d.comb += [
-            dut.sig_in.eq(sig_in),
-            count.eq(dut.lz)]
-
-        sim = Simulator(m)
+class TestCLZ(unittest.TestCase):
+    def tst(self, width):
+        assert isinstance(width, int) and 0 <= width
+        dut = CLZ(width)
 
         def process():
-            for i in inputs:
-                yield sig_in.eq(i)
-                yield Delay(1e-6)
-        sim.add_process(process)
-        with sim.write_vcd("clz.vcd", "clz.gtkw", traces=[
-                sig_in, count]):
+            for inp in range(1 << width):
+                expected = reference_clz(inp, width)
+                with self.subTest(inp=hex(inp), expected=expected):
+                    yield dut.sig_in.eq(inp)
+                    yield Delay(1e-6)
+                    sim_lz = yield dut.lz
+                    py_lz = clz(inp, width)
+                    with self.subTest(sim_lz=sim_lz, py_lz=py_lz):
+                        self.assertEqual(sim_lz, expected)
+                        self.assertEqual(py_lz, expected)
+        with do_sim(self, dut, [dut.sig_in, dut.lz]) as sim:
+            sim.add_process(process)
             sim.run()
 
-    def test_selected(self):
-        inputs = [0, 15, 10, 127]
-        self.run_tst(iter(inputs), width=8)
+    def test_1(self):
+        self.tst(1)
+
+    def test_2(self):
+        self.tst(2)
+
+    def test_3(self):
+        self.tst(3)
+
+    def test_4(self):
+        self.tst(4)
+
+    def test_5(self):
+        self.tst(5)
+
+    def test_6(self):
+        self.tst(6)
+
+    def test_7(self):
+        self.tst(7)
+
+    def test_8(self):
+        self.tst(8)
+
+    def test_9(self):
+        self.tst(9)
+
+    def test_10(self):
+        self.tst(10)
+
+    def test_11(self):
+        self.tst(11)
 
-    def test_non_power_2(self):
-        inputs = [0, 128, 512]
-        self.run_tst(iter(inputs), width=11)
+    def test_12(self):
+        self.tst(12)
 
 
 if __name__ == "__main__":