Coverage for hdl_registers/parser/test/test_parser/test_parser.py: 100%
82 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-07 20:51 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-07 20:51 +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
12from tsfpga.system_utils import create_file
14# First party libraries
15from hdl_registers.parser.toml import from_toml
16from hdl_registers.register_modes import REGISTER_MODES
19def test_unknown_top_level_property_should_raise_exception(tmp_path):
20 toml_path = create_file(
21 file=tmp_path / "regs.toml",
22 contents="""
23mode = "w"
24""",
25 )
27 with pytest.raises(ValueError) as exception_info:
28 from_toml(name="", toml_file=toml_path)
29 assert str(exception_info.value) == (
30 f'Error while parsing {toml_path}: Got unknown top-level property "mode".'
31 )
34def test_unknown_top_level_item_type_should_raise_exception(tmp_path):
35 toml_path = create_file(
36 file=tmp_path / "regs.toml",
37 contents="""
38hest.type = "register_constant"
39""",
40 )
42 with pytest.raises(ValueError) as exception_info:
43 from_toml(name="", toml_file=toml_path)
44 assert str(exception_info.value) == (
45 f'Error while parsing "hest" in {toml_path}: Got unknown type "register_constant". '
46 'Expected one of "constant", "register", "register_array".'
47 )
50def test_order_of_registers_and_fields(tmp_path): # pylint: disable=too-many-statements
51 toml_data = """
52################################################################################
53[data]
55type = "register"
56mode = "w"
59################################################################################
60[status]
62type = "register"
63mode = "r_w"
64description = "Status register"
66direction.type = "enumeration"
67direction.description = "The direction mode"
68direction.default_value = "input"
69direction.element.passthrough = ""
70direction.element.input = ""
71direction.element.output = "use in output mode"
73bad.type = "bit"
74bad.description = "Bad things happen"
76interrupts.type = "bit_vector"
77interrupts.width = 4
78interrupts.description = "Many interrupts"
79interrupts.default_value = "0110"
81not_good.type = "bit"
82not_good.description = ""
83not_good.default_value = "1"
85count.type = "integer"
86count.description = "The number of things"
87count.min_value = -5
88count.max_value = 15
91################################################################################
92[config]
94type = "register_array"
95array_length = 3
96description = "A register array"
99# ------------------------------------------------------------------------------
100[config.input_settings]
102type = "register"
103description = "Input configuration"
104mode = "r_w"
106[config.input_settings.enable]
108type = "bit"
109description = "Enable things"
110default_value = "1"
112[config.input_settings.disable]
114type = "bit"
115description = ""
116default_value = "0"
118[config.input_settings.number]
120type = "integer"
121description = "Configure number"
122max_value = 3
123default_value = 1
125[config.input_settings.size]
127type = "enumeration"
128default_value = "large"
129element.small = ""
130element.medium = ""
131element.large = ""
134# ------------------------------------------------------------------------------
135[config.output_settings]
137type = "register"
138mode = "w"
140[config.output_settings.data]
142type = "bit_vector"
143width = 16
144description = "Some data"
145default_value = "0000000000000011"
146"""
147 toml_file = create_file(file=tmp_path / "sensor_regs.toml", contents=toml_data)
149 registers = from_toml(name="sensor", toml_file=toml_file).register_objects
151 assert registers[0].name == "data"
152 assert registers[0].mode == REGISTER_MODES["w"]
153 assert registers[0].index == 0
154 assert registers[0].description == ""
155 assert registers[0].default_value == 0
156 assert registers[0].fields == []
158 assert registers[1].name == "status"
159 assert registers[1].mode == REGISTER_MODES["r_w"]
160 assert registers[1].index == 1
161 assert registers[1].description == "Status register"
163 # Enumeration field
164 assert registers[1].fields[0].name == "direction"
165 assert registers[1].fields[0].description == "The direction mode"
166 assert registers[1].fields[0].width == 2
167 assert registers[1].fields[0].default_value.name == "input"
168 assert registers[1].fields[0].elements[0].name == "passthrough"
169 assert registers[1].fields[0].elements[2].name == "output"
170 assert registers[1].fields[0].elements[2].description == "use in output mode"
172 # Bit field
173 assert registers[1].fields[1].name == "bad"
174 assert registers[1].fields[1].description == "Bad things happen"
175 assert registers[1].fields[1].default_value == "0"
177 # Bit vector field
178 assert registers[1].fields[2].name == "interrupts"
179 assert registers[1].fields[2].description == "Many interrupts"
180 assert registers[1].fields[2].width == 4
181 assert registers[1].fields[2].default_value == "0110"
183 # Bit field
184 assert registers[1].fields[3].name == "not_good"
185 assert registers[1].fields[3].description == ""
186 assert registers[1].fields[3].default_value == "1"
188 # Integer field
189 assert registers[1].fields[4].name == "count"
190 assert registers[1].fields[4].description == "The number of things"
191 assert registers[1].fields[4].width == 5
192 assert registers[1].fields[4].min_value == -5
193 assert registers[1].fields[4].max_value == 15
194 assert registers[1].fields[4].default_value == -5
196 assert registers[1].default_value == (
197 # Enum
198 1 * 2**0
199 # Bit
200 + 0 * 2**2
201 # Bit vector
202 + 6 * 2**3
203 # Bit
204 + 1 * 2**7
205 # Integer, negative value converted to positive
206 + 0b11011 * 2**8
207 )
209 assert registers[2].name == "config"
210 assert registers[2].length == 3
211 assert registers[2].description == "A register array"
212 assert registers[2].index == 2 + 2 * 3 - 1
213 assert len(registers[2].registers) == 2
215 assert registers[2].registers[0].name == "input_settings"
216 assert registers[2].registers[0].mode == REGISTER_MODES["r_w"]
217 assert registers[2].registers[0].index == 0
218 assert registers[2].registers[0].description == "Input configuration"
219 assert registers[2].registers[0].fields[0].name == "enable"
220 assert registers[2].registers[0].fields[0].description == "Enable things"
221 assert registers[2].registers[0].fields[0].default_value == "1"
222 assert registers[2].registers[0].fields[1].name == "disable"
223 assert registers[2].registers[0].fields[1].description == ""
224 assert registers[2].registers[0].fields[1].default_value == "0"
225 assert registers[2].registers[0].fields[2].name == "number"
226 assert registers[2].registers[0].fields[2].description == "Configure number"
227 assert registers[2].registers[0].fields[2].default_value == 1
228 assert registers[2].registers[0].fields[3].name == "size"
229 assert registers[2].registers[0].fields[3].default_value.name == "large"
230 assert registers[2].registers[0].default_value == (
231 # First bit
232 1 * 2**0
233 # Integer
234 + 1 * 2**2
235 # Enumeration
236 + 2 * 2**4
237 )
239 assert registers[2].registers[1].name == "output_settings"
240 assert registers[2].registers[1].mode == REGISTER_MODES["w"]
241 assert registers[2].registers[1].index == 1
242 assert registers[2].registers[1].description == ""
243 assert registers[2].registers[1].default_value == 3
244 assert registers[2].registers[1].fields[0].name == "data"
245 assert registers[2].registers[1].fields[0].description == "Some data"
246 assert registers[2].registers[1].fields[0].width == 16
247 assert registers[2].registers[1].fields[0].default_value == "0000000000000011"