diff --git a/src/kyupy/techlib.py b/src/kyupy/techlib.py index f8b3a19..7c0ba0e 100644 --- a/src/kyupy/techlib.py +++ b/src/kyupy/techlib.py @@ -1,6 +1,7 @@ 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) if in1 is not None: @@ -29,6 +30,8 @@ class TechLib: @staticmethod def pin_index(kind, pin): """Returns a pin list position for a given node kind and pin name.""" + if isinstance(pin, int): + return max(0, pin-1) if kind[:3] in ('OAI', 'AOI'): if pin[0] == 'A': return int(pin[1]) - 1 if pin == 'B': return int(kind[3]) @@ -63,270 +66,31 @@ class TechLib: @staticmethod def pin_is_output(kind, pin): """Returns True, if given pin name of a node kind is an output.""" + if isinstance(pin, int): + return pin == 0 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)'), + '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)'), + 'HADD' : bench.parse('input(a,b) output(s,co) co=xor(a,b) s=and(a,b)'), + 'FADD' : bench.parse('input(a,b,ci) output(s,co) ab=xor(a,b) co=xor(ab,ci) s=ao22(ab,ci,a,b)'), } 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 - for n in node_list: - name = n.name - ins = n.ins - outs = n.outs - if n.kind.startswith('AO21X'): - n.remove() - n_and = add_and_connect(circuit, name+'~and', 'AND2', ins[0], ins[1], None) - n_or = add_and_connect(circuit, name+'~or', 'OR2', None, ins[2], outs[0]) - Line(circuit, n_and, n_or) - elif n.kind.startswith('AOI21X'): - n.remove() - n_and = add_and_connect(circuit, name+'~and', 'AND2', ins[0], ins[1], None) - n_nor = add_and_connect(circuit, name+'~nor', 'NOR2', None, ins[2], outs[0]) - Line(circuit, n_and, n_nor) - elif n.kind.startswith('OA21X'): - n.remove() - n_or = add_and_connect(circuit, name+'~or', 'OR2', ins[0], ins[1], None) - n_and = add_and_connect(circuit, name+'~and', 'AND2', None, ins[2], outs[0]) - Line(circuit, n_or, n_and) - elif n.kind.startswith('OAI21X'): - n.remove() - n_or = add_and_connect(circuit, name+'~or', 'OR2', ins[0], ins[1], None) - n_nand = add_and_connect(circuit, name+'~nand', 'NAND2', None, ins[2], outs[0]) - Line(circuit, n_or, n_nand) - elif n.kind.startswith('OA22X'): - n.remove() - n_or0 = add_and_connect(circuit, name+'~or0', 'OR2', ins[0], ins[1], None) - n_or1 = add_and_connect(circuit, name+'~or1', 'OR2', ins[2], ins[3], None) - n_and = add_and_connect(circuit, name+'~and', 'AND2', None, None, outs[0]) - Line(circuit, n_or0, n_and) - Line(circuit, n_or1, n_and) - elif n.kind.startswith('OAI22X'): - n.remove() - n_or0 = add_and_connect(circuit, name+'~or0', 'OR2', ins[0], ins[1], None) - n_or1 = add_and_connect(circuit, name+'~or1', 'OR2', ins[2], ins[3], None) - n_nand = add_and_connect(circuit, name+'~nand', 'NAND2', None, None, outs[0]) - Line(circuit, n_or0, n_nand) - Line(circuit, n_or1, n_nand) - elif n.kind.startswith('AO22X'): - n.remove() - n_and0 = add_and_connect(circuit, name+'~and0', 'AND2', ins[0], ins[1], None) - n_and1 = add_and_connect(circuit, name+'~and1', 'AND2', ins[2], ins[3], None) - n_or = add_and_connect(circuit, name+'~or', 'OR2', None, None, outs[0]) - Line(circuit, n_and0, n_or) - Line(circuit, n_and1, n_or) - elif n.kind.startswith('AOI22X'): - n.remove() - n_and0 = add_and_connect(circuit, name+'~and0', 'AND2', ins[0], ins[1], None) - n_and1 = add_and_connect(circuit, name+'~and1', 'AND2', ins[2], ins[3], None) - n_nor = add_and_connect(circuit, name+'~nor', 'NOR2', None, None, outs[0]) - Line(circuit, n_and0, n_nor) - Line(circuit, n_and1, n_nor) - elif n.kind.startswith('AO221X'): - n.remove() - n_and0 = add_and_connect(circuit, name+'~and0', 'AND2', ins[0], ins[1], None) - n_and1 = add_and_connect(circuit, name+'~and1', 'AND2', ins[2], ins[3], None) - n_or0 = add_and_connect(circuit, name+'~or0', 'OR2', None, None, None) - n_or1 = add_and_connect(circuit, name+'~or1', 'OR2', None, ins[4], outs[0]) - Line(circuit, n_and0, n_or0) - Line(circuit, n_and1, n_or0) - Line(circuit, n_or0, n_or1) - elif n.kind.startswith('AOI221X'): - n.remove() - n_and0 = add_and_connect(circuit, name+'~and0', 'AND2', ins[0], ins[1], None) - n_and1 = add_and_connect(circuit, name+'~and1', 'AND2', ins[2], ins[3], None) - n_or = add_and_connect(circuit, name+'~or', 'OR2', None, None, None) - n_nor = add_and_connect(circuit, name+'~nor', 'NOR2', None, ins[4], outs[0]) - Line(circuit, n_and0, n_or) - Line(circuit, n_and1, n_or) - Line(circuit, n_or, n_nor) - elif n.kind.startswith('OA221X'): - n.remove() - n_or0 = add_and_connect(circuit, name+'~or0', 'OR2', ins[0], ins[1], None) - n_or1 = add_and_connect(circuit, name+'~or1', 'OR2', ins[2], ins[3], None) - n_and0 = add_and_connect(circuit, name+'~and0', 'AND2', None, None, None) - n_and1 = add_and_connect(circuit, name+'~and1', 'AND2', None, ins[4], outs[0]) - Line(circuit, n_or0, n_and0) - Line(circuit, n_or1, n_and0) - Line(circuit, n_and0, n_and1) - elif n.kind.startswith('OAI221X'): - n.remove() - n_or0 = add_and_connect(circuit, name+'~or0', 'OR2', ins[0], ins[1], None) - n_or1 = add_and_connect(circuit, name+'~or1', 'OR2', ins[2], ins[3], None) - n_and0 = add_and_connect(circuit, name+'~and0', 'AND2', None, None, None) - n_nand1 = add_and_connect(circuit, name+'~nand1', 'NAND2', None, ins[4], outs[0]) - Line(circuit, n_or0, n_and0) - Line(circuit, n_or1, n_and0) - Line(circuit, n_and0, n_nand1) - elif n.kind.startswith('AO222X'): - n.remove() - n_and0 = add_and_connect(circuit, name+'~and0', 'AND2', ins[0], ins[1], None) - n_and1 = add_and_connect(circuit, name+'~and1', 'AND2', ins[2], ins[3], None) - n_and2 = add_and_connect(circuit, name+'~and2', 'AND2', ins[4], ins[5], None) - n_or0 = add_and_connect(circuit, name+'~or0', 'OR2', None, None, None) - n_or1 = add_and_connect(circuit, name+'~or1', 'OR2', None, None, outs[0]) - Line(circuit, n_and0, n_or0) - Line(circuit, n_and1, n_or0) - Line(circuit, n_and2, n_or1) - Line(circuit, n_or0, n_or1) - elif n.kind.startswith('AOI222X'): - n.remove() - n_and0 = add_and_connect(circuit, name+'~and0', 'AND2', ins[0], ins[1], None) - n_and1 = add_and_connect(circuit, name+'~and1', 'AND2', ins[2], ins[3], None) - n_and2 = add_and_connect(circuit, name+'~and2', 'AND2', ins[4], ins[5], None) - n_or0 = add_and_connect(circuit, name+'~or0', 'OR2', None, None, None) - n_nor1 = add_and_connect(circuit, name+'~nor1', 'NOR2', None, None, outs[0]) - Line(circuit, n_and0, n_or0) - Line(circuit, n_and1, n_or0) - Line(circuit, n_and2, n_nor1) - Line(circuit, n_or0, n_nor1) - elif n.kind.startswith('OA222X'): - n.remove() - n_or0 = add_and_connect(circuit, name+'~or0', 'OR2', ins[0], ins[1], None) - n_or1 = add_and_connect(circuit, name+'~or1', 'OR2', ins[2], ins[3], None) - n_or2 = add_and_connect(circuit, name+'~or2', 'OR2', ins[4], ins[5], None) - n_and0 = add_and_connect(circuit, name+'~and0', 'AND2', None, None, None) - n_and1 = add_and_connect(circuit, name+'~and1', 'AND2', None, None, outs[0]) - Line(circuit, n_or0, n_and0) - Line(circuit, n_or1, n_and0) - Line(circuit, n_or2, n_and1) - Line(circuit, n_and0, n_and1) - elif n.kind.startswith('OAI222X'): - n.remove() - n0 = add_and_connect(circuit, name+'~or0', 'OR2', ins[0], ins[1], None) - n1 = add_and_connect(circuit, name+'~or1', 'OR2', ins[2], ins[3], None) - n2 = add_and_connect(circuit, name+'~or2', 'OR2', ins[4], ins[5], None) - n3 = add_and_connect(circuit, name+'~and0', 'AND2', None, None, None) - n4 = add_and_connect(circuit, name+'~nand1', 'NAND2', None, None, outs[0]) - Line(circuit, n0, n3) - Line(circuit, n1, n3) - Line(circuit, n2, n4) - Line(circuit, n3, n4) - elif n.kind.startswith('AND3X'): - n.remove() - n0 = add_and_connect(circuit, name+'~and0', 'AND2', ins[0], ins[1], None) - n1 = add_and_connect(circuit, name+'~and1', 'AND2', None, ins[2], outs[0]) - Line(circuit, n0, n1) - elif n.kind.startswith('OR3X'): - n.remove() - n0 = add_and_connect(circuit, name+'~or0', 'OR2', ins[0], ins[1], None) - n1 = add_and_connect(circuit, name+'~or1', 'OR2', None, ins[2], outs[0]) - Line(circuit, n0, n1) - elif n.kind.startswith('XOR3X'): - n.remove() - n0 = add_and_connect(circuit, name+'~xor0', 'XOR2', ins[0], ins[1], None) - n1 = add_and_connect(circuit, name+'~xor1', 'XOR2', None, ins[2], outs[0]) - Line(circuit, n0, n1) - elif n.kind.startswith('NAND3X'): - n.remove() - n0 = add_and_connect(circuit, name+'~and', 'AND2', ins[0], ins[1], None) - n1 = add_and_connect(circuit, name+'~nand', 'NAND2', None, ins[2], outs[0]) - Line(circuit, n0, n1) - elif n.kind.startswith('NOR3X'): - n.remove() - n0 = add_and_connect(circuit, name+'~or', 'OR2', ins[0], ins[1], None) - n1 = add_and_connect(circuit, name+'~nor', 'NOR2', None, ins[2], outs[0]) - Line(circuit, n0, n1) - elif n.kind.startswith('XNOR3X'): - n.remove() - n0 = add_and_connect(circuit, name+'~xor', 'XOR2', ins[0], ins[1], None) - n1 = add_and_connect(circuit, name+'~xnor', 'XNOR2', None, ins[2], outs[0]) - Line(circuit, n0, n1) - elif n.kind.startswith('AND4X'): - n.remove() - n0 = add_and_connect(circuit, name+'~and0', 'AND2', ins[0], ins[1], None) - n1 = add_and_connect(circuit, name+'~and1', 'AND2', ins[2], ins[3], None) - n2 = add_and_connect(circuit, name+'~and2', 'AND2', None, None, outs[0]) - Line(circuit, n0, n2) - Line(circuit, n1, n2) - elif n.kind.startswith('OR4X'): - n.remove() - n0 = add_and_connect(circuit, name+'~or0', 'OR2', ins[0], ins[1], None) - n1 = add_and_connect(circuit, name+'~or1', 'OR2', ins[2], ins[3], None) - n2 = add_and_connect(circuit, name+'~or2', 'OR2', None, None, outs[0]) - Line(circuit, n0, n2) - Line(circuit, n1, n2) - elif n.kind.startswith('NAND4X'): - n.remove() - n0 = add_and_connect(circuit, name+'~and0', 'AND2', ins[0], ins[1], None) - n1 = add_and_connect(circuit, name+'~and1', 'AND2', ins[2], ins[3], None) - n2 = add_and_connect(circuit, name+'~nand2', 'NAND2', None, None, outs[0]) - Line(circuit, n0, n2) - Line(circuit, n1, n2) - elif n.kind.startswith('NOR4X'): - n.remove() - n0 = add_and_connect(circuit, name+'~or0', 'OR2', ins[0], ins[1], None) - n1 = add_and_connect(circuit, name+'~or1', 'OR2', ins[2], ins[3], None) - n2 = add_and_connect(circuit, name+'~nor2', 'NOR2', None, None, outs[0]) - Line(circuit, n0, n2) - Line(circuit, n1, n2) - elif n.kind.startswith('FADDX'): - n.remove() - # forks for fan-outs - f_a = add_and_connect(circuit, name + '~fork0', '__fork__', ins[0]) - f_b = add_and_connect(circuit, name + '~fork1', '__fork__', ins[1]) - f_ci = add_and_connect(circuit, name + '~fork2', '__fork__', ins[2]) - f_ab = Node(circuit, name + '~fork3') - # sum-block - n_xor0 = Node(circuit, name + '~xor0', 'XOR2') - Line(circuit, f_a, n_xor0) - Line(circuit, f_b, n_xor0) - Line(circuit, n_xor0, f_ab) - if len(outs) > 0 and outs[0] is not None: - n_xor1 = add_and_connect(circuit, name + '~xor1', 'XOR2', None, None, outs[0]) - Line(circuit, f_ab, n_xor1) - Line(circuit, f_ci, n_xor1) - # carry-block - if len(outs) > 1 and outs[1] is not None: - n_and0 = Node(circuit, name + '~and0', 'AND2') - Line(circuit, f_ab, n_and0) - Line(circuit, f_ci, n_and0) - n_and1 = Node(circuit, name + '~and1', 'AND2') - Line(circuit, f_a, n_and1) - Line(circuit, f_b, n_and1) - n_or = add_and_connect(circuit, name + '~or0', 'OR2', None, None, outs[1]) - Line(circuit, n_and0, n_or) - Line(circuit, n_and1, n_or) - elif n.kind.startswith('HADDX'): - n.remove() - # forks for fan-outs - f_a = add_and_connect(circuit, name + '~fork0', '__fork__', ins[0]) - f_b = add_and_connect(circuit, name + '~fork1', '__fork__', ins[1]) - n_xor0 = add_and_connect(circuit, name + '~xor0', 'XOR2', None, None, outs[1]) - Line(circuit, f_a, n_xor0) - Line(circuit, f_b, n_xor0) - n_and0 = add_and_connect(circuit, name + '~and0', 'AND2', None, None, outs[0]) - Line(circuit, f_a, n_and0) - Line(circuit, f_b, n_and0) - elif n.kind.startswith('MUX21X'): - n.remove() - f_s = add_and_connect(circuit, name + '~fork0', '__fork__', ins[2]) - n_not = Node(circuit, name + '~not', 'INV') - Line(circuit, f_s, n_not) - n_and0 = add_and_connect(circuit, name + '~and0', 'AND2', ins[0]) - n_and1 = add_and_connect(circuit, name + '~and1', 'AND2', ins[1]) - n_or0 = add_and_connect(circuit, name + '~or0', 'OR2', None, None, outs[0]) - Line(circuit, n_not, n_and0) - Line(circuit, f_s, n_and1) - Line(circuit, n_and0, n_or0) - Line(circuit, n_and1, n_or0) - elif n.kind.startswith('DFFSSR'): + if n.kind.startswith('DFFSSR'): n.kind = 'DFFX1' - n_and0 = add_and_connect(circuit, name + '~and0', 'AND2', ins[0], ins[2], None) + n_and0 = add_and_connect(circuit, n.name + '~and0', 'AND2', n.ins[0], n.ins[2], None) Line(circuit, n_and0, (n, 0)) + else: + for k, v in tmap.items(): + if n.kind.startswith(k): + circuit.substitute(n, v) diff --git a/src/kyupy/verilog.py b/src/kyupy/verilog.py index fef8b13..687435e 100644 --- a/src/kyupy/verilog.py +++ b/src/kyupy/verilog.py @@ -48,9 +48,13 @@ class VerilogTransformer(Transformer): @staticmethod def instantiation(args): - return Instantiation(args[0], args[1], - dict((pin.children[0], - pin.children[1]) for pin in args[2:] if len(pin.children) > 1)) + pinmap = {} + for idx, pin in enumerate(args[2:]): + if len(pin.children) > 1: + pinmap[pin.children[0]] = pin.children[1] + else: + pinmap[idx] = pin.children[0] + return Instantiation(args[0], args[1], pinmap) def range(self, args): left = int(args[0].value) @@ -186,7 +190,7 @@ GRAMMAR = r""" wire: "wire" range? _namelist ";" assign: "assign" sigsel "=" sigsel ";" instantiation: name name "(" [ pin ( "," pin )* ] ")" ";" - pin: "." name "(" sigsel? ")" + pin: ("." name "(" sigsel? ")" ) | sigsel range: "[" /[0-9]+/ (":" /[0-9]+/)? "]" sigsel: name range? | concat concat: "{" sigsel ( "," sigsel )* "}"