Coverage for hdl_registers/test/unit/test_register_field_type.py: 100%

89 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-01-29 22:03 +0000

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

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

3# 

4# This file is part of the hdl_registers project, a HDL register generator fast enough to be run 

5# in real time. 

6# https://hdl-registers.com 

7# https://gitlab.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.register_field_type import ( 

16 FieldType, 

17 Signed, 

18 SignedFixedPoint, 

19 Unsigned, 

20 UnsignedFixedPoint, 

21) 

22 

23 

24@pytest.mark.parametrize( 

25 "field_type, bit_width, min_value, max_value", 

26 [ 

27 (Unsigned(), 2, 0.0, 3), 

28 (Unsigned(), 8, 0.0, 255), 

29 (Signed(), 2, -2, 1), 

30 (Signed(), 6, -32, 31), 

31 (Signed(), 8, -128, 127), 

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

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

34 (UnsignedFixedPoint(max_bit_index=5, min_bit_index=0), 6, 0.0, 63), 

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

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

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

38 ], 

39) 

40def test_min_max_zero(field_type, bit_width, min_value, max_value): 

41 assert field_type.min_value(bit_width) == min_value 

42 assert field_type.max_value(bit_width) == max_value 

43 assert field_type.convert_to_unsigned_binary(bit_width, 0.0) == 0b0 

44 

45 

46@pytest.mark.parametrize( 

47 "field_type, bit_width", 

48 [ 

49 (Unsigned(), 2), 

50 (Unsigned(), 8), 

51 (Signed(), 2), 

52 (Signed(), 6), 

53 (Signed(), 8), 

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

55 (UnsignedFixedPoint(max_bit_index=5, min_bit_index=-2), 8), 

56 (UnsignedFixedPoint(max_bit_index=5, min_bit_index=0), 6), 

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

58 (SignedFixedPoint(max_bit_index=5, min_bit_index=-2), 8), 

59 (SignedFixedPoint(max_bit_index=5, min_bit_index=0), 6), 

60 ], 

61) 

62def test_zero_min_max_restore(field_type, bit_width): 

63 value = 0 

64 field_type._check_value_in_range(bit_width, value) 

65 unsigned = field_type.convert_to_unsigned_binary(bit_width, value) 

66 assert unsigned == 0x0 

67 restored = field_type.convert_from_unsigned_binary(bit_width, unsigned) 

68 assert restored == value 

69 

70 value = field_type.min_value(bit_width) 

71 field_type._check_value_in_range(bit_width, value) 

72 unsigned = field_type.convert_to_unsigned_binary(bit_width, value) 

73 restored = field_type.convert_from_unsigned_binary(bit_width, unsigned) 

74 assert restored == value 

75 

76 value = field_type.max_value(bit_width) 

77 field_type._check_value_in_range(bit_width, value) 

78 unsigned = field_type.convert_to_unsigned_binary(bit_width, value) 

79 restored = field_type.convert_from_unsigned_binary(bit_width, unsigned) 

80 assert restored == value 

81 

82 

83@pytest.mark.parametrize( 

84 "field_type, bit_width", 

85 [ 

86 (Unsigned(), 2), 

87 (Unsigned(), 8), 

88 (Signed(), 2), 

89 (Signed(), 6), 

90 (Signed(), 8), 

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

92 (UnsignedFixedPoint(max_bit_index=5, min_bit_index=-2), 8), 

93 (UnsignedFixedPoint(max_bit_index=5, min_bit_index=0), 6), 

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

95 (SignedFixedPoint(max_bit_index=5, min_bit_index=-2), 8), 

96 (SignedFixedPoint(max_bit_index=5, min_bit_index=0), 6), 

97 ], 

98) 

99def test_out_of_range(field_type: FieldType, bit_width: int): 

100 value = field_type.min_value(bit_width) - 0.00001 

101 with pytest.raises(ValueError): 

102 field_type._check_value_in_range(bit_width, value) 

103 with pytest.raises(ValueError): 

104 field_type.convert_to_unsigned_binary(bit_width, value) 

105 

106 value = field_type.max_value(bit_width) + 0.00001 

107 with pytest.raises(ValueError): 

108 field_type._check_value_in_range(bit_width, value) 

109 with pytest.raises(ValueError): 

110 field_type.convert_to_unsigned_binary(bit_width, value) 

111 

112 

113@pytest.mark.parametrize( 

114 "bit_width, value, expected", 

115 [ 

116 (8, 1, 0b00000001), 

117 (8, -1, 0b11111111), 

118 (8, 40, 0b00101000), 

119 (8, -40, 0b11011000), 

120 (8, 126, 0b01111110), 

121 (8, -126, 0b10000010), 

122 ], 

123) 

124def test_singed(bit_width, value, expected): 

125 field_type = Signed() 

126 field_type._check_value_in_range(bit_width, value) 

127 unsigned = field_type.convert_to_unsigned_binary(bit_width, value) 

