create SIMD pipe multiply unit test
[ieee754fpu.git] / src / ieee754 / part_mul_add / test / test_multiply.py
index 0c0b420b7f53cbeb9623207fba82eabaf8221bc1..e1120fd708126be391789c2779890c5f902fc32a 100644 (file)
@@ -14,11 +14,19 @@ import unittest
 from hashlib import sha256
 import enum
 import pdb
+from nmigen.cli import verilog, rtlil
+
+
+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: Any,
                      traces: List[Signal],
                      test_name: str) -> Simulator:
+    create_ilang(module, traces, test_name)
     return Simulator(module,
                      vcd_file=open(test_name + ".vcd", "w"),
                      gtkw_file=open(test_name + ".gtkw", "w"),
@@ -48,10 +56,10 @@ class TestPartitionPoints(unittest.TestCase):
                 self.assertEqual((yield partition_points[1]), True)
                 self.assertEqual((yield partition_points[5]), False)
                 yield partition_point_10.eq(0)
-                yield Delay(1e-6)
+                yield Delay(0.1e-6)
                 self.assertEqual((yield mask), 0xFFFD)
                 yield partition_point_10.eq(1)
-                yield Delay(1e-6)
+                yield Delay(0.1e-6)
                 self.assertEqual((yield mask), 0xFBFD)
 
             sim.add_process(async_process)
@@ -86,7 +94,7 @@ class TestPartitionedAdder(unittest.TestCase):
                                  (0x0000, 0xFFFF)]:
                         yield module.a.eq(a)
                         yield module.b.eq(b)
-                        yield Delay(1e-6)
+                        yield Delay(0.1e-6)
                         y = 0
                         for mask in mask_list:
                             y |= mask & ((a & mask) + (b & mask))
@@ -146,14 +154,14 @@ class TestAddReduce(unittest.TestCase):
         if gen_or_check == GenOrCheck.Generate:
             for i, v in zip(inputs, values):
                 yield i.eq(v)
-        yield Delay(1e-6)
+        yield Delay(0.1e-6)
         y = 0
         for mask in mask_list:
             v = 0
             for value in values:
                 v += value & mask
             y |= mask & v
-        output = (yield module.output)
+        output = (yield module.o.output)
         if gen_or_check == GenOrCheck.Check:
             self.assertEqual(y, output, f"0x{y:X} != 0x{output:X}")
         yield Tick()
@@ -227,7 +235,7 @@ class TestAddReduce(unittest.TestCase):
                     yield Tick()
             yield from generic_process(GenOrCheck.Check)
 
-        sim.add_clock(2e-6)
+        sim.add_clock(2e-6, if_exists=True)
         sim.add_process(generate_process)
         sim.add_process(check_process)
         sim.run()
@@ -250,17 +258,15 @@ class TestAddReduce(unittest.TestCase):
         module = AddReduce(inputs,
                            width,
                            register_levels,
-                           partition_points)
+                           partition_points,
+                           [])
         file_name = "add_reduce"
         if len(register_levels) != 0:
             file_name += f"-{'_'.join(map(repr, register_levels))}"
         file_name += f"-{input_count:02d}"
