Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

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

3# 

4# This file is part of the tsfpga project. 

5# https://tsfpga.com 

6# https://gitlab.com/tsfpga/tsfpga 

7# -------------------------------------------------------------------------------------------------- 

8 

9import copy 

10from pathlib import Path 

11import unittest 

12from unittest.mock import patch 

13 

14import pytest 

15 

16from tsfpga.system_utils import create_file 

17from tsfpga.registers.parser import from_toml 

18from tsfpga.registers.register import Register 

19from tsfpga.registers.register_list import RegisterList 

20 

21 

22def test_from_default_registers(): 

23 register_a = Register(name="a", index=0, mode="r", description="AA") 

24 register_b = Register(name="b", index=1, mode="w", description="BB") 

25 default_registers = [register_a, register_b] 

26 

27 register_list = RegisterList.from_default_registers( 

28 name="apa", source_definition_file=None, default_registers=default_registers 

29 ) 

30 

31 # Change some things in the register objects to show that they are copied 

32 default_registers.append(Register(name="c", index=2, mode="r_w", description="CC")) 

33 register_a.mode = "w" 

34 register_b.name = "x" 

35 

36 assert len(register_list.register_objects) == 2 

37 assert register_list.get_register("a").mode == "r" 

38 assert register_list.get_register("b").name == "b" 

39 

40 

41@patch("tsfpga.registers.register_list.git_commands_are_available", autospec=True) 

42@patch("tsfpga.registers.register_list.get_git_commit", autospec=True) 

43@patch("tsfpga.registers.register_list.svn_commands_are_available", autospec=True) 

44@patch("tsfpga.registers.register_list.get_svn_revision_information", autospec=True) 

45def test_generated_source_info( 

46 get_svn_revision_information, 

47 svn_commands_are_available, 

48 get_git_commit, 

49 git_commands_are_available, 

50): 

51 source_definition_file = Path("/apa/whatever/regs.toml") 

52 register_list = RegisterList(name="a", source_definition_file=source_definition_file) 

53 expected_first_line = "This file is automatically generated by tsfpga." 

54 

55 # Test with git information 

56 git_commands_are_available.return_value = True 

57 get_git_commit.return_value = "HASH" 

58 

59 got = register_list.generated_source_info() 

60 assert got[0] == expected_first_line 

61 assert " from file regs.toml at commit HASH." in got[1] 

62 

63 # Test with SVN information 

64 git_commands_are_available.return_value = False 

65 svn_commands_are_available.return_value = True 

66 get_svn_revision_information.return_value = "REVISION" 

67 

68 got = register_list.generated_source_info() 

69 assert got[0] == expected_first_line 

70 assert " from file regs.toml at revision REVISION." in got[1] 

71 

72 # Test with no source definition file 

73 register_list = RegisterList(name="a", source_definition_file=None) 

74 

75 got = register_list.generated_source_info() 

76 assert got[0] == expected_first_line 

77 assert "from file" not in got[1] 

78 assert " at revision REVISION." in got[1] 

79 

80 

81def test_header_constants(): 

82 registers = RegisterList(name="apa", source_definition_file=None) 

83 hest = registers.add_constant("hest", 123) 

84 zebra = registers.add_constant("zebra", 456, "description") 

85 

86 assert len(registers.constants) == 2 

87 

88 assert registers.get_constant("hest") == hest 

89 assert registers.get_constant("zebra") == zebra 

90 

91 with pytest.raises(ValueError) as exception_info: 

92 assert registers.get_constant("non existing") is None 

93 assert ( 

94 str(exception_info.value) 

95 == 'Could not find constant "non existing" within register list "apa"' 

96 ) 

97 

98 zebra.value = -5 

99 assert registers.get_constant("zebra").value == -5 

100 

101 

102def test_invalid_register_mode_should_raise_exception(): 

103 registers = RegisterList(None, None) 

104 registers.append_register(name="test", mode="r_w", description="") 

105 

106 with pytest.raises(ValueError) as exception_info: 

107 registers.append_register(name="hest", mode="x", description="") 

108 assert str(exception_info.value) == 'Invalid mode "x" for register "hest"' 

