switch to exact version of cython
[ieee754fpu.git] / src / ieee754 / div_rem_sqrt_rsqrt / test_core.py
index 3220388432d3f3ad88faca2235be2b07a6defa2e..d7aeded694f783ccb2b2982fe25172918af5a427 100755 (executable)
@@ -16,6 +16,7 @@ from nmigen.hdl.ir import Fragment
 from nmigen.back import rtlil
 from nmigen.back.pysim import Simulator, Delay, Tick
 from itertools import chain
 from nmigen.back import rtlil
 from nmigen.back.pysim import Simulator, Delay, Tick
 from itertools import chain
+import inspect
 
 
 def show_fixed(bits, fract_width, bit_width):
 
 
 def show_fixed(bits, fract_width, bit_width):
@@ -162,6 +163,8 @@ def get_test_cases(core_config,
         assert isinstance(radicands, list)
 
     for alg_op in reversed(Operation):  # put UDivRem at end
         assert isinstance(radicands, list)
 
     for alg_op in reversed(Operation):  # put UDivRem at end
+        if get_core_op(alg_op) not in core_config.supported:
+            continue
         if alg_op is Operation.UDivRem:
             for dividend in dividends:
                 for divisor in divisors:
         if alg_op is Operation.UDivRem:
             for dividend in dividends:
                 for divisor in divisors:
@@ -212,6 +215,30 @@ class DivPipeCoreTestPipeline(Elaboratable):
         yield from self.o
 
 
         yield from self.o
 
 
+def trace_process(process, prefix="trace:", silent=False):
+    def generator():
+        if inspect.isgeneratorfunction(process):
+            proc = process()
+        else:
+            proc = process
+        response = None
+        while True:
+            try:
+                command = proc.send(response)
+                if not silent:
+                    print(prefix, command)
+            except StopIteration:
+                return
+            except Exception as e:
+                if not silent:
+                    print(prefix, "raised:", e)
+                raise e
+            response = (yield command)
+            if not silent:
+                print(prefix, "->", response)
+    return generator
+
+
 class TestDivPipeCore(unittest.TestCase):
     def handle_config(self,
                       core_config,
 class TestDivPipeCore(unittest.TestCase):
     def handle_config(self,
                       core_config,
@@ -225,36 +252,59 @@ class TestDivPipeCore(unittest.TestCase):
         base_name += f"_radix_{1 << core_config.log2_radix}"
         if not sync:
             base_name += "_comb"
         base_name += f"_radix_{1 << core_config.log2_radix}"
         if not sync:
             base_name += "_comb"
+        if core_config.supported != frozenset(DivPipeCoreOperation):
+            name_map = {
+                DivPipeCoreOperation.UDivRem: "div",
+                DivPipeCoreOperation.SqrtRem: "sqrt",
+                DivPipeCoreOperation.RSqrtRem: "rsqrt",
+            }
+            # loop using iter(DivPipeCoreOperation) to maintain order
+            for op in DivPipeCoreOperation:
+                if op in core_config.supported:
+                    base_name += f"_{name_map[op]}"
+            base_name+="_only"
+
         with self.subTest(part="synthesize"):
             dut = DivPipeCoreTestPipeline(core_config, sync)
             vl = rtlil.convert(dut, ports=[*dut.i, *dut.o])
             with open(f"{base_name}.il", "w") as f:
                 f.write(vl)
         dut = DivPipeCoreTestPipeline(core_config, sync)
         with self.subTest(part="synthesize"):
             dut = DivPipeCoreTestPipeline(core_config, sync)
             vl = rtlil.convert(dut, ports=[*dut.i, *dut.o])
             with open(f"{base_name}.il", "w") as f:
                 f.write(vl)
         dut = DivPipeCoreTestPipeline(core_config, sync)
-        with Simulator(dut,
-                       vcd_file=open(f"{base_name}.vcd", "w"),
-                       gtkw_file=open(f"{base_name}.gtkw", "w"),
-                       traces=[*dut.traces()]) as sim:
+        sim = Simulator(dut)
+        with sim.write_vcd(vcd_file=open(f"{base_name}.vcd", "w"),
+                           gtkw_file=open(f"{base_name}.gtkw", "w"),
+                           traces=[*dut.traces()]):
             def generate_process():
             def generate_process():
+                if not sync:
+                    yield Delay(1e-6)
                 for test_case in test_cases:
                 for test_case in test_cases:
-                    yield Tick()
+                    if sync:
+                        yield Tick()
                     yield dut.i.dividend.eq(test_case.dividend)
                     yield dut.i.divisor_radicand.eq(test_case.divisor_radicand)
                     yield dut.i.operation.eq(int(test_case.core_op))
                     yield dut.i.dividend.eq(test_case.dividend)
                     yield dut.i.divisor_radicand.eq(test_case.divisor_radicand)
                     yield dut.i.operation.eq(int(test_case.core_op))
-                    yield Delay(0.9e-6)
+                    if sync:
+                        yield Delay(0.9e-6)
+                    else:
+                        yield Delay(1e-6)
 
             def check_process():
                 # sync with generator
                 if sync:
 
             def check_process():
                 # sync with generator
                 if sync:
-                    yield
+                    yield Tick()
                     for _ in range(core_config.n_stages):
                     for _ in range(core_config.n_stages):
-                        yield
-                    yield
+                        yield Tick()
+                    yield Tick()
+                else:
+                    yield Delay(0.5e-6)
 
                 # now synched with generator
                 for test_case in test_cases:
 
                 # now synched with generator
                 for test_case in test_cases:
-                    yield Tick()
-                    yield Delay(0.9e-6)
+                    if sync:
+                        yield Tick()
+                        yield Delay(0.9e-6)
+                    else:
+                        yield Delay(1e-6)
                     quotient_root = (yield dut.o.quotient_root)
                     remainder = (yield dut.o.remainder)
                     with self.subTest(test_case=str(test_case)):
                     quotient_root = (yield dut.o.quotient_root)
                     remainder = (yield dut.o.remainder)
                     with self.subTest(test_case=str(test_case)):
@@ -263,9 +313,11 @@ class TestDivPipeCore(unittest.TestCase):
                                          str(test_case))
                         self.assertEqual(remainder, test_case.remainder,
                                          str(test_case))
                                          str(test_case))
                         self.assertEqual(remainder, test_case.remainder,
                                          str(test_case))
-            sim.add_clock(2e-6)
-            sim.add_sync_process(generate_process)
-            sim.add_sync_process(check_process)
+            if sync:
+                sim.add_clock(2e-6)
+            silent = True
+            sim.add_process(trace_process(generate_process, "generate:", silent=silent))
+            sim.add_process(trace_process(check_process, "check:", silent=silent))
             sim.run()
 
     def test_bit_width_2_fract_width_1_radix_2_comb(self):
             sim.run()
 
     def test_bit_width_2_fract_width_1_radix_2_comb(self):
@@ -290,6 +342,32 @@ class TestDivPipeCore(unittest.TestCase):
                                              fract_width=4,
                                              log2_radix=1))
 
                                              fract_width=4,
                                              log2_radix=1))
 
