Coverage for hdl_registers/field/test/test_numerical_interpretation.py: 100%

97 statements  

« prev     ^ index     » next       coverage.py v7.6.9, created at 2024-12-19 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# pylint: disable=protected-access 

10 

11# Third party libraries 

12import pytest 

13 

14# First party libraries 

15from hdl_registers.field.numerical_interpretation import ( 

16 Signed, 

17 SignedFixedPoint, 

18 Unsigned, 

19 UnsignedFixedPoint, 

20) 

21 

22 

23@pytest.mark.parametrize( 

24 "numerical_interpretation, min_value, max_value", 

25 [ 

26 (Unsigned(bit_width=2), 0.0, 3), 

27 (Unsigned(bit_width=8), 0.0, 255), 

28 (Signed(bit_width=2), -2, 1), 

29 (Signed(bit_width=6), -32, 31), 

30 (Signed(bit_width=8), -128, 127), 

31 (UnsignedFixedPoint(max_bit_index=-1, min_bit_index=-2), 0.0, 0.75), 

32 (UnsignedFixedPoint(max_bit_index=5, min_bit_index=-2), 0.0, 63.75), 

33 (UnsignedFixedPoint(max_bit_index=5, min_bit_index=0), 0.0, 63), 

34 (SignedFixedPoint(max_bit_index=-1, min_bit_index=-2), -0.5, 0.25), 

35 (SignedFixedPoint(max_bit_index=5, min_bit_index=-2), -32, 31.75), 

36 (SignedFixedPoint(max_bit_index=5, min_bit_index=0), -32, 31), 

37 ], 

38) 

39def test_min_max_zero(numerical_interpretation, min_value, max_value): 

40 assert numerical_interpretation.min_value == min_value 

41 assert numerical_interpretation.max_value == max_value 

42 assert numerical_interpretation.convert_to_unsigned_binary(0.0) == 0b0 

43 

44 

45@pytest.mark.parametrize( 

46 "numerical_interpretation", 

47 [ 

48 (Unsigned(bit_width=2)), 

49 (Unsigned(bit_width=8)), 

50 (Signed(bit_width=2)), 

51 (Signed(bit_width=6)), 

52 (Signed(bit_width=8)), 

53 (UnsignedFixedPoint(max_bit_index=-1, min_bit_index=-2)), 

54 (UnsignedFixedPoint(max_bit_index=5, min_bit_index=-2)), 

55 (UnsignedFixedPoint(max_bit_index=5, min_bit_index=0)), 

56 (SignedFixedPoint(max_bit_index=-1, min_bit_index=-2)), 

57 (SignedFixedPoint(max_bit_index=5, min_bit_index=-2)), 

58 (SignedFixedPoint(max_bit_index=5, min_bit_index=0)), 

59 ], 

60) 

61def test_zero_min_max_restore(numerical_interpretation): 

62 value = 0 

63 numerical_interpretation._check_native_value_in_range(value) 

64 unsigned = numerical_interpretation.convert_to_unsigned_binary(value) 

65 assert unsigned == 0x0 

66 restored = numerical_interpretation.convert_from_unsigned_binary(unsigned) 

67 assert restored == value 

68 

69 value = numerical_interpretation.min_value 

70 numerical_interpretation._check_native_value_in_range(value) 

71 unsigned = numerical_interpretation.convert_to_unsigned_binary(value) 

72 restored = numerical_interpretation.convert_from_unsigned_binary(unsigned) 

73 assert restored == value 

74 

75 value = numerical_interpretation.max_value 

76 numerical_interpretation._check_native_value_in_range(value) 

77 unsigned = numerical_interpretation.convert_to_unsigned_binary(value) 

78 restored = numerical_interpretation.convert_from_unsigned_binary(unsigned) 

79 assert restored == value 

80 

81 

82@pytest.mark.parametrize( 

83 "numerical_interpretation", 

84 [ 

85 (Unsigned(bit_width=2)), 

86 (Unsigned(bit_width=8)), 

87 (Signed(bit_width=2)), 

88 (Signed(bit_width=6)), 

89 (Signed(bit_width=8)), 

90 (UnsignedFixedPoint(max_bit_index=-1, min_bit_index=-2)), 

91 (UnsignedFixedPoint(max_bit_index=5, min_bit_index=-2)), 

92 (UnsignedFixedPoint(max_bit_index=5, min_bit_index=0)), 

93 (SignedFixedPoint(max_bit_index=-1, min_bit_index=-2)), 

94 (SignedFixedPoint(max_bit_index=5, min_bit_index=-2)), 

95 (SignedFixedPoint(max_bit_index=5, min_bit_index=0)), 

96 ], 

97) 

