1 # SPDX-License-Identifier: LGPL-3-or-later
2 # Copyright 2021 Jacob Lifshay
4 # Funded by NLnet Assure Programme 2021-02-052, https://nlnet.nl/assure part
5 # of Horizon 2020 EU Programme 957073.
8 from nmigen
.hdl
.ast
import AnyConst
, Assert
, Signal
9 from nmigen
.hdl
.dsl
import Module
10 from nmutil
.formaltest
import FHDLTestCase
11 from nmutil
.lut
import BitwiseMux
, BitwiseLut
, TreeBitwiseLut
12 from nmigen
.sim
import Delay
13 from nmutil
.sim_util
import do_sim
, hash_256
16 class TestBitwiseMux(FHDLTestCase
):
19 dut
= BitwiseMux(width
)
21 def case(sel
, t
, f
, expected
):
22 with self
.subTest(sel
=bin(sel
), t
=bin(t
), f
=bin(f
)):
27 output
= yield dut
.output
28 with self
.subTest(output
=bin(output
), expected
=bin(expected
)):
29 self
.assertEqual(expected
, output
)
32 for sel
in range(2 ** width
):
33 for t
in range(2 ** width
):
34 for f
in range(2**width
):
36 for i
in range(width
):
42 yield from case(sel
, t
, f
, expected
)
43 with
do_sim(self
, dut
, [dut
.sel
, dut
.t
, dut
.f
, dut
.output
]) as sim
:
44 sim
.add_process(process
)
47 def test_formal(self
):
49 dut
= BitwiseMux(width
)
51 m
.submodules
.dut
= dut
52 m
.d
.comb
+= dut
.sel
.eq(AnyConst(width
))
53 m
.d
.comb
+= dut
.f
.eq(AnyConst(width
))
54 m
.d
.comb
+= dut
.t
.eq(AnyConst(width
))
55 for i
in range(width
):
56 with m
.If(dut
.sel
[i
]):
57 m
.d
.comb
+= Assert(dut
.t
[i
] == dut
.output
[i
])
59 m
.d
.comb
+= Assert(dut
.f
[i
] == dut
.output
[i
])
63 class TestBitwiseLut(FHDLTestCase
):
66 mask
= 2 ** dut
.width
- 1
67 lut_mask
= 2 ** dut
.lut
.width
- 1
69 def case(in0
, in1
, in2
, lut
):
71 for i
in range(dut
.width
):
79 if lut
& 2 ** lut_index
:
81 with self
.subTest(in0
=bin(in0
), in1
=bin(in1
), in2
=bin(in2
),
83 yield dut
.inputs
[0].eq(in0
)
84 yield dut
.inputs
[1].eq(in1
)
85 yield dut
.inputs
[2].eq(in2
)
88 output
= yield dut
.output
89 with self
.subTest(output
=bin(output
), expected
=bin(expected
)):
90 self
.assertEqual(expected
, output
)
93 for shift
in range(dut
.lut
.width
):
94 with self
.subTest(shift
=shift
):
95 yield from case(in0
=0xAAAA, in1
=0xCCCC, in2
=0xF0F0,
97 for case_index
in range(100):
98 with self
.subTest(case_index
=case_index
):
99 in0
= hash_256(f
"{case_index} in0") & mask
100 in1
= hash_256(f
"{case_index} in1") & mask
101 in2
= hash_256(f
"{case_index} in2") & mask
102 lut
= hash_256(f
"{case_index} lut") & lut_mask
103 yield from case(in0
, in1
, in2
, lut
)
104 with
do_sim(self
, dut
, [*dut
.inputs
, dut
.lut
, dut
.output
]) as sim
:
105 sim
.add_process(process
)
108 def tst_formal(self
, cls
):
111 m
.submodules
.dut
= dut
112 m
.d
.comb
+= dut
.inputs
[0].eq(AnyConst(dut
.width
))
113 m
.d
.comb
+= dut
.inputs
[1].eq(AnyConst(dut
.width
))
114 m
.d
.comb
+= dut
.inputs
[2].eq(AnyConst(dut
.width
))
115 m
.d
.comb
+= dut
.lut
.eq(AnyConst(dut
.lut
.width
))
116 for i
in range(dut
.width
):
117 lut_index
= Signal(dut
.input_count
, name
=f
"lut_index_{i}")
118 for j
in range(dut
.input_count
):
119 m
.d
.comb
+= lut_index
[j
].eq(dut
.inputs
[j
][i
])
120 for j
in range(dut
.lut
.width
):
121 with m
.If(lut_index
== j
):
122 m
.d
.comb
+= Assert(dut
.lut
[j
] == dut
.output
[i
])
129 self
.tst(TreeBitwiseLut
)
131 def test_formal(self
):
132 self
.tst_formal(BitwiseLut
)
134 def test_tree_formal(self
):
135 self
.tst_formal(TreeBitwiseLut
)
138 if __name__
== "__main__":