Skip to content

Commit 445a25f

Browse files
authored
fix XOR implementation in and_inverter_synth pass and add tests (#469)
* fix XOR implementation in `and_inverter_synth` pass * add tests for `nand_synth` and `and_inverter_synth`
1 parent 609a468 commit 445a25f

File tree

2 files changed

+84
-3
lines changed

2 files changed

+84
-3
lines changed

pyrtl/passes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ def arg(num):
848848
elif net.op == '^':
849849
all_1 = arg(0) & arg(1)
850850
all_0 = ~arg(0) & ~arg(1)
851-
dest <<= all_0 & ~all_1
851+
dest <<= ~all_0 & ~all_1
852852
elif net.op == 'n':
853853
dest <<= ~(arg(0) & arg(1))
854854
else:

tests/test_passes.py

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
import os
44
import sys
55
import unittest
6+
from typing import Callable
67

78
import pyrtl
8-
from pyrtl.wire import Const, Output
99
from pyrtl.rtllib import testingutils as utils
10-
10+
from pyrtl.wire import Const, Output
1111
from .test_transform import NetWireNumTestCases
1212

1313

@@ -733,6 +733,87 @@ def test_nested_elimination(self):
733733
pyrtl.working_block().sanity_check()
734734

735735

736+
class TestSynthPasses(unittest.TestCase):
737+
in0: pyrtl.Input
738+
in1: pyrtl.Input
739+
out: pyrtl.Output
740+
741+
def setUp(self):
742+
pyrtl.reset_working_block()
743+
self.in0 = pyrtl.Input(bitwidth=5, name='in0')
744+
self.in1 = pyrtl.Input(bitwidth=5, name='in1')
745+
self.out = pyrtl.Output(bitwidth=5, name='out')
746+
747+
def check_synth(self, operation: Callable[[int, int], int]):
748+
"""
749+
Simulates the current circuit with some test input pairs (in0, in1) and checks the outputs
750+
against the provided operation. Any synthesis/passes should be run before this gets called.
751+
752+
:param operation: The operation to test against. This should be a lambda taking an input
753+
pair (in0, in1) and returning the expected output from this circuit.
754+
"""
755+
sim_trace = pyrtl.SimulationTrace()
756+
sim = pyrtl.Simulation(tracer=sim_trace)
757+
758+
values = [(1, 2), (4, 5), (7, 11)]
759+
"""A list of input pairs (in0, in1) to test on."""
760+
761+
for in0, in1 in values:
762+
expected_output = operation(in0, in1)
763+
sim.step({'in0': in0, 'in1': in1})
764+
# compare simulation output to expected output
765+
self.assertEqual(sim.inspect('out'), expected_output,
766+
msg=f"Failed on inputs {in0} and {in1}")
767+
768+
def test_nand_synth_and(self):
769+
self.out <<= self.in0 & self.in1
770+
pyrtl.synthesize()
771+
pyrtl.nand_synth()
772+
self.check_synth(lambda a, b: a & b)
773+
774+
def test_nand_synth_or(self):
775+
self.out <<= self.in0 | self.in1
776+
pyrtl.synthesize()
777+
pyrtl.nand_synth()
778+
self.check_synth(lambda a, b: a | b)
779+
780+
def test_nand_synth_xor(self):
781+
self.out <<= self.in0 ^ self.in1
782+
pyrtl.synthesize()
783+
pyrtl.nand_synth()
784+
self.check_synth(lambda a, b: a ^ b)
785+
786+
def test_nand_synth_adder(self):
787+
self.out <<= self.in0 + self.in1
788+
pyrtl.synthesize()
789+
pyrtl.nand_synth()
790+
self.check_synth(lambda a, b: a + b)
791+
792+
def test_and_inverter_synth_and(self):
793+
self.out <<= self.in0 & self.in1
794+
pyrtl.synthesize()
795+
pyrtl.and_inverter_synth()
796+
self.check_synth(lambda a, b: a & b)
797+
798+
def test_and_inverter_synth_or(self):
799+
self.out <<= self.in0 | self.in1
800+
pyrtl.synthesize()
801+
pyrtl.and_inverter_synth()
802+
self.check_synth(lambda a, b: a | b)
803+
804+
def test_and_inverter_synth_xor(self):
805+
self.out <<= self.in0 ^ self.in1
806+
pyrtl.synthesize()
807+
pyrtl.and_inverter_synth()
808+
self.check_synth(lambda a, b: a ^ b)
809+
810+
def test_and_inverter_synth_adder(self):
811+
self.out <<= self.in0 + self.in1
812+
pyrtl.synthesize()
813+
pyrtl.and_inverter_synth()
814+
self.check_synth(lambda a, b: a + b)
815+
816+
736817
class TestSynthOptTiming(NetWireNumTestCases):
737818
def setUp(self):
738819
pyrtl.reset_working_block()

0 commit comments

Comments
 (0)