hdl.ast: Fix width for unary minus operator on signed argument.
authorMarcin Kościelnicki <mwk@0x04.net>
Tue, 3 Dec 2019 17:33:26 +0000 (18:33 +0100)
committerwhitequark <cz@m-labs.hk>
Wed, 4 Dec 2019 06:55:35 +0000 (06:55 +0000)
To properly represent a negation of a signed X-bit quantity we may, in
general, need a signed (X+1)-bit signal — for example, negation of
3-bit -4 is 4, which is not representable in signed 3 bits.

nmigen/hdl/ast.py
nmigen/test/test_hdl_ast.py

index 15d1d6544fb95327fd5e2f9a224dadaa7ce9d264..34c8e2be81d43ea5e9bc818d1b906f771325f2a7 100644 (file)
@@ -556,10 +556,7 @@ class Operator(Value):
             if self.operator in ("+", "~"):
                 return Shape(a_width, a_signed)
             if self.operator == "-":
-                if not a_signed:
-                    return Shape(a_width + 1, True)
-                else:
-                    return Shape(a_width, a_signed)
+                return Shape(a_width + 1, True)
             if self.operator in ("b", "r|", "r&", "r^"):
                 return Shape(1, False)
         elif len(op_shapes) == 2:
index 84f818432440fc5366a8f34ab6ab7f2b9c14d515..d5e19f1850844992ef2b0f7c7cbbaf8e7a4e6ba9 100644 (file)
@@ -252,7 +252,7 @@ class OperatorTestCase(FHDLTestCase):
         self.assertEqual(v1.shape(), signed(5))
         v2 = -Const(0, signed(4))
         self.assertEqual(repr(v2), "(- (const 4'sd0))")
-        self.assertEqual(v2.shape(), signed(4))
+        self.assertEqual(v2.shape(), signed(5))
 
     def test_add(self):
         v1 = Const(0, unsigned(4)) + Const(0, unsigned(6))