1 # SPDX-License-Identifier: LGPL-3-or-later
2 # Copyright 2022 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
, Const
, unsigned
, Cat
)
9 from nmigen
.hdl
.dsl
import Module
10 from nmutil
.formaltest
import FHDLTestCase
11 from nmigen_gf
.hdl
.cldivrem
import (equal_leading_zero_count_reference
,
12 EqualLeadingZeroCount
)
13 from nmigen
.sim
import Delay
14 from nmutil
.sim_util
import do_sim
, hash_256
17 class TestEqualLeadingZeroCount(FHDLTestCase
):
18 def tst(self
, width
, full
):
19 dut
= EqualLeadingZeroCount(width
)
20 self
.assertEqual(dut
.a
.shape(), unsigned(width
))
21 self
.assertEqual(dut
.b
.shape(), unsigned(width
))
22 self
.assertEqual(dut
.out
.shape(), unsigned(1))
25 assert isinstance(a
, int)
26 assert isinstance(b
, int)
27 expected
= a
.bit_length() == b
.bit_length()
28 with self
.subTest(a
=hex(a
), b
=hex(b
),
30 reference
= equal_leading_zero_count_reference(a
, b
, width
)
31 with self
.subTest(reference
=reference
):
32 self
.assertEqual(expected
, reference
)
34 with self
.subTest(a
=hex(a
), b
=hex(b
),
40 with self
.subTest(out
=out
):
41 self
.assertEqual(expected
, out
)
45 for a
in range(1 << width
):
46 for b
in range(1 << width
):
50 a
= hash_256(f
"eqlzc input a {i}")
51 a
= Const
.normalize(a
, dut
.a
.shape())
52 b
= hash_256(f
"eqlzc input b {i}")
53 b
= Const
.normalize(b
, dut
.b
.shape())
56 with
do_sim(self
, dut
, [dut
.a
, dut
.b
, dut
.out
]) as sim
:
57 sim
.add_process(process
)
60 def tst_formal(self
, width
):
61 dut
= EqualLeadingZeroCount(width
)
63 m
.submodules
.dut
= dut
64 m
.d
.comb
+= dut
.a
.eq(AnyConst(width
))
65 m
.d
.comb
+= dut
.b
.eq(AnyConst(width
))
66 # use a bunch of Value.matches() and boolean logic rather than a
67 # giant Switch()/If() to avoid
68 # https://github.com/YosysHQ/yosys/issues/3268
70 for leading_zeros
in range(width
+ 1):
71 pattern
= '0' * leading_zeros
+ '1' + '-' * width
72 pattern
= pattern
[0:width
]
73 a_has_count
= Signal(name
=f
"a_has_{leading_zeros}")
74 b_has_count
= Signal(name
=f
"b_has_{leading_zeros}")
76 a_has_count
.eq(dut
.a
.matches(pattern
)),
77 b_has_count
.eq(dut
.b
.matches(pattern
)),
79 expected_v |
= a_has_count
& b_has_count
81 m
.d
.comb
+= expected
.eq(expected_v
)
82 m
.d
.comb
+= Assert(dut
.out
== expected
)
86 self
.tst(64, full
=False)
89 self
.tst(8, full
=False)
92 self
.tst(3, full
=True)
94 def test_formal_64(self
):
97 def test_formal_8(self
):
100 def test_formal_3(self
):
103 # TODO: add TestCLDivRem
106 if __name__
== "__main__":