1 from nmigen
import Module
, Signal
, Elaboratable
2 from nmutil
.formaltest
import FHDLTestCase
3 from nmutil
.sim_util
import do_sim
, hash_256
5 from ieee754
.fpcommon
.fpbase
import MultiShift
, MultiShiftR
, MultiShiftRMerge
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
)
15 def elaborate(self
, platform
=None):
18 m
.d
.comb
+= self
.x
.eq(self
.ms
.lshift(self
.a
, self
.b
))
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
)
30 def elaborate(self
, platform
=None):
33 m
.d
.comb
+= self
.x
.eq(self
.ms
.rshift(self
.a
, self
.b
))
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
)
45 def elaborate(self
, platform
=None):
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
)
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
)
63 def elaborate(self
, platform
=None):
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
)
74 class TestMultiShift(FHDLTestCase
):
75 def check_case(self
, dut
, width
, a
, b
):
80 x
= (a
<< b
) & ((1 << width
) - 1)
84 out_x
, x
, "Output x 0x%x not equal to expected 0x%x" % (out_x
, x
))
86 def check_caser(self
, dut
, width
, a
, b
):
91 x
= (a
>> b
) & ((1 << width
) - 1)
95 out_x
, x
, "Output x 0x%x not equal to expected 0x%x" % (out_x
, x
))
97 def check_case_merge(self
, dut
, width
, a
, b
):
102 x
= (a
>> b
) & ((1 << width
) - 1) # actual shift
103 if (a
& ((2 << b
) - 1)) != 0: # mask for sticky bit
108 out_x
, x
, "\nshift %d\nInput\n%+32s\nOutput x\n%+32s != \n%+32s" %
109 (b
, bin(a
), bin(out_x
), bin(x
)))
111 def tst_multi_shift_r_merge(self
, width
):
112 dut
= MultiShiftRMergeMod(width
=width
)
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
)
120 with
do_sim(self
, dut
, [dut
.a
, dut
.b
, dut
.x
]) as sim
:
121 sim
.add_sync_process(process
)
125 def test_multi_shift_r_merge_32(self
):
126 self
.tst_multi_shift_r_merge(32)
128 def test_multi_shift_r_merge_24(self
):
129 self
.tst_multi_shift_r_merge(24)
131 def tst_multi_shift_r_mod(self
, width
):
132 dut
= MultiShiftModRMod(width
=width
)
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
)
140 with
do_sim(self
, dut
, [dut
.a
, dut
.b
, dut
.x
]) as sim
:
141 sim
.add_sync_process(process
)
145 def test_multi_shift_r_mod_32(self
):
146 self
.tst_multi_shift_r_mod(32)
148 def test_multi_shift_r_mod_24(self
):
149 self
.tst_multi_shift_r_mod(24)
151 def tst_multi_shift_r(self
, width
):
152 dut
= MultiShiftModR(width
=width
)
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
)
160 with
do_sim(self
, dut
, [dut
.a
, dut
.b
, dut
.x
]) as sim
:
161 sim
.add_sync_process(process
)
165 def test_multi_shift_r_32(self
):
166 self
.tst_multi_shift_r(32)
168 def test_multi_shift_r_24(self
):
169 self
.tst_multi_shift_r(24)
171 def tst_multi_shift_l(self
, width
):
172 dut
= MultiShiftModL(width
=width
)
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
)
180 with
do_sim(self
, dut
, [dut
.a
, dut
.b
, dut
.x
]) as sim
:
181 sim
.add_sync_process(process
)
185 def test_multi_shift_l_32(self
):
186 self
.tst_multi_shift_l(32)
188 def test_multi_shift_l_24(self
):
189 self
.tst_multi_shift_l(24)
192 if __name__
== '__main__':