Coverage for hdl_registers/parser/test/test_parser/test_parser_field.py: 100%

87 statements  

« prev     ^ index     » next       coverage.py v7.11.3, created at 2025-11-16 20:50 +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 create_file 

12 

13from hdl_registers.field.numerical_interpretation import ( 

14 Signed, 

15 SignedFixedPoint, 

16 Unsigned, 

17 UnsignedFixedPoint, 

18) 

19from hdl_registers.parser.toml import from_toml 

20 

21 

22def test_register_field_without_type_property_should_raise_exception(tmp_path): 

23 toml_path = create_file( 

24 file=tmp_path / "regs.toml", 

25 contents=""" 

26[apa] 

27 

28mode = "r_w" 

29 

30hest.width = 4 

31""", 

32 ) 

33 

34 with pytest.raises(ValueError) as exception_info: 

35 from_toml(name="", toml_file=toml_path) 

36 assert str(exception_info.value) == ( 

37 f'Error while parsing field "hest" in register "apa" in {toml_path}: ' 

38 'Missing required property "type".' 

39 ) 

40 

41 

42def test_array_register_field_without_type_property_should_raise_exception(tmp_path): 

43 toml_path = create_file( 

44 file=tmp_path / "regs.toml", 

45 contents=""" 

46[apa] 

47 

48type = "register_array" 

49array_length = 2 

50 

51[apa.hest] 

52 

53mode = "r_w" 

54 

55zebra.width = 4 

56""", 

57 ) 

58 

59 with pytest.raises(ValueError) as exception_info: 

60 from_toml(name="", toml_file=toml_path) 

61 assert str(exception_info.value) == ( 

62 f'Error while parsing field "zebra" in register "hest" within array "apa" in {toml_path}: ' 

63 'Missing required property "type".' 

64 ) 

65 

66 

67def test_register_field_with_unknown_type_should_raise_exception(tmp_path): 

68 toml_path = create_file( 

69 file=tmp_path / "regs.toml", 

70 contents=""" 

71[apa] 

72 

73mode = "r_w" 

74 

75hest.type = "bits" 

76hest.width = 4 

77""", 

78 ) 

79 

80 with pytest.raises(ValueError) as exception_info: 

81 from_toml(name="", toml_file=toml_path) 

82 assert str(exception_info.value) == ( 

83 f'Error while parsing field "hest" in register "apa" in {toml_path}: ' 

84 'Unknown field type "bits". Expected one of "bit", "bit_vector", "enumeration", "integer".' 

85 ) 

86 

87 

88def test_array_register_field_with_unknown_type_should_raise_exception(tmp_path): 

89 toml_path = create_file( 

90 file=tmp_path / "regs.toml", 

91 contents=""" 

92[apa] 

93 

94type = "register_array" 

95array_length = 2 

96 

97[apa.hest] 

98 

99mode = "r_w" 

100 

101zebra.type = "bits" 

102zebra.width = 4 

103""", 

104 ) 

105 

106 with pytest.raises(ValueError) as exception_info: 

107 from_toml(name="", toml_file=toml_path) 

108 assert str(exception_info.value) == ( 

109 f'Error while parsing field "zebra" in register "hest" within array "apa" in {toml_path}: ' 

110 'Unknown field type "bits". Expected one of "bit", "bit_vector", "enumeration", "integer".' 

111 ) 

112 

113 

114def test_unknown_bit_property_should_raise_exception(tmp_path): 

115 toml_path = create_file( 

116 file=tmp_path / "regs.toml", 

117 contents=""" 

118[dummy_reg] 

119 

120mode = "w" 

121 

122dummy_bit.type = "bit" 

123dummy_bit.description = "Stuff" 

124 

125dummy_bit.dummy_integer.max_value = 3 

126""", 

127 ) 

128 

129 with pytest.raises(ValueError) as exception_info: 

130 from_toml(name="", toml_file=toml_path) 

