1 # SPDX-License-Identifier: LGPL-3-or-later
2 # See Notices.txt for copyright information
4 from typing
import Set
, Tuple
5 from nmigen
.hdl
.ast
import AnyConst
, Assert
, Assume
, Signal
6 from nmigen
.hdl
.dsl
import Module
7 from ieee754
.partitioned_signal_tester
import (
8 PartitionedSignalTester
, Layout
, Lane
, formal
)
12 class TestFormal(unittest
.TestCase
):
13 def test_formal(self
):
17 m
.d
.comb
+= a
.eq(AnyConst(10))
18 m
.d
.comb
+= b
.eq(AnyConst(10))
19 m
.d
.comb
+= Assume(a
* b
== 1021 * 1019)
20 m
.d
.comb
+= Assert((a
== 1021) |
(a
== 1019))
23 @unittest.expectedFailure
24 def test_formal_fail(self
):
28 m
.d
.comb
+= a
.eq(AnyConst(10))
29 m
.d
.comb
+= b
.eq(AnyConst(10))
30 m
.d
.comb
+= Assume(a
* b
== 1021 * 1019)
31 m
.d
.comb
+= Assert(a
== 1021)
35 class TestLayout(unittest
.TestCase
):
39 self
.assertEqual(repr(Layout({3: False, 7: True}, 16)),
40 "Layout((0, 3, 7, 16), width=16)")
41 self
.assertEqual(repr(Layout({7: False, 3: True}, 16)),
42 "Layout((0, 3, 7, 16), width=16)")
43 self
.assertEqual(repr(Layout(range(0, 10, 2), 10)),
44 "Layout((0, 2, 4, 6, 8, 10), width=10)")
45 self
.assertEqual(repr(Layout(range(0, 10, 2))),
46 "Layout((0, 2, 4, 6, 8), width=8)")
47 self
.assertEqual(repr(Layout(())),
48 "Layout((0,), width=0)")
49 self
.assertEqual(repr(Layout((1,))),
50 "Layout((0, 1), width=1)")
53 a
= Layout
.cast((1, 2, 3))
54 self
.assertEqual(repr(a
),
55 "Layout((0, 1, 2, 3), width=3)")
59 def test_part_signal_count(self
):
62 c
= Layout
.cast((1, 3))
63 d
= Layout
.cast((0, 1, 3))
64 e
= Layout
.cast((1, 2, 3))
65 self
.assertEqual(a
.part_signal_count
, 0)
66 self
.assertEqual(b
.part_signal_count
, 0)
67 self
.assertEqual(c
.part_signal_count
, 1)
68 self
.assertEqual(d
.part_signal_count
, 1)
69 self
.assertEqual(e
.part_signal_count
, 2)
73 self
.assertEqual(list(a
.lanes()), [])
75 self
.assertEqual(list(b
.lanes()), [Lane(0, 1, b
)])
76 c
= Layout
.cast((1, 3))
77 self
.assertEqual(list(c
.lanes()),
81 d
= Layout
.cast((1, 4, 5))
82 self
.assertEqual(list(d
.lanes()),
89 e
= Layout(range(0, 32, 8), 32)
90 self
.assertEqual(list(e
.lanes()),
102 def test_is_compatible(self
):
104 b
= Layout
.cast((1,))
105 c
= Layout
.cast((1, 2))
106 d
= Layout
.cast((4, 5))
107 e
= Layout
.cast((1, 2, 3, 4))
108 f
= Layout
.cast((8, 16, 24, 32))
109 compatibility_classes
= {
117 for lhs
in compatibility_classes
:
118 for rhs
in compatibility_classes
:
119 with self
.subTest(lhs
=lhs
, rhs
=rhs
):
120 self
.assertEqual(compatibility_classes
[lhs
]
121 == compatibility_classes
[rhs
],
122 lhs
.is_compatible(rhs
))
124 def test_translate_lanes_to(self
):
125 src
= Layout((0, 3, 7, 12, 13))
126 dest
= Layout((0, 8, 16, 24, 32))
127 src_lanes
= list(src
.lanes())
128 src_lanes
.sort(key
=lambda lane
: lane
.start
)
129 dest_lanes
= list(dest
.lanes())
130 dest_lanes
.sort(key
=lambda lane
: lane
.start
)
131 self
.assertEqual(len(src_lanes
), len(dest_lanes
))
132 for src_lane
, dest_lane
in zip(src_lanes
, dest_lanes
):
133 with self
.subTest(src_lane
=src_lane
, dest_lane
=dest_lane
):
134 self
.assertEqual(src_lane
.translate_to(dest
), dest_lane
)
135 self
.assertEqual(dest_lane
.translate_to(src
), src_lane
)
138 class TestLane(unittest
.TestCase
):
139 def test_is_active(self
):
140 layout
= Layout((0, 8, 16, 24, 32))
141 def do_test(part_starts
: Tuple
[bool, ...],
142 expected_lanes
: Set
[Tuple
[int, int]]):
143 with self
.subTest(part_starts
=part_starts
,
144 expected_lanes
=expected_lanes
):
145 for lane
in layout
.lanes():
146 expected
= (lane
.start
, lane
.size
) in expected_lanes
147 with self
.subTest(lane
=lane
):
148 self
.assertEqual(lane
.is_active(part_starts
),
153 do_test((_1
, _0
, _0
, _0
, _1
),
155 do_test((_1
, _0
, _0
, _1
, _1
),
157 do_test((_1
, _0
, _1
, _0
, _1
),
159 do_test((_1
, _0
, _1
, _1
, _1
),
160 {(0, 16), (16, 8), (24, 8)})
161 do_test((_1
, _1
, _0
, _0
, _1
),
163 do_test((_1
, _1
, _0
, _1
, _1
),
164 {(0, 8), (8, 16), (24, 8)})
165 do_test((_1
, _1
, _1
, _0
, _1
),
166 {(0, 8), (8, 8), (16, 16)})
167 do_test((_1
, _1
, _1
, _1
, _1
),
168 {(0, 8), (8, 8), (16, 8), (24, 8)})
170 def test_as_slice(self
):
171 slice_target
= tuple(range(8))
172 layout
= Layout((0, 2, 4, 6, 8))
173 slices
= list(slice_target
[lane
.as_slice()]
174 for lane
in layout
.lanes())
175 self
.assertEqual(slices
,
185 (0, 1, 2, 3, 4, 5, 6, 7)])
188 class TestPartitionedSignalTester(unittest
.TestCase
):
189 def test_sim_identity(self
):
191 PartitionedSignalTester(m
,
192 lambda inputs
: inputs
[0],
193 lambda lane
, inputs
: inputs
[0],
194 (0, 8, 16, 24, 32)).run_sim(self
)
196 def test_formal_identity(self
):
198 PartitionedSignalTester(m
,
199 lambda inputs
: inputs
[0],
200 lambda lane
, inputs
: inputs
[0],
201 (0, 8, 16, 24, 32)).run_formal(self
)
203 def test_sim_pass_through_input(self
):
204 for which_input
in range(0, 2):
206 PartitionedSignalTester(m
,
207 lambda inputs
: inputs
[which_input
],
208 lambda lane
, inputs
: inputs
[which_input
],
210 (0, 1, 2, 3, 4)).run_sim(self
)
212 def test_formal_pass_through_input(self
):
213 for which_input
in range(0, 2):
215 PartitionedSignalTester(m
,
216 lambda inputs
: inputs
[which_input
],
217 lambda lane
, inputs
: inputs
[which_input
],
219 (0, 1, 2, 3, 4)).run_formal(self
)
222 if __name__
== '__main__':