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

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# -------------------------------------------------------------------------------------------------- 

9 

10import pytest 

11from tsfpga.system_utils import read_file 

12 

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 

18 

19 

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 ) 

26 

27 def create_html_page(self): 

28 return read_file(HtmlPageGenerator(self.register_list, self.tmp_path).create()) 

29 

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 

49 

50 @staticmethod 

51 def check_field(name, index, default_value, html, description=None): 

52 expected = f""" 

53 <tr> 

54 <td><p>&nbsp;&nbsp;<em>{name}</em></p></td> 

55 <td><p>&nbsp;&nbsp;{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 

71 

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 

92 

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 

105 

106 

107@pytest.fixture 

108def html_test(tmp_path): 

109 return HtmlTest(tmp_path=tmp_path) 

110 

111 

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() 

117 

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 ) 

127 

128 html_test.check_register_array( 

129 name="dummies", 

130 length=3, 

131 iterator_range="i &isin; [0, 2]", 

132 description="An <strong>array</strong> with some dummy regs", 

133 html=html, 

134 ) 

135 

136 html_test.check_register( 

137 name="first", 

138 index="7 + i &times; 2", 

139 address="0x001C + i &times; 0x0008", 

140 mode="Read, Write", 

141 default_value="0x5880", 

142 description="The first register in the array.", 

143 html=html, 

144 ) 

145 

146 html_test.check_register( 

147 name="second", 

148 index="8 + i &times; 2", 

149 address="0x0020 + i &times; 0x0008", 

150 mode="Read", 

151 default_value="0xC7", 

152 description="The second register in the array.", 

153 html=html, 

154 ) 

155 

156 

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() 

162 

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 ) 

197 

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 ) 

220 

221 

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" 

228 

229 html = html_test.create_html_page() 

230 

231 # Check that registers are there 

232 assert "Registers" in html, html 

233 assert "dummies" in html, html 

234 

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) 

243 

244 # Test again with no constants 

245 html_test.register_list.constants = [] 

246 html = html_test.create_html_page() 

247 

248 # Registers should still be there 

249 assert "Registers" in html, html 

250 assert "dummies" in html, html 

251 

252 # But no constants 

253 assert constants_text not in html, html 

254 

255 

256def test_constants_and_no_registers(html_test): 

257 html_test.register_list.register_objects = [] 

258 

259 html = html_test.create_html_page() 

260 

261 assert "This module does not have any registers" in html, html 

262 assert "dummies" not in html, html 

263 

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) 

267 

268 

269def test_register_table_is_empty_file_if_no_registers_are_available(html_test): 

270 html_test.register_list.register_objects = [] 

271 

272 generator = HtmlRegisterTableGenerator(html_test.register_list, html_test.tmp_path) 

273 html = read_file(generator.create()) 

274 assert html == generator.header + "\n", html 

275 

276 

277def test_constant_table_is_empty_file_if_no_constants_are_available(html_test): 

278 html_test.register_list.constants = [] 

279 

280 generator = HtmlConstantTableGenerator(html_test.register_list, html_test.tmp_path) 

281 html = read_file(generator.create()) 

282 assert html == generator.header + "\n", html