131 assert str(exception_info.value) == ( 

132 f'Error while parsing field "dummy_bit" in register "dummy_reg" in {toml_path}: ' 

133 'Unknown property "dummy_integer".' 

134 ) 

135 

136 

137def test_unknown_bit_vector_property_should_raise_exception(tmp_path): 

138 toml_path = create_file( 

139 file=tmp_path / "regs.toml", 

140 contents=""" 

141[apa] 

142 

143type = "register_array" 

144array_length = 2 

145 

146[apa.dummy_reg] 

147 

148mode = "w" 

149 

150[apa.dummy_reg.dummy_bit_vector] 

151 

152type = "bit_vector" 

153description = "Stuff" 

154width = 3 

155height = 4 

156 

157""", 

158 ) 

159 

160 with pytest.raises(ValueError) as exception_info: 

161 from_toml(name="", toml_file=toml_path) 

162 assert str(exception_info.value) == ( 

163 f'Error while parsing field "dummy_bit_vector" in register "dummy_reg" within array "apa" ' 

164 f'in {toml_path}: Unknown property "height".' 

165 ) 

166 

167 

168def test_bit_vector_without_width_should_raise_exception(tmp_path): 

169 toml_path = create_file( 

170 file=tmp_path / "regs.toml", 

171 contents=""" 

172[test_reg] 

173mode = "w" 

174 

175test_bit_vector.type = "bit_vector" 

176""", 

177 ) 

178 

179 with pytest.raises(ValueError) as exception_info: 

180 from_toml(name="", toml_file=toml_path) 

181 assert str(exception_info.value) == ( 

182 f'Error while parsing field "test_bit_vector" in register "test_reg" in {toml_path}: ' 

183 'Missing required property "width".' 

184 ) 

185 

186 

187def test_numerical_interpretation_properties_on_anything_but_bit_vector_should_raise_exception( 

188 tmp_path, 

189): 

190 toml_path = create_file( 

191 file=tmp_path / "regs.toml", 

192 contents=""" 

193[test_reg] 

194mode = "w" 

195 

196my_field.type = "integer" 

197my_field.max_value = 255 

198my_field.numerical_interpretation = "unsigned" 

199""", 

200 ) 

201 

202 with pytest.raises(ValueError) as exception_info: 

203 from_toml(name="", toml_file=toml_path) 

204 assert str(exception_info.value) == ( 

205 f'Error while parsing field "my_field" in register "test_reg" in {toml_path}: ' 

206 'Unknown property "numerical_interpretation".' 

207 ) 

208 

209 

210def test_bit_vector_different_numerical_interpretations(tmp_path): 

211 toml_path = create_file( 

212 file=tmp_path / "regs.toml", 

213 contents=""" 

214[test_reg] 

215mode = "w" 

216 

217unsigned_implied.type = "bit_vector" 

218unsigned_implied.width = 1 

219 

220unsigned_explicit.type = "bit_vector" 

221unsigned_explicit.width = 2 

222unsigned_explicit.numerical_interpretation = "unsigned" 

223 

224signed.type = "bit_vector" 

225signed.width = 3 

226signed.numerical_interpretation = "signed" 

227 

228ufixed_implied.type = "bit_vector" 

229ufixed_implied.width = 4 

230ufixed_implied.numerical_interpretation = "unsigned_fixed_point" 

231 

232ufixed_explicit.type = "bit_vector" 

233ufixed_explicit.width = 5 

234ufixed_explicit.numerical_interpretation = "unsigned_fixed_point" 

235ufixed_explicit.min_bit_index = -2 

236 

237sfixed_implied.type = "bit_vector" 

238sfixed_implied.width = 6 

239sfixed_implied.numerical_interpretation = "signed_fixed_point" 

240 

241sfixed_explicit.type = "bit_vector" 

242sfixed_explicit.width = 7 

243sfixed_explicit.numerical_interpretation = "signed_fixed_point" 

244sfixed_explicit.min_bit_index = 2 

245""", 

246 ) 

247 register = from_toml(name="", toml_file=toml_path).get_register("test_reg") 

