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

82 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-09-07 20:51 +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 

10# Third party libraries 

11import pytest 

12from tsfpga.system_utils import create_file 

13 

14# First party libraries 

15from hdl_registers.parser.toml import from_toml 

16from hdl_registers.register_modes import REGISTER_MODES 

17 

18 

19def test_unknown_top_level_property_should_raise_exception(tmp_path): 

20 toml_path = create_file( 

21 file=tmp_path / "regs.toml", 

22 contents=""" 

23mode = "w" 

24""", 

25 ) 

26 

27 with pytest.raises(ValueError) as exception_info: 

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

29 assert str(exception_info.value) == ( 

30 f'Error while parsing {toml_path}: Got unknown top-level property "mode".' 

31 ) 

32 

33 

34def test_unknown_top_level_item_type_should_raise_exception(tmp_path): 

35 toml_path = create_file( 

36 file=tmp_path / "regs.toml", 

37 contents=""" 

38hest.type = "register_constant" 

39""", 

40 ) 

41 

42 with pytest.raises(ValueError) as exception_info: 

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

44 assert str(exception_info.value) == ( 

45 f'Error while parsing "hest" in {toml_path}: Got unknown type "register_constant". ' 

46 'Expected one of "constant", "register", "register_array".' 

47 ) 

48 

49 

50def test_order_of_registers_and_fields(tmp_path): # pylint: disable=too-many-statements 

51 toml_data = """ 

52################################################################################ 

53[data] 

54 

55type = "register" 

56mode = "w" 

57 

58 

59################################################################################ 

60[status] 

61 

62type = "register" 

63mode = "r_w" 

64description = "Status register" 

65 

66direction.type = "enumeration" 

67direction.description = "The direction mode" 

68direction.default_value = "input" 

69direction.element.passthrough = "" 

70direction.element.input = "" 

71direction.element.output = "use in output mode" 

72 

73bad.type = "bit" 

74bad.description = "Bad things happen" 

75 

76interrupts.type = "bit_vector" 

77interrupts.width = 4 

78interrupts.description = "Many interrupts" 

79interrupts.default_value = "0110" 

80 

81not_good.type = "bit" 

82not_good.description = "" 

83not_good.default_value = "1" 

84 

85count.type = "integer" 

86count.description = "The number of things" 

87count.min_value = -5 

88count.max_value = 15 

89 

90 

91################################################################################ 

92[config] 

93 

94type = "register_array" 

95array_length = 3 

96description = "A register array" 

97 

98 

99# ------------------------------------------------------------------------------ 

100[config.input_settings] 

101 

102type = "register" 

103description = "Input configuration" 

104mode = "r_w" 

105 

106[config.input_settings.enable] 

107 

108type = "bit" 

109description = "Enable things" 

110default_value = "1" 

111 

112[config.input_settings.disable] 

113 

114type = "bit" 

115description = "" 

116default_value = "0" 

117 

118[config.input_settings.number] 

119 

120type = "integer" 

121description = "Configure number" 

122max_value = 3 

123default_value = 1 

124 

125[config.input_settings.size] 

126 

127type = "enumeration" 

128default_value = "large" 

129element.small = "" 

130element.medium = "" 

131element.large = "" 

132 

133 

134# ------------------------------------------------------------------------------ 

135[config.output_settings] 

136 

137type = "register" 

138mode = "w" 

139 

140[config.output_settings.data] 

141 

142type = "bit_vector" 

143width = 16 

144description = "Some data" 

145default_value = "0000000000000011" 

146""" 

147 toml_file = create_file(file=tmp_path / "sensor_regs.toml", contents=toml_data) 

148 

149 registers = from_toml(name="sensor", toml_file=toml_file).register_objects 

150 

151 assert registers[0].name == "data" 

152 assert registers[0].mode == REGISTER_MODES["w"] 

153 assert registers[0].index == 0 

154 assert registers[0].description == "" 

155 assert registers[0].default_value == 0 

156 assert registers[0].fields == [] 

157 

158 assert registers[1].name == "status" 

159 assert registers[1].mode == REGISTER_MODES["r_w"] 

