Browse Source

TechLib class, remove unnecessary .index

devel
Stefan Holst 4 years ago
parent
commit
62cf56e98a
  1. 17
      Demo.ipynb
  2. 4
      docs/miscellaneous.rst
  3. 2
      src/kyupy/bench.py
  4. 16
      src/kyupy/circuit.py
  5. 2
      src/kyupy/logic.py
  6. 289
      src/kyupy/saed.py
  7. 28
      src/kyupy/sdf.py
  8. 301
      src/kyupy/techlib.py
  9. 19
      src/kyupy/verilog.py
  10. 6
      src/kyupy/wave_sim.py
  11. 19
      tests/test_sdf.py
  12. 7
      tests/test_wave_sim.py

17
Demo.ipynb

@ -44,7 +44,7 @@ @@ -44,7 +44,7 @@
{
"data": {
"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,
@ -64,7 +64,7 @@ @@ -64,7 +64,7 @@
{
"data": {
"text/plain": [
"<Circuit with 10 nodes, 8 lines, 5 ports>"
"<Circuit cells=4 forks=6 lines=8 ports=5>"
]
},
"execution_count": 3,
@ -362,7 +362,7 @@ @@ -362,7 +362,7 @@
{
"data": {
"text/plain": [
"<Circuit 'b14' with 31715 nodes, 46891 lines, 91 ports>"
"<Circuit b14 cells=15873 forks=15842 lines=46891 ports=91>"
]
},
"execution_count": 13,
@ -445,7 +445,7 @@ @@ -445,7 +445,7 @@
{
"data": {
"text/plain": [
"<Circuit 'b14' with 31715 nodes, 46891 lines, 91 ports>"
"<Circuit b14 cells=15873 forks=15842 lines=46891 ports=91>"
]
},
"execution_count": 15,
@ -591,7 +591,7 @@ @@ -591,7 +591,7 @@
{
"data": {
"text/plain": [
"<MVArray length=1081 width=306 m=8 nbytes=330786>"
"<MVArray length=1081 width=306 m=8 mem=323.0kiB>"
]
},
"execution_count": 19,
@ -697,7 +697,7 @@ @@ -697,7 +697,7 @@
{
"data": {
"text/plain": [
"<BPArray length=1081 width=306 m=8 bytes=124848>"
"<BPArray length=1081 width=306 m=8 mem=121.9kiB>"
]
},
"execution_count": 23,
@ -829,7 +829,7 @@ @@ -829,7 +829,7 @@
{
"data": {
"text/plain": [
"<MVArray length=1392 width=306 m=8 nbytes=425952>"
"<MVArray length=1392 width=306 m=8 mem=416.0kiB>"
]
},
"execution_count": 29,
@ -962,10 +962,9 @@ @@ -962,10 +962,9 @@
"outputs": [],
"source": [
"from kyupy import sdf\n",
"from kyupy.saed import pin_index\n",
"\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)"
]
},
{

4
docs/miscellaneous.rst

@ -1,6 +1,10 @@ @@ -1,6 +1,10 @@
Miscellaneous
=============
.. automodule:: kyupy.techlib
:members:
.. automodule:: kyupy
:members:

2
src/kyupy/bench.py

@ -29,7 +29,7 @@ class BenchTransformer(Transformer): @@ -29,7 +29,7 @@ class BenchTransformer(Transformer):
name, cell_type, drivers = args
cell = Node(self.c, str(name), str(cell_type))
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"""

16
src/kyupy/circuit.py

@ -262,8 +262,8 @@ class Circuit: @@ -262,8 +262,8 @@ class Circuit:
for line in n.outs:
if line is None: continue
succ = line.reader
visit_count[succ.index] += 1
if visit_count[succ.index] == len(succ.ins) and 'DFF' not in succ.kind:
visit_count[succ] += 1
if visit_count[succ] == len(succ.ins) and 'DFF' not in succ.kind:
queue.append(succ)
yield n
@ -287,8 +287,8 @@ class Circuit: @@ -287,8 +287,8 @@ class Circuit:
n = queue.popleft()
for line in n.ins:
pred = line.driver
visit_count[pred.index] += 1
if visit_count[pred.index] == len(pred.outs) and 'DFF' not in pred.kind:
visit_count[pred] += 1
if visit_count[pred] == len(pred.outs) and 'DFF' not in pred.kind:
queue.append(pred)
yield n
@ -299,13 +299,13 @@ class Circuit: @@ -299,13 +299,13 @@ class Circuit:
"""
marks = [False] * len(self.nodes)
for n in origin_nodes:
marks[n.index] = True
marks[n] = True
for n in self.reversed_topological_order():
if not marks[n.index]:
if not marks[n]:
for line in n.outs:
if line is not None:
marks[n.index] |= marks[line.reader.index]
if marks[n.index]:
marks[n] |= marks[line.reader]
if marks[n]:
yield n
def fanout_free_regions(self):

2
src/kyupy/logic.py

@ -116,7 +116,7 @@ class MVArray: @@ -116,7 +116,7 @@ class MVArray:
if isinstance(a, MVArray):
self.data = a.data.copy()
"""The wrapped 2-dimensional ndarray of logic values.
* 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".
"""

289
src/kyupy/saed.py

@ -1,289 +0,0 @@ @@ -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))

28
src/kyupy/sdf.py

@ -14,6 +14,7 @@ import numpy as np @@ -14,6 +14,7 @@ import numpy as np
from lark import Lark, Transformer
from . import log, readtext
from .techlib import TechLib
Interconnect = namedtuple('Interconnect', ['orig', 'dest', 'r', 'f'])
@ -35,7 +36,7 @@ class DelayFile: @@ -35,7 +36,7 @@ class DelayFile:
return '\n'.join(f'{n}: {l}' for n, l in self.cells.items()) + '\n' + \
'\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``.
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: @@ -45,7 +46,8 @@ class DelayFile:
:param circuit: The circuit to annotate. Names from the STIL file are matched to the node names.
: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).
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.
@ -91,8 +93,8 @@ class DelayFile: @@ -91,8 +93,8 @@ class DelayFile:
if cell is None:
log.warn(f'Cell from SDF not found in circuit: {cn}')
continue
ipin = pin_index_f(cell.kind, ipn)
opin = pin_index_f(cell.kind, opn)
ipin = tlib.pin_index(cell.kind, ipn)
opin = tlib.pin_index(cell.kind, opn)
kind = cell.kind.lower()
ipn2 = ipn.replace('(posedge A1)', 'A1').replace('(negedge A1)', 'A1')\
@ -100,8 +102,8 @@ class DelayFile: @@ -100,8 +102,8 @@ class DelayFile:
def add_delays(_line):
if _line is not None:
timing[_line.index, :, 0] += select_del(delvals, 0)
timing[_line.index, :, 1] += select_del(delvals, 1)
timing[_line, :, 0] += select_del(delvals, 0)
timing[_line, :, 1] += select_del(delvals, 1)
take_avg = False
if kind.startswith('sdff'):
@ -111,12 +113,12 @@ class DelayFile: @@ -111,12 +113,12 @@ class DelayFile:
add_delays(cell.outs[opin])
else:
if kind.startswith(('xor', 'xnor')):
ipin = pin_index_f(cell.kind, ipn2)
# print(ipn, ipin, times[cell.i_lines[ipin].index, 0, 0])
take_avg = timing[cell.ins[ipin].index].sum() > 0
ipin = tlib.pin_index(cell.kind, ipn2)
# print(ipn, ipin, times[cell.i_lines[ipin], 0, 0])
take_avg = timing[cell.ins[ipin]].sum() > 0
add_delays(cell.ins[ipin])
if take_avg:
timing[cell.ins[ipin].index] /= 2
timing[cell.ins[ipin]] /= 2
if not interconnect or self.interconnects is None:
return timing
@ -145,7 +147,7 @@ class DelayFile: @@ -145,7 +147,7 @@ class DelayFile:
if c2 is None:
log.warn(f'Cell from SDF not found in circuit: {cn2}')
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
f1, f2 = c1.outs[p1].reader, c2.ins[p2].driver
if f1 != f2: # possible branchfork
@ -155,8 +157,8 @@ class DelayFile: @@ -155,8 +157,8 @@ class DelayFile:
elif len(f2.outs) == 1: # no fanout?
line = f2.ins[0]
if line is not None:
timing[line.index, :, 0] += select_del(delvals, 0)
timing[line.index, :, 1] += select_del(delvals, 1)
timing[line, :, 0] += select_del(delvals, 0)
timing[line, :, 1] += select_del(delvals, 1)
else:
log.warn(f'No branchfork for annotating interconnect delay {c1.name}/{p1}->{c2.name}/{p2}')
return timing

301
src/kyupy/techlib.py

@ -0,0 +1,301 @@ @@ -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))

19
src/kyupy/verilog.py

@ -10,7 +10,7 @@ from lark import Lark, Transformer @@ -10,7 +10,7 @@ from lark import Lark, Transformer
from . import readtext
from .circuit import Circuit, Node, Line
from .saed import pin_index, pin_is_output
from .techlib import TechLib
Instantiation = namedtuple('Instantiation', ['type', 'name', 'pins'])
@ -41,10 +41,11 @@ class SignalDeclaration: @@ -41,10 +41,11 @@ class SignalDeclaration:
class VerilogTransformer(Transformer):
def __init__(self, branchforks=False):
def __init__(self, branchforks=False, tlib=TechLib()):
super().__init__()
self._signal_declarations = {}
self.branchforks = branchforks
self.tlib = tlib
@staticmethod
def name(args):
@ -87,8 +88,8 @@ class VerilogTransformer(Transformer): @@ -87,8 +88,8 @@ class VerilogTransformer(Transformer):
if isinstance(stmt, Instantiation):
n = Node(c, stmt.name, kind=stmt.type)
for p, s in stmt.pins.items():
if pin_is_output(n.kind, p):
Line(c, (n, pin_index(stmt.type, p)), Node(c, s))
if self.tlib.pin_is_output(n.kind, p):
Line(c, (n, self.tlib.pin_index(stmt.type, p)), Node(c, s))
elif stmt is not None and stmt.data == 'assign':
assignments.append((stmt.children[0], stmt.children[1]))
for sd in self._signal_declarations.values():
@ -110,7 +111,7 @@ class VerilogTransformer(Transformer): @@ -110,7 +111,7 @@ class VerilogTransformer(Transformer):
if isinstance(stmt, Instantiation):
for p, s in stmt.pins.items():
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"):
const = f'__const{s[3]}__'
if const not in c.cells:
@ -120,7 +121,7 @@ class VerilogTransformer(Transformer): @@ -120,7 +121,7 @@ class VerilogTransformer(Transformer):
branchfork = Node(c, fork.name + "~" + n.name + "/" + p)
Line(c, 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():
if sd.kind == 'output':
for name in sd.names:
@ -153,16 +154,18 @@ GRAMMAR = """ @@ -153,16 +154,18 @@ GRAMMAR = """
"""
def parse(text, *, branchforks=False):
def parse(text, *, branchforks=False, tlib=TechLib()):
"""Parses the given ``text`` as 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.
These forks are needed to correctly annotate interconnect delays
(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 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):

6
src/kyupy/wave_sim.py

@ -192,7 +192,7 @@ class WaveSim: @@ -192,7 +192,7 @@ class WaveSim:
prev_line = prev_line.driver.ins[0]
stem_idx = prev_line.index
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
levels = np.zeros(self.sat_length, dtype='int32')
@ -230,7 +230,7 @@ class WaveSim: @@ -230,7 +230,7 @@ class WaveSim:
self.sat[self.ppi_offset + i] = h.alloc(intf_wavecap), intf_wavecap, 0
ref_count[self.ppi_offset + i] += 1
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
# allocate memory for the rest of the circuit
@ -259,7 +259,7 @@ class WaveSim: @@ -259,7 +259,7 @@ class WaveSim:
# copy memory location to PO/PPO area
for i, n in enumerate(self.interface):
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
self.timing = np.zeros((self.sat_length, 2, 2))

19
tests/test_sdf.py

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
from kyupy import sdf, verilog
from kyupy.saed import pin_index
def test_parse():
@ -81,20 +80,20 @@ def test_b14(mydir): @@ -81,20 +80,20 @@ def test_b14(mydir):
def test_gates(mydir):
c = verilog.load(mydir / 'gates.v')
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_b = c.cells['nandgate'].ins[1]
and_a = c.cells['andgate'].ins[0]
and_b = c.cells['andgate'].ins[1]
assert lt[nand_a.index, 0, 0] == 0.103
assert lt[nand_a.index, 0, 1] == 0.127
assert lt[nand_a, 0, 0] == 0.103
assert lt[nand_a, 0, 1] == 0.127
assert lt[nand_b.index, 0, 0] == 0.086
assert lt[nand_b.index, 0, 1] == 0.104
assert lt[nand_b, 0, 0] == 0.086
assert lt[nand_b, 0, 1] == 0.104
assert lt[and_a.index, 0, 0] == 0.378
assert lt[and_a.index, 0, 1] == 0.377
assert lt[and_a, 0, 0] == 0.378
assert lt[and_a, 0, 1] == 0.377
assert lt[and_b.index, 0, 0] == 0.375
assert lt[and_b.index, 0, 1] == 0.370
assert lt[and_b, 0, 0] == 0.375
assert lt[and_b, 0, 1] == 0.370

7
tests/test_wave_sim.py

@ -3,7 +3,6 @@ import numpy as np @@ -3,7 +3,6 @@ import numpy as np
from kyupy.wave_sim import WaveSim, WaveSimCuda, wave_eval, TMIN, TMAX
from kyupy.logic_sim import LogicSim
from kyupy import verilog, sdf, logic
from kyupy.saed import pin_index
from kyupy.logic import MVArray, BPArray
@ -128,7 +127,7 @@ def compare_to_logic_sim(wsim): @@ -128,7 +127,7 @@ def compare_to_logic_sim(wsim):
def test_b14(mydir):
c = verilog.load(mydir / 'b14.v.gz', branchforks=True)
df = sdf.load(mydir / 'b14.sdf.gz')
lt = df.annotation(c, pin_index)
lt = df.annotation(c)
wsim = WaveSim(c, lt, 8)
compare_to_logic_sim(wsim)
@ -136,7 +135,7 @@ def test_b14(mydir): @@ -136,7 +135,7 @@ def test_b14(mydir):
def test_b14_strip_forks(mydir):
c = verilog.load(mydir / 'b14.v.gz', branchforks=True)
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)
compare_to_logic_sim(wsim)
@ -144,6 +143,6 @@ def test_b14_strip_forks(mydir): @@ -144,6 +143,6 @@ def test_b14_strip_forks(mydir):
def test_b14_cuda(mydir):
c = verilog.load(mydir / 'b14.v.gz', branchforks=True)
df = sdf.load(mydir / 'b14.sdf.gz')
lt = df.annotation(c, pin_index)
lt = df.annotation(c)
wsim = WaveSimCuda(c, lt, 8)
compare_to_logic_sim(wsim)

Loading…
Cancel
Save