248 

249 unsigned_implied = register.get_field("unsigned_implied").numerical_interpretation 

250 assert isinstance(unsigned_implied, Unsigned) 

251 assert unsigned_implied.bit_width == 1 

252 

253 unsigned_explicit = register.get_field("unsigned_explicit").numerical_interpretation 

254 assert isinstance(unsigned_explicit, Unsigned) 

255 assert unsigned_explicit.bit_width == 2 

256 

257 signed = register.get_field("signed").numerical_interpretation 

258 assert isinstance(signed, Signed) 

259 assert signed.bit_width == 3 

260 

261 ufixed_implied = register.get_field("ufixed_implied").numerical_interpretation 

262 assert isinstance(ufixed_implied, UnsignedFixedPoint) 

263 assert ufixed_implied.max_bit_index == 3 

264 assert ufixed_implied.min_bit_index == 0 

265 

266 ufixed_explicit = register.get_field("ufixed_explicit").numerical_interpretation 

267 assert isinstance(ufixed_explicit, UnsignedFixedPoint) 

268 assert ufixed_explicit.max_bit_index == 2 

269 assert ufixed_explicit.min_bit_index == -2 

270 

271 sfixed_implied = register.get_field("sfixed_implied").numerical_interpretation 

272 assert isinstance(sfixed_implied, SignedFixedPoint) 

273 assert sfixed_implied.max_bit_index == 5 

274 assert sfixed_implied.min_bit_index == 0 

275 

276 sfixed_explicit = register.get_field("sfixed_explicit").numerical_interpretation 

277 assert isinstance(sfixed_explicit, SignedFixedPoint) 

278 assert sfixed_explicit.max_bit_index == 8 

279 assert sfixed_explicit.min_bit_index == 2 

280 

281 

282def test_bit_vector_unknown_numerical_interpretation_should_raise_exception(tmp_path): 

283 toml_path = create_file( 

284 file=tmp_path / "regs.toml", 

285 contents=""" 

286[test_reg] 

287mode = "w" 

288 

289my_field.type = "bit_vector" 

290my_field.width = 2 

291my_field.numerical_interpretation = "apa" 

292""", 

293 ) 

294 with pytest.raises(ValueError) as exception_info: 

295 from_toml(name="", toml_file=toml_path) 

296 assert str(exception_info.value) == ( 

297 f'Error while parsing field "my_field" in register "test_reg" in {toml_path}: ' 

298 'Unknown value "apa" for property "numerical_interpretation". ' 

299 'Expected one of "unsigned", "signed", "unsigned_fixed_point", "signed_fixed_point".' 

300 ) 

301 

302 

303def test_enumeration_without_elements_should_raise_exception(tmp_path): 

304 toml_path = create_file( 

305 file=tmp_path / "regs.toml", 

306 contents=""" 

307[apa] 

308 

309type = "register_array" 

310array_length = 2 

311 

312[apa.test_reg] 

313 

314mode = "w" 

315 

316test.type = "enumeration" 

317""", 

318 ) 

319 

320 with pytest.raises(ValueError) as exception_info: 

321 from_toml(name="", toml_file=toml_path) 

322 assert str(exception_info.value) == ( 

323 'Error while parsing field "test" in register "test_reg" within array "apa" ' 

324 f'in {toml_path}: Missing required property "element".' 

325 ) 

326 

327 

328def test_integer_without_max_value_should_raise_exception(tmp_path): 

329 toml_path = create_file( 

330 file=tmp_path / "regs.toml", 

331 contents=""" 

332[test_reg] 

333mode = "w" 

334 

335test_integer.type = "integer" 

336test_integer.min_value = 3 

337""", 

338 ) 

339 

340 with pytest.raises(ValueError) as exception_info: 

341 from_toml(name="", toml_file=toml_path) 

342 assert str(exception_info.value) == ( 

343 f'Error while parsing field "test_integer" in register "test_reg" in {toml_path}: ' 

344 'Missing required property "max_value".' 

345 )