Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: amaranth-lang/amaranth
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9301e31b69a7
Choose a base ref
...
head repository: amaranth-lang/amaranth
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 27b47faf1699
Choose a head ref
  • 1 commit
  • 5 files changed
  • 1 contributor

Commits on Feb 6, 2020

  1. hdl.ast: add Value.{as_signed,as_unsigned}.

    Before this commit, there was no way to do so besides creating and
    assigning an intermediate signal, which could not be extracted into
    a helper function due to Module statefulness.
    
    Fixes #292.
    whitequark committed Feb 6, 2020
    Copy the full SHA
    27b47fa View commit details
Showing with 51 additions and 0 deletions.
  1. +3 −0 nmigen/back/pysim.py
  2. +4 −0 nmigen/back/rtlil.py
  3. +24 −0 nmigen/hdl/ast.py
  4. +10 −0 nmigen/test/test_hdl_ast.py
  5. +10 −0 nmigen/test/test_sim.py
3 changes: 3 additions & 0 deletions nmigen/back/pysim.py
Original file line number Diff line number Diff line change
@@ -426,6 +426,9 @@ def sign(value):
if value.operator == "r^":
# Believe it or not, this is the fastest way to compute a sideways XOR in Python.
return f"(format({mask(arg)}, 'b').count('1') % 2)"
if value.operator in ("u", "s"):
# These operators don't change the bit pattern, only its interpretation.
return self(arg)
elif len(value.operands) == 2:
lhs, rhs = value.operands
lhs_mask = (1 << len(lhs)) - 1
4 changes: 4 additions & 0 deletions nmigen/back/rtlil.py
Original file line number Diff line number Diff line change
@@ -454,6 +454,10 @@ def on_Signal(self, value):

def on_Operator_unary(self, value):
arg, = value.operands
if value.operator in ("u", "s"):
# These operators don't change the bit pattern, only its interpretation.
return self(arg)

arg_bits, arg_sign = arg.shape()
res_bits, res_sign = value.shape()
res = self.s.rtlil.wire(width=res_bits, src=src(value.src_loc))
24 changes: 24 additions & 0 deletions nmigen/hdl/ast.py
Original file line number Diff line number Diff line change
@@ -239,6 +239,26 @@ def __getitem__(self, key):
else:
raise TypeError("Cannot index value with {}".format(repr(key)))

def as_unsigned(self):
"""Conversion to unsigned.
Returns
-------
Value, out
This ``Value`` reinterpreted as a unsigned integer.
"""
return Operator("u", [self])

def as_signed(self):
"""Conversion to signed.
Returns
-------
Value, out
This ``Value`` reinterpreted as a signed integer.
"""
return Operator("s", [self])

def bool(self):
"""Conversion to boolean.
@@ -552,6 +572,10 @@ def _bitwise_binary_shape(a_shape, b_shape):
return Shape(a_width + 1, True)
if self.operator in ("b", "r|", "r&", "r^"):
return Shape(1, False)
if self.operator == "u":
return Shape(a_width, False)
if self.operator == "s":
return Shape(a_width, True)
elif len(op_shapes) == 2:
(a_width, a_signed), (b_width, b_signed) = op_shapes
if self.operator in ("+", "-"):
10 changes: 10 additions & 0 deletions nmigen/test/test_hdl_ast.py
Original file line number Diff line number Diff line change
@@ -246,6 +246,16 @@ def test_invert(self):
self.assertEqual(repr(v), "(~ (const 4'd0))")
self.assertEqual(v.shape(), unsigned(4))

def test_as_unsigned(self):
v = Const(-1, signed(4)).as_unsigned()
self.assertEqual(repr(v), "(u (const 4'sd-1))")
self.assertEqual(v.shape(), unsigned(4))

def test_as_signed(self):
v = Const(1, unsigned(4)).as_signed()
self.assertEqual(repr(v), "(s (const 4'd1))")
self.assertEqual(v.shape(), signed(4))

def test_neg(self):
v1 = -Const(0, unsigned(4))
self.assertEqual(repr(v1), "(- (const 4'd0))")
10 changes: 10 additions & 0 deletions nmigen/test/test_sim.py
Original file line number Diff line number Diff line change
@@ -56,6 +56,16 @@ def test_bool(self):
self.assertStatement(stmt, [C(1, 4)], C(1))
self.assertStatement(stmt, [C(2, 4)], C(1))

def test_as_unsigned(self):
stmt = lambda y, a, b: y.eq(a.as_unsigned() == b)
self.assertStatement(stmt, [C(0b01, signed(2)), C(0b0001, unsigned(4))], C(1))
self.assertStatement(stmt, [C(0b11, signed(2)), C(0b0011, unsigned(4))], C(1))

def test_as_signed(self):
stmt = lambda y, a, b: y.eq(a.as_signed() == b)
self.assertStatement(stmt, [C(0b01, unsigned(2)), C(0b0001, signed(4))], C(1))
self.assertStatement(stmt, [C(0b11, unsigned(2)), C(0b1111, signed(4))], C(1))

def test_any(self):
stmt = lambda y, a: y.eq(a.any())
self.assertStatement(stmt, [C(0b00, 2)], C(0))