hdl.ast: add Value.xor, mapping to $reduce_xor.
authorwhitequark <whitequark@whitequark.org>
Fri, 13 Sep 2019 14:28:43 +0000 (14:28 +0000)
committerwhitequark <whitequark@whitequark.org>
Fri, 13 Sep 2019 14:29:46 +0000 (14:29 +0000)
Fixes #147.

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

index cf4b998fe8996f7608c4c1f4b3f82a542bc3e08f..4ff3ed587ad6a856de0a51c8afb3c9134d5eeadd 100644 (file)
@@ -135,6 +135,9 @@ class _RHSValueCompiler(_ValueCompiler):
                 val, = value.operands
                 mask = (1 << len(val)) - 1
                 return lambda state: normalize(arg(state) == mask, shape)
+            if value.op == "r^":
+                # Believe it or not, this is the fastest way to compute a sideways XOR in Python.
+                return lambda state: normalize(str(arg(state)).count("1") % 2, shape)
         elif len(value.operands) == 2:
             lhs, rhs = map(self, value.operands)
             if value.op == "+":
index b91fb50564abc5742ca489cd45c28fa60130d624..51e1d0d28350a2f14f426f4c85b2d1cc3873997b 100644 (file)
@@ -157,6 +157,16 @@ class Value(metaclass=ABCMeta):
         """
         return Operator("r&", [self])
 
+    def xor(self):
+        """Compute pairwise exclusive-or of every bit.
+
+        Returns
+        -------
+        Value, out
+            ``1`` if an odd number of bits are set, ``0`` if an even number of bits are set.
+        """
+        return Operator("r^", [self])
+
     def implies(premise, conclusion):
         """Implication.
 
index e0c43caf1142bf84782041909383b253bfb3a19b..2b851195d407a160c672610a150310b404c0a837 100644 (file)
@@ -259,6 +259,10 @@ class OperatorTestCase(FHDLTestCase):
         v = Const(0b101).all()
         self.assertEqual(repr(v), "(r& (const 3'd5))")
 
+    def test_xor(self):
+        v = Const(0b101).xor()
+        self.assertEqual(repr(v), "(r^ (const 3'd5))")
+
     def test_hash(self):
         with self.assertRaises(TypeError):
             hash(Const(0) + Const(0))
index eb283a243b37f3dc3d277513533a0241b9faafb0..fae57189f81f95c20175d4601b4cf8bcfca5334b 100644 (file)
@@ -69,6 +69,12 @@ class SimulatorUnitTestCase(FHDLTestCase):
         self.assertStatement(stmt, [C(0b01, 2)], C(0))
         self.assertStatement(stmt, [C(0b11, 2)], C(1))
 
+    def test_xor(self):
+        stmt = lambda y, a: y.eq(a.xor())
+        self.assertStatement(stmt, [C(0b00, 2)], C(0))
+        self.assertStatement(stmt, [C(0b01, 2)], C(1))
+        self.assertStatement(stmt, [C(0b11, 2)], C(0))
+
     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))