109 

110 register_array = registers.append_register_array("array", 2, "") 

111 register_array.append_register(name="apa", mode="r", description="") 

112 with pytest.raises(ValueError) as exception_info: 

113 register_array.append_register(name="zebra", mode="y", description="") 

114 assert str(exception_info.value) == 'Invalid mode "y" for register "zebra"' 

115 

116 

117def test_registers_are_appended_properly_and_can_be_edited_in_place(): 

118 register_array = RegisterList(name="apa", source_definition_file=Path(".")) 

119 

120 register_hest = register_array.append_register(name="hest", mode="r", description="") 

121 assert register_hest.index == 0 

122 

123 register_zebra = register_array.append_register(name="zebra", mode="r", description="") 

124 assert register_zebra.index == 1 

125 

126 register_hest.description = "new desc" 

127 assert register_array.register_objects[0].description == "new desc" 

128 

129 

130def test_register_arrays_are_appended_properly_and_can_be_edited_in_place(): 

131 register_array = RegisterList(name="apa", source_definition_file=Path(".")) 

132 

133 register_array_hest = register_array.append_register_array( 

134 name="hest", length=4, description="" 

135 ) 

136 assert register_array_hest.base_index == 0 

137 register_array_hest.append_register(name="foo", mode="r", description="") 

138 register_array_hest.append_register(name="bar", mode="w", description="") 

139 

140 register_array_zebra = register_array.append_register_array( 

141 name="zebra", length=2, description="" 

142 ) 

143 assert register_array_zebra.base_index == 8 

144 

145 

146def test_get_register(): 

147 register_list = RegisterList(name="apa", source_definition_file=None) 

148 hest = register_list.append_register(name="hest", mode="r", description="") 

149 zebra = register_list.append_register(name="zebra", mode="r", description="") 

150 register_list.append_register_array(name="register_array", length=3, description="") 

151 

152 assert register_list.get_register("hest") is hest 

153 assert register_list.get_register("zebra") is zebra 

154 

155 with pytest.raises(ValueError) as exception_info: 

156 assert register_list.get_register("non existing") is None 

157 assert ( 

158 str(exception_info.value) 

159 == 'Could not find register "non existing" within register list "apa"' 

160 ) 

161 

162 with pytest.raises(ValueError) as exception_info: 

163 assert register_list.get_register("register_array") is None 

164 assert ( 

165 str(exception_info.value) 

166 == 'Could not find register "register_array" within register list "apa"' 

167 ) 

168 register_list.get_register_array("register_array") 

169 

170 

171def test_get_register_array(): 

172 register_list = RegisterList(name="apa", source_definition_file=None) 

173 hest = register_list.append_register_array(name="hest", length=3, description="") 

174 zebra = register_list.append_register_array(name="zebra", length=2, description="") 

175 register_list.append_register(name="register", mode="r", description="") 

176 

177 assert register_list.get_register_array("hest") is hest 

178 assert register_list.get_register_array("zebra") is zebra 

179 

180 with pytest.raises(ValueError) as exception_info: 

181 assert register_list.get_register_array("non existing") is None 

182 assert ( 

183 str(exception_info.value) 

184 == 'Could not find register array "non existing" within register list "apa"' 

185 ) 

186 

187 with pytest.raises(ValueError) as exception_info: 

188 assert register_list.get_register_array("register") is None 

189 assert ( 

190 str(exception_info.value) 

191 == 'Could not find register array "register" within register list "apa"' 

192 ) 

193 register_list.get_register("register") 

194 

195 

196def test_get_register_index(): 

197 register_list = RegisterList(name=None, source_definition_file=None) 

198 

199 register_list.append_register(name="apa", mode="r", description="") 

200 register_list.append_register(name="hest", mode="r", description="") 

201 

202 zebra = register_list.append_register_array(name="zebra", length=2, description="") 

203 zebra.append_register(name="bar", mode="r", description="") 

204 zebra.append_register(name="baz", mode="r", description="") 

205 

206 assert register_list.get_register_index(register_name="apa") == 0 

207 assert register_list.get_register_index(register_name="hest") == 1 

