hdl.ast: add Value.{any,all}, mapping to $reduce_{or,and}.
authorwhitequark <cz@m-labs.hk>
Fri, 13 Sep 2019 13:14:52 +0000 (13:14 +0000)
committerwhitequark <cz@m-labs.hk>
Fri, 13 Sep 2019 13:14:52 +0000 (13:14 +0000)
Refs #147.

nmigen/back/pysim.py
nmigen/back/rtlil.py
nmigen/hdl/ast.py
nmigen/test/test_hdl_ast.py
nmigen/test/test_sim.py

index 82df6055cb64d05cecb1b3b700a9e15d4aa0d1b7..cf4b998fe8996f7608c4c1f4b3f82a542bc3e08f 100644 (file)
@@ -129,6 +129,12 @@ class _RHSValueCompiler(_ValueCompiler):
                 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 == "+":
index 470bd120abf6b0f263edf706828fa3d3accb339b..460d1d424e51608f39de0a48f1b92faf1f20beb9 100644 (file)
@@ -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",
index 56671eda88c43666dcd17b68d4a49f6c2d3f8e6f..b91fb50564abc5742ca489cd45c28fa60130d624 100644 (file)
@@ -133,10 +133,30 @@ class Value(metaclass=ABCMeta):
         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.
 
@@ -361,7 +381,7 @@ class Operator(Value):
                     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
@@ -372,7 +392,7 @@ class Operator(Value):
                 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)
index 9ad4d327242db20a012b2b989346aac0d38151f7..e0c43caf1142bf84782041909383b253bfb3a19b 100644 (file)
@@ -251,6 +251,14 @@ class OperatorTestCase(FHDLTestCase):
         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))
index 585bbeb170a2d7b28c41e528c266bfb4a2d4f0c1..eb283a243b37f3dc3d277513533a0241b9faafb0 100644 (file)
@@ -57,6 +57,18 @@ class SimulatorUnitTestCase(FHDLTestCase):
         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))