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

96 statements  

« prev     ^ index     » next       coverage.py v7.6.3, created at 2024-10-17 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", 

172 [ 

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

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

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

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

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

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

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

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

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

182 ], 

183) 

184def test_sfixed(max_bit_index, min_bit_index, value, expected): 

185 numerical_interpretation = SignedFixedPoint( 

186 max_bit_index=max_bit_index, min_bit_index=min_bit_index 

187 ) 

188 numerical_interpretation._check_native_value_in_range(value) 

189 

190 unsigned = numerical_interpretation.convert_to_unsigned_binary(value) 

191 assert unsigned == expected 

192 

193 restored = numerical_interpretation.convert_from_unsigned_binary(unsigned) 

194 assert restored == value 

195 

196 

197@pytest.mark.parametrize( 

198 "numerical_interpretation_class, integer_bit_width, fraction_bit_width", 

199 [ 

200 (UnsignedFixedPoint, 9, 2), 

201 (UnsignedFixedPoint, 11, -8), 

202 (UnsignedFixedPoint, -1, 3), 

203 (SignedFixedPoint, 9, 2), 

204 (SignedFixedPoint, 11, -8), 

205 (SignedFixedPoint, -1, 3), 

206 ], 

207) 

208def test_via_bit_widths(numerical_interpretation_class, integer_bit_width, fraction_bit_width): 

209 numerical_interpretation = numerical_interpretation_class.from_bit_widths( 

210 integer_bit_width=integer_bit_width, fraction_bit_width=fraction_bit_width 

211 ) 

212 assert numerical_interpretation.integer_bit_width == integer_bit_width 

213 assert numerical_interpretation.fraction_bit_width == fraction_bit_width 

214 

215 

216@pytest.mark.parametrize( 

217 "numerical_interpretation", 

218 [ 

219 (Unsigned(bit_width=8)), 

220 (Signed(bit_width=8)), 

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

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

223 ], 

224) 

225def test_convert_from_unsigned_binary_value_out_of_range_should_raise_exception( 

226 numerical_interpretation, 

227): 

228 assert numerical_interpretation.bit_width == 8 

229 

230 numerical_interpretation.convert_from_unsigned_binary(0) 

231 with pytest.raises(ValueError) as exception_info: 

232 numerical_interpretation.convert_from_unsigned_binary(-1) 

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

234 

235 numerical_interpretation.convert_from_unsigned_binary(255) 

236 with pytest.raises(ValueError) as exception_info: 

237 numerical_interpretation.convert_from_unsigned_binary(256) 

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

239 

240 

241def test_repr(): 

242 unsigned0 = Unsigned(2) 

243 unsigned1 = Unsigned(2) 

244 unsigned2 = Unsigned(3) 

245 signed0 = Signed(2) 

246 signed1 = Signed(2) 

247 signed2 = Signed(3) 

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

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

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

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

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

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

254 

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

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

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

258 

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

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

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