Modify gt experiment to handle eq as well
[ieee754fpu.git] / src / ieee754 / part / test / test_partsig.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: LGPL-2.1-or-later
3 # See Notices.txt for copyright information
4
5 from nmigen import Signal, Module, Elaboratable
6 from nmigen.back.pysim import Simulator, Delay, Tick, Passive
7 from nmigen.cli import verilog, rtlil
8
9 from ieee754.part.partsig import PartitionedSignal
10
11 import unittest
12
13 def create_ilang(dut, traces, test_name):
14 vl = rtlil.convert(dut, ports=traces)
15 with open("%s.il" % test_name, "w") as f:
16 f.write(vl)
17
18
19 def create_simulator(module, traces, test_name):
20 create_ilang(module, traces, test_name)
21 return Simulator(module,
22 vcd_file=open(test_name + ".vcd", "w"),
23 gtkw_file=open(test_name + ".gtkw", "w"),
24 traces=traces)
25
26 class TestAddMod(Elaboratable):
27 def __init__(self, width, partpoints):
28 self.a = PartitionedSignal(partpoints, width)
29 self.b = PartitionedSignal(partpoints, width)
30 self.add_output = Signal(width)
31 self.eq_output = Signal(len(partpoints)+1)
32
33 def elaborate(self, platform):
34 m = Module()
35 self.a.set_module(m)
36 self.b.set_module(m)
37 m.d.comb += self.eq_output.eq(self.a == self.b)
38 m.d.comb += self.add_output.eq(self.a + self.b)
39
40 return m
41
42
43 class TestPartitionPoints(unittest.TestCase):
44 def test(self):
45 width = 16
46 part_mask = Signal(4) # divide into 4-bits
47 module = TestAddMod(width, part_mask)
48
49 sim = create_simulator(module,
50 [part_mask,
51 module.a.sig,
52 module.b.sig,
53 module.add_output,
54 module.eq_output],
55 "part_sig_add")
56 def async_process():
57 def test_add(msg_prefix, *mask_list):
58 for a, b in [(0x0000, 0x0000),
59 (0x1234, 0x1234),
60 (0xABCD, 0xABCD),
61 (0xFFFF, 0x0000),
62 (0x0000, 0x0000),
63 (0xFFFF, 0xFFFF),
64 (0x0000, 0xFFFF)]:
65 yield module.a.eq(a)
66 yield module.b.eq(b)
67 yield Delay(0.1e-6)
68 y = 0
69 for mask in mask_list:
70 y |= mask & ((a & mask) + (b & mask))
71 outval = (yield module.add_output)
72 msg = f"{msg_prefix}: 0x{a:X} + 0x{b:X}" + \
73 f" => 0x{y:X} != 0x{outval:X}"
74 self.assertEqual(y, outval, msg)
75 yield part_mask.eq(0)
76 yield from test_add("16-bit", 0xFFFF)
77 yield part_mask.eq(0b10)
78 yield from test_add("8-bit", 0xFF00, 0x00FF)
79 yield part_mask.eq(0b1111)
80 yield from test_add("4-bit", 0xF000, 0x0F00, 0x00F0, 0x000F)
81
82 def test_eq(msg_prefix, *maskbit_list):
83 for a, b in [(0x0000, 0x0000),
84 (0x1234, 0x1234),
85 (0xABCD, 0xABCD),
86 (0xFFFF, 0x0000),
87 (0x0000, 0x0000),
88 (0xFFFF, 0xFFFF),
89 (0x0000, 0xFFFF)]:
90 yield module.a.eq(a)
91 yield module.b.eq(b)
92 yield Delay(0.1e-6)
93 # convert to mask_list
94 mask_list = []
95 for mb in maskbit_list:
96 v = 0
97 for i in range(4):
98 if mb & (1<<i):
99 v |= 0xf << (i*4)
100 mask_list.append(v)
101 y = 0
102 # do the partitioned tests
103 for i, mask in enumerate(mask_list):
104 if (a & mask) == (b & mask):
105 y |= maskbit_list[i]
106 # check the result
107 outval = (yield module.eq_output)
108 msg = f"{msg_prefix}: 0x{a:X} + 0x{b:X}" + \
109 f" => 0x{y:X} != 0x{outval:X}, masklist %s"
110 #print ((msg % str(maskbit_list)).format(locals()))
111 self.assertEqual(y, outval, msg % str(maskbit_list))
112 yield part_mask.eq(0)
113 yield from test_eq("16-bit", 0b1111)
114 yield part_mask.eq(0b10)
115 yield from test_eq("8-bit", 0b1100, 0b0011)
116 yield part_mask.eq(0b1111)
117 yield from test_eq("4-bit", 0b1000, 0b0100, 0b0010, 0b0001)
118
119 sim.add_process(async_process)
120 sim.run()
121
122 if __name__ == '__main__':
123 unittest.main()
124