98def test_out_of_range(numerical_interpretation): 

99 value = numerical_interpretation.min_value - 0.00001 

100 with pytest.raises(ValueError): 

101 numerical_interpretation._check_native_value_in_range(value) 

102 with pytest.raises(ValueError): 

103 numerical_interpretation.convert_to_unsigned_binary(value) 

104 

105 value = numerical_interpretation.max_value + 0.00001 

106 with pytest.raises(ValueError): 

107 numerical_interpretation._check_native_value_in_range(value) 

108 with pytest.raises(ValueError): 

109 numerical_interpretation.convert_to_unsigned_binary(value) 

110 

111 

112@pytest.mark.parametrize( 

113 "bit_width, value, expected", 

114 [ 

115 (8, 1, 0b00000001), 

116 (8, -1, 0b11111111), 

117 (8, 40, 0b00101000), 

118 (8, -40, 0b11011000), 

119 (8, 126, 0b01111110), 

120 (8, -126, 0b10000010), 

121 ], 

122) 

123def test_signed(bit_width, value, expected): 

124 numerical_interpretation = Signed(bit_width=bit_width) 

125 numerical_interpretation._check_native_value_in_range(value) 

126 

127 unsigned = numerical_interpretation.convert_to_unsigned_binary(value) 

128 assert unsigned == expected 

129 

130 restored = numerical_interpretation.convert_from_unsigned_binary(unsigned) 

131 assert restored == value 

132 

133 

134@pytest.mark.parametrize( 

135 "max_bit_index, min_bit_index, value, exp_uint, exp_return", 

136 [ 

137 (-1, -1, 0.00, 0b0, 0.00), 

138 (-1, -1, 0.25, 0b0, 0.00), 

139 (-1, -1, 0.50, 0b1, 0.50), 

140 (-1, -2, 0.00, 0b00, 0.00), 

141 (-1, -2, 0.25, 0b01, 0.25), 

142 (-1, -2, 0.50, 0b10, 0.50), 

143 (-1, -2, 0.75, 0b11, 0.75), 

144 (-1, -2, 0.125, 0b000, 0.00), 

145 (-1, -3, 0.125, 0b001, 0.125), 

146 (0, -3, 1.125, 0b1001, 1.125), 

147 (4, -4, 9.75, 0b010011100, 9.75), 

148 (3, -3, 4.625, 0b0100101, 4.625), 

149 (9, 8, 256.0, 0b01, 256.0), 

150 (9, 8, 768.0, 0b11, 768.0), 

151 (-2, -3, 0.375, 0b11, 0.375), 

152 (-3, -4, 0.1875, 0b11, 0.1875), 

153 (4, -5, 6.5, 0b0011010000, 6.5), 

154 ], 

155) 

156def test_ufixed(max_bit_index, min_bit_index, value, exp_uint, exp_return): 

157 numerical_interpretation = UnsignedFixedPoint( 

158 max_bit_index=max_bit_index, min_bit_index=min_bit_index 

159 ) 

160 

161 numerical_interpretation._check_native_value_in_range(value) 

162 

163 unsigned = numerical_interpretation.convert_to_unsigned_binary(value) 

164 assert unsigned == exp_uint 

165 

166 restored = numerical_interpretation.convert_from_unsigned_binary(unsigned) 

167 assert restored == exp_return 

168 

169 

170@pytest.mark.parametrize( 

171 "max_bit_index, min_bit_index, value, expected, expected_restored", 

172 [ 

173 (-1, -2, -0.25, 0b11, -0.25), 

174 (-1, -2, 0.25, 0b01, 0.25), 

175 (4, -4, 9.75, 0b010011100, 9.75), 

176 (5, -4, -13.8125, 0b1100100011, -13.8125), 

177 (9, 8, 256.0, 0b01, 256.0), 

178 (9, 8, -256.0, 0b11, -256.0), 

179 (-2, -3, -0.125, 0b11, -0.125), 

180 (-3, -4, -0.0625, 0b11, -0.0625), 

181 (4, -5, -6.5, 0b1100110000, -6.5), 

182 (8, -3, -0.01, 0, 0.0), 

183 ], 

184) 

