Coverage for hdl_registers/parser/test/test_parser/test_parser.py: 100%
82 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
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_unknown_top_level_property_should_raise_exception(tmp_path):
18 toml_path = create_file(
19 file=tmp_path / "regs.toml",
20 contents="""
21mode = "w"
22""",
23 )
25 with pytest.raises(ValueError) as exception_info:
26 from_toml(name="", toml_file=toml_path)
27 assert str(exception_info.value) == (
28 f'Error while parsing {toml_path}: Got unknown top-level property "mode".'
29 )
32def test_unknown_top_level_item_type_should_raise_exception(tmp_path):
33 toml_path = create_file(
34 file=tmp_path / "regs.toml",
35 contents="""
36hest.type = "register_constant"
37""",
38 )
40 with pytest.raises(ValueError) as exception_info:
41 from_toml(name="", toml_file=toml_path)
42 assert str(exception_info.value) == (
43 f'Error while parsing "hest" in {toml_path}: Got unknown type "register_constant". '
44 'Expected one of "constant", "register", "register_array".'
45 )
48def test_order_of_registers_and_fields(tmp_path): # noqa: PLR0915
49 toml_data = """
50################################################################################
51[data]
53type = "register"
54mode = "w"
57################################################################################
58[status]
60type = "register"
61mode = "r_w"
62description = "Status register"
64direction.type = "enumeration"
65direction.description = "The direction mode"
66direction.default_value = "input"
67direction.element.passthrough = ""
68direction.element.input = ""
69direction.element.output = "use in output mode"
71bad.type = "bit"
72bad.description = "Bad things happen"
74interrupts.type = "bit_vector"
75interrupts.width = 4
76interrupts.description = "Many interrupts"
77interrupts.default_value = "0110"
79not_good.type = "bit"
80not_good.description = ""
81not_good.default_value = "1"
83count.type = "integer"
84count.description = "The number of things"
85count.min_value = -5
86count.max_value = 15
89################################################################################
90[config]
92type = "register_array"
93array_length = 3
94description = "A register array"
97# ------------------------------------------------------------------------------
98[config.input_settings]
100type = "register"
101description = "Input configuration"
102mode = "r_w"
104[config.input_settings.enable]
106type = "bit"
107description = "Enable things"
108default_value = "1"
110[config.input_settings.disable]
112type = "bit"
113description = ""
114default_value = "0"
116[config.input_settings.number]
118type = "integer"
119description = "Configure number"
120max_value = 3
121default_value = 1
123[config.input_settings.size]
125type = "enumeration"
126default_value = "large"
127element.small = ""
128element.medium = ""
129element.large = ""
132# ------------------------------------------------------------------------------
133[config.output_settings]
135type = "register"
136mode = "w"
138[config.output_settings.data]
140type = "bit_vector"
141width = 16
142description = "Some data"
143default_value = "0000000000000011"
144"""
145 toml_file = create_file(file=tmp_path / "sensor_regs.toml", contents=toml_data)
147 registers = from_toml(name="sensor", toml_file=toml_file).register_objects
149 assert registers[0].name == "data"
150 assert registers[0].mode == REGISTER_MODES["w"]
151 assert registers[0].index == 0
152 assert registers[0].description == ""
153 assert registers[0].default_value == 0
154 assert registers[0].fields == []
156 assert registers[1].name == "status"
157 assert registers[1].mode == REGISTER_MODES["r_w"]
158 assert registers[1].index == 1
159 assert registers[1].description == "Status register"
161 # Enumeration field
162 assert registers[1].fields[0].name == "direction"
163 assert registers[1].fields[0].description == "The direction mode"
164 assert registers[1].fields[0].width == 2
165 assert registers[1].fields[0].default_value.name == "input"
166 assert registers[1].fields[0].elements[0].name == "passthrough"
167 assert registers[1].fields[0].elements[2].name == "output"
168 assert registers[1].fields[0].elements[2].description == "use in output mode"
170 # Bit field
171 assert registers[1].fields[1].name == "bad"
172 assert registers[1].fields[1].description == "Bad things happen"
173 assert registers[1].fields[1].default_value == "0"
175 # Bit vector field
176 assert registers[1].fields[2].name == "interrupts"
177 assert registers[1].fields[2].description == "Many interrupts"
178 assert registers[1].fields[2].width == 4
179 assert registers[1].fields[2].default_value == "0110"
181 # Bit field
182 assert registers[1].fields[3].name == "not_good"
183 assert registers[1].fields[3].description == ""
184 assert registers[1].fields[3].default_value == "1"
186 # Integer field
187 assert registers[1].fields[4].name == "count"
188 assert registers[1].fields[4].description == "The number of things"
189 assert registers[1].fields[4].width == 5
190 assert registers[1].fields[4].min_value == -5
191 assert registers[1].fields[4].max_value == 15
192 assert registers[1].fields[4].default_value == -5
194 assert registers[1].default_value == (
195 # Enum
196 1 * 2**0
197 # Bit
198 + 0 * 2**2
199 # Bit vector
200 + 6 * 2**3
201 # Bit
202 + 1 * 2**7
203 # Integer, negative value converted to positive
204 + 0b11011 * 2**8
205 )
207 assert registers[2].name == "config"
208 assert registers[2].length == 3
209 assert registers[2].description == "A register array"
210 assert registers[2].index == 2 + 2 * 3 - 1
211 assert len(registers[2].registers) == 2
213 assert registers[2].registers[0].name == "input_settings"
214 assert registers[2].registers[0].mode == REGISTER_MODES["r_w"]
215 assert registers[2].registers[0].index == 0
216 assert registers[2].registers[0].description == "Input configuration"
217 assert registers[2].registers[0].fields[0].name == "enable"
218 assert registers[2].registers[0].fields[0].description == "Enable things"
219 assert registers[2].registers[0].fields[0].default_value == "1"
220 assert registers[2].registers[0].fields[1].name == "disable"
221 assert registers[2].registers[0].fields[1].description == ""
222 assert registers[2].registers[0].fields[1].default_value == "0"
223 assert registers[2].registers[0].fields[2].name == "number"
224 assert registers[2].registers[0].fields[2].description == "Configure number"
225 assert registers[2].registers[0].fields[2].default_value == 1
226 assert registers[2].registers[0].fields[3].name == "size"
227 assert registers[2].registers[0].fields[3].default_value.name == "large"
228 assert registers[2].registers[0].default_value == (
229 # First bit
230 1 * 2**0
231 # Integer
232 + 1 * 2**2
233 # Enumeration
234 + 2 * 2**4
235 )
237 assert registers[2].registers[1].name == "output_settings"
238 assert registers[2].registers[1].mode == REGISTER_MODES["w"]
239 assert registers[2].registers[1].index == 1
240 assert registers[2].registers[1].description == ""
241 assert registers[2].registers[1].default_value == 3
242 assert registers[2].registers[1].fields[0].name == "data"
243 assert registers[2].registers[1].fields[0].description == "Some data"
244 assert registers[2].registers[1].fields[0].width == 16
245 assert registers[2].registers[1].fields[0].default_value == "0000000000000011"