Coverage for hdl_registers/parser/test/test_parser/test_parser_field.py: 100%
87 statements
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-16 20:50 +0000
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-16 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# --------------------------------------------------------------------------------------------------
10import pytest
11from tsfpga.system_utils import create_file
13from hdl_registers.field.numerical_interpretation import (
14 Signed,
15 SignedFixedPoint,
16 Unsigned,
17 UnsignedFixedPoint,
18)
19from hdl_registers.parser.toml import from_toml
22def test_register_field_without_type_property_should_raise_exception(tmp_path):
23 toml_path = create_file(
24 file=tmp_path / "regs.toml",
25 contents="""
26[apa]
28mode = "r_w"
30hest.width = 4
31""",
32 )
34 with pytest.raises(ValueError) as exception_info:
35 from_toml(name="", toml_file=toml_path)
36 assert str(exception_info.value) == (
37 f'Error while parsing field "hest" in register "apa" in {toml_path}: '
38 'Missing required property "type".'
39 )
42def test_array_register_field_without_type_property_should_raise_exception(tmp_path):
43 toml_path = create_file(
44 file=tmp_path / "regs.toml",
45 contents="""
46[apa]
48type = "register_array"
49array_length = 2
51[apa.hest]
53mode = "r_w"
55zebra.width = 4
56""",
57 )
59 with pytest.raises(ValueError) as exception_info:
60 from_toml(name="", toml_file=toml_path)
61 assert str(exception_info.value) == (
62 f'Error while parsing field "zebra" in register "hest" within array "apa" in {toml_path}: '
63 'Missing required property "type".'
64 )
67def test_register_field_with_unknown_type_should_raise_exception(tmp_path):
68 toml_path = create_file(
69 file=tmp_path / "regs.toml",
70 contents="""
71[apa]
73mode = "r_w"
75hest.type = "bits"
76hest.width = 4
77""",
78 )
80 with pytest.raises(ValueError) as exception_info:
81 from_toml(name="", toml_file=toml_path)
82 assert str(exception_info.value) == (
83 f'Error while parsing field "hest" in register "apa" in {toml_path}: '
84 'Unknown field type "bits". Expected one of "bit", "bit_vector", "enumeration", "integer".'
85 )
88def test_array_register_field_with_unknown_type_should_raise_exception(tmp_path):
89 toml_path = create_file(
90 file=tmp_path / "regs.toml",
91 contents="""
92[apa]
94type = "register_array"
95array_length = 2
97[apa.hest]
99mode = "r_w"
101zebra.type = "bits"
102zebra.width = 4
103""",
104 )
106 with pytest.raises(ValueError) as exception_info:
107 from_toml(name="", toml_file=toml_path)
108 assert str(exception_info.value) == (
109 f'Error while parsing field "zebra" in register "hest" within array "apa" in {toml_path}: '
110 'Unknown field type "bits". Expected one of "bit", "bit_vector", "enumeration", "integer".'
111 )
114def test_unknown_bit_property_should_raise_exception(tmp_path):
115 toml_path = create_file(
116 file=tmp_path / "regs.toml",
117 contents="""
118[dummy_reg]
120mode = "w"
122dummy_bit.type = "bit"
123dummy_bit.description = "Stuff"
125dummy_bit.dummy_integer.max_value = 3
126""",
127 )
129 with pytest.raises(ValueError) as exception_info:
130 from_toml(name="", toml_file=toml_path)
131 assert str(exception_info.value) == (
132 f'Error while parsing field "dummy_bit" in register "dummy_reg" in {toml_path}: '
133 'Unknown property "dummy_integer".'
134 )
137def test_unknown_bit_vector_property_should_raise_exception(tmp_path):
138 toml_path = create_file(
139 file=tmp_path / "regs.toml",
140 contents="""
141[apa]
143type = "register_array"
144array_length = 2
146[apa.dummy_reg]
148mode = "w"
150[apa.dummy_reg.dummy_bit_vector]
152type = "bit_vector"
153description = "Stuff"
154width = 3
155height = 4
157""",
158 )
160 with pytest.raises(ValueError) as exception_info:
161 from_toml(name="", toml_file=toml_path)
162 assert str(exception_info.value) == (
163 f'Error while parsing field "dummy_bit_vector" in register "dummy_reg" within array "apa" '
164 f'in {toml_path}: Unknown property "height".'
165 )
168def test_bit_vector_without_width_should_raise_exception(tmp_path):
169 toml_path = create_file(
170 file=tmp_path / "regs.toml",
171 contents="""
172[test_reg]
173mode = "w"
175test_bit_vector.type = "bit_vector"
176""",
177 )
179 with pytest.raises(ValueError) as exception_info:
180 from_toml(name="", toml_file=toml_path)
181 assert str(exception_info.value) == (
182 f'Error while parsing field "test_bit_vector" in register "test_reg" in {toml_path}: '
183 'Missing required property "width".'
184 )
187def test_numerical_interpretation_properties_on_anything_but_bit_vector_should_raise_exception(
188 tmp_path,
189):
190 toml_path = create_file(
191 file=tmp_path / "regs.toml",
192 contents="""
193[test_reg]
194mode = "w"
196my_field.type = "integer"
197my_field.max_value = 255
198my_field.numerical_interpretation = "unsigned"
199""",
200 )
202 with pytest.raises(ValueError) as exception_info:
203 from_toml(name="", toml_file=toml_path)
204 assert str(exception_info.value) == (
205 f'Error while parsing field "my_field" in register "test_reg" in {toml_path}: '
206 'Unknown property "numerical_interpretation".'
207 )
210def test_bit_vector_different_numerical_interpretations(tmp_path):
211 toml_path = create_file(
212 file=tmp_path / "regs.toml",
213 contents="""
214[test_reg]
215mode = "w"
217unsigned_implied.type = "bit_vector"
218unsigned_implied.width = 1
220unsigned_explicit.type = "bit_vector"
221unsigned_explicit.width = 2
222unsigned_explicit.numerical_interpretation = "unsigned"
224signed.type = "bit_vector"
225signed.width = 3
226signed.numerical_interpretation = "signed"
228ufixed_implied.type = "bit_vector"
229ufixed_implied.width = 4
230ufixed_implied.numerical_interpretation = "unsigned_fixed_point"
232ufixed_explicit.type = "bit_vector"
233ufixed_explicit.width = 5
234ufixed_explicit.numerical_interpretation = "unsigned_fixed_point"
235ufixed_explicit.min_bit_index = -2
237sfixed_implied.type = "bit_vector"
238sfixed_implied.width = 6
239sfixed_implied.numerical_interpretation = "signed_fixed_point"
241sfixed_explicit.type = "bit_vector"
242sfixed_explicit.width = 7
243sfixed_explicit.numerical_interpretation = "signed_fixed_point"
244sfixed_explicit.min_bit_index = 2
245""",
246 )
247 register = from_toml(name="", toml_file=toml_path).get_register("test_reg")
249 unsigned_implied = register.get_field("unsigned_implied").numerical_interpretation
250 assert isinstance(unsigned_implied, Unsigned)
251 assert unsigned_implied.bit_width == 1
253 unsigned_explicit = register.get_field("unsigned_explicit").numerical_interpretation
254 assert isinstance(unsigned_explicit, Unsigned)
255 assert unsigned_explicit.bit_width == 2
257 signed = register.get_field("signed").numerical_interpretation
258 assert isinstance(signed, Signed)
259 assert signed.bit_width == 3
261 ufixed_implied = register.get_field("ufixed_implied").numerical_interpretation
262 assert isinstance(ufixed_implied, UnsignedFixedPoint)
263 assert ufixed_implied.max_bit_index == 3
264 assert ufixed_implied.min_bit_index == 0
266 ufixed_explicit = register.get_field("ufixed_explicit").numerical_interpretation
267 assert isinstance(ufixed_explicit, UnsignedFixedPoint)
268 assert ufixed_explicit.max_bit_index == 2
269 assert ufixed_explicit.min_bit_index == -2
271 sfixed_implied = register.get_field("sfixed_implied").numerical_interpretation
272 assert isinstance(sfixed_implied, SignedFixedPoint)
273 assert sfixed_implied.max_bit_index == 5
274 assert sfixed_implied.min_bit_index == 0
276 sfixed_explicit = register.get_field("sfixed_explicit").numerical_interpretation
277 assert isinstance(sfixed_explicit, SignedFixedPoint)
278 assert sfixed_explicit.max_bit_index == 8
279 assert sfixed_explicit.min_bit_index == 2
282def test_bit_vector_unknown_numerical_interpretation_should_raise_exception(tmp_path):
283 toml_path = create_file(
284 file=tmp_path / "regs.toml",
285 contents="""
286[test_reg]
287mode = "w"
289my_field.type = "bit_vector"
290my_field.width = 2
291my_field.numerical_interpretation = "apa"
292""",
293 )
294 with pytest.raises(ValueError) as exception_info:
295 from_toml(name="", toml_file=toml_path)
296 assert str(exception_info.value) == (
297 f'Error while parsing field "my_field" in register "test_reg" in {toml_path}: '
298 'Unknown value "apa" for property "numerical_interpretation". '
299 'Expected one of "unsigned", "signed", "unsigned_fixed_point", "signed_fixed_point".'
300 )
303def test_enumeration_without_elements_should_raise_exception(tmp_path):
304 toml_path = create_file(
305 file=tmp_path / "regs.toml",
306 contents="""
307[apa]
309type = "register_array"
310array_length = 2
312[apa.test_reg]
314mode = "w"
316test.type = "enumeration"
317""",
318 )
320 with pytest.raises(ValueError) as exception_info:
321 from_toml(name="", toml_file=toml_path)
322 assert str(exception_info.value) == (
323 'Error while parsing field "test" in register "test_reg" within array "apa" '
324 f'in {toml_path}: Missing required property "element".'
325 )
328def test_integer_without_max_value_should_raise_exception(tmp_path):
329 toml_path = create_file(
330 file=tmp_path / "regs.toml",
331 contents="""
332[test_reg]
333mode = "w"
335test_integer.type = "integer"
336test_integer.min_value = 3
337""",
338 )
340 with pytest.raises(ValueError) as exception_info:
341 from_toml(name="", toml_file=toml_path)
342 assert str(exception_info.value) == (
343 f'Error while parsing field "test_integer" in register "test_reg" in {toml_path}: '
344 'Missing required property "max_value".'
345 )