160 assert registers[1].index == 1 

161 assert registers[1].description == "Status register" 

162 

163 # Enumeration field 

164 assert registers[1].fields[0].name == "direction" 

165 assert registers[1].fields[0].description == "The direction mode" 

166 assert registers[1].fields[0].width == 2 

167 assert registers[1].fields[0].default_value.name == "input" 

168 assert registers[1].fields[0].elements[0].name == "passthrough" 

169 assert registers[1].fields[0].elements[2].name == "output" 

170 assert registers[1].fields[0].elements[2].description == "use in output mode" 

171 

172 # Bit field 

173 assert registers[1].fields[1].name == "bad" 

174 assert registers[1].fields[1].description == "Bad things happen" 

175 assert registers[1].fields[1].default_value == "0" 

176 

177 # Bit vector field 

178 assert registers[1].fields[2].name == "interrupts" 

179 assert registers[1].fields[2].description == "Many interrupts" 

180 assert registers[1].fields[2].width == 4 

181 assert registers[1].fields[2].default_value == "0110" 

182 

183 # Bit field 

184 assert registers[1].fields[3].name == "not_good" 

185 assert registers[1].fields[3].description == "" 

186 assert registers[1].fields[3].default_value == "1" 

187 

188 # Integer field 

189 assert registers[1].fields[4].name == "count" 

190 assert registers[1].fields[4].description == "The number of things" 

191 assert registers[1].fields[4].width == 5 

192 assert registers[1].fields[4].min_value == -5 

193 assert registers[1].fields[4].max_value == 15 

194 assert registers[1].fields[4].default_value == -5 

195 

196 assert registers[1].default_value == ( 

197 # Enum 

198 1 * 2**0 

199 # Bit 

200 + 0 * 2**2 

201 # Bit vector 

202 + 6 * 2**3 

203 # Bit 

204 + 1 * 2**7 

205 # Integer, negative value converted to positive 

206 + 0b11011 * 2**8 

207 ) 

208 

209 assert registers[2].name == "config" 

210 assert registers[2].length == 3 

211 assert registers[2].description == "A register array" 

212 assert registers[2].index == 2 + 2 * 3 - 1 

213 assert len(registers[2].registers) == 2 

214 

215 assert registers[2].registers[0].name == "input_settings" 

216 assert registers[2].registers[0].mode == REGISTER_MODES["r_w"] 

217 assert registers[2].registers[0].index == 0 

218 assert registers[2].registers[0].description == "Input configuration" 

219 assert registers[2].registers[0].fields[0].name == "enable" 

220 assert registers[2].registers[0].fields[0].description == "Enable things" 

221 assert registers[2].registers[0].fields[0].default_value == "1" 

222 assert registers[2].registers[0].fields[1].name == "disable" 

223 assert registers[2].registers[0].fields[1].description == "" 

224 assert registers[2].registers[0].fields[1].default_value == "0" 

225 assert registers[2].registers[0].fields[2].name == "number" 

226 assert registers[2].registers[0].fields[2].description == "Configure number" 

227 assert registers[2].registers[0].fields[2].default_value == 1 

228 assert registers[2].registers[0].fields[3].name == "size" 

229 assert registers[2].registers[0].fields[3].default_value.name == "large" 

230 assert registers[2].registers[0].default_value == ( 

231 # First bit 

232 1 * 2**0 

233 # Integer 

234 + 1 * 2**2 

235 # Enumeration 

236 + 2 * 2**4 

237 ) 

238 

239 assert registers[2].registers[1].name == "output_settings" 

240 assert registers[2].registers[1].mode == REGISTER_MODES["w"] 

241 assert registers[2].registers[1].index == 1 

242 assert registers[2].registers[1].description == "" 

243 assert registers[2].registers[1].default_value == 3 

244 assert registers[2].registers[1].fields[0].name == "data" 

245 assert registers[2].registers[1].fields[0].description == "Some data" 

246 assert registers[2].registers[1].fields[0].width == 16 

247 assert registers[2].registers[1].fields[0].default_value == "0000000000000011"