Coverage for hdl_registers/field/test/test_bit_vector.py: 100%
124 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 11:11 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 11:11 +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# --------------------------------------------------------------------------------------------------
10import pytest
12from hdl_registers.field.bit_vector import BitVector
13from hdl_registers.field.numerical_interpretation import (
14 Signed,
15 SignedFixedPoint,
16 Unsigned,
17 UnsignedFixedPoint,
18)
21def test_get_value_plain():
22 field = BitVector(name="", base_index=2, description="", width=4, default_value="0000")
24 register_value = int("1110000_11", base=2)
25 assert field.get_value(register_value) == 0
27 register_value = int("0001111_00", base=2)
28 assert field.get_value(register_value) == 15
30 register_value = int("1010101_01", base=2)
31 assert field.get_value(register_value) == 5
34def test_get_value_fixed():
35 field = BitVector(
36 name="",
37 base_index=2,
38 description="",
39 width=16,
40 default_value="0" * 16,
41 numerical_interpretation=SignedFixedPoint.from_bit_widths(
42 integer_bit_width=8, fraction_bit_width=8
43 ),
44 )
45 register_value = 0b11111111_00000011_11111111_11111100
46 assert field.get_value(register_value) == -0.00390625
49def test_set_value():
50 bit_vector = BitVector(
51 name="", base_index=0, description="", width=2, default_value=format(0, "02b")
52 )
53 assert bit_vector.set_value(0b10) == 0b10
54 assert bit_vector.set_value(0b11) == 0b11
56 with pytest.raises(ValueError):
57 bit_vector.set_value(0b111)
59 bit_vector = BitVector(
60 name="", base_index=2, description="", width=2, default_value=format(0, "02b")
61 )
62 assert bit_vector.set_value(0b10) == 0b10_00
64 bit_vector = BitVector(
65 name="", base_index=3, description="", width=4, default_value=format(0, "04b")
66 )
67 assert bit_vector.set_value(0b1111) == 0b1111_000
69 bit_vector0 = BitVector(name="", base_index=0, description="", width=2, default_value="00")
70 bit_vector1 = BitVector(name="", base_index=2, description="", width=4, default_value="0000")
71 bit_vector2 = BitVector(name="", base_index=6, description="", width=3, default_value="000")
73 register_value = int("111000011", base=2)
74 value0 = bit_vector0.set_value(bit_vector0.get_value(register_value))
75 value1 = bit_vector1.set_value(bit_vector1.get_value(register_value))
76 value2 = bit_vector2.set_value(bit_vector2.get_value(register_value))
77 assert value0 | value1 | value2 == register_value
79 register_value = int("000111100", base=2)
80 value0 = bit_vector0.set_value(bit_vector0.get_value(register_value))
81 value1 = bit_vector1.set_value(bit_vector1.get_value(register_value))
82 value2 = bit_vector2.set_value(bit_vector2.get_value(register_value))
83 assert value0 | value1 | value2 == register_value
85 register_value = int("101010101", base=2)
86 value0 = bit_vector0.set_value(bit_vector0.get_value(register_value))
87 value1 = bit_vector1.set_value(bit_vector1.get_value(register_value))
88 value2 = bit_vector2.set_value(bit_vector2.get_value(register_value))
89 assert value0 | value1 | value2 == register_value
91 # Test numerical_interpretation
92 field = BitVector(
93 name="",
94 base_index=2,
95 description="",
96 width=16,
97 default_value="0" * 16,
98 numerical_interpretation=SignedFixedPoint.from_bit_widths(
99 integer_bit_width=8, fraction_bit_width=8
100 ),
101 )
102 assert field.set_value(-0.00390625) == 0b11_11111111_11111100
105def test_min_and_max_value():
106 bit_vector = BitVector(name="", base_index=0, description="", width=4, default_value="0000")
107 assert bit_vector.numerical_interpretation.min_value == 0
108 assert bit_vector.numerical_interpretation.max_value == 15
110 bit_vector = BitVector(
111 name="",
112 base_index=0,
113 description="",
114 width=4,
115 default_value="0000",
116 numerical_interpretation=Signed(bit_width=4),
117 )
118 assert bit_vector.numerical_interpretation.min_value == -8
119 assert bit_vector.numerical_interpretation.max_value == 7
121 bit_vector = BitVector(
122 name="",
123 base_index=0,
124 description="",
125 width=4,
126 default_value="0000",
127 numerical_interpretation=UnsignedFixedPoint(1, -2),
128 )
129 assert bit_vector.numerical_interpretation.min_value == 0
130 assert bit_vector.numerical_interpretation.max_value == 3.75
132 bit_vector = BitVector(
133 name="",
134 base_index=0,
135 description="",
136 width=4,
137 default_value="0000",
138 numerical_interpretation=SignedFixedPoint(1, -2),
139 )
140 assert bit_vector.numerical_interpretation.min_value == -2
141 assert bit_vector.numerical_interpretation.max_value == 1.75
144def test_repr():
145 # Check that repr is an actual representation, not just "X object at 0xABCDEF"
146 assert "apa" in repr(
147 BitVector(name="apa", base_index=0, description="", width=1, default_value="0")
148 )
150 # Different name
151 assert repr(
152 BitVector(name="apa", base_index=0, description="", width=1, default_value="0")
153 ) != repr(BitVector(name="hest", base_index=0, description="", width=1, default_value="0"))
155 # Different base_index
156 assert repr(
157 BitVector(name="apa", base_index=0, description="", width=1, default_value="0")
158 ) != repr(BitVector(name="apa", base_index=1, description="", width=1, default_value="0"))
160 # Different description
161 assert repr(
162 BitVector(name="apa", base_index=0, description="Blah", width=1, default_value="0")
163 ) != repr(BitVector(name="apa", base_index=0, description="Gaah", width=1, default_value="0"))
165 # Different width
166 assert repr(
167 BitVector(name="apa", base_index=0, description="", width=1, default_value="1")
168 ) != repr(BitVector(name="apa", base_index=0, description="", width=2, default_value="11"))
170 # Different default_value
171 assert repr(
172 BitVector(name="apa", base_index=0, description="", width=1, default_value="1")
173 ) != repr(BitVector(name="apa", base_index=0, description="", width=1, default_value="0"))
175 # Different numerical_interpretation
176 field0 = BitVector(
177 name="apa",
178 base_index=0,
179 description="",
180 width=10,
181 default_value="0" * 10,
182 numerical_interpretation=UnsignedFixedPoint(max_bit_index=7, min_bit_index=-2),
183 )
184 field1 = BitVector(
185 name="apa",
186 base_index=0,
187 description="",
188 width=10,
189 default_value="0" * 10,
190 numerical_interpretation=UnsignedFixedPoint(max_bit_index=7, min_bit_index=-2),
191 )
192 field2 = BitVector(
193 name="apa",
194 base_index=0,
195 description="",
196 width=10,
197 default_value="0" * 10,
198 numerical_interpretation=UnsignedFixedPoint(max_bit_index=8, min_bit_index=-1),
199 )
200 assert repr(field0) == repr(field1) != repr(field2)
203def test_invalid_width():
204 with pytest.raises(TypeError) as exception_info:
205 BitVector(name="foo", base_index=0, width="4", description="", default_value="0000")
206 assert (
207 str(exception_info.value)
208 == 'Bit vector "foo" should have integer value for "width". Got: "4".'
209 )
211 with pytest.raises(ValueError) as exception_info:
212 BitVector(name="foo", base_index=0, width=33, description="", default_value="0")
213 assert str(exception_info.value) == 'Invalid width for bit vector "foo". Got: "33".'
215 with pytest.raises(ValueError) as exception_info:
216 BitVector(name="foo", base_index=0, width=0, description="", default_value="0")
217 assert str(exception_info.value) == 'Invalid width for bit vector "foo". Got: "0".'
220def test_invalid_default_value_should_raise_exception():
221 with pytest.raises(TypeError) as exception_info:
222 BitVector(name="hest", base_index=0, description="", width=4, default_value=1111)
223 assert str(exception_info.value) == (
224 'Bit vector "hest" should have string value for "default_value". Got: "1111"'
225 )
227 with pytest.raises(ValueError) as exception_info:
228 BitVector(name="hest", base_index=0, description="", width=4, default_value="11")
229 assert str(exception_info.value) == (
230 'Bit vector "hest" should have "default_value" of length 4. Got: "11".'
231 )
233 with pytest.raises(ValueError) as exception_info:
234 BitVector(name="hest", base_index=0, description="", width=4, default_value="1121")
235 assert str(exception_info.value) == (
236 'Bit vector "hest" invalid binary value for "default_value". Got: "1121".'
237 )
240def test_can_update_default_value():
241 bit_vector = BitVector(name="hest", base_index=0, description="", width=4, default_value="1111")
242 assert bit_vector.default_value == "1111"
244 bit_vector.default_value = "0000"
245 assert bit_vector.default_value == "0000"
248def test_updating_to_invalid_default_value_should_raise_exception():
249 # Create with a valid default_value
250 bit_vector = BitVector(name="hest", base_index=0, description="", width=4, default_value="1111")
252 # Update to an invalid value
253 with pytest.raises(TypeError) as exception_info:
254 bit_vector.default_value = 1111
255 assert str(exception_info.value) == (
256 'Bit vector "hest" should have string value for "default_value". Got: "1111"'
257 )
260def test_default_value_uint():
261 bit_vector = BitVector(name="apa", base_index=0, description="", width=4, default_value="0000")
262 assert bit_vector.default_value_uint == 0
264 bit_vector.default_value = "0010"
265 assert bit_vector.default_value_uint == 2
267 bit_vector.default_value = "1001"
268 assert bit_vector.default_value_uint == 9
271def test_numeric_interpretation():
272 bit_vector = BitVector(name="", base_index=5, description="", width=4, default_value="1111")
273 assert isinstance(bit_vector.numerical_interpretation, Unsigned)
274 assert bit_vector.numerical_interpretation.bit_width == 4
276 numerical_interpretation = Signed(bit_width=10)
277 bit_vector = BitVector(
278 name="",
279 base_index=0,
280 description="",
281 width=10,
282 default_value="1111111111",
283 numerical_interpretation=numerical_interpretation,
284 )
285 assert bit_vector.numerical_interpretation is numerical_interpretation
288def test_invalid_numerical_interpretation_width_should_raise_exception():
289 def test(numerical_interpretation):
290 with pytest.raises(ValueError) as exception_info:
291 BitVector(
292 name="apa",
293 base_index=0,
294 description="",
295 width=4,
296 default_value="1111",
297 numerical_interpretation=numerical_interpretation,
298 )
300 bit_width = (
301 numerical_interpretation.integer_bit_width + numerical_interpretation.fraction_bit_width
302 )
303 expected = (
304 f'Inconsistent width for bit vector "apa". '
305 f'Field is "4" bits, numerical interpretation specification is "{bit_width}".'
306 )
307 assert str(exception_info.value) == expected
309 test(SignedFixedPoint(max_bit_index=7, min_bit_index=0))
310 test(UnsignedFixedPoint(max_bit_index=9, min_bit_index=-3))
312 test(SignedFixedPoint(max_bit_index=5, min_bit_index=0))
313 test(UnsignedFixedPoint(max_bit_index=3, min_bit_index=-3))