185def test_sfixed(max_bit_index, min_bit_index, value, expected, expected_restored): 

186 numerical_interpretation = SignedFixedPoint( 

187 max_bit_index=max_bit_index, min_bit_index=min_bit_index 

188 ) 

189 numerical_interpretation._check_native_value_in_range(value) 

190 

191 unsigned = numerical_interpretation.convert_to_unsigned_binary(value) 

192 assert unsigned.bit_length() <= numerical_interpretation.bit_width 

193 assert unsigned == expected 

194 

195 restored = numerical_interpretation.convert_from_unsigned_binary(unsigned) 

196 assert restored == expected_restored 

197 

198 

199@pytest.mark.parametrize( 

200 "numerical_interpretation_class, integer_bit_width, fraction_bit_width", 

201 [ 

202 (UnsignedFixedPoint, 9, 2), 

203 (UnsignedFixedPoint, 11, -8), 

204 (UnsignedFixedPoint, -1, 3), 

205 (SignedFixedPoint, 9, 2), 

206 (SignedFixedPoint, 11, -8), 

207 (SignedFixedPoint, -1, 3), 

208 ], 

209) 

210def test_via_bit_widths(numerical_interpretation_class, integer_bit_width, fraction_bit_width): 

211 numerical_interpretation = numerical_interpretation_class.from_bit_widths( 

212 integer_bit_width=integer_bit_width, fraction_bit_width=fraction_bit_width 

213 ) 

214 assert numerical_interpretation.integer_bit_width == integer_bit_width 

215 assert numerical_interpretation.fraction_bit_width == fraction_bit_width 

216 

217 

218@pytest.mark.parametrize( 

219 "numerical_interpretation", 

220 [ 

221 (Unsigned(bit_width=8)), 

222 (Signed(bit_width=8)), 

223 (UnsignedFixedPoint(max_bit_index=4, min_bit_index=-3)), 

224 (SignedFixedPoint(max_bit_index=5, min_bit_index=-2)), 

225 ], 

226) 

227def test_convert_from_unsigned_binary_value_out_of_range_should_raise_exception( 

228 numerical_interpretation, 

229): 

230 assert numerical_interpretation.bit_width == 8 

231 

232 numerical_interpretation.convert_from_unsigned_binary(0) 

233 with pytest.raises(ValueError) as exception_info: 

234 numerical_interpretation.convert_from_unsigned_binary(-1) 

235 assert str(exception_info.value).startswith("Value: -1 out of range of 8-bit ") 

236 

237 numerical_interpretation.convert_from_unsigned_binary(255) 

238 with pytest.raises(ValueError) as exception_info: 

239 numerical_interpretation.convert_from_unsigned_binary(256) 

240 assert str(exception_info.value).startswith("Value: 256 out of range of 8-bit ") 

241 

242 

243def test_repr(): 

244 unsigned0 = Unsigned(2) 

245 unsigned1 = Unsigned(2) 

246 unsigned2 = Unsigned(3) 

247 signed0 = Signed(2) 

248 signed1 = Signed(2) 

249 signed2 = Signed(3) 

250 ufixed0 = UnsignedFixedPoint(max_bit_index=7, min_bit_index=-2) 

251 ufixed1 = UnsignedFixedPoint(max_bit_index=7, min_bit_index=-2) 

252 ufixed2 = UnsignedFixedPoint(max_bit_index=8, min_bit_index=-2) 

253 sfixed0 = SignedFixedPoint(max_bit_index=7, min_bit_index=-2) 

254 sfixed1 = SignedFixedPoint(max_bit_index=7, min_bit_index=-2) 

255 sfixed2 = SignedFixedPoint(max_bit_index=8, min_bit_index=-2) 

256 

257 assert repr(unsigned0) == repr(unsigned1) != repr(unsigned2) 

258 assert repr(signed0) == repr(signed1) != repr(signed2) 

259 assert repr(unsigned0) != repr(signed0) 

260 

261 assert repr(ufixed0) == repr(ufixed1) != repr(ufixed2) 

262 assert repr(sfixed0) == repr(sfixed1) != repr(sfixed2) 

263 assert repr(ufixed0) != repr(sfixed0)