Coverage for hdl_registers/field/test/test_bit_vector.py: 100%
124 statements
« prev ^ index » next coverage.py v7.6.8, created at 2024-12-01 20:50 +0000
« prev ^ index » next coverage.py v7.6.8, created at 2024-12-01 20:50 +0000
1# --------------------------------------------------------------------------------------------------
2# Copyright (c) Lukas Vik. All rights reserved.
3#
4# This file is part of the hdl-registers project, an HDL register generator fast enough to run
5# in real time.
6# https://hdl-registers.com
7# https://github.com/hdl-registers/hdl-registers
8# --------------------------------------------------------------------------------------------------
10# Third party libraries
11import pytest
13# First party libraries
14from hdl_registers.field.bit_vector import BitVector
15from hdl_registers.field.numerical_interpretation import (
16 Signed,
17 SignedFixedPoint,
18 Unsigned,
19 UnsignedFixedPoint,
20)
23def test_get_value_plain():
24 field = BitVector(name="", base_index=2, description="", width=4, default_value="0000")
26 register_value = int("1110000_11", base=2)
27 assert field.get_value(register_value) == 0
29 register_value = int("0001111_00", base=2)
30 assert field.get_value(register_value) == 15
32 register_value = int("1010101_01", base=2)
33 assert field.get_value(register_value) == 5
36def test_get_value_fixed():
37 field = BitVector(
38 name="",
39 base_index=2,
40 description="",
41 width=16,
42 default_value="0" * 16,
43 numerical_interpretation=SignedFixedPoint.from_bit_widths(
44 integer_bit_width=8, fraction_bit_width=8
45 ),
46 )
47 register_value = 0b11111111_00000011_11111111_11111100
48 assert field.get_value(register_value) == -0.00390625
51def test_set_value():
52 bit_vector = BitVector(
53 name="", base_index=0, description="", width=2, default_value=format(0, "02b")
54 )
55 assert bit_vector.set_value(0b10) == 0b10
56 assert bit_vector.set_value(0b11) == 0b11
58 with pytest.raises(ValueError):
59 bit_vector.set_value(0b111)
61 bit_vector = BitVector(
62 name="", base_index=2, description="", width=2, default_value=format(0, "02b")
63 )
64 assert bit_vector.set_value(0b10) == 0b10_00
66 bit_vector = BitVector(
67 name="", base_index=3, description="", width=4, default_value=format(0, "04b")
68 )
69 assert bit_vector.set_value(0b1111) == 0b1111_000
71 bit_vector0 = BitVector(name="", base_index=0, description="", width=2, default_value="00")
72 bit_vector1 = BitVector(name="", base_index=2, description="", width=4, default_value="0000")
73 bit_vector2 = BitVector(name="", base_index=6, description="", width=3, default_value="000")
75 register_value = int("111000011", base=2)
76 value0 = bit_vector0.set_value(bit_vector0.get_value(register_value))
77 value1 = bit_vector1.set_value(bit_vector1.get_value(register_value))
78 value2 = bit_vector2.set_value(bit_vector2.get_value(register_value))
79 assert value0 | value1 | value2 == register_value
81 register_value = int("000111100", base=2)
82 value0 = bit_vector0.set_value(bit_vector0.get_value(register_value))
83 value1 = bit_vector1.set_value(bit_vector1.get_value(register_value))
84 value2 = bit_vector2.set_value(bit_vector2.get_value(register_value))
85 assert value0 | value1 | value2 == register_value
87 register_value = int("101010101", base=2)
88 value0 = bit_vector0.set_value(bit_vector0.get_value(register_value))
89 value1 = bit_vector1.set_value(bit_vector1.get_value(register_value))
90 value2 = bit_vector2.set_value(bit_vector2.get_value(register_value))
91 assert value0 | value1 | value2 == register_value
93 # Test numerical_interpretation
94 field = BitVector(
95 name="",
96 base_index=2,
97 description="",
98 width=16,
99 default_value="0" * 16,
100 numerical_interpretation=SignedFixedPoint.from_bit_widths(
101 integer_bit_width=8, fraction_bit_width=8
102 ),
103 )
104 assert field.set_value(-0.00390625) == 0b11_11111111_11111100
107def test_min_and_max_value():
108 bit_vector = BitVector(name="", base_index=0, description="", width=4, default_value="0000")
109 assert bit_vector.numerical_interpretation.min_value == 0
110 assert bit_vector.numerical_interpretation.max_value == 15
112 bit_vector = BitVector(
113 name="",
114 base_index=0,
115 description="",
116 width=4,
117 default_value="0000",
118 numerical_interpretation=Signed(bit_width=4),
119 )
120 assert bit_vector.numerical_interpretation.min_value == -8
121 assert bit_vector.numerical_interpretation.max_value == 7
123 bit_vector = BitVector(
124 name="",
125 base_index=0,
126 description="",
127 width=4,
128 default_value="0000",
129 numerical_interpretation=UnsignedFixedPoint(1, -2),
130 )
131 assert bit_vector.numerical_interpretation.min_value == 0
132 assert bit_vector.numerical_interpretation.max_value == 3.75
134 bit_vector = BitVector(
135 name="",
136 base_index=0,
137 description="",
138 width=4,
139 default_value="0000",
140 numerical_interpretation=SignedFixedPoint(1, -2),
141 )
142 assert bit_vector.numerical_interpretation.min_value == -2
143 assert bit_vector.numerical_interpretation.max_value == 1.75
146def test_repr():
147 # Check that repr is an actual representation, not just "X object at 0xABCDEF"
148 assert "apa" in repr(
149 BitVector(name="apa", base_index=0, description="", width=1, default_value="0")
150 )
152 # Different name
153 assert repr(
154 BitVector(name="apa", base_index=0, description="", width=1, default_value="0")
155 ) != repr(BitVector(name="hest", base_index=0, description="", width=1, default_value="0"))
157 # Different base_index
158 assert repr(
159 BitVector(name="apa", base_index=0, description="", width=1, default_value="0")
160 ) != repr(BitVector(name="apa", base_index=1, description="", width=1, default_value="0"))
162 # Different description
163 assert repr(
164 BitVector(name="apa", base_index=0, description="Blah", width=1, default_value="0")
165 ) != repr(BitVector(name="apa", base_index=0, description="Gaah", width=1, default_value="0"))
167 # Different width
168 assert repr(
169 BitVector(name="apa", base_index=0, description="", width=1, default_value="1")
170 ) != repr(BitVector(name="apa", base_index=0, description="", width=2, default_value="11"))
172 # Different default_value
173 assert repr(
174 BitVector(name="apa", base_index=0, description="", width=1, default_value="1")
175 ) != repr(BitVector(name="apa", base_index=0, description="", width=1, default_value="0"))
177 # Different numerical_interpretation
178 field0 = BitVector(
179 name="apa",
180 base_index=0,
181 description="",
182 width=10,
183 default_value="0" * 10,
184 numerical_interpretation=UnsignedFixedPoint(max_bit_index=7, min_bit_index=-2),
185 )
186 field1 = BitVector(
187 name="apa",
188 base_index=0,
189 description="",
190 width=10,
191 default_value="0" * 10,
192 numerical_interpretation=UnsignedFixedPoint(max_bit_index=7, min_bit_index=-2),
193 )
194 field2 = BitVector(
195 name="apa",
196 base_index=0,
197 description="",
198 width=10,
199 default_value="0" * 10,
200 numerical_interpretation=UnsignedFixedPoint(max_bit_index=8, min_bit_index=-1),
201 )
202 assert repr(field0) == repr(field1) != repr(field2)
205def test_invalid_width():
206 with pytest.raises(ValueError) as exception_info:
207 BitVector(name="foo", base_index=0, width="4", description="", default_value="0000")
208 assert (
209 str(exception_info.value)
210 == 'Bit vector "foo" should have integer value for "width". Got: "4".'
211 )
213 with pytest.raises(ValueError) as exception_info:
214 BitVector(name="foo", base_index=0, width=33, description="", default_value="0")
215 assert str(exception_info.value) == 'Invalid width for bit vector "foo". Got: "33".'
217 with pytest.raises(ValueError) as exception_info:
218 BitVector(name="foo", base_index=0, width=0, description="", default_value="0")
219 assert str(exception_info.value) == 'Invalid width for bit vector "foo". Got: "0".'
222def test_invalid_default_value_should_raise_exception():
223 with pytest.raises(ValueError) as exception_info:
224 BitVector(name="hest", base_index=0, description="", width=4, default_value=1111)
225 assert str(exception_info.value) == (
226 'Bit vector "hest" should have string value for "default_value". Got: "1111"'
227 )
229 with pytest.raises(ValueError) as exception_info:
230 BitVector(name="hest", base_index=0, description="", width=4, default_value="11")
231 assert str(exception_info.value) == (
232 'Bit vector "hest" should have "default_value" of length 4. Got: "11".'
233 )
235 with pytest.raises(ValueError) as exception_info:
236 BitVector(name="hest", base_index=0, description="", width=4, default_value="1121")
237 assert str(exception_info.value) == (
238 'Bit vector "hest" invalid binary value for "default_value". Got: "1121".'
239 )
242def test_can_update_default_value():
243 bit_vector = BitVector(name="hest", base_index=0, description="", width=4, default_value="1111")
244 assert bit_vector.default_value == "1111"
246 bit_vector.default_value = "0000"
247 assert bit_vector.default_value == "0000"
250def test_updating_to_invalid_default_value_should_raise_exception():
251 # Create with a valid default_value
252 bit_vector = BitVector(name="hest", base_index=0, description="", width=4, default_value="1111")
254 # Update to an invalid value
255 with pytest.raises(ValueError) as exception_info:
256 bit_vector.default_value = 1111
257 assert str(exception_info.value) == (
258 'Bit vector "hest" should have string value for "default_value". Got: "1111"'
259 )
262def test_default_value_uint():
263 bit_vector = BitVector(name="apa", base_index=0, description="", width=4, default_value="0000")
264 assert bit_vector.default_value_uint == 0
266 bit_vector.default_value = "0010"
267 assert bit_vector.default_value_uint == 2
269 bit_vector.default_value = "1001"
270 assert bit_vector.default_value_uint == 9
273def test_numeric_interpretation():
274 bit_vector = BitVector(name="", base_index=5, description="", width=4, default_value="1111")
275 assert isinstance(bit_vector.numerical_interpretation, Unsigned)
276 assert bit_vector.numerical_interpretation.bit_width == 4
278 numerical_interpretation = Signed(bit_width=10)
279 bit_vector = BitVector(
280 name="",
281 base_index=0,
282 description="",
283 width=10,
284 default_value="1111111111",
285 numerical_interpretation=numerical_interpretation,
286 )
287 assert bit_vector.numerical_interpretation is numerical_interpretation
290def test_invalid_numerical_interpretation_width_should_raise_exception():
291 def test(numerical_interpretation):
292 with pytest.raises(ValueError) as exception_info:
293 BitVector(
294 name="apa",
295 base_index=0,
296 description="",
297 width=4,
298 default_value="1111",
299 numerical_interpretation=numerical_interpretation,
300 )
302 bit_width = (
303 numerical_interpretation.integer_bit_width + numerical_interpretation.fraction_bit_width
304 )
305 expected = (
306 f'Inconsistent width for bit vector "apa". '
307 f'Field is "4" bits, numerical interpretation specification is "{bit_width}".'
308 )
309 assert str(exception_info.value) == expected
311 test(SignedFixedPoint(max_bit_index=7, min_bit_index=0))
312 test(UnsignedFixedPoint(max_bit_index=9, min_bit_index=-3))
314 test(SignedFixedPoint(max_bit_index=5, min_bit_index=0))
315 test(UnsignedFixedPoint(max_bit_index=3, min_bit_index=-3))