Skip to content

Commit

Permalink
hdl.ast: add Value.{any,all}, mapping to $reduce_{or,and}.
Browse files Browse the repository at this point in the history
Refs #147.
  • Loading branch information
whitequark committed Sep 13, 2019
1 parent bdb70ad commit b23a979
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 3 deletions.
6 changes: 6 additions & 0 deletions nmigen/back/pysim.py
Expand Up @@ -129,6 +129,12 @@ def on_Operator(self, value):
return lambda state: normalize(-arg(state), shape)
if value.op == "b":
return lambda state: normalize(bool(arg(state)), shape)
if value.op == "r|":
return lambda state: normalize(arg(state) != 0, shape)
if value.op == "r&":
val, = value.operands
mask = (1 << len(val)) - 1
return lambda state: normalize(arg(state) == mask, shape)
elif len(value.operands) == 2:
lhs, rhs = map(self, value.operands)
if value.op == "+":
Expand Down
3 changes: 3 additions & 0 deletions nmigen/back/rtlil.py
Expand Up @@ -375,6 +375,9 @@ class _RHSValueCompiler(_ValueCompiler):
(1, "~"): "$not",
(1, "-"): "$neg",
(1, "b"): "$reduce_bool",
(1, "r|"): "$reduce_or",
(1, "r&"): "$reduce_and",
(1, "r^"): "$reduce_xor",
(2, "+"): "$add",
(2, "-"): "$sub",
(2, "*"): "$mul",
Expand Down
26 changes: 23 additions & 3 deletions nmigen/hdl/ast.py
Expand Up @@ -133,10 +133,30 @@ def bool(self):
Returns
-------
Value, out
Output ``Value``. If any bits are set, returns ``1``, else ``0``.
``1`` if any bits are set, ``0`` otherwise.
"""
return Operator("b", [self])

def any(self):
"""Check if any bits are ``1``.
Returns
-------
Value, out
``1`` if any bits are set, ``0`` otherwise.
"""
return Operator("r|", [self])

def all(self):
"""Check if all bits are ``1``.
Returns
-------
Value, out
``1`` if all bits are set, ``0`` otherwise.
"""
return Operator("r&", [self])

def implies(premise, conclusion):
"""Implication.
Expand Down Expand Up @@ -361,7 +381,7 @@ def shape(self):
return a_bits + 1, True
else:
return a_bits, a_sign
if self.op == "b":
if self.op in ("b", "r|", "r&", "r^"):
return 1, False
elif len(op_shapes) == 2:
(a_bits, a_sign), (b_bits, b_sign) = op_shapes
Expand All @@ -372,7 +392,7 @@ def shape(self):
return a_bits + b_bits, a_sign or b_sign
if self.op == "%":
return a_bits, a_sign
if self.op in ("<", "<=", "==", "!=", ">", ">=", "b"):
if self.op in ("<", "<=", "==", "!=", ">", ">="):
return 1, False
if self.op in ("&", "^", "|"):
return self._bitwise_binary_shape(*op_shapes)
Expand Down
8 changes: 8 additions & 0 deletions nmigen/test/test_hdl_ast.py
Expand Up @@ -251,6 +251,14 @@ def test_bool(self):
self.assertEqual(repr(v), "(b (const 1'd0))")
self.assertEqual(v.shape(), (1, False))

def test_any(self):
v = Const(0b101).any()
self.assertEqual(repr(v), "(r| (const 3'd5))")

def test_all(self):
v = Const(0b101).all()
self.assertEqual(repr(v), "(r& (const 3'd5))")

def test_hash(self):
with self.assertRaises(TypeError):
hash(Const(0) + Const(0))
Expand Down
12 changes: 12 additions & 0 deletions nmigen/test/test_sim.py
Expand Up @@ -57,6 +57,18 @@ def test_bool(self):
self.assertStatement(stmt, [C(1, 4)], C(1))
self.assertStatement(stmt, [C(2, 4)], C(1))

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

def test_all(self):
stmt = lambda y, a: y.eq(a.all())
self.assertStatement(stmt, [C(0b00, 2)], C(0))
self.assertStatement(stmt, [C(0b01, 2)], C(0))
self.assertStatement(stmt, [C(0b11, 2)], C(1))

def test_add(self):
stmt = lambda y, a, b: y.eq(a + b)
self.assertStatement(stmt, [C(0, 4), C(1, 4)], C(1, 4))
Expand Down

0 comments on commit b23a979

Please sign in to comment.