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

76 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2022-09-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/tsfpga/hdl_registers 

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

9 

10import unittest 

11 

12import pytest 

13 

14from tsfpga.system_utils import read_file 

15 

16from hdl_registers import HDL_REGISTERS_TEST 

17from hdl_registers.parser import from_toml 

18 

19 

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

21class TestRegisterHtmlGenerator(unittest.TestCase): 

22 tmp_path = None 

23 

24 def setUp(self): 

25 toml_file = HDL_REGISTERS_TEST / "regs_test.toml" 

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

27 

28 def test_registers(self): 

29 """ 

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

31 """ 

32 html = self._create_html_page() 

33 

34 self._check_register( 

35 name="plain_dummy_reg", 

36 index=0, 

37 address="0x0000", 

38 mode="Read, Write", 

39 default_value="0xE", 

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

41 html=html, 

42 ) 

43 

44 self._check_register_array( 

45 name="dummy_regs", 

46 length=3, 

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

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

49 html=html, 

50 ) 

51 

52 self._check_register( 

53 name="array_dummy_reg", 

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

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

56 mode="Read, Write", 

57 default_value="0x31", 

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

59 html=html, 

60 ) 

61 

62 self._check_register( 

63 name="second_array_dummy_reg", 

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

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

66 mode="Read", 

67 default_value="0x0", 

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

69 html=html, 

70 ) 

71 

72 def test_register_fields(self): 

73 """ 

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

75 """ 

76 html = self._create_html_page() 

77 

78 # Fields in plain register 

79 self._check_field( 

80 name="plain_bit_a", 

81 index="0", 

82 default_value="0b0", 

83 description="Bit A", 

84 html=html, 

85 ) 

86 self._check_field( 

87 name="plain_bit_b", 

88 index="1", 

89 default_value="0b1", 

90 description="Bit B", 

91 html=html, 

92 ) 

93 self._check_field( 

94 name="plain_bit_vector", 

95 index="5:2", 

96 default_value="0b0011", 

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

98 html=html, 

99 ) 

100 

101 # Fields in register array 

102 self._check_field( 

103 name="array_bit_a", 

104 index="0", 

105 default_value="0b1", 

106 description="Array register bit A", 

107 html=html, 

108 ) 

109 self._check_field( 

110 name="array_bit_b", 

111 index="1", 

112 default_value="0b0", 

113 description="Array register bit B", 

114 html=html, 

115 ) 

116 self._check_field( 

117 name="array_bit_vector", 

118 index="6:2", 

119 default_value="0b01100", 

120 description="Array register bit vector", 

121 html=html, 

122 ) 

123 

124 def test_registers_and_constants(self): 

125 """ 

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

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

128 """ 

129 html = self._create_html_page() 

130 assert "The following constants are part of the register interface" not in html, html 

131 

132 # Add some constants and assert 

133 self.registers.add_constant("data_width", 24) 

134 self.registers.add_constant("decrement", -8) 

135 html = self._create_html_page() 

136 

137 assert "Registers" in html, html 

138 assert "dummy_regs" in html, html 

139 

140 assert "The following constants are part of the register interface" 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 def test_constants_and_no_registers(self): 

145 self.registers.register_objects = [] 

146 

147 # Add some constants and assert 

148 self.registers.add_constant("data_width", 24) 

149 self.registers.add_constant("decrement", -8) 

150 html = self._create_html_page() 

151 

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

153 assert "dummy_regs" not in html, html 

154 

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

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

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

158 

159 def _create_html_page(self): 

160 self.registers.create_html_page(self.tmp_path) 

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

162 return html 

163 

164 @staticmethod 

165 # pylint: disable=too-many-arguments 

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

167 expected = f""" 

168 <tr> 

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

170 <td>{index}</td> 

171 <td>{address}</td> 

172 <td>{mode}</td> 

173 <td>{default_value}</td> 

174 <td>{description}</td> 

175 </tr> 

176""" 

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

178 

179 @staticmethod 

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

181 expected = f""" 

182 <tr> 

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

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

185 <td></td> 

186 <td></td> 

187 <td>{default_value}</td> 

188 <td>{description}</td> 

189""" 

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

191 

192 @staticmethod 

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

194 expected = f""" 

195 <tr> 

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

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

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

199 </td> 

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

201 </tr> 

202""" 

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

204 

205 @staticmethod 

206 def _check_constant(name, value, html): 

207 expected = f""" 

208 <tr> 

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

210 <td>{value}</td> 

211""" 

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

213 

214 def test_register_table_is_empty_string_if_no_registers_are_available(self): 

215 self.registers.register_objects = [] 

216 

217 self.registers.create_html_register_table(self.tmp_path) 

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

219 assert html == "", html 

220 

221 def test_constant_table_is_empty_string_if_no_constants_are_available(self): 

222 self.registers.constants = [] 

223 

224 self.registers.create_html_constant_table(self.tmp_path) 

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

226 assert html == "", html