+    def test_bit_width_8_fract_width_4_radix_4_comb(self):
+        self.handle_config(DivPipeCoreConfig(bit_width=8,
+                                             fract_width=4,
+                                             log2_radix=2),
+                           sync=False)
+
+    def test_bit_width_8_fract_width_4_radix_4(self):
+        self.handle_config(DivPipeCoreConfig(bit_width=8,
+                                             fract_width=4,
+                                             log2_radix=2))
+
+    def test_bit_width_8_fract_width_4_radix_4_div_only(self):
+        supported = (DivPipeCoreOperation.UDivRem,)
+        self.handle_config(DivPipeCoreConfig(bit_width=8,
+                                             fract_width=4,
+                                             log2_radix=2,
+                                             supported=supported))
+
+    def test_bit_width_8_fract_width_4_radix_4_comb_div_only(self):
+        supported = (DivPipeCoreOperation.UDivRem,)
+        self.handle_config(DivPipeCoreConfig(bit_width=8,
+                                             fract_width=4,
+                                             log2_radix=2,
+                                             supported=supported),
+                           sync=False)
+
     @unittest.skip("really slow")
     def test_bit_width_32_fract_width_24_radix_8_comb(self):
         self.handle_config(DivPipeCoreConfig(bit_width=32,
     @unittest.skip("really slow")
     def test_bit_width_32_fract_width_24_radix_8_comb(self):
         self.handle_config(DivPipeCoreConfig(bit_width=32,