Coverage for hdl_registers/test/unit/test_register_html_generator.py: 100%

76 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-01-29 22:03 +0000

1# -------------------------------------------------------------------------------------------------- 

2# Copyright (c) Lukas Vik. All rights reserved. 

3# 

4# This file is part of the hdl_registers project, a HDL register generator fast enough to be run 

5# in real time. 

6# https://hdl-registers.com 

7# https://gitlab.com/hdl_registers/hdl_registers 

8# -------------------------------------------------------------------------------------------------- 

9 

10# Standard libraries 

11import unittest 

12 

13# Third party libraries 

14import pytest 

15from tsfpga.system_utils import read_file 

16 

17# First party libraries 

18from hdl_registers import HDL_REGISTERS_TEST 

19from hdl_registers.parser import from_toml 

20 

21 

22@pytest.mark.usefixtures("fixture_tmp_path") 

23class TestRegisterHtmlGenerator(unittest.TestCase): 

24 tmp_path = None 

25 

26 def setUp(self): 

27 toml_file = HDL_REGISTERS_TEST / "regs_test.toml" 

28 self.registers = from_toml("test", toml_file) 

29 

30 def test_registers(self): 

31 """ 

32 Test that all registers show up in the HTML with correct attributes. 

33 """ 

34 html = self._create_html_page() 

35 

36 self._check_register( 

37 name="plain_dummy_reg", 

38 index=0, 

39 address="0x0000", 

40 mode="Read, Write", 

41 default_value="0xE", 

42 description="A plain <strong>dummy</strong> register.", 

43 html=html, 

44 ) 

45 

46 self._check_register_array( 

47 name="dummy_regs", 

48 length=3, 

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

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

51 html=html, 

52 ) 

53 

54 self._check_register( 

55 name="array_dummy_reg", 

56 index="5 + i &times; 2", 

57 address="0x0014 + i &times; 0x0008", 

58 mode="Read, Write", 

59 default_value="0x31", 

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

61 html=html, 

62 ) 

63 

64 self._check_register( 

65 name="second_array_dummy_reg", 

66 index="6 + i &times; 2", 

67 address="0x0018 + i &times; 0x0008", 

68 mode="Read", 

69 default_value="0x0", 

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

71 html=html, 

72 ) 

73 

74 def test_register_fields(self): 

75 """ 

76 Test that all bits show up in the HTML with correct attributes. 

77 """ 

78 html = self._create_html_page() 

79 

80 # Fields in plain register 

81 self._check_field( 

82 name="plain_bit_a", 

83 index="0", 

84 default_value="0b0", 

85 description="Bit A", 

86 html=html, 

87 ) 

88 self._check_field( 

89 name="plain_bit_b", 

90 index="1", 

91 default_value="0b1", 

92 description="Bit B", 

93 html=html, 

94 ) 

95 self._check_field( 

96 name="plain_bit_vector", 

97 index="5:2", 

98 default_value="0b0011", 

99 description="Bit <strong>vector</strong>", 

100 html=html, 

101 ) 

102 

103 # Fields in register array 

104 self._check_field( 

105 name="array_bit_a", 

106 index="0", 

107 default_value="0b1", 

108 description="Array register bit A", 

109 html=html, 

110 ) 

111 self._check_field( 

112 name="array_bit_b", 

113 index="1", 

114 default_value="0b0", 

115 description="Array register bit B", 

116 html=html, 

117 ) 

118 self._check_field( 

119 name="array_bit_vector", 

120 index="6:2", 

121 default_value="0b01100", 

122 description="Array register bit vector", 

123 html=html, 

124 ) 

125 

126 def test_registers_and_constants(self): 

127 """ 

128 Test that all constant show up in the HTML with correct attributes. 

129 Should only appear if there are actually any constants set. 

130 """ 

131 constants_text = "The following constants are part of the register interface" 

132 

133 html = self._create_html_page() 

134 

135 # Check that registers are there 

136 assert "Registers" in html, html 

137 assert "dummy_regs" in html, html 

138 

139 # Check that constants are there 

140 assert constants_text in html, html 

141 self._check_constant(name="data_width", value=24, html=html) 

142 self._check_constant(name="decrement", value=-8, html=html) 

143 

144 # Test again with no constants 

145 self.registers.constants = [] 

146 html = self._create_html_page() 

147 

148 # Registers should still be there 

149 assert "Registers" in html, html 

150 assert "dummy_regs" in html, html 

151 

152 # But no constants 

153 assert constants_text not in html, html 

154 

155 def test_constants_and_no_registers(self): 

156 self.registers.register_objects = [] 

157 

158 html = self._create_html_page() 

159 

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

161 assert "dummy_regs" not in html, html 

162 

163 assert "<h2>Constants</h2>" in html, html 

164 self._check_constant(name="data_width", value=24, html=html) 

165 self._check_constant(name="decrement", value=-8, html=html) 

166 

167 def _create_html_page(self): 

168 self.registers.create_html_page(self.tmp_path) 

169 html = read_file(self.tmp_path / "test_regs.html") 

170 return html 

171 

172 @staticmethod 

173 # pylint: disable=too-many-arguments 

174 def _check_register(name, index, address, mode, default_value, description, html): 

175 expected = f""" 

176 <tr> 

177 <td><strong>{name}</strong></td> 

178 <td>{index}</td> 

179 <td>{address}</td> 

180 <td>{mode}</td> 

181 <td>{default_value}</td> 

182 <td>{description}</td> 

183 </tr> 

184""" 

185 assert expected in html, f"{expected}\n\n{html}" 

186 

187 @staticmethod 

188 def _check_field(name, index, default_value, description, html): 

189 expected = f""" 

190 <tr> 

191 <td>&nbsp;&nbsp;<em>{name}</em></td> 

192 <td>&nbsp;&nbsp;{index}</td> 

193 <td></td> 

194 <td></td> 

195 <td>{default_value}</td> 

196 <td>{description}</td> 

197""" 

198 assert expected in html, f"{expected}\n\n{html}" 

199 

200 @staticmethod 

201 def _check_register_array(name, length, iterator_range, description, html): 

202 expected = f""" 

203 <tr> 

204 <td class="array_header" colspan=5> 

205 Register array <strong>{name}</strong>, repeated {length} times. 

206 Iterator <i>{iterator_range}.</i> 

207 </td> 

208 <td class="array_header">{description}</td> 

209 </tr> 

210""" 

211 assert expected in html, f"{expected}\n\n{html}" 

212 

213 @staticmethod 

214 def _check_constant(name, value, html): 

215 expected = f""" 

216 <tr> 

217 <td><strong>{name}</strong></td> 

218 <td>{value}</td> 

219""" 

220 assert expected in html, f"{expected}\n\n{html}" 

221 

222 def test_register_table_is_empty_string_if_no_registers_are_available(self): 

223 self.registers.register_objects = [] 

224 

225 self.registers.create_html_register_table(self.tmp_path) 

226 html = read_file(self.tmp_path / "test_register_table.html") 

227 assert html == "", html 

228 

229 def test_constant_table_is_empty_string_if_no_constants_are_available(self): 

230 self.registers.constants = [] 

231 

232 self.registers.create_html_constant_table(self.tmp_path) 

233 html = read_file(self.tmp_path / "test_constant_table.html") 

234 assert html == "", html