eb12b8a601cad98a12badbf151a0b45d68247a95
2 # SPDX-License-Identifier: LGPL-2.1-or-later
3 # See Notices.txt for copyright information
5 from nmigen
import Signal
, Module
, Elaboratable
6 from nmigen
.back
.pysim
import Simulator
, Delay
, Tick
, Passive
7 from nmigen
.cli
import verilog
, rtlil
9 from ieee754
.part
.partsig
import PartitionedSignal
10 from ieee754
.part_mux
.part_mux
import PMux
14 def create_ilang(dut
, traces
, test_name
):
15 vl
= rtlil
.convert(dut
, ports
=traces
)
16 with
open("%s.il" % test_name
, "w") as f
:
20 def create_simulator(module
, traces
, test_name
):
21 create_ilang(module
, traces
, test_name
)
22 return Simulator(module
,
23 vcd_file
=open(test_name
+ ".vcd", "w"),
24 gtkw_file
=open(test_name
+ ".gtkw", "w"),
27 class TestAddMod(Elaboratable
):
28 def __init__(self
, width
, partpoints
):
29 self
.a
= PartitionedSignal(partpoints
, width
)
30 self
.b
= PartitionedSignal(partpoints
, width
)
31 self
.add_output
= Signal(width
)
32 self
.eq_output
= Signal(len(partpoints
)+1)
33 self
.gt_output
= Signal(len(partpoints
)+1)
34 self
.ge_output
= Signal(len(partpoints
)+1)
35 self
.ne_output
= Signal(len(partpoints
)+1)
36 self
.lt_output
= Signal(len(partpoints
)+1)
37 self
.le_output
= Signal(len(partpoints
)+1)
38 self
.mux_sel
= Signal(len(partpoints
)+1)
39 self
.mux_out
= Signal(width
)
41 def elaborate(self
, platform
):
45 m
.d
.comb
+= self
.lt_output
.eq(self
.a
< self
.b
)
46 m
.d
.comb
+= self
.ne_output
.eq(self
.a
!= self
.b
)
47 m
.d
.comb
+= self
.le_output
.eq(self
.a
<= self
.b
)
48 m
.d
.comb
+= self
.gt_output
.eq(self
.a
> self
.b
)
49 m
.d
.comb
+= self
.eq_output
.eq(self
.a
== self
.b
)
50 m
.d
.comb
+= self
.ge_output
.eq(self
.a
>= self
.b
)
51 m
.d
.comb
+= self
.add_output
.eq(self
.a
+ self
.b
)
52 m
.d
.comb
+= self
.mux_out
.eq(PMux(m
, self
.a
, self
.b
, self
.mux_sel
))
57 class TestPartitionPoints(unittest
.TestCase
):
60 part_mask
= Signal(4) # divide into 4-bits
61 module
= TestAddMod(width
, part_mask
)
63 sim
= create_simulator(module
,
71 def test_add(msg_prefix
, *mask_list
):
72 for a
, b
in [(0x0000, 0x0000),
83 for mask
in mask_list
:
84 y |
= mask
& ((a
& mask
) + (b
& mask
))
85 outval
= (yield module
.add_output
)
86 msg
= f
"{msg_prefix}: 0x{a:X} + 0x{b:X}" + \
87 f
" => 0x{y:X} != 0x{outval:X}"
88 self
.assertEqual(y
, outval
, msg
)
90 yield from test_add("16-bit", 0xFFFF)
91 yield part_mask
.eq(0b10)
92 yield from test_add("8-bit", 0xFF00, 0x00FF)
93 yield part_mask
.eq(0b1111)
94 yield from test_add("4-bit", 0xF000, 0x0F00, 0x00F0, 0x000F)
96 def test_ne_fn(a
, b
, mask
):
97 return (a
& mask
) != (b
& mask
)
99 def test_lt_fn(a
, b
, mask
):
100 return (a
& mask
) < (b
& mask
)
102 def test_le_fn(a
, b
, mask
):
103 return (a
& mask
) <= (b
& mask
)
105 def test_eq_fn(a
, b
, mask
):
106 return (a
& mask
) == (b
& mask
)
108 def test_gt_fn(a
, b
, mask
):
109 return (a
& mask
) > (b
& mask
)
111 def test_ge_fn(a
, b
, mask
):
112 return (a
& mask
) >= (b
& mask
)
114 def test_binop(msg_prefix
, test_fn
, mod_attr
, *maskbit_list
):
115 for a
, b
in [(0x0000, 0x0000),
128 # convert to mask_list
130 for mb
in maskbit_list
:
137 # do the partitioned tests
138 for i
, mask
in enumerate(mask_list
):
139 if test_fn(a
, b
, mask
):
140 # OR y with the lowest set bit in the mask
143 outval
= (yield getattr(module
, "%s_output" % mod_attr
))
144 msg
= f
"{msg_prefix}: {mod_attr} 0x{a:X} == 0x{b:X}" + \
145 f
" => 0x{y:X} != 0x{outval:X}, masklist %s"
146 print ((msg
% str(maskbit_list
)).format(locals()))
147 self
.assertEqual(y
, outval
, msg
% str(maskbit_list
))
149 for (test_fn
, mod_attr
) in ((test_eq_fn
, "eq"),
156 yield part_mask
.eq(0)
157 yield from test_binop("16-bit", test_fn
, mod_attr
, 0b1111)
158 yield part_mask
.eq(0b10)
159 yield from test_binop("8-bit", test_fn
, mod_attr
,
161 yield part_mask
.eq(0b1111)
162 yield from test_binop("4-bit", test_fn
, mod_attr
,
163 0b1000, 0b0100, 0b0010, 0b0001)
165 def test_muxop(msg_prefix
, *maskbit_list
):
166 for a
, b
, sel
in [(0x0000, 0x0000, 0b0110),
167 (0x1234, 0x1234, 0b1010),
168 (0xABCD, 0xABCD, 0b1100),
169 (0xFFFF, 0x0000, 0b0011),
170 (0x0000, 0x0000, 0b1001),
171 (0xFFFF, 0xFFFF, 0b1101),
172 (0x0000, 0xFFFF, 0b1100)]:
175 yield module
.mux_sel
.eq(sel
)
177 # convert to mask_list
179 for mb
in maskbit_list
:
186 # do the partitioned tests
187 for i
, mask
in enumerate(mask_list
):
193 outval
= (yield module
.mux_out
)
194 msg
= f
"{msg_prefix}: mux 0x{a:X} == 0x{b:X}" + \
195 f
" => 0x{y:X} != 0x{outval:X}, masklist %s"
196 #print ((msg % str(maskbit_list)).format(locals()))
197 self
.assertEqual(y
, outval
, msg
% str(maskbit_list
))
199 yield part_mask
.eq(0)
200 yield from test_muxop("16-bit", 0b1111)
201 yield part_mask
.eq(0b10)
202 yield from test_muxop("8-bit", 0b1100, 0b0011)
203 yield part_mask
.eq(0b1111)
204 yield from test_muxop("4-bit", 0b1000, 0b0100, 0b0010, 0b0001)
206 sim
.add_process(async_process
)
209 if __name__
== '__main__':