128 assert unsigned == expected 

129 restored = field_type.convert_from_unsigned_binary(bit_width, unsigned) 

130 assert restored == value 

131 

132 

133@pytest.mark.parametrize( 

134 "bit_width, max_bit_index, min_bit_index, value, exp_uint, exp_return", 

135 [ 

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

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

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

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

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

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

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

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

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

145 (4, 0, -3, 1.125, 0b1001, 1.125), 

146 (9, 4, -4, 9.75, 0b010011100, 9.75), 

147 (7, 3, -3, 4.625, 0b0100101, 4.625), 

148 (2, 9, 8, 256.0, 0b01, 256.0), 

149 (2, 9, 8, 768.0, 0b11, 768.0), 

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

151 (2, -3, -4, 0.1875, 0b11, 0.1875), 

152 (10, 4, -5, 6.5, 0b0011010000, 6.5), 

153 ], 

154) 

155def test_ufixed(bit_width, max_bit_index, min_bit_index, value, exp_uint, exp_return): 

156 field_type = UnsignedFixedPoint(max_bit_index=max_bit_index, min_bit_index=min_bit_index) 

157 field_type._check_value_in_range(bit_width, value) 

158 unsigned = field_type.convert_to_unsigned_binary(bit_width, value) 

159 assert unsigned == exp_uint 

160 restored = field_type.convert_from_unsigned_binary(bit_width, unsigned) 

161 assert restored == exp_return 

162 

163 

164@pytest.mark.parametrize( 

165 "bit_width, max_bit_index, min_bit_index, value, expected", 

166 [ 

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

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

169 (9, 4, -4, 9.75, 0b010011100), 

170 (10, 5, -4, -13.8125, 0b1100100011), 

171 (2, 9, 8, 256.0, 0b01), 

172 (2, 9, 8, -256.0, 0b11), 

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

174 (2, -3, -4, -0.0625, 0b11), 

175 (10, 4, -5, -6.5, 0b1100110000), 

176 ], 

177) 

178def test_sfixed(bit_width, max_bit_index, min_bit_index, value, expected): 

179 field_type = SignedFixedPoint(max_bit_index=max_bit_index, min_bit_index=min_bit_index) 

180 field_type._check_value_in_range(bit_width, value) 

181 unsigned = field_type.convert_to_unsigned_binary(bit_width, value) 

182 assert unsigned == expected 

183 restored = field_type.convert_from_unsigned_binary(bit_width, unsigned) 

184 assert restored == value 

185 

186 

187@pytest.mark.parametrize( 

188 "field_type_class, integer_bit_width, fraction_bit_width", 

189 [ 

190 (UnsignedFixedPoint, 9, 2), 

191 (UnsignedFixedPoint, 11, -8), 

192 (UnsignedFixedPoint, -1, 3), 

193 (SignedFixedPoint, 9, 2), 

194 (SignedFixedPoint, 11, -8), 

195 (SignedFixedPoint, -1, 3), 

196 ], 

197) 

198def test_via_bit_widths(field_type_class, integer_bit_width, fraction_bit_width): 

199 field_type = field_type_class.from_bit_widths( 

200 integer_bit_width=integer_bit_width, fraction_bit_width=fraction_bit_width 

201 ) 

202 assert field_type.integer_bit_width == integer_bit_width 

203 assert field_type.fraction_bit_width == fraction_bit_width 

204 

205 

206@pytest.mark.parametrize( 

207 "field_type, bit_width, raise_valueerror", 

208 [ 

209 (Unsigned(), 8, False), 

210 (Unsigned(), 16, False), 

211 (Signed(), 8, False), 

212 (Signed(), 16, False), 

213 (UnsignedFixedPoint.from_bit_widths(integer_bit_width=8, fraction_bit_width=8), 16, False), 

214 (SignedFixedPoint.from_bit_widths(integer_bit_width=8, fraction_bit_width=8), 16, False), 

215 (UnsignedFixedPoint.from_bit_widths(integer_bit_width=8, fraction_bit_width=8), 32, True), 

216 (SignedFixedPoint.from_bit_widths(integer_bit_width=8, fraction_bit_width=8), 32, True), 

217 ], 

218) 

219def test_vhdl_typedef(field_type, bit_width, raise_valueerror): 

220 if raise_valueerror: 

221 with pytest.raises(ValueError): 

222 field_type.vhdl_typedef(bit_width=bit_width) 

223 else: 

224 vhdl_str = field_type.vhdl_typedef(bit_width=bit_width) 

225 assert "downto" in vhdl_str 

226 

227 

228def test_repr(): 

229 unsigned0 = Unsigned() 

230 unsigned1 = Unsigned() 

231 signed0 = Signed() 

232 signed1 = Signed() 

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

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

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

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

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

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

239 

240 assert repr(unsigned0) == repr(unsigned1) 

241 assert repr(signed0) == repr(signed1) 

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

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

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