Coverage for hdl_registers/parser/test/test_parser/test_parser.py: 100%
84 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-27 20:50 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-27 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.parser.toml import from_toml
14from hdl_registers.register_modes import REGISTER_MODES
17def test_property_names_and_values_are_case_sensitive(tmp_path):
18 """
19 Explicitly show that we do not do any case normalization.
20 """
21 toml_path = create_file(
22 file=tmp_path / "regs.toml",
23 contents="""
24[data]
26mode = "w"
27""",
28 )
29 from_toml(name="", toml_file=toml_path)
31 toml_path = create_file(
32 file=tmp_path / "regs.toml",
33 contents="""
34[data]
36Mode = "w"
37""",
38 )
39 with pytest.raises(ValueError) as exception_info:
40 from_toml(name="", toml_file=toml_path)
41 assert str(exception_info.value) == (
42 f'Error while parsing register "data" in {toml_path}: Missing required property "mode".'
43 )
45 toml_path = create_file(
46 file=tmp_path / "regs.toml",
47 contents="""
48[data]
50mode = "W"
51""",
52 )
53 with pytest.raises(ValueError) as exception_info:
54 from_toml(name="", toml_file=toml_path)
55 assert str(exception_info.value) == (
56 f'Error while parsing register "data" in {toml_path}: Got unknown mode "W". '
57 'Expected one of "r", "w", "r_w", "wpulse", "r_wpulse".'
58 )
61def test_unknown_top_level_item_type_should_raise_exception(tmp_path):
62 toml_path = create_file(
63 file=tmp_path / "regs.toml",
64 contents="""
65hest.type = "register_constant"
66""",
67 )
69 with pytest.raises(ValueError) as exception_info:
70 from_toml(name="", toml_file=toml_path)
71 assert str(exception_info.value) == (
72 f'Error while parsing "hest" in {toml_path}: Got unknown type "register_constant". '
73 'Expected one of "constant", "register", "register_array".'
74 )
77def test_order_of_registers_and_fields(tmp_path): # noqa: PLR0915
78 toml_data = """
79################################################################################
80[data]
82type = "register"
83mode = "w"
86################################################################################
87[status]
89type = "register"
90mode = "r_w"
91description = "Status register"
93direction.type = "enumeration"
94direction.description = "The direction mode"
95direction.default_value = "input"
96direction.element.passthrough = ""
97direction.element.input = ""
98direction.element.output = "use in output mode"
100bad.type = "bit"
101bad.description = "Bad things happen"
103interrupts.type = "bit_vector"
104interrupts.width = 4
105interrupts.description = "Many interrupts"
106interrupts.default_value = "0110"
108not_good.type = "bit"
109not_good.description = ""
110not_good.default_value = "1"
112count.type = "integer"
113count.description = "The number of things"
114count.min_value = -5
115count.max_value = 15
118################################################################################
119[conf]
121type = "register_array"
122array_length = 3
123description = "A register array"
126# ------------------------------------------------------------------------------
127[conf.input_settings]
129type = "register"
130description = "Input configuration"
131mode = "r_w"
133[conf.input_settings.enable]
135type = "bit"
136description = "Enable things"
137default_value = "1"
139[conf.input_settings.disable]
141type = "bit"
142description = ""
143default_value = "0"
145[conf.input_settings.number]
147type = "integer"
148description = "Configure number"
149max_value = 3
150default_value = 1
152[conf.input_settings.size]
154type = "enumeration"
155default_value = "large"
156element.small = ""
157element.medium = ""
158element.large = ""
161# ------------------------------------------------------------------------------
162[conf.output_settings]
164type = "register"
165mode = "w"
167[conf.output_settings.data]
169type = "bit_vector"
170width = 16
171description = "Some data"
172default_value = "0000000000000011"
173"""
174 toml_file = create_file(file=tmp_path / "sensor_regs.toml", contents=toml_data)
176 registers = from_toml(name="sensor", toml_file=toml_file).register_objects
178 assert registers[0].name == "data"
179 assert registers[0].mode == REGISTER_MODES["w"]
180 assert registers[0].index == 0
181 assert registers[0].description == ""
182 assert registers[0].fields == []
184 assert registers[1].name == "status"
185 assert registers[1].mode == REGISTER_MODES["r_w"]
186 assert registers[1].index == 1
187 assert registers[1].description == "Status register"
189 # Enumeration field
190 assert registers[1].fields[0].name == "direction"
191 assert registers[1].fields[0].description == "The direction mode"
192 assert registers[1].fields[0].width == 2
193 assert registers[1].fields[0].default_value.name == "input"
194 assert registers[1].fields[0].elements[0].name == "passthrough"
195 assert registers[1].fields[0].elements[2].name == "output"
196 assert registers[1].fields[0].elements[2].description == "use in output mode"
198 # Bit field
199 assert registers[1].fields[1].name == "bad"
200 assert registers[1].fields[1].description == "Bad things happen"
201 assert registers[1].fields[1].default_value == "0"
203 # Bit vector field
204 assert registers[1].fields[2].name == "interrupts"
205 assert registers[1].fields[2].description == "Many interrupts"
206 assert registers[1].fields[2].width == 4
207 assert registers[1].fields[2].default_value == "0110"
209 # Bit field
210 assert registers[1].fields[3].name == "not_good"
211 assert registers[1].fields[3].description == ""
212 assert registers[1].fields[3].default_value == "1"
214 # Integer field
215 assert registers[1].fields[4].name == "count"
216 assert registers[1].fields[4].description == "The number of things"
217 assert registers[1].fields[4].width == 5
218 assert registers[1].fields[4].min_value == -5
219 assert registers[1].fields[4].max_value == 15
220 assert registers[1].fields[4].default_value == -5
222 assert registers[2].name == "conf"
223 assert registers[2].length == 3
224 assert registers[2].description == "A register array"
225 assert registers[2].index == 2 + 2 * 3 - 1
226 assert len(registers[2].registers) == 2
228 assert registers[2].registers[0].name == "input_settings"
229 assert registers[2].registers[0].mode == REGISTER_MODES["r_w"]
230 assert registers[2].registers[0].index == 0
231 assert registers[2].registers[0].description == "Input configuration"
232 assert registers[2].registers[0].fields[0].name == "enable"
233 assert registers[2].registers[0].fields[0].description == "Enable things"
234 assert registers[2].registers[0].fields[0].default_value == "1"
235 assert registers[2].registers[0].fields[1].name == "disable"
236 assert registers[2].registers[0].fields[1].description == ""
237 assert registers[2].registers[0].fields[1].default_value == "0"
238 assert registers[2].registers[0].fields[2].name == "number"
239 assert registers[2].registers[0].fields[2].description == "Configure number"
240 assert registers[2].registers[0].fields[2].default_value == 1
241 assert registers[2].registers[0].fields[3].name == "size"
242 assert registers[2].registers[0].fields[3].default_value.name == "large"
244 assert registers[2].registers[1].name == "output_settings"
245 assert registers[2].registers[1].mode == REGISTER_MODES["w"]
246 assert registers[2].registers[1].index == 1
247 assert registers[2].registers[1].description == ""
248 assert registers[2].registers[1].fields[0].name == "data"
249 assert registers[2].registers[1].fields[0].description == "Some data"
250 assert registers[2].registers[1].fields[0].width == 16
251 assert registers[2].registers[1].fields[0].default_value == "0000000000000011"