switch to exact version of cython
[ieee754fpu.git] / src / ieee754 / add / test_multishift.py
1 from nmigen import Module, Signal, Elaboratable
2 from nmutil.formaltest import FHDLTestCase
3 from nmutil.sim_util import do_sim, hash_256
4 import unittest
5 from ieee754.fpcommon.fpbase import MultiShift, MultiShiftR, MultiShiftRMerge
6
7
8 class MultiShiftModL(Elaboratable):
9 def __init__(self, width):
10 self.ms = MultiShift(width)
11 self.a = Signal(width)
12 self.b = Signal(self.ms.smax)
13 self.x = Signal(width)
14
15 def elaborate(self, platform=None):
16
17 m = Module()
18 m.d.comb += self.x.eq(self.ms.lshift(self.a, self.b))
19
20 return m
21
22
23 class MultiShiftModR(Elaboratable):
24 def __init__(self, width):
25 self.ms = MultiShift(width)
26 self.a = Signal(width)
27 self.b = Signal(self.ms.smax)
28 self.x = Signal(width)
29
30 def elaborate(self, platform=None):
31
32 m = Module()
33 m.d.comb += self.x.eq(self.ms.rshift(self.a, self.b))
34
35 return m
36
37
38 class MultiShiftModRMod(Elaboratable):
39 def __init__(self, width):
40 self.ms = MultiShiftR(width)
41 self.a = Signal(width)
42 self.b = Signal(self.ms.smax)
43 self.x = Signal(width)
44
45 def elaborate(self, platform=None):
46
47 m = Module()
48 m.submodules += self.ms
49 m.d.comb += self.ms.i.eq(self.a)
50 m.d.comb += self.ms.s.eq(self.b)
51 m.d.comb += self.x.eq(self.ms.o)
52
53 return m
54
55
56 class MultiShiftRMergeMod(Elaboratable):
57 def __init__(self, width):
58 self.ms = MultiShiftRMerge(width)
59 self.a = Signal(width)
60 self.b = Signal(self.ms.smax)
61 self.x = Signal(width)
62
63 def elaborate(self, platform=None):
64
65 m = Module()
66 m.submodules += self.ms
67 m.d.comb += self.ms.inp.eq(self.a)
68 m.d.comb += self.ms.diff.eq(self.b)
69 m.d.comb += self.x.eq(self.ms.m)
70
71 return m
72
73
74 class TestMultiShift(FHDLTestCase):
75 def check_case(self, dut, width, a, b):
76 yield dut.a.eq(a)
77 yield dut.b.eq(b)
78 yield
79
80 x = (a << b) & ((1 << width) - 1)
81
82 out_x = yield dut.x
83 self.assertEqual(
84 out_x, x, "Output x 0x%x not equal to expected 0x%x" % (out_x, x))
85
86 def check_caser(self, dut, width, a, b):
87 yield dut.a.eq(a)
88 yield dut.b.eq(b)
89 yield
90
91 x = (a >> b) & ((1 << width) - 1)
92
93 out_x = yield dut.x
94 self.assertEqual(
95 out_x, x, "Output x 0x%x not equal to expected 0x%x" % (out_x, x))
96
97 def check_case_merge(self, dut, width, a, b):
98 yield dut.a.eq(a)
99 yield dut.b.eq(b)
100 yield
101
102 x = (a >> b) & ((1 << width) - 1) # actual shift
103 if (a & ((2 << b) - 1)) != 0: # mask for sticky bit
104 x |= 1 # set LSB
105
106 out_x = yield dut.x
107 self.assertEqual(
108 out_x, x, "\nshift %d\nInput\n%+32s\nOutput x\n%+32s != \n%+32s" %
109 (b, bin(a), bin(out_x), bin(x)))
110
111 def tst_multi_shift_r_merge(self, width):
112 dut = MultiShiftRMergeMod(width=width)
113
114 def process():
115 for i in range(width):
116 for j in range(1000):
117 a = hash_256(f"MultiShiftRMerge {i} {j}") % (1 << width)
118 yield from self.check_case_merge(dut, width, a, i)
119
120 with do_sim(self, dut, [dut.a, dut.b, dut.x]) as sim:
121 sim.add_sync_process(process)
122 sim.add_clock(1e-6)
123 sim.run()
124
125 def test_multi_shift_r_merge_32(self):
126 self.tst_multi_shift_r_merge(32)
127
128 def test_multi_shift_r_merge_24(self):
129 self.tst_multi_shift_r_merge(24)
130
131 def tst_multi_shift_r_mod(self, width):
132 dut = MultiShiftModRMod(width=width)
133
134 def process():
135 for i in range(width):
136 for j in range(1000):
137 a = hash_256(f"MultiShiftRMod {i} {j}") % (1 << width)
138 yield from self.check_caser(dut, width, a, i)
139
140 with do_sim(self, dut, [dut.a, dut.b, dut.x]) as sim:
141 sim.add_sync_process(process)
142 sim.add_clock(1e-6)
143 sim.run()
144
145 def test_multi_shift_r_mod_32(self):
146 self.tst_multi_shift_r_mod(32)
147
148 def test_multi_shift_r_mod_24(self):
149 self.tst_multi_shift_r_mod(24)
150
151 def tst_multi_shift_r(self, width):
152 dut = MultiShiftModR(width=width)
153
154 def process():
155 for i in range(width):
156 for j in range(1000):
157 a = hash_256(f"MultiShiftModR {i} {j}") % (1 << width)
158 yield from self.check_caser(dut, width, a, i)
159
160 with do_sim(self, dut, [dut.a, dut.b, dut.x]) as sim:
161 sim.add_sync_process(process)
162 sim.add_clock(1e-6)
163 sim.run()
164
165 def test_multi_shift_r_32(self):
166 self.tst_multi_shift_r(32)
167
168 def test_multi_shift_r_24(self):
169 self.tst_multi_shift_r(24)
170
171 def tst_multi_shift_l(self, width):
172 dut = MultiShiftModL(width=width)
173
174 def process():
175 for i in range(width):
176 for j in range(1000):
177 a = hash_256(f"MultiShiftModL {i} {j}") % (1 << width)
178 yield from self.check_case(dut, width, a, i)
179
180 with do_sim(self, dut, [dut.a, dut.b, dut.x]) as sim:
181 sim.add_sync_process(process)
182 sim.add_clock(1e-6)
183 sim.run()
184
185 def test_multi_shift_l_32(self):
186 self.tst_multi_shift_l(32)
187
188 def test_multi_shift_l_24(self):
189 self.tst_multi_shift_l(24)
190
191
192 if __name__ == '__main__':
193 unittest.main()