hdl._ast: fix shift_right and as_signed edge cases.

This commit is contained in:
Wanda 2024-02-13 05:31:51 +01:00 committed by Catherine
parent 0056e982c5
commit e2fd819742
2 changed files with 26 additions and 4 deletions

View file

@ -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

View file

@ -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)")