Browse Source

circuit node substitution

devel
Stefan Holst 1 year ago
parent
commit
670fb0b3fc
  1. 35
      src/kyupy/circuit.py
  2. 19
      src/kyupy/techlib.py
  3. 22
      tests/test_circuit.py

35
src/kyupy/circuit.py

@ -314,6 +314,41 @@ class Circuit:
def get_or_add_fork(self, name): def get_or_add_fork(self, name):
return self.forks[name] if name in self.forks else Node(self, name) return self.forks[name] if name in self.forks else Node(self, name)
def substitute(self, node, impl):
"""Replaces a given node with the given implementation circuit.
The given node will be removed, the implementation is copied in and
the signal lines are connected appropriately. The number and arrangement
of the input and output ports must match the pins of the replaced node.
"""
node_in_lines = [l for l in node.ins if l]
node_out_lines = [l for l in node.outs if l]
impl_in_lines = [n.outs[0] for n in impl.io_nodes if len(n.outs) > 0]
impl_out_lines = [n.ins[0] for n in impl.io_nodes if len(n.ins) > 0]
assert len(node_in_lines) == len(impl_in_lines)
assert len(node_out_lines) == len(impl_out_lines)
in_lines_map = dict(zip(impl_in_lines, node_in_lines))
out_lines_map = dict(zip(impl_out_lines, node_out_lines))
node.remove()
node_map = dict()
ios = set(impl.io_nodes)
for n in impl.nodes:
if n not in ios:
node_map[n] = Node(self, node.name + '~' + n.name, n.kind)
for l in impl.lines:
if l in in_lines_map:
ll = in_lines_map[l]
ll.reader = node_map[l.reader]
ll.reader_pin = l.reader_pin
ll.reader.ins[ll.reader_pin] = ll
elif l in out_lines_map:
ll = out_lines_map[l]
ll.driver = node_map[l.driver]
ll.driver_pin = l.driver_pin
ll.driver.outs[ll.driver_pin] = ll
else:
Line(self, (node_map[l.driver], l.driver_pin), (node_map[l.reader], l.reader_pin))
def copy(self): def copy(self):
"""Returns a deep copy of the circuit. """Returns a deep copy of the circuit.
""" """

19
src/kyupy/techlib.py

@ -1,5 +1,5 @@
from .circuit import Node, Line from .circuit import Node, Line
from . import bench
def add_and_connect(circuit, name, kind, in1=None, in2=None, out=None): def add_and_connect(circuit, name, kind, in1=None, in2=None, out=None):
n = Node(circuit, name, kind) n = Node(circuit, name, kind)
@ -66,6 +66,23 @@ class TechLib:
if 'MUX' in kind and pin == 'S': return False if 'MUX' in kind and pin == 'S': return False
return pin in ('Q', 'QN', 'Z', 'ZN', 'Y', 'CO', 'S', 'SO', 'C1') return pin in ('Q', 'QN', 'Z', 'ZN', 'Y', 'CO', 'S', 'SO', 'C1')
@staticmethod
def substitute_nonsim_cells(circuit):
tmap = {'ISOLAND': bench.parse('input(iso, d) output(q) not_iso=not(iso) q=and(not_iso, d)'),
'AO221' : bench.parse('input(in1, in2, in3, in4, in5) output(q) a=ao22(in1, in2, in3, in4) q=or(a, in5)'),
'AOI221' : bench.parse('input(in1, in2, in3, in4, in5) output(qn) a=ao22(in1, in2, in3, in4) qn=nor(a, in5)'),
'OA221' : bench.parse('input(in1, in2, in3, in4, in5) output(q) a=oa22(in1, in2, in3, in4) q=and(a, in5)'),
'OAI221' : bench.parse('input(in1, in2, in3, in4, in5) output(qn) a=oa22(in1, in2, in3, in4) qn=nand(a, in5)'),
'AO222' : bench.parse('input(in1, in2, in3, in4, in5, in6) output(q) a=ao22(in1, in2, in3, in4) q=ao21(in5, in6, a)'),
'AOI222' : bench.parse('input(in1, in2, in3, in4, in5, in6) output(qn) a=ao22(in1, in2, in3, in4) qn=aoi21(in5, in6, a)'),
'OA222' : bench.parse('input(in1, in2, in3, in4, in5, in6) output(q) a=oa22(in1, in2, in3, in4) q=oa21(in5, in6, a)'),
'OAI222' : bench.parse('input(in1, in2, in3, in4, in5, in6) output(qn) a=oa22(in1, in2, in3, in4) qn=oai21(in5, in6, a)'),
}
for n in list(circuit.nodes):
for k, v in tmap.items():
if n.kind.startswith(k):
circuit.substitute(n, v)
@staticmethod @staticmethod
def split_complex_gates(circuit): def split_complex_gates(circuit):
node_list = circuit.nodes node_list = circuit.nodes

22
tests/test_circuit.py

@ -1,7 +1,8 @@
import pickle import pickle
from kyupy.circuit import Circuit, Node, Line from kyupy.circuit import Circuit, Node, Line
from kyupy import verilog from kyupy import verilog, bench
from kyupy.techlib import TechLib
def test_lines(): def test_lines():
c = Circuit() c = Circuit()
@ -104,9 +105,26 @@ def test_circuit():
def test_pickle(mydir): def test_pickle(mydir):
c = verilog.load(mydir / 'b14.v.gz') c = verilog.load(mydir / 'b15_4ig.v.gz')
assert c is not None assert c is not None
cs = pickle.dumps(c) cs = pickle.dumps(c)
assert cs is not None assert cs is not None
c2 = pickle.loads(cs) c2 = pickle.loads(cs)
assert c == c2 assert c == c2
def test_substitute():
c = bench.parse('input(i1, i2, i3, i4, i5) output(o1) aoi=AOI221(i1, i2, i3, i4, i5) o1=not(aoi)')
assert len(c.cells) == 2
assert len(c.io_nodes) == 6
aoi221_impl = bench.parse('input(in1, in2, in3, in4, in5) output(q) a1=and(in1, in2) a2=and(in3, in4) q=or(a1, a2, in5)')
assert len(aoi221_impl.cells) == 3
assert len(aoi221_impl.io_nodes) == 6
c.substitute(c.cells['aoi'], aoi221_impl)
assert len(c.cells) == 4
assert len(c.io_nodes) == 6
c = bench.parse('input(i1, i2, i3, i4, i5) output(o1) aoi221=AOI221(i1, i2, i3, i4, i5) o1=not(aoi221)')
assert len(c.cells) == 2
TechLib.substitute_nonsim_cells(c)
assert len(c.cells) == 3
print('\n'.join(map(str, c.nodes)))
Loading…
Cancel
Save