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: @@ -314,6 +314,41 @@ class Circuit:
def get_or_add_fork(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):
"""Returns a deep copy of the circuit.
"""

19
src/kyupy/techlib.py

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
from .circuit import Node, Line
from . import bench
def add_and_connect(circuit, name, kind, in1=None, in2=None, out=None):
n = Node(circuit, name, kind)
@ -66,6 +66,23 @@ class TechLib: @@ -66,6 +66,23 @@ class TechLib:
if 'MUX' in kind and pin == 'S': return False
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
def split_complex_gates(circuit):
node_list = circuit.nodes

22
tests/test_circuit.py

@ -1,7 +1,8 @@ @@ -1,7 +1,8 @@
import pickle
from kyupy.circuit import Circuit, Node, Line
from kyupy import verilog
from kyupy import verilog, bench
from kyupy.techlib import TechLib
def test_lines():
c = Circuit()
@ -104,9 +105,26 @@ def test_circuit(): @@ -104,9 +105,26 @@ def test_circuit():
def test_pickle(mydir):
c = verilog.load(mydir / 'b14.v.gz')
c = verilog.load(mydir / 'b15_4ig.v.gz')
assert c is not None
cs = pickle.dumps(c)
assert cs is not None
c2 = pickle.loads(cs)
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