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
« 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
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, 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)
191 unsigned = numerical_interpretation.convert_to_unsigned_binary(value)
192 assert unsigned.bit_length() <= numerical_interpretation.bit_width
193 assert unsigned == expected
195 restored = numerical_interpretation.convert_from_unsigned_binary(unsigned)
196 assert restored == expected_restored
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
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
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 ")
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 ")
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)
257 assert repr(unsigned0) == repr(unsigned1) != repr(unsigned2)
258 assert repr(signed0) == repr(signed1) != repr(signed2)
259 assert repr(unsigned0) != repr(signed0)
261 assert repr(ufixed0) == repr(ufixed1) != repr(ufixed2)
262 assert repr(sfixed0) == repr(sfixed1) != repr(sfixed2)
263 assert repr(ufixed0) != repr(sfixed0)