switch to exact version of cython
[ieee754fpu.git] / src / ieee754 / div_rem_sqrt_rsqrt / test_core.py
index fc42829ba24a3cbe51b0ce4b5e3a3a3a2fd03356..d7aeded694f783ccb2b2982fe25172918af5a427 100755 (executable)
@@ -2,11 +2,13 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 # See Notices.txt for copyright information
 
-from .core import (DivPipeCoreConfig, DivPipeCoreSetupStage,
-                   DivPipeCoreCalculateStage, DivPipeCoreFinalStage,
-                   DivPipeCoreOperation, DivPipeCoreInputData,
-                   DivPipeCoreInterstageData, DivPipeCoreOutputData)
-from .algorithm import (FixedUDivRemSqrtRSqrt, Fixed, Operation, div_rem,
+from ieee754.div_rem_sqrt_rsqrt.core import (DivPipeCoreConfig,
+                    DivPipeCoreSetupStage,
+                    DivPipeCoreCalculateStage, DivPipeCoreFinalStage,
+                    DivPipeCoreOperation, DivPipeCoreInputData,
+                    DivPipeCoreInterstageData, DivPipeCoreOutputData)
+from ieee754.div_rem_sqrt_rsqrt.algorithm import (FixedUDivRemSqrtRSqrt,
+                        Fixed, Operation, div_rem,
                         fixed_sqrt, fixed_rsqrt)
 import unittest
 from nmigen import Module, Elaboratable, Signal
@@ -14,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
+import inspect
 
 
 def show_fixed(bits, fract_width, bit_width):
@@ -160,6 +163,8 @@ def get_test_cases(core_config,
         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:
@@ -210,6 +215,30 @@ class DivPipeCoreTestPipeline(Elaboratable):
         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,
@@ -223,45 +252,72 @@ class TestDivPipeCore(unittest.TestCase):
         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 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():
+                if not sync:
+                    yield Delay(1e-6)
                 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 Delay(0.9e-6)
+                    if sync:
+                        yield Delay(0.9e-6)
+                    else:
+                        yield Delay(1e-6)
 
             def check_process():
                 # sync with generator
                 if sync:
-                    yield
+                    yield Tick()
                     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:
-                    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)):
                         self.assertEqual(quotient_root,
-                                         test_case.quotient_root)
-                        self.assertEqual(remainder, test_case.remainder)
-            sim.add_clock(2e-6)
-            sim.add_sync_process(generate_process)
-            sim.add_sync_process(check_process)
+                                         test_case.quotient_root,
+                                         str(test_case))
+                        self.assertEqual(remainder, test_case.remainder,
+                                         str(test_case))
+            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):
@@ -286,23 +342,53 @@ class TestDivPipeCore(unittest.TestCase):
                                              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,
                                              fract_width=24,
                                              log2_radix=3),
                            sync=False)
 
+    @unittest.skip("really slow")
     def test_bit_width_32_fract_width_24_radix_8(self):
         self.handle_config(DivPipeCoreConfig(bit_width=32,
                                              fract_width=24,
                                              log2_radix=3))
 
+    @unittest.skip("really slow")
     def test_bit_width_32_fract_width_28_radix_8_comb(self):
         self.handle_config(DivPipeCoreConfig(bit_width=32,
                                              fract_width=28,
                                              log2_radix=3),
                            sync=False)
 
+    @unittest.skip("really slow")
     def test_bit_width_32_fract_width_28_radix_8(self):
         self.handle_config(DivPipeCoreConfig(bit_width=32,
                                              fract_width=28,