hdl._ast: fix shift_right
and as_signed
edge cases.
This commit is contained in:
parent
0056e982c5
commit
e2fd819742
|
@ -483,7 +483,14 @@ class Value(metaclass=ABCMeta):
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
:class:`Value`, :pc:`signed(len(self))`, :ref:`assignable <lang-assignable>`
|
:class:`Value`, :pc:`signed(len(self))`, :ref:`assignable <lang-assignable>`
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
ValueError
|
||||||
|
If :pc:`len(self) == 0`.
|
||||||
"""
|
"""
|
||||||
|
if len(self) == 0:
|
||||||
|
raise ValueError("Cannot create a 0-width signed value")
|
||||||
return Operator("s", [self])
|
return Operator("s", [self])
|
||||||
|
|
||||||
def __bool__(self):
|
def __bool__(self):
|
||||||
|
@ -900,9 +907,9 @@ class Value(metaclass=ABCMeta):
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
:class:`Value`, :pc:`unsigned(len(self) + amount)`
|
:class:`Value`, :pc:`unsigned(max(len(self) + amount, 0))`
|
||||||
If :pc:`self` is unsigned.
|
If :pc:`self` is unsigned.
|
||||||
:class:`Value`, :pc:`signed(len(self) + amount)`
|
:class:`Value`, :pc:`signed(max(len(self) + amount, 1))`
|
||||||
If :pc:`self` is signed.
|
If :pc:`self` is signed.
|
||||||
"""
|
"""
|
||||||
if not isinstance(amount, int):
|
if not isinstance(amount, int):
|
||||||
|
@ -974,6 +981,8 @@ class Value(metaclass=ABCMeta):
|
||||||
if amount < 0:
|
if amount < 0:
|
||||||
return self.shift_left(-amount)
|
return self.shift_left(-amount)
|
||||||
if self.shape().signed:
|
if self.shape().signed:
|
||||||
|
if amount >= len(self):
|
||||||
|
amount = len(self) - 1
|
||||||
return self[amount:].as_signed()
|
return self[amount:].as_signed()
|
||||||
else:
|
else:
|
||||||
return self[amount:] # unsigned
|
return self[amount:] # unsigned
|
||||||
|
|
|
@ -343,7 +343,7 @@ class ValueTestCase(FHDLTestCase):
|
||||||
self.assertRepr(Const(256, signed(9)).shift_left(-5),
|
self.assertRepr(Const(256, signed(9)).shift_left(-5),
|
||||||
"(s (slice (const 9'sd-256) 5:9))")
|
"(s (slice (const 9'sd-256) 5:9))")
|
||||||
self.assertRepr(Const(256, signed(9)).shift_left(-15),
|
self.assertRepr(Const(256, signed(9)).shift_left(-15),
|
||||||
"(s (slice (const 9'sd-256) 9:9))")
|
"(s (slice (const 9'sd-256) 8:9))")
|
||||||
|
|
||||||
def test_shift_left_wrong(self):
|
def test_shift_left_wrong(self):
|
||||||
with self.assertRaisesRegex(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
|
@ -367,12 +367,20 @@ class ValueTestCase(FHDLTestCase):
|
||||||
"(slice (const 9'd256) 1:9)")
|
"(slice (const 9'd256) 1:9)")
|
||||||
self.assertRepr(Const(256, unsigned(9)).shift_right(5),
|
self.assertRepr(Const(256, unsigned(9)).shift_right(5),
|
||||||
"(slice (const 9'd256) 5:9)")
|
"(slice (const 9'd256) 5:9)")
|
||||||
|
self.assertRepr(Const(256, unsigned(9)).shift_right(15),
|
||||||
|
"(slice (const 9'd256) 9:9)")
|
||||||
self.assertRepr(Const(256, signed(9)).shift_right(1),
|
self.assertRepr(Const(256, signed(9)).shift_right(1),
|
||||||
"(s (slice (const 9'sd-256) 1:9))")
|
"(s (slice (const 9'sd-256) 1:9))")
|
||||||
self.assertRepr(Const(256, signed(9)).shift_right(5),
|
self.assertRepr(Const(256, signed(9)).shift_right(5),
|
||||||
"(s (slice (const 9'sd-256) 5:9))")
|
"(s (slice (const 9'sd-256) 5:9))")
|
||||||
|
self.assertRepr(Const(256, signed(9)).shift_right(7),
|
||||||
|
"(s (slice (const 9'sd-256) 7:9))")
|
||||||
|
self.assertRepr(Const(256, signed(9)).shift_right(8),
|
||||||
|
"(s (slice (const 9'sd-256) 8:9))")
|
||||||
|
self.assertRepr(Const(256, signed(9)).shift_right(9),
|
||||||
|
"(s (slice (const 9'sd-256) 8:9))")
|
||||||
self.assertRepr(Const(256, signed(9)).shift_right(15),
|
self.assertRepr(Const(256, signed(9)).shift_right(15),
|
||||||
"(s (slice (const 9'sd-256) 9:9))")
|
"(s (slice (const 9'sd-256) 8:9))")
|
||||||
|
|
||||||
def test_shift_right_wrong(self):
|
def test_shift_right_wrong(self):
|
||||||
with self.assertRaisesRegex(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
|
@ -516,6 +524,11 @@ class OperatorTestCase(FHDLTestCase):
|
||||||
self.assertEqual(repr(v), "(s (const 4'd1))")
|
self.assertEqual(repr(v), "(s (const 4'd1))")
|
||||||
self.assertEqual(v.shape(), signed(4))
|
self.assertEqual(v.shape(), signed(4))
|
||||||
|
|
||||||
|
def test_as_signed_wrong(self):
|
||||||
|
with self.assertRaisesRegex(ValueError,
|
||||||
|
r"^Cannot create a 0-width signed value$"):
|
||||||
|
Const(0, 0).as_signed()
|
||||||
|
|
||||||
def test_pos(self):
|
def test_pos(self):
|
||||||
self.assertRepr(+Const(10), "(const 4'd10)")
|
self.assertRepr(+Const(10), "(const 4'd10)")
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue