Coverage for hdl_registers/generator/html/test/test_register_html_generator.py: 84%
101 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 read_file
13from hdl_registers import HDL_REGISTERS_TESTS
14from hdl_registers.generator.html.constant_table import HtmlConstantTableGenerator
15from hdl_registers.generator.html.page import HtmlPageGenerator
16from hdl_registers.generator.html.register_table import HtmlRegisterTableGenerator
17from hdl_registers.parser.toml import from_toml
20class HtmlTest:
21 def __init__(self, tmp_path):
22 self.tmp_path = tmp_path
23 self.register_list = from_toml(
24 name="caesar", toml_file=HDL_REGISTERS_TESTS / "regs_test.toml"
25 )
27 def create_html_page(self):
28 return read_file(HtmlPageGenerator(self.register_list, self.tmp_path).create())
30 @staticmethod
31 def check_register(name, index, address, mode, default_value, description, html):
32 expected = f"""
33 <tr>
34 <td><p><strong>{name}</strong></p></td>
35 <td><p>{index}</p></td>
36 <td><p>{address}</p></td>
37 <td><p>{mode}</p></td>
38 <td><p>{default_value}</p></td>
39 <td>
40<p>{description}</p>
41 </td>
42 </tr>
43"""
44 if expected not in html:
45 print(html)
46 print()
47 print(expected)
48 raise ValueError
50 @staticmethod
51 def check_field(name, index, default_value, html, description=None):
52 expected = f"""
53 <tr>
54 <td><p> <em>{name}</em></p></td>
55 <td><p> {index}</p></td>
56 <td><p></p></td>
57 <td><p></p></td>
58 <td><p>{default_value}</p></td>
59"""
60 if description:
61 expected += f"""\
62 <td>
63<p>{description}</p>
64 </td>
65"""
66 if expected not in html:
67 print(html)
68 print()
69 print(expected)
70 raise ValueError
72 @staticmethod
73 def check_register_array(name, length, iterator_range, description, html):
74 expected = f"""
75 <tr>
76 <td class="array_header" colspan=5>
77 <p>
78 Register array <strong>{name}</strong>, repeated {length} times.
79 Iterator <span class="formula">{iterator_range}</span>.
80 </p>
81 </td>
82 <td class="array_header">
83<p>{description}</p>
84 </td>
85 </tr>
86"""
87 if expected not in html:
88 print(html)
89 print()
90 print(expected)
91 raise ValueError
93 @staticmethod
94 def check_constant(name, value, html):
95 expected = f"""
96 <tr>
97 <td><p><strong>{name}</strong></p></td>
98 <td><p>{value}</p></td>
99"""
100 if expected not in html:
101 print(html)
102 print()
103 print(expected)
104 raise ValueError
107@pytest.fixture
108def html_test(tmp_path):
109 return HtmlTest(tmp_path=tmp_path)
112def test_registers(html_test):
113 """
114 Test that all registers show up in the HTML with correct attributes.
115 """
116 html = html_test.create_html_page()
118 html_test.check_register(
119 name="config",
120 index=0,
121 address="0x0000",
122 mode="Read, Write",
123 default_value="0x14846",
124 description="A plain <strong>dummy</strong> register.",
125 html=html,
126 )
128 html_test.check_register_array(
129 name="dummies",
130 length=3,
131 iterator_range="i ∈ [0, 2]",
132 description="An <strong>array</strong> with some dummy regs",
133 html=html,
134 )
136 html_test.check_register(
137 name="first",
138 index="7 + i × 2",
139 address="0x001C + i × 0x0008",
140 mode="Read, Write",
141 default_value="0x5880",
142 description="The first register in the array.",
143 html=html,
144 )
146 html_test.check_register(
147 name="second",
148 index="8 + i × 2",
149 address="0x0020 + i × 0x0008",
150 mode="Read",
151 default_value="0xC7",
152 description="The second register in the array.",
153 html=html,
154 )
157def test_register_fields(html_test):
158 """
159 Test that all bits show up in the HTML with correct attributes.
160 """
161 html = html_test.create_html_page()
163 # Fields in plain register
164 html_test.check_field(
165 name="plain_bit_a",
166 index="0",
167 default_value="0b0",
168 description="Bit A",
169 html=html,
170 )
171 html_test.check_field(
172 name="plain_bit_vector",
173 index="4:1",
174 default_value="0b0011",
175 description="Bit <strong>vector</strong>",
176 html=html,
177 )
178 html_test.check_field(
179 name="plain_integer",
180 index="12:5",
181 default_value="66",
182 html=html,
183 )
184 html_test.check_field(
185 name="plain_enumeration",
186 index="15:13",
187 default_value='<span class="docutils literal">third</span>',
188 html=html,
189 )
190 html_test.check_field(
191 name="plain_bit_b",
192 index="16",
193 default_value="0b1",
194 description="Bit B",
195 html=html,
196 )
198 # Fields in register array
199 html_test.check_field(
200 name="array_bit_a",
201 index="7",
202 default_value="0b1",
203 description="Array register bit A",
204 html=html,
205 )
206 html_test.check_field(
207 name="array_bit_b",
208 index="8",
209 default_value="0b0",
210 description="Array register bit B",
211 html=html,
212 )
213 html_test.check_field(
214 name="array_bit_vector",
215 index="13:9",
216 default_value="0b01100",
217 description="Array register bit vector",
218 html=html,
219 )
222def test_registers_and_constants(html_test):
223 """
224 Test that all constant show up in the HTML with correct attributes.
225 Should only appear if there are actually any constants set.
226 """
227 constants_text = "The following constants are part of the register interface"
229 html = html_test.create_html_page()
231 # Check that registers are there
232 assert "Registers" in html, html
233 assert "dummies" in html, html
235 # Check that constants are there
236 assert constants_text in html, html
237 html_test.check_constant(name="data_width", value=24, html=html)
238 html_test.check_constant(name="decrement", value=-8, html=html)
239 html_test.check_constant(name="enabled", value="True", html=html)
240 html_test.check_constant(name="disabled", value="False", html=html)
241 html_test.check_constant(name="rate", value="3.5", html=html)
242 html_test.check_constant(name="paragraph", value='"hello there :)"', html=html)
244 # Test again with no constants
245 html_test.register_list.constants = []
246 html = html_test.create_html_page()
248 # Registers should still be there
249 assert "Registers" in html, html
250 assert "dummies" in html, html
252 # But no constants
253 assert constants_text not in html, html
256def test_constants_and_no_registers(html_test):
257 html_test.register_list.register_objects = []
259 html = html_test.create_html_page()
261 assert "This module does not have any registers" in html, html
262 assert "dummies" not in html, html
264 assert "<h2>Constants</h2>" in html, html
265 html_test.check_constant(name="data_width", value=24, html=html)
266 html_test.check_constant(name="decrement", value=-8, html=html)
269def test_register_table_is_empty_file_if_no_registers_are_available(html_test):
270 html_test.register_list.register_objects = []
272 generator = HtmlRegisterTableGenerator(html_test.register_list, html_test.tmp_path)
273 html = read_file(generator.create())
274 assert html == generator.header + "\n", html
277def test_constant_table_is_empty_file_if_no_constants_are_available(html_test):
278 html_test.register_list.constants = []
280 generator = HtmlConstantTableGenerator(html_test.register_list, html_test.tmp_path)
281 html = read_file(generator.create())
282 assert html == generator.header + "\n", html