208 assert ( 

209 register_list.get_register_index( 

210 register_name="bar", register_array_name="zebra", register_array_index=0 

211 ) 

212 == 2 

213 ) 

214 assert ( 

215 register_list.get_register_index( 

216 register_name="baz", register_array_name="zebra", register_array_index=1 

217 ) 

218 == 5 

219 ) 

220 

221 

222def test_repr_basic(): 

223 # Check that repr is an actual representation, not just "X object at 0xABCDEF" 

224 assert "apa" in repr(RegisterList(name="apa", source_definition_file=Path("."))) 

225 

226 # Different name 

227 assert repr(RegisterList(name="apa", source_definition_file=Path("."))) != repr( 

228 RegisterList(name="hest", source_definition_file=Path(".")) 

229 ) 

230 

231 # Different source_definition_file 

232 assert repr(RegisterList(name="apa", source_definition_file=Path("."))) != repr( 

233 RegisterList(name="apa", source_definition_file=Path("./zebra")) 

234 ) 

235 

236 

237def test_repr_with_constant_added(): 

238 register_list_a = RegisterList(name="apa", source_definition_file=Path(".")) 

239 register_list_b = RegisterList(name="apa", source_definition_file=Path(".")) 

240 assert repr(register_list_a) == repr(register_list_b) 

241 

242 register_list_a.add_constant(name="zebra", value=3) 

243 

244 assert repr(register_list_a) != repr(register_list_b) 

245 

246 

247def test_repr_with_register_appended(): 

248 register_list_a = RegisterList(name="apa", source_definition_file=Path(".")) 

249 register_list_b = RegisterList(name="apa", source_definition_file=Path(".")) 

250 assert repr(register_list_a) == repr(register_list_b) 

251 

252 register_list_a.append_register(name="zebra", mode="w", description="") 

253 

254 assert repr(register_list_a) != repr(register_list_b) 

255 

256 

257def test_repr_with_register_array_appended(): 

258 register_list_a = RegisterList(name="apa", source_definition_file=Path(".")) 

259 register_list_b = RegisterList(name="apa", source_definition_file=Path(".")) 

260 assert repr(register_list_a) == repr(register_list_b) 

261 

262 register_list_a.append_register_array(name="zebra", length=4, description="") 

263 

264 assert repr(register_list_a) != repr(register_list_b) 

265 

266 

267def test_deep_copy_of_register_list_actually_copies_everything(): 

268 original_list = RegisterList("original", Path("/original_file.txt")) 

269 original_list.add_constant("original_constant", value=2, description="original constant") 

270 original_list.append_register("original_register", "w", description="original register") 

271 original_array = original_list.append_register_array("original_array", length=4, description="") 

272 original_array.append_register(name="original_register_in_array", mode="r", description="") 

273 

274 copied_list = copy.deepcopy(original_list) 

275 

276 assert copied_list.constants is not original_list.constants 

277 assert copied_list.constants[0] is not original_list.constants[0] 

278 

279 copied_list.add_constant(name="new_constant", value=5) 

280 assert len(copied_list.constants) == 2 and len(original_list.constants) == 1 

281 

282 assert copied_list.register_objects is not original_list.register_objects 

283 assert copied_list.register_objects[0] is not original_list.register_objects[0] 

284 

285 # Original register in position 0, original register array in position 1, new register in 2 

286 copied_list.append_register(name="new_register", mode="r", description="") 

287 assert len(copied_list.register_objects) == 3 and len(original_list.register_objects) == 2 

288 

289 assert copied_list.register_objects[1] is not original_list.register_objects[1] 

290 assert ( 

291 copied_list.register_objects[1].registers is not original_list.register_objects[1].registers 

292 ) 

293 assert ( 

294 copied_list.register_objects[1].registers[0] 

295 is not original_list.register_objects[1].registers[0] 

296 ) 

297 copied_list.register_objects[1].append_register( 

298 name="new_register_in_array", mode="r_w", description="" 

299 ) 

300 assert len(copied_list.register_objects[1].registers) == 2 

301 assert len(original_list.register_objects[1].registers) == 1 

302 

303 

304# pylint: disable=too-many-public-methods 

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

