diff --git a/kyupy/__init__.py b/kyupy/__init__.py index 087659c..b87bade 100644 --- a/kyupy/__init__.py +++ b/kyupy/__init__.py @@ -45,6 +45,7 @@ class MockCuda: self.y = 0 def jit(self, device=False): + _ = device # silence "not used" warning outer = self def make_launcher(func): @@ -84,6 +85,7 @@ class MockCuda: pass def grid(self, dims): + _ = dims # silence "not used" warning return self.x, self.y diff --git a/kyupy/saed.py b/kyupy/saed.py index 10fca85..21771fd 100644 --- a/kyupy/saed.py +++ b/kyupy/saed.py @@ -2,10 +2,14 @@ from kyupy.circuit import Node, Line def pin_index(cell_type, pin): + if cell_type.startswith('HADD') and pin == 'B0': return 1 + if cell_type.startswith('HADD') and pin == 'SO': return 1 if cell_type.startswith('MUX21') and pin == 'S': return 2 if cell_type.startswith('SDFF') and pin == 'QN': return 1 if cell_type.startswith('DFF') and pin == 'QN': return 1 if cell_type.startswith('DFF') and pin == 'CLK': return 1 + if cell_type.startswith('DFF') and pin == 'RSTB': return 2 + if cell_type.startswith('DFF') and pin == 'SETB': return 3 if pin in ['A2', 'IN2', 'SE', 'B', 'CO']: return 1 if pin in ['A3', 'IN3', 'SI', 'CI']: return 2 if pin == 'A4' or pin == 'IN4' or pin == 'CLK': return 3 # CLK for scan cells SDFF @@ -17,7 +21,7 @@ def pin_index(cell_type, pin): def pin_is_output(kind, pin): if 'MUX' in kind and pin == 'S': return False - return pin in ['Q', 'QN', 'Z', 'ZN', 'Y', 'CO', 'S'] + return pin in ['Q', 'QN', 'Z', 'ZN', 'Y', 'CO', 'S', 'SO', 'C1'] def add_and_connect(circuit, name, kind, in1=None, in2=None, out=None): @@ -58,7 +62,7 @@ def split_complex_gates(circuit): 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('OAI21'): + 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]) @@ -70,6 +74,13 @@ def split_complex_gates(circuit): 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) @@ -77,6 +88,13 @@ def split_complex_gates(circuit): 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) @@ -104,6 +122,15 @@ def split_complex_gates(circuit): 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) @@ -137,11 +164,75 @@ def split_complex_gates(circuit): 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() - n_or = add_and_connect(circuit, name+'~or', 'OR2', ins[0], ins[1], None) - n_nor = add_and_connect(circuit, name+'~nor', 'NOR2', None, ins[2], outs[0]) - Line(circuit, n_or, n_nor) + 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 @@ -169,6 +260,17 @@ def split_complex_gates(circuit): 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]) @@ -181,5 +283,7 @@ def split_complex_gates(circuit): Line(circuit, f_s, n_and1) Line(circuit, n_and0, n_or0) Line(circuit, n_and1, n_or0) - - + elif n.kind.startswith('DFFSSR'): + n.kind = 'DFFX1' + n_and0 = add_and_connect(circuit, name + '~and0', 'AND2', ins[0], ins[2], None) + Line(circuit, n_and0, (n, 0)) diff --git a/kyupy/sdf.py b/kyupy/sdf.py index e6db7f7..ed24b3c 100644 --- a/kyupy/sdf.py +++ b/kyupy/sdf.py @@ -170,7 +170,7 @@ class SdfTransformer(Transformer): return DelayFile(name, cells) -def parse(sdf) -> DelayFile: +def parse(sdf): grammar = r""" start: "(DELAYFILE" ( "(SDFVERSION" _NOB ")" | "(DESIGN" "\"" NAME "\"" ")" diff --git a/kyupy/verilog.py b/kyupy/verilog.py index 2516a81..971ba7a 100644 --- a/kyupy/verilog.py +++ b/kyupy/verilog.py @@ -1,6 +1,8 @@ -from lark import Lark, Transformer from collections import namedtuple import gzip + +from lark import Lark, Transformer + from .circuit import Circuit, Node, Line from .saed import pin_index, pin_is_output @@ -110,7 +112,7 @@ class VerilogTransformer(Transformer): Line(c, Node(c, const, const), Node(c, s)) fork = c.forks[s] if self.branchforks: - branchfork = Node(c, fork.name + "~" + n.name) + branchfork = Node(c, fork.name + "~" + n.name + "/" + p) Line(c, fork, branchfork) fork = branchfork Line(c, fork, (n, pin_index(stmt.type, p))) @@ -126,10 +128,9 @@ class VerilogTransformer(Transformer): return args[0] else: return args - -def parse(verilog, branchforks=False) -> Circuit: - grammar = """ + +grammar = """ start: (module)* module: "module" name parameters ";" (_statement)* "endmodule" parameters: "(" [ name ( "," name )* ] ")" @@ -143,12 +144,23 @@ def parse(verilog, branchforks=False) -> Circuit: instantiation: name name "(" [ pin ( "," pin )* ] ")" ";" pin: "." name "(" name ")" signal: ( name | "[" /[0-9]+/ ":" /[0-9]+/ "]" name ) - + name: ( /[a-z_][a-z0-9_\\[\\]]*/i | /\\\\[^\\t \\r\\n]+[\\t \\r\\n](\\[[0-9]+\\])?/i | /1'b0/i | /1'b1/i ) COMMENT: "//" /[^\\n]*/ %ignore ( /\\r?\\n/ | COMMENT )+ %ignore /[\\t \\f]+/ """ + + +def loads(s, *, branchforks=False): + return Lark(grammar, parser="lalr", transformer=VerilogTransformer(branchforks)).parse(s) + + +def load(fp, *, branchforks=False): + return loads(fp.read(), branchforks=branchforks) + + +def parse(verilog, branchforks=False): if '\n' not in str(verilog): # One line?: Assuming it is a file name. if str(verilog).endswith('.gz'): with gzip.open(verilog, 'rt') as f: @@ -158,4 +170,4 @@ def parse(verilog, branchforks=False) -> Circuit: text = f.read() else: text = str(verilog) - return Lark(grammar, parser="lalr", transformer=VerilogTransformer(branchforks)).parse(text) + return loads(text, branchforks=branchforks)