-        with create_simulator(module,
-                              [partition_4,
-                               partition_8,
-                               *inputs,
-                               module.output],
-                              file_name) as sim:
+        ports = [partition_4, partition_8, *inputs, module.o.output]
+        #create_ilang(module, ports, file_name)
+        with create_simulator(module, ports, file_name) as sim:
             self.subtest_run_sim(input_count,
                                  sim,
                                  partition_4,
@@ -328,11 +334,7 @@ class TestAddReduce(unittest.TestCase):
 
 
 class SIMDMulLane:
-    def __init__(self,
-                 a_signed: bool,
-                 b_signed: bool,
-                 bit_width: int,
-                 high_half: bool):
+    def __init__(self, a_signed, b_signed, bit_width, high_half):
         self.a_signed = a_signed
         self.b_signed = b_signed
         self.bit_width = bit_width
@@ -343,35 +345,35 @@ class SIMDMulLane:
             f"{self.bit_width}, {self.high_half})"
 
 
+def simd_mul(a, b, lanes):
+    output = 0
+    intermediate_output = 0
+    shift = 0
+    for lane in lanes:
+        a_signed = lane.a_signed or not lane.high_half
+        b_signed = lane.b_signed or not lane.high_half
+        mask = (1 << lane.bit_width) - 1
+        sign_bit = 1 << (lane.bit_width - 1)
+        a_part = (a >> shift) & mask
+        if a_signed and (a_part & sign_bit) != 0:
+            a_part -= 1 << lane.bit_width
+        b_part = (b >> shift) & mask
+        if b_signed and (b_part & sign_bit) != 0:
+            b_part -= 1 << lane.bit_width
+        value = a_part * b_part
+        value &= (1 << (lane.bit_width * 2)) - 1
+        intermediate_output |= value << (shift * 2)
+        if lane.high_half:
+            value >>= lane.bit_width
+        value &= mask
+        output |= value << shift
+        shift += lane.bit_width
+    return output, intermediate_output
+
 class TestMul8_16_32_64(unittest.TestCase):
-    @staticmethod
-    def simd_mul(a: int, b: int, lanes: List[SIMDMulLane]) -> Tuple[int, int]:
-        output = 0
-        intermediate_output = 0
-        shift = 0
-        for lane in lanes:
-            a_signed = lane.a_signed or not lane.high_half
-            b_signed = lane.b_signed or not lane.high_half
-            mask = (1 << lane.bit_width) - 1
-            sign_bit = 1 << (lane.bit_width - 1)
-            a_part = (a >> shift) & mask
-            if a_signed and (a_part & sign_bit) != 0:
-                a_part -= 1 << lane.bit_width
-            b_part = (b >> shift) & mask
-            if b_signed and (b_part & sign_bit) != 0:
-                b_part -= 1 << lane.bit_width
-            value = a_part * b_part
-            value &= (1 << (lane.bit_width * 2)) - 1
-            intermediate_output |= value << (shift * 2)
-            if lane.high_half:
-                value >>= lane.bit_width
-            value &= mask
-            output |= value << shift
-            shift += lane.bit_width
-        return output, intermediate_output
 
     @staticmethod
-    def get_test_cases(lanes: List[SIMDMulLane],
+    def get_tst_cases(lanes: List[SIMDMulLane],
                        keys: Iterable[int]) -> Iterable[Tuple[int, int]]:
         mask = (1 << 64) - 1
         for i in range(8):
@@ -413,13 +415,13 @@ class TestMul8_16_32_64(unittest.TestCase):
         b = 0xFEDCBA9876543210
         output = 0x0121FA00FE1C28FE
         intermediate_output = 0x0121FA0023E20B28C94DFE1C280AFEF0
-        self.assertEqual(self.simd_mul(a, b, lanes),
+        self.assertEqual(simd_mul(a, b, lanes),
                          (output, intermediate_output))
         a = 0x8123456789ABCDEF
         b = 0xFEDCBA9876543210
         output = 0x81B39CB4FE1C28FE
         intermediate_output = 0x81B39CB423E20B28C94DFE1C280AFEF0
-        self.assertEqual(self.simd_mul(a, b, lanes),
+        self.assertEqual(simd_mul(a, b, lanes),
                          (output, intermediate_output))
 
     def test_signed_mul_from_unsigned(self):
@@ -452,10 +454,10 @@ class TestMul8_16_32_64(unittest.TestCase):
         if gen_or_check == GenOrCheck.Generate:
             yield module.a.eq(a)
             yield module.b.eq(b)
-        output2, intermediate_output2 = self.simd_mul(a, b, lanes)
-        yield Delay(1e-6)
+        output2, intermediate_output2 = simd_mul(a, b, lanes)
+        yield Delay(0.1e-6)
         if gen_or_check == GenOrCheck.Check:
-            intermediate_output = (yield module._intermediate_output)
+            intermediate_output = (yield module.intermediate_output)
             self.assertEqual(intermediate_output,
                              intermediate_output2,
                              f"0x{intermediate_output:X} "
@@ -496,7 +498,7 @@ class TestMul8_16_32_64(unittest.TestCase):
                 yield module.part_pts[bit_index].eq(1)
             bit_index += 8
         self.assertEqual(part_index, 8)
-        for a, b in self.get_test_cases(lanes, ()):
+        for a, b in self.get_tst_cases(lanes, ()):
             if gen_or_check == GenOrCheck.Check:
                 with self.subTest(a=f"{a:X}", b=f"{b:X}"):
                     yield from self.subtest_value(a, b, module, lanes, gen_or_check)
@@ -521,16 +523,10 @@ class TestMul8_16_32_64(unittest.TestCase):
             file_name += f"-{'_'.join(map(repr, register_levels))}"
         ports = [module.a,
                  module.b,
-                 module._intermediate_output,
+                 module.intermediate_output,
                  module.output]
         ports.extend(module.part_ops)
         ports.extend(module.part_pts.values())
-        ports += [module._output_64,
-                  module._output_32,
-                  module._output_16,
-                  module._output_8]
-        ports.extend(module._a_signed)
-        ports.extend(module._b_signed)
         with create_simulator(module, ports, file_name) as sim:
             def process(gen_or_check: GenOrCheck) -> AsyncProcessGenerator:
                 for a_signed in False, True:
@@ -632,7 +628,7 @@ class TestMul8_16_32_64(unittest.TestCase):
                         yield Tick()
                 yield from process(GenOrCheck.Check)
 
-            sim.add_clock(2e-6)
+            sim.add_clock(2e-6, if_exists=True)
             sim.add_process(generate_process)
             sim.add_process(check_process)
             sim.run()