306class TestRegisterList(unittest.TestCase): 

307 

308 tmp_path = None 

309 

310 module_name = "sensor" 

311 toml_data = """\ 

312################################################################################ 

313[register.data] 

314 

315mode = "w" 

316description = "My register" 

317 

318""" 

319 

320 def setUp(self): 

321 self.toml_file = self.create_toml_file_with_extras() 

322 

323 def create_toml_file_with_extras(self, toml_extras=""): 

324 data = self.toml_data + toml_extras 

325 return create_file(self.tmp_path / "sensor_regs.toml", data) 

326 

327 def test_create_vhdl_package_should_not_run_if_nothing_has_changed(self): 

328 register_list = from_toml(self.module_name, self.toml_file) 

329 register_list.add_constant(name="apa", value=3) 

330 register_list.create_vhdl_package(self.tmp_path) 

331 

332 register_list = from_toml(self.module_name, self.toml_file) 

333 register_list.add_constant(name="apa", value=3) 

334 with patch( 

335 "tsfpga.registers.register_list.RegisterList._create_vhdl_package", autospec=True 

336 ) as mocked_create_vhdl_package: 

337 register_list.create_vhdl_package(self.tmp_path) 

338 mocked_create_vhdl_package.assert_not_called() 

339 

340 def test_create_vhdl_package_should_run_if_hash_or_version_can_not_be_read(self): 

341 register_list = from_toml(self.module_name, self.toml_file) 

342 register_list.create_vhdl_package(self.tmp_path) 

343 

344 # Overwrite the generated file, without a valid header 

345 vhd_file = self.tmp_path / "sensor_regs_pkg.vhd" 

346 assert vhd_file.exists() 

347 create_file(vhd_file, contents="-- Mumbo jumbo\n") 

348 

349 register_list = from_toml(self.module_name, self.toml_file) 

350 with patch( 

351 "tsfpga.registers.register_list.RegisterList._create_vhdl_package", autospec=True 

352 ) as mocked_create_vhdl_package: 

353 register_list.create_vhdl_package(self.tmp_path) 

354 mocked_create_vhdl_package.assert_called_once() 

355 

356 def test_create_vhdl_package_should_run_again_if_toml_file_has_changed(self): 

357 register_list = from_toml(self.module_name, self.toml_file) 

358 register_list.create_vhdl_package(self.tmp_path) 

359 

360 self.create_toml_file_with_extras( 

361 """ 

362[constant.apa] 

363 

364value = 3 

365""" 

366 ) 

367 register_list = from_toml(self.module_name, self.toml_file) 

368 with patch( 

369 "tsfpga.registers.register_list.RegisterList._create_vhdl_package", autospec=True 

370 ) as mocked_create_vhdl_package: 

371 register_list.create_vhdl_package(self.tmp_path) 

372 mocked_create_vhdl_package.assert_called_once() 

373 

374 def test_create_vhdl_package_should_run_again_if_list_is_modified(self): 

375 register_list = from_toml(self.module_name, self.toml_file) 

376 register_list.create_vhdl_package(self.tmp_path) 

377 

378 register_list = from_toml(self.module_name, self.toml_file) 

379 register_list.add_constant(name="apa", value=3) 

380 with patch( 

381 "tsfpga.registers.register_list.RegisterList._create_vhdl_package", autospec=True 

382 ) as mocked_create_vhdl_package: 

383 register_list.create_vhdl_package(self.tmp_path) 

384 mocked_create_vhdl_package.assert_called_once() 

385 

386 def test_create_vhdl_package_should_run_again_if_version_is_changed(self): 

387 register_list = from_toml(self.module_name, self.toml_file) 

388 register_list.create_vhdl_package(self.tmp_path) 

389 

390 with patch( 

391 "tsfpga.registers.register_list.RegisterList._create_vhdl_package", autospec=True 

392 ) as mocked_create_vhdl_package, patch( 

393 "tsfpga.registers.register_list.__version__", autospec=True 

394 ) as _: 

395 register_list.create_vhdl_package(self.tmp_path) 

396 mocked_create_vhdl_package.assert_called_once()