TechLib class, remove unnecessary .index
This commit is contained in:
1 parent
dc003fa624
commit
62cf56e98a
12 files changed
+364
-346
No files matched your search
+8
-9
@@ -44,7 +44,7 @@
|
|||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"<Circuit 'tests/b01.bench' with 92 nodes, 130 lines, 4 ports>"
|
"<Circuit tests/b01.bench cells=45 forks=47 lines=130 ports=4>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 2,
|
"execution_count": 2,
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"<Circuit with 10 nodes, 8 lines, 5 ports>"
|
"<Circuit cells=4 forks=6 lines=8 ports=5>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 3,
|
"execution_count": 3,
|
||||||
@@ -362,7 +362,7 @@
|
|||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"<Circuit 'b14' with 31715 nodes, 46891 lines, 91 ports>"
|
"<Circuit b14 cells=15873 forks=15842 lines=46891 ports=91>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 13,
|
"execution_count": 13,
|
||||||
@@ -445,7 +445,7 @@
|
|||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"<Circuit 'b14' with 31715 nodes, 46891 lines, 91 ports>"
|
"<Circuit b14 cells=15873 forks=15842 lines=46891 ports=91>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 15,
|
"execution_count": 15,
|
||||||
@@ -591,7 +591,7 @@
|
|||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"<MVArray length=1081 width=306 m=8 nbytes=330786>"
|
"<MVArray length=1081 width=306 m=8 mem=323.0kiB>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 19,
|
"execution_count": 19,
|
||||||
@@ -697,7 +697,7 @@
|
|||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"<BPArray length=1081 width=306 m=8 bytes=124848>"
|
"<BPArray length=1081 width=306 m=8 mem=121.9kiB>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 23,
|
"execution_count": 23,
|
||||||
@@ -829,7 +829,7 @@
|
|||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"<MVArray length=1392 width=306 m=8 nbytes=425952>"
|
"<MVArray length=1392 width=306 m=8 mem=416.0kiB>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 29,
|
"execution_count": 29,
|
||||||
@@ -962,10 +962,9 @@
|
|||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"from kyupy import sdf\n",
|
"from kyupy import sdf\n",
|
||||||
"from kyupy.saed import pin_index\n",
|
|
||||||
"\n",
|
"\n",
|
||||||
"df = sdf.load('tests/b14.sdf.gz')\n",
|
"df = sdf.load('tests/b14.sdf.gz')\n",
|
||||||
"lt = df.annotation(b14, pin_index, dataset=0, interconnect=False)"
|
"lt = df.annotation(b14, dataset=0, interconnect=False)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
Miscellaneous
|
Miscellaneous
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
.. automodule:: kyupy.techlib
|
||||||
|
:members:
|
||||||
|
|
||||||
.. automodule:: kyupy
|
.. automodule:: kyupy
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
||||||
+1
-1
@@ -29,7 +29,7 @@ class BenchTransformer(Transformer):
|
|||||||
name, cell_type, drivers = args
|
name, cell_type, drivers = args
|
||||||
cell = Node(self.c, str(name), str(cell_type))
|
cell = Node(self.c, str(name), str(cell_type))
|
||||||
Line(self.c, cell, self.c.get_or_add_fork(str(name)))
|
Line(self.c, cell, self.c.get_or_add_fork(str(name)))
|
||||||
[Line(self.c, d, cell) for d in drivers]
|
for d in drivers: Line(self.c, d, cell)
|
||||||
|
|
||||||
|
|
||||||
GRAMMAR = r"""
|
GRAMMAR = r"""
|
||||||
|
|||||||
@@ -262,8 +262,8 @@ class Circuit:
|
|||||||
for line in n.outs:
|
for line in n.outs:
|
||||||
if line is None: continue
|
if line is None: continue
|
||||||
succ = line.reader
|
succ = line.reader
|
||||||
visit_count[succ.index] += 1
|
visit_count[succ] += 1
|
||||||
if visit_count[succ.index] == len(succ.ins) and 'DFF' not in succ.kind:
|
if visit_count[succ] == len(succ.ins) and 'DFF' not in succ.kind:
|
||||||
queue.append(succ)
|
queue.append(succ)
|
||||||
yield n
|
yield n
|
||||||
|
|
||||||
@@ -287,8 +287,8 @@ class Circuit:
|
|||||||
n = queue.popleft()
|
n = queue.popleft()
|
||||||
for line in n.ins:
|
for line in n.ins:
|
||||||
pred = line.driver
|
pred = line.driver
|
||||||
visit_count[pred.index] += 1
|
visit_count[pred] += 1
|
||||||
if visit_count[pred.index] == len(pred.outs) and 'DFF' not in pred.kind:
|
if visit_count[pred] == len(pred.outs) and 'DFF' not in pred.kind:
|
||||||
queue.append(pred)
|
queue.append(pred)
|
||||||
yield n
|
yield n
|
||||||
|
|
||||||
@@ -299,13 +299,13 @@ class Circuit:
|
|||||||
"""
|
"""
|
||||||
marks = [False] * len(self.nodes)
|
marks = [False] * len(self.nodes)
|
||||||
for n in origin_nodes:
|
for n in origin_nodes:
|
||||||
marks[n.index] = True
|
marks[n] = True
|
||||||
for n in self.reversed_topological_order():
|
for n in self.reversed_topological_order():
|
||||||
if not marks[n.index]:
|
if not marks[n]:
|
||||||
for line in n.outs:
|
for line in n.outs:
|
||||||
if line is not None:
|
if line is not None:
|
||||||
marks[n.index] |= marks[line.reader.index]
|
marks[n] |= marks[line.reader]
|
||||||
if marks[n.index]:
|
if marks[n]:
|
||||||
yield n
|
yield n
|
||||||
|
|
||||||
def fanout_free_regions(self):
|
def fanout_free_regions(self):
|
||||||
|
|||||||
+1
-1
@@ -116,7 +116,7 @@ class MVArray:
|
|||||||
if isinstance(a, MVArray):
|
if isinstance(a, MVArray):
|
||||||
self.data = a.data.copy()
|
self.data = a.data.copy()
|
||||||
"""The wrapped 2-dimensional ndarray of logic values.
|
"""The wrapped 2-dimensional ndarray of logic values.
|
||||||
|
|
||||||
* Axis 0 is PI/PO/FF position, the length of this axis is called "width".
|
* Axis 0 is PI/PO/FF position, the length of this axis is called "width".
|
||||||
* Axis 1 is vector/pattern, the length of this axis is called "length".
|
* Axis 1 is vector/pattern, the length of this axis is called "length".
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,289 +0,0 @@
|
|||||||
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 in ('A4', 'IN4', 'CLK'): return 3 # CLK for scan cells SDFF
|
|
||||||
if pin in ('A5', 'IN5', 'RSTB'): return 4
|
|
||||||
if pin in ('A6', 'IN6', 'SETB'): return 5
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
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', 'SO', 'C1')
|
|
||||||
|
|
||||||
|
|
||||||
def add_and_connect(circuit, name, kind, in1=None, in2=None, out=None):
|
|
||||||
n = Node(circuit, name, kind)
|
|
||||||
if in1 is not None:
|
|
||||||
n.ins[0] = in1
|
|
||||||
in1.reader = n
|
|
||||||
in1.reader_pin = 0
|
|
||||||
if in2 is not None:
|
|
||||||
n.ins[1] = in2
|
|
||||||
in2.reader = n
|
|
||||||
in2.reader_pin = 1
|
|
||||||
if out is not None:
|
|
||||||
n.outs[0] = out
|
|
||||||
out.driver = n
|
|
||||||
out.driver_pin = 0
|
|
||||||
return n
|
|
||||||
|
|
||||||
|
|
||||||
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'):
|
|
||||||
n.kind = 'DFFX1'
|
|
||||||
n_and0 = add_and_connect(circuit, name + '~and0', 'AND2', ins[0], ins[2], None)
|
|
||||||
Line(circuit, n_and0, (n, 0))
|
|
||||||
+15
-13
@@ -14,6 +14,7 @@ import numpy as np
|
|||||||
from lark import Lark, Transformer
|
from lark import Lark, Transformer
|
||||||
|
|
||||||
from . import log, readtext
|
from . import log, readtext
|
||||||
|
from .techlib import TechLib
|
||||||
|
|
||||||
|
|
||||||
Interconnect = namedtuple('Interconnect', ['orig', 'dest', 'r', 'f'])
|
Interconnect = namedtuple('Interconnect', ['orig', 'dest', 'r', 'f'])
|
||||||
@@ -35,7 +36,7 @@ class DelayFile:
|
|||||||
return '\n'.join(f'{n}: {l}' for n, l in self.cells.items()) + '\n' + \
|
return '\n'.join(f'{n}: {l}' for n, l in self.cells.items()) + '\n' + \
|
||||||
'\n'.join(str(i) for i in self.interconnects)
|
'\n'.join(str(i) for i in self.interconnects)
|
||||||
|
|
||||||
def annotation(self, circuit, pin_index_f, dataset=1, interconnect=True, ffdelays=True):
|
def annotation(self, circuit, tlib=TechLib(), dataset=1, interconnect=True, ffdelays=True):
|
||||||
"""Constructs an 3-dimensional ndarray with timing data for each line in ``circuit``.
|
"""Constructs an 3-dimensional ndarray with timing data for each line in ``circuit``.
|
||||||
|
|
||||||
An IOPATH delay for a node is annotated to the line connected to the input pin specified in the IOPATH.
|
An IOPATH delay for a node is annotated to the line connected to the input pin specified in the IOPATH.
|
||||||
@@ -45,7 +46,8 @@ class DelayFile:
|
|||||||
|
|
||||||
:param circuit: The circuit to annotate. Names from the STIL file are matched to the node names.
|
:param circuit: The circuit to annotate. Names from the STIL file are matched to the node names.
|
||||||
:type circuit: :class:`~kyupy.circuit.Circuit`
|
:type circuit: :class:`~kyupy.circuit.Circuit`
|
||||||
:param pin_index_f: A function that returns a pin position by node type and pin name.
|
:param tlib: A technology library object that provides pin name mappings.
|
||||||
|
:type tlib: :py:class:`~kyupy.techlib.TechLib`
|
||||||
:param dataset: SDFs store multiple values for each delay (e.g. minimum, typical, maximum).
|
:param dataset: SDFs store multiple values for each delay (e.g. minimum, typical, maximum).
|
||||||
An integer selects the dataset to use (default is 1 for 'typical').
|
An integer selects the dataset to use (default is 1 for 'typical').
|
||||||
If a tuple is given, the annotator will calculate the average of multiple datasets.
|
If a tuple is given, the annotator will calculate the average of multiple datasets.
|
||||||
@@ -91,8 +93,8 @@ class DelayFile:
|
|||||||
if cell is None:
|
if cell is None:
|
||||||
log.warn(f'Cell from SDF not found in circuit: {cn}')
|
log.warn(f'Cell from SDF not found in circuit: {cn}')
|
||||||
continue
|
continue
|
||||||
ipin = pin_index_f(cell.kind, ipn)
|
ipin = tlib.pin_index(cell.kind, ipn)
|
||||||
opin = pin_index_f(cell.kind, opn)
|
opin = tlib.pin_index(cell.kind, opn)
|
||||||
kind = cell.kind.lower()
|
kind = cell.kind.lower()
|
||||||
|
|
||||||
ipn2 = ipn.replace('(posedge A1)', 'A1').replace('(negedge A1)', 'A1')\
|
ipn2 = ipn.replace('(posedge A1)', 'A1').replace('(negedge A1)', 'A1')\
|
||||||
@@ -100,8 +102,8 @@ class DelayFile:
|
|||||||
|
|
||||||
def add_delays(_line):
|
def add_delays(_line):
|
||||||
if _line is not None:
|
if _line is not None:
|
||||||
timing[_line.index, :, 0] += select_del(delvals, 0)
|
timing[_line, :, 0] += select_del(delvals, 0)
|
||||||
timing[_line.index, :, 1] += select_del(delvals, 1)
|
timing[_line, :, 1] += select_del(delvals, 1)
|
||||||
|
|
||||||
take_avg = False
|
take_avg = False
|
||||||
if kind.startswith('sdff'):
|
if kind.startswith('sdff'):
|
||||||
@@ -111,12 +113,12 @@ class DelayFile:
|
|||||||
add_delays(cell.outs[opin])
|
add_delays(cell.outs[opin])
|
||||||
else:
|
else:
|
||||||
if kind.startswith(('xor', 'xnor')):
|
if kind.startswith(('xor', 'xnor')):
|
||||||
ipin = pin_index_f(cell.kind, ipn2)
|
ipin = tlib.pin_index(cell.kind, ipn2)
|
||||||
# print(ipn, ipin, times[cell.i_lines[ipin].index, 0, 0])
|
# print(ipn, ipin, times[cell.i_lines[ipin], 0, 0])
|
||||||
take_avg = timing[cell.ins[ipin].index].sum() > 0
|
take_avg = timing[cell.ins[ipin]].sum() > 0
|
||||||
add_delays(cell.ins[ipin])
|
add_delays(cell.ins[ipin])
|
||||||
if take_avg:
|
if take_avg:
|
||||||
timing[cell.ins[ipin].index] /= 2
|
timing[cell.ins[ipin]] /= 2
|
||||||
|
|
||||||
if not interconnect or self.interconnects is None:
|
if not interconnect or self.interconnects is None:
|
||||||
return timing
|
return timing
|
||||||
@@ -145,7 +147,7 @@ class DelayFile:
|
|||||||
if c2 is None:
|
if c2 is None:
|
||||||
log.warn(f'Cell from SDF not found in circuit: {cn2}')
|
log.warn(f'Cell from SDF not found in circuit: {cn2}')
|
||||||
continue
|
continue
|
||||||
p1, p2 = pin_index_f(c1.kind, pn1), pin_index_f(c2.kind, pn2)
|
p1, p2 = tlib.pin_index(c1.kind, pn1), tlib.pin_index(c2.kind, pn2)
|
||||||
line = None
|
line = None
|
||||||
f1, f2 = c1.outs[p1].reader, c2.ins[p2].driver
|
f1, f2 = c1.outs[p1].reader, c2.ins[p2].driver
|
||||||
if f1 != f2: # possible branchfork
|
if f1 != f2: # possible branchfork
|
||||||
@@ -155,8 +157,8 @@ class DelayFile:
|
|||||||
elif len(f2.outs) == 1: # no fanout?
|
elif len(f2.outs) == 1: # no fanout?
|
||||||
line = f2.ins[0]
|
line = f2.ins[0]
|
||||||
if line is not None:
|
if line is not None:
|
||||||
timing[line.index, :, 0] += select_del(delvals, 0)
|
timing[line, :, 0] += select_del(delvals, 0)
|
||||||
timing[line.index, :, 1] += select_del(delvals, 1)
|
timing[line, :, 1] += select_del(delvals, 1)
|
||||||
else:
|
else:
|
||||||
log.warn(f'No branchfork for annotating interconnect delay {c1.name}/{p1}->{c2.name}/{p2}')
|
log.warn(f'No branchfork for annotating interconnect delay {c1.name}/{p1}->{c2.name}/{p2}')
|
||||||
return timing
|
return timing
|
||||||
|
|||||||
@@ -0,0 +1,301 @@
|
|||||||
|
from .circuit import Node, Line
|
||||||
|
|
||||||
|
|
||||||
|
def add_and_connect(circuit, name, kind, in1=None, in2=None, out=None):
|
||||||
|
n = Node(circuit, name, kind)
|
||||||
|
if in1 is not None:
|
||||||
|
n.ins[0] = in1
|
||||||
|
in1.reader = n
|
||||||
|
in1.reader_pin = 0
|
||||||
|
if in2 is not None:
|
||||||
|
n.ins[1] = in2
|
||||||
|
in2.reader = n
|
||||||
|
in2.reader_pin = 1
|
||||||
|
if out is not None:
|
||||||
|
n.outs[0] = out
|
||||||
|
out.driver = n
|
||||||
|
out.driver_pin = 0
|
||||||
|
return n
|
||||||
|
|
||||||
|
|
||||||
|
class TechLib:
|
||||||
|
"""Provides some information specific to standard cell libraries necessary
|
||||||
|
for loading gate-level designs. :py:class:`~kyupy.circuit.Node` objects do not
|
||||||
|
have pin names. The methods defined here map pin names to pin directions and defined
|
||||||
|
positions in the ``node.ins`` and ``node.outs`` lists. The default implementation
|
||||||
|
provides mappings for SAED-inspired standard cell libraries.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def pin_index(kind, pin):
|
||||||
|
"""Returns a pin list position for a given node kind and pin name."""
|
||||||
|
for prefix, pins, index in [('HADD', ('B0', 'SO'), 1),
|
||||||
|
('MUX21', ('S',), 2),
|
||||||
|
('DFF', ('QN',), 1),
|
||||||
|
('SDFF', ('QN',), 1),
|
||||||
|
('SDFF', ('CLK',), 3),
|
||||||
|
('SDFF', ('RSTB',), 4),
|
||||||
|
('SDFF', ('SETB',), 5)]:
|
||||||
|
if kind.startswith(prefix) and pin in pins: return index
|
||||||
|
for index, pins in enumerate([('A1', 'IN1', 'D', 'S', 'INP', 'A', 'Q', 'QN', 'Y', 'Z', 'ZN'),
|
||||||
|
('A2', 'IN2', 'CLK', 'CO', 'SE', 'B'),
|
||||||
|
('A3', 'IN3', 'RSTB', 'CI', 'SI'),
|
||||||
|
('A4', 'IN4', 'SETB'),
|
||||||
|
('A5', 'IN5'),
|
||||||
|
('A6', 'IN6')]):
|
||||||
|
if pin in pins: return index
|
||||||
|
raise ValueError(f'Unknown pin index for {kind}.{pin}')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def pin_is_output(kind, pin):
|
||||||
|
"""Returns True, if given pin name of a node kind is an output."""
|
||||||
|
if 'MUX' in kind and pin == 'S': return False
|
||||||
|
return pin in ('Q', 'QN', 'Z', 'ZN', 'Y', 'CO', 'S', 'SO', 'C1')
|
||||||
|
|
||||||
|
@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'):
|
||||||
|
n.kind = 'DFFX1'
|
||||||
|
n_and0 = add_and_connect(circuit, name + '~and0', 'AND2', ins[0], ins[2], None)
|
||||||
|
Line(circuit, n_and0, (n, 0))
|
||||||
+11
-8
@@ -10,7 +10,7 @@ from lark import Lark, Transformer
|
|||||||
|
|
||||||
from . import readtext
|
from . import readtext
|
||||||
from .circuit import Circuit, Node, Line
|
from .circuit import Circuit, Node, Line
|
||||||
from .saed import pin_index, pin_is_output
|
from .techlib import TechLib
|
||||||
|
|
||||||
Instantiation = namedtuple('Instantiation', ['type', 'name', 'pins'])
|
Instantiation = namedtuple('Instantiation', ['type', 'name', 'pins'])
|
||||||
|
|
||||||
@@ -41,10 +41,11 @@ class SignalDeclaration:
|
|||||||
|
|
||||||
|
|
||||||
class VerilogTransformer(Transformer):
|
class VerilogTransformer(Transformer):
|
||||||
def __init__(self, branchforks=False):
|
def __init__(self, branchforks=False, tlib=TechLib()):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._signal_declarations = {}
|
self._signal_declarations = {}
|
||||||
self.branchforks = branchforks
|
self.branchforks = branchforks
|
||||||
|
self.tlib = tlib
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def name(args):
|
def name(args):
|
||||||
@@ -87,8 +88,8 @@ class VerilogTransformer(Transformer):
|
|||||||
if isinstance(stmt, Instantiation):
|
if isinstance(stmt, Instantiation):
|
||||||
n = Node(c, stmt.name, kind=stmt.type)
|
n = Node(c, stmt.name, kind=stmt.type)
|
||||||
for p, s in stmt.pins.items():
|
for p, s in stmt.pins.items():
|
||||||
if pin_is_output(n.kind, p):
|
if self.tlib.pin_is_output(n.kind, p):
|
||||||
Line(c, (n, pin_index(stmt.type, p)), Node(c, s))
|
Line(c, (n, self.tlib.pin_index(stmt.type, p)), Node(c, s))
|
||||||
elif stmt is not None and stmt.data == 'assign':
|
elif stmt is not None and stmt.data == 'assign':
|
||||||
assignments.append((stmt.children[0], stmt.children[1]))
|
assignments.append((stmt.children[0], stmt.children[1]))
|
||||||
for sd in self._signal_declarations.values():
|
for sd in self._signal_declarations.values():
|
||||||
@@ -110,7 +111,7 @@ class VerilogTransformer(Transformer):
|
|||||||
if isinstance(stmt, Instantiation):
|
if isinstance(stmt, Instantiation):
|
||||||
for p, s in stmt.pins.items():
|
for p, s in stmt.pins.items():
|
||||||
n = c.cells[stmt.name]
|
n = c.cells[stmt.name]
|
||||||
if pin_is_output(n.kind, p): continue
|
if self.tlib.pin_is_output(n.kind, p): continue
|
||||||
if s.startswith("1'b"):
|
if s.startswith("1'b"):
|
||||||
const = f'__const{s[3]}__'
|
const = f'__const{s[3]}__'
|
||||||
if const not in c.cells:
|
if const not in c.cells:
|
||||||
@@ -120,7 +121,7 @@ class VerilogTransformer(Transformer):
|
|||||||
branchfork = Node(c, fork.name + "~" + n.name + "/" + p)
|
branchfork = Node(c, fork.name + "~" + n.name + "/" + p)
|
||||||
Line(c, fork, branchfork)
|
Line(c, fork, branchfork)
|
||||||
fork = branchfork
|
fork = branchfork
|
||||||
Line(c, fork, (n, pin_index(stmt.type, p)))
|
Line(c, fork, (n, self.tlib.pin_index(stmt.type, p)))
|
||||||
for sd in self._signal_declarations.values():
|
for sd in self._signal_declarations.values():
|
||||||
if sd.kind == 'output':
|
if sd.kind == 'output':
|
||||||
for name in sd.names:
|
for name in sd.names:
|
||||||
@@ -153,16 +154,18 @@ GRAMMAR = """
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def parse(text, *, branchforks=False):
|
def parse(text, *, branchforks=False, tlib=TechLib()):
|
||||||
"""Parses the given ``text`` as Verilog code.
|
"""Parses the given ``text`` as Verilog code.
|
||||||
|
|
||||||
:param text: A string with Verilog code.
|
:param text: A string with Verilog code.
|
||||||
:param branchforks: If set to ``True``, the returned circuit will include additional `forks` on each fanout branch.
|
:param branchforks: If set to ``True``, the returned circuit will include additional `forks` on each fanout branch.
|
||||||
These forks are needed to correctly annotate interconnect delays
|
These forks are needed to correctly annotate interconnect delays
|
||||||
(see :py:func:`kyupy.sdf.DelayFile.annotation`).
|
(see :py:func:`kyupy.sdf.DelayFile.annotation`).
|
||||||
|
:param tlib: A technology library object that provides pin name mappings.
|
||||||
|
:type tlib: :py:class:`~kyupy.techlib.TechLib`
|
||||||
:return: A :class:`~kyupy.circuit.Circuit` object.
|
:return: A :class:`~kyupy.circuit.Circuit` object.
|
||||||
"""
|
"""
|
||||||
return Lark(GRAMMAR, parser="lalr", transformer=VerilogTransformer(branchforks)).parse(text)
|
return Lark(GRAMMAR, parser="lalr", transformer=VerilogTransformer(branchforks, tlib)).parse(text)
|
||||||
|
|
||||||
|
|
||||||
def load(file, *args, **kwargs):
|
def load(file, *args, **kwargs):
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ class WaveSim:
|
|||||||
prev_line = prev_line.driver.ins[0]
|
prev_line = prev_line.driver.ins[0]
|
||||||
stem_idx = prev_line.index
|
stem_idx = prev_line.index
|
||||||
for ol in f.outs:
|
for ol in f.outs:
|
||||||
stems[ol.index] = stem_idx
|
stems[ol] = stem_idx
|
||||||
|
|
||||||
# calculate level (distance from PI/PPI) and reference count for each line
|
# calculate level (distance from PI/PPI) and reference count for each line
|
||||||
levels = np.zeros(self.sat_length, dtype='int32')
|
levels = np.zeros(self.sat_length, dtype='int32')
|
||||||
@@ -230,7 +230,7 @@ class WaveSim:
|
|||||||
self.sat[self.ppi_offset + i] = h.alloc(intf_wavecap), intf_wavecap, 0
|
self.sat[self.ppi_offset + i] = h.alloc(intf_wavecap), intf_wavecap, 0
|
||||||
ref_count[self.ppi_offset + i] += 1
|
ref_count[self.ppi_offset + i] += 1
|
||||||
if len(n.ins) > 0:
|
if len(n.ins) > 0:
|
||||||
i0_idx = stems[n.ins[0].index] if stems[n.ins[0].index] >= 0 else n.ins[0].index
|
i0_idx = stems[n.ins[0]] if stems[n.ins[0]] >= 0 else n.ins[0]
|
||||||
ref_count[i0_idx] += 1
|
ref_count[i0_idx] += 1
|
||||||
|
|
||||||
# allocate memory for the rest of the circuit
|
# allocate memory for the rest of the circuit
|
||||||
@@ -259,7 +259,7 @@ class WaveSim:
|
|||||||
# copy memory location to PO/PPO area
|
# copy memory location to PO/PPO area
|
||||||
for i, n in enumerate(self.interface):
|
for i, n in enumerate(self.interface):
|
||||||
if len(n.ins) > 0:
|
if len(n.ins) > 0:
|
||||||
self.sat[self.ppo_offset + i] = self.sat[n.ins[0].index]
|
self.sat[self.ppo_offset + i] = self.sat[n.ins[0]]
|
||||||
|
|
||||||
# pad timing
|
# pad timing
|
||||||
self.timing = np.zeros((self.sat_length, 2, 2))
|
self.timing = np.zeros((self.sat_length, 2, 2))
|
||||||
|
|||||||
+9
-10
@@ -1,5 +1,4 @@
|
|||||||
from kyupy import sdf, verilog
|
from kyupy import sdf, verilog
|
||||||
from kyupy.saed import pin_index
|
|
||||||
|
|
||||||
|
|
||||||
def test_parse():
|
def test_parse():
|
||||||
@@ -81,20 +80,20 @@ def test_b14(mydir):
|
|||||||
def test_gates(mydir):
|
def test_gates(mydir):
|
||||||
c = verilog.load(mydir / 'gates.v')
|
c = verilog.load(mydir / 'gates.v')
|
||||||
df = sdf.load(mydir / 'gates.sdf')
|
df = sdf.load(mydir / 'gates.sdf')
|
||||||
lt = df.annotation(c, pin_index, dataset=1)
|
lt = df.annotation(c, dataset=1)
|
||||||
nand_a = c.cells['nandgate'].ins[0]
|
nand_a = c.cells['nandgate'].ins[0]
|
||||||
nand_b = c.cells['nandgate'].ins[1]
|
nand_b = c.cells['nandgate'].ins[1]
|
||||||
and_a = c.cells['andgate'].ins[0]
|
and_a = c.cells['andgate'].ins[0]
|
||||||
and_b = c.cells['andgate'].ins[1]
|
and_b = c.cells['andgate'].ins[1]
|
||||||
|
|
||||||
assert lt[nand_a.index, 0, 0] == 0.103
|
assert lt[nand_a, 0, 0] == 0.103
|
||||||
assert lt[nand_a.index, 0, 1] == 0.127
|
assert lt[nand_a, 0, 1] == 0.127
|
||||||
|
|
||||||
assert lt[nand_b.index, 0, 0] == 0.086
|
assert lt[nand_b, 0, 0] == 0.086
|
||||||
assert lt[nand_b.index, 0, 1] == 0.104
|
assert lt[nand_b, 0, 1] == 0.104
|
||||||
|
|
||||||
assert lt[and_a.index, 0, 0] == 0.378
|
assert lt[and_a, 0, 0] == 0.378
|
||||||
assert lt[and_a.index, 0, 1] == 0.377
|
assert lt[and_a, 0, 1] == 0.377
|
||||||
|
|
||||||
assert lt[and_b.index, 0, 0] == 0.375
|
assert lt[and_b, 0, 0] == 0.375
|
||||||
assert lt[and_b.index, 0, 1] == 0.370
|
assert lt[and_b, 0, 1] == 0.370
|
||||||
@@ -3,7 +3,6 @@ import numpy as np
|
|||||||
from kyupy.wave_sim import WaveSim, WaveSimCuda, wave_eval, TMIN, TMAX
|
from kyupy.wave_sim import WaveSim, WaveSimCuda, wave_eval, TMIN, TMAX
|
||||||
from kyupy.logic_sim import LogicSim
|
from kyupy.logic_sim import LogicSim
|
||||||
from kyupy import verilog, sdf, logic
|
from kyupy import verilog, sdf, logic
|
||||||
from kyupy.saed import pin_index
|
|
||||||
from kyupy.logic import MVArray, BPArray
|
from kyupy.logic import MVArray, BPArray
|
||||||
|
|
||||||
|
|
||||||
@@ -128,7 +127,7 @@ def compare_to_logic_sim(wsim):
|
|||||||
def test_b14(mydir):
|
def test_b14(mydir):
|
||||||
c = verilog.load(mydir / 'b14.v.gz', branchforks=True)
|
c = verilog.load(mydir / 'b14.v.gz', branchforks=True)
|
||||||
df = sdf.load(mydir / 'b14.sdf.gz')
|
df = sdf.load(mydir / 'b14.sdf.gz')
|
||||||
lt = df.annotation(c, pin_index)
|
lt = df.annotation(c)
|
||||||
wsim = WaveSim(c, lt, 8)
|
wsim = WaveSim(c, lt, 8)
|
||||||
compare_to_logic_sim(wsim)
|
compare_to_logic_sim(wsim)
|
||||||
|
|
||||||
@@ -136,7 +135,7 @@ def test_b14(mydir):
|
|||||||
def test_b14_strip_forks(mydir):
|
def test_b14_strip_forks(mydir):
|
||||||
c = verilog.load(mydir / 'b14.v.gz', branchforks=True)
|
c = verilog.load(mydir / 'b14.v.gz', branchforks=True)
|
||||||
df = sdf.load(mydir / 'b14.sdf.gz')
|
df = sdf.load(mydir / 'b14.sdf.gz')
|
||||||
lt = df.annotation(c, pin_index)
|
lt = df.annotation(c)
|
||||||
wsim = WaveSim(c, lt, 8, strip_forks=True)
|
wsim = WaveSim(c, lt, 8, strip_forks=True)
|
||||||
compare_to_logic_sim(wsim)
|
compare_to_logic_sim(wsim)
|
||||||
|
|
||||||
@@ -144,6 +143,6 @@ def test_b14_strip_forks(mydir):
|
|||||||
def test_b14_cuda(mydir):
|
def test_b14_cuda(mydir):
|
||||||
c = verilog.load(mydir / 'b14.v.gz', branchforks=True)
|
c = verilog.load(mydir / 'b14.v.gz', branchforks=True)
|
||||||
df = sdf.load(mydir / 'b14.sdf.gz')
|
df = sdf.load(mydir / 'b14.sdf.gz')
|
||||||
lt = df.annotation(c, pin_index)
|
lt = df.annotation(c)
|
||||||
wsim = WaveSimCuda(c, lt, 8)
|
wsim = WaveSimCuda(c, lt, 8)
|
||||||
compare_to_logic_sim(wsim)
|
compare_to_logic_sim(wsim)
|
||||||
Reference in new issue
Block a user