Coverage for hdl_registers/field/test/test_numerical_interpretation.py: 100%
96 statements
« prev ^ index » next coverage.py v7.6.8, created at 2024-12-01 20:50 +0000
« prev ^ index » next coverage.py v7.6.8, created at 2024-12-01 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# pylint: disable=protected-access
11# Third party libraries
12import pytest
14# First party libraries
15from hdl_registers.field.numerical_interpretation import (
16 Signed,
17 SignedFixedPoint,
18 Unsigned,
19 UnsignedFixedPoint,
20)
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
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
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
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
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)
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)
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)
127 unsigned = numerical_interpretation.convert_to_unsigned_binary(value)
128 assert unsigned == expected
130 restored = numerical_interpretation.convert_from_unsigned_binary(unsigned)
131 assert restored == value
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 )
161 numerical_interpretation._check_native_value_in_range(value)
163 unsigned = numerical_interpretation.convert_to_unsigned_binary(value)
164 assert unsigned == exp_uint
166 restored = numerical_interpretation.convert_from_unsigned_binary(unsigned)
167 assert restored == exp_return
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)
190 unsigned = numerical_interpretation.convert_to_unsigned_binary(value)
191 assert unsigned == expected
193 restored = numerical_interpretation.convert_from_unsigned_binary(unsigned)
194 assert restored == value
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
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
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 ")
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 ")
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)
255 assert repr(unsigned0) == repr(unsigned1) != repr(unsigned2)
256 assert repr(signed0) == repr(signed1) != repr(signed2)
257 assert repr(unsigned0) != repr(signed0)
259 assert repr(ufixed0) == repr(ufixed1) != repr(ufixed2)
260 assert repr(sfixed0) == repr(sfixed1) != repr(sfixed2)
261 assert repr(ufixed0) != repr(sfixed0)