Browse Source

de-lint and repr improvements

devel
Stefan Holst 4 years ago
parent
commit
ff4de6d782
  1. 11
      src/kyupy/__init__.py
  2. 12
      src/kyupy/bench.py
  3. 14
      src/kyupy/circuit.py
  4. 6
      src/kyupy/logic.py
  5. 2
      src/kyupy/logic_sim.py
  6. 18
      src/kyupy/saed.py
  7. 24
      src/kyupy/sdf.py
  8. 34
      src/kyupy/stil.py
  9. 35
      src/kyupy/verilog.py
  10. 27
      src/kyupy/wave_sim.py
  11. 4
      tests/test_bench.py
  12. 4
      tests/test_logic_sim.py
  13. 7
      tests/test_stil.py
  14. 42
      tests/test_wave_sim.py

11
src/kyupy/__init__.py

@ -77,14 +77,15 @@ class Log: @@ -77,14 +77,15 @@ class Log:
yield i
current_time = time.perf_counter()
if current_time > lastlog_time + log_interval:
work_done = (elem + 1) / elems
done = (elem + 1) / elems
elapsed_time = current_time - start_time
total_time = elapsed_time / work_done
remaining_time = total_time - elapsed_time
self.log(':', f'{work_done*100:.0f}% done {hr_time(elapsed_time)} elapsed {hr_time(remaining_time)} remaining')
total_time = elapsed_time / done
rem_time = total_time - elapsed_time
self.log(':', f'{done*100:.0f}% done {hr_time(elapsed_time)} elapsed {hr_time(rem_time)} remaining')
log_interval = min(600, int(log_interval*1.5))
lastlog_time = current_time
log = Log()
@ -107,7 +108,7 @@ class MockCuda: @@ -107,7 +108,7 @@ class MockCuda:
outer = self
def make_launcher(func):
class Launcher(object):
class Launcher:
def __init__(self, funcc):
self.func = funcc

12
src/kyupy/bench.py

@ -14,15 +14,15 @@ from . import readtext @@ -14,15 +14,15 @@ from . import readtext
class BenchTransformer(Transformer):
def __init__(self, name):
super().__init__()
self.c = Circuit(name)
def start(self, _): return self.c
def parameters(self, args): return [self.c.get_or_add_fork(name) for name in args]
def interface(self, args): self.c.interface.extend(args[0])
def assignment(self, args):
@ -32,7 +32,7 @@ class BenchTransformer(Transformer): @@ -32,7 +32,7 @@ class BenchTransformer(Transformer):
[Line(self.c, d, cell) for d in drivers]
grammar = r"""
GRAMMAR = r"""
start: (statement)*
statement: input | output | assignment
input: ("INPUT" | "input") parameters -> interface
@ -51,7 +51,7 @@ def parse(text, name=None): @@ -51,7 +51,7 @@ def parse(text, name=None):
:param name: The name of the circuit. Circuit names are not included in bench descriptions.
:return: A :class:`Circuit` object.
"""
return Lark(grammar, parser="lalr", transformer=BenchTransformer(name)).parse(text)
return Lark(GRAMMAR, parser="lalr", transformer=BenchTransformer(name)).parse(text)
def load(file, name=None):

14
src/kyupy/circuit.py

@ -53,7 +53,7 @@ class Node: @@ -53,7 +53,7 @@ class Node:
"""
self.kind = kind
"""A string describing the type of the node.
Common types are the names from a standard cell library or general gate names like 'AND' or 'NOR'.
If :py:attr:`kind` is set to '__fork__', it receives special treatment.
A `fork` describes a named signal or a fan-out point in the circuit and not a physical `cell` like a gate.
@ -130,7 +130,7 @@ class Line: @@ -130,7 +130,7 @@ class Line:
"""
self.driver_pin = driver[1]
"""The output pin position of the driver node this line is connected to.
This is the position in the outs-list of the driving node this line referenced from:
:code:`self.driver.outs[self.driver_pin] == self`.
"""
@ -187,17 +187,17 @@ class Circuit: @@ -187,17 +187,17 @@ class Circuit:
"""
self.nodes = IndexList()
"""A list of all :class:`Node` objects contained in the circuit.
The position of a node in this list equals its index :code:`self.nodes[42].index == 42`.
"""
self.lines = IndexList()
"""A list of all :class:`Line` objects contained in the circuit.
The position of a line in this list equals its index :code:`self.lines[42].index == 42`.
"""
self.interface = GrowingList()
"""A list of nodes that are designated as primary input- or output-ports.
Port-nodes are contained in :py:attr:`nodes` as well as :py:attr:`interface`.
The position of a node in the interface list corresponds to positions of logic values in test vectors.
The port direction is not stored explicitly.
@ -213,7 +213,7 @@ class Circuit: @@ -213,7 +213,7 @@ class Circuit:
def get_or_add_fork(self, name):
return self.forks[name] if name in self.forks else Node(self, name)
def copy(self):
"""Returns a deep copy of the circuit.
"""
@ -231,7 +231,7 @@ class Circuit: @@ -231,7 +231,7 @@ class Circuit:
n = c.cells[node.name]
c.interface.append(n)
return c
def dump(self):
"""Returns a string representation of the circuit and all its nodes.
"""

6
src/kyupy/logic.py

@ -25,7 +25,7 @@ from collections.abc import Iterable @@ -25,7 +25,7 @@ from collections.abc import Iterable
import numpy as np
from . import numba
from . import numba, hr_bytes
ZERO = 0b000
@ -247,7 +247,7 @@ class MVArray: @@ -247,7 +247,7 @@ class MVArray:
self.width = self.data.shape[-2]
def __repr__(self):
return f'<MVArray length={self.length} width={self.width} m={self.m} nbytes={self.data.nbytes}>'
return f'<MVArray length={self.length} width={self.width} m={self.m} mem={hr_bytes(self.data.nbytes)}>'
def __str__(self):
return str([self[idx] for idx in range(self.length)])
@ -396,7 +396,7 @@ class BPArray: @@ -396,7 +396,7 @@ class BPArray:
self.width = a.width
def __repr__(self):
return f'<BPArray length={self.length} width={self.width} m={self.m} bytes={self.data.nbytes}>'
return f'<BPArray length={self.length} width={self.width} m={self.m} mem={hr_bytes(self.data.nbytes)}>'
def __len__(self):
return self.length

2
src/kyupy/logic_sim.py

@ -37,7 +37,7 @@ class LogicSim: @@ -37,7 +37,7 @@ class LogicSim:
self.zero = np.zeros((mdim, nbytes), dtype='uint8')
self.epoch = 0
known_fct = [(f[:-4], getattr(self, f)) for f in dir(self) if f.endswith(f'_fct')]
known_fct = [(f[:-4], getattr(self, f)) for f in dir(self) if f.endswith('_fct')]
self.node_fct = []
for n in circuit.nodes:
t = n.kind.lower().replace('__fork__', 'fork')

18
src/kyupy/saed.py

@ -10,18 +10,18 @@ def pin_index(cell_type, pin): @@ -10,18 +10,18 @@ def pin_index(cell_type, pin):
if cell_type.startswith('DFF') and pin == 'CLK': return 1
if cell_type.startswith('DFF') and pin == 'RSTB': return 2
if cell_type.startswith('DFF') and pin == 'SETB': return 3
if pin in ['A2', 'IN2', 'SE', 'B', 'CO']: return 1
if pin in ['A3', 'IN3', 'SI', 'CI']: return 2
if pin == 'A4' or pin == 'IN4' or pin == 'CLK': return 3 # CLK for scan cells SDFF
if pin == 'A5' or pin == 'IN5' or pin == 'RSTB': return 4
if pin == 'A6' or pin == 'IN6' or pin == 'SETB': return 5
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']
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):
@ -103,7 +103,7 @@ def split_complex_gates(circuit): @@ -103,7 +103,7 @@ def split_complex_gates(circuit):
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)
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)
@ -112,7 +112,7 @@ def split_complex_gates(circuit): @@ -112,7 +112,7 @@ def split_complex_gates(circuit):
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)
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)
@ -121,7 +121,7 @@ def split_complex_gates(circuit): @@ -121,7 +121,7 @@ def split_complex_gates(circuit):
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)
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)

24
src/kyupy/sdf.py

@ -58,14 +58,10 @@ class DelayFile: @@ -58,14 +58,10 @@ class DelayFile:
E.g., timing[42,1,0] is the rejection limit of a negative pulse at the output of the reader of line 42.
"""
def select_del(_delvals, idx):
if type(dataset) is tuple:
s = 0
for d in dataset:
s += _delvals[idx][d]
return s / len(dataset)
else:
return _delvals[idx][dataset]
if isinstance(dataset, tuple):
return sum(_delvals[idx][d] for d in dataset) / len(dataset)
return _delvals[idx][dataset]
def find_cell(name):
if name not in circuit.cells:
name = name.replace('\\', '')
@ -74,7 +70,7 @@ class DelayFile: @@ -74,7 +70,7 @@ class DelayFile:
if name not in circuit.cells:
return None
return circuit.cells[name]
timing = np.zeros((len(circuit.lines), 2, 2))
for cn, iopaths in self.cells.items():
for ipn, opn, *delvals in iopaths:
@ -91,7 +87,7 @@ class DelayFile: @@ -91,7 +87,7 @@ class DelayFile:
ipn2 = ipn.replace('(posedge A1)', 'A1').replace('(negedge A1)', 'A1')\
.replace('(posedge A2)', 'A2').replace('(negedge A2)', 'A2')
def add_delays(_line):
if _line is not None:
timing[_line.index, :, 0] += select_del(delvals, 0)
@ -111,10 +107,10 @@ class DelayFile: @@ -111,10 +107,10 @@ class DelayFile:
add_delays(cell.ins[ipin])
if take_avg:
timing[cell.ins[ipin].index] /= 2
if not interconnect or self.interconnects is None:
return timing
for n1, n2, *delvals in self.interconnects:
delvals = [d if len(d) > 0 else [0, 0, 0] for d in delvals]
if max(max(delvals)) == 0:
@ -184,7 +180,7 @@ class SdfTransformer(Transformer): @@ -184,7 +180,7 @@ class SdfTransformer(Transformer):
return DelayFile(name, cells)
grammar = r"""
GRAMMAR = r"""
start: "(DELAYFILE" ( "(SDFVERSION" _NOB ")"
| "(DESIGN" "\"" NAME "\"" ")"
| "(DATE" _NOB ")"
@ -218,7 +214,7 @@ grammar = r""" @@ -218,7 +214,7 @@ grammar = r"""
def parse(text):
"""Parses the given ``text`` and returns a :class:`DelayFile` object."""
return Lark(grammar, parser="lalr", transformer=SdfTransformer()).parse(text)
return Lark(GRAMMAR, parser="lalr", transformer=SdfTransformer()).parse(text)
def load(file):

34
src/kyupy/stil.py

@ -54,26 +54,26 @@ class StilFile: @@ -54,26 +54,26 @@ class StilFile:
launch = dict((k, v.replace('\n', '')) for k, v in call.parameters.items())
else:
capture = dict((k, v.replace('\n', '')) for k, v in call.parameters.items())
def _maps(self, c):
interface = list(c.interface) + [n for n in c.nodes if 'DFF' in n.kind]
intf_pos = dict([(n.name, i) for i, n in enumerate(interface)])
intf_pos = dict((n.name, i) for i, n in enumerate(interface))
pi_map = [intf_pos[n] for n in self.signal_groups['_pi']]
po_map = [intf_pos[n] for n in self.signal_groups['_po']]
scan_maps = {}
scan_inversions = {}
for chain_name, chain in self.scan_chains.items():
for chain in self.scan_chains.values():
scan_map = []
scan_in_inversion = []
scan_out_inversion = []
inversion = False
for n in chain[1:-1]:
if n == '!':
if n == '!':
inversion = not inversion
else:
scan_in_inversion.append(inversion)
scan_in_inversion = list(reversed(scan_in_inversion))
inversion = False
inversion = False
for n in reversed(chain[1:-1]):
if n == '!':
inversion = not inversion
@ -85,13 +85,13 @@ class StilFile: @@ -85,13 +85,13 @@ class StilFile:
scan_inversions[chain[0]] = scan_in_inversion
scan_inversions[chain[-1]] = scan_out_inversion
return interface, pi_map, po_map, scan_maps, scan_inversions
def tests(self, circuit):
"""Assembles and returns a scan test pattern set for given circuit.
This function assumes a static (stuck-at fault) test.
"""
interface, pi_map, po_map, scan_maps, scan_inversions = self._maps(circuit)
interface, pi_map, _, scan_maps, scan_inversions = self._maps(circuit)
tests = logic.MVArray((len(interface), len(self.patterns)))
for i, p in enumerate(self.patterns):
for si_port in self.si_ports.keys():
@ -133,10 +133,10 @@ class StilFile: @@ -133,10 +133,10 @@ class StilFile:
launch.data[po_map, i] = logic.UNASSIGNED
return logic.mv_transition(init, launch)
def responses(self, circuit):
"""Assembles and returns a scan test response pattern set for given circuit."""
interface, pi_map, po_map, scan_maps, scan_inversions = self._maps(circuit)
interface, _, po_map, scan_maps, scan_inversions = self._maps(circuit)
resp = logic.MVArray((len(interface), len(self.patterns)))
# resp = PackedVectors(len(self.patterns), len(interface), 2)
for i, p in enumerate(self.patterns):
@ -150,27 +150,27 @@ class StilFile: @@ -150,27 +150,27 @@ class StilFile:
resp.data[scan_maps[so_port], i] = pattern.data[:, 0]
# resp.set_values(i, p.unload[so_port], scan_maps[so_port], scan_inversions[so_port])
return resp
class StilTransformer(Transformer):
def __init__(self):
super().__init__()
self._signal_groups = None
self._calls = None
self._scan_chains = None
@staticmethod
def quoted(args): return args[0][1:-1]
@staticmethod
def call(args): return Call(args[0], dict(args[1:]))
@staticmethod
def call_parameter(args): return args[0], args[1].value
@staticmethod
def signal_group(args): return args[0], args[1:]
@staticmethod
def scan_chain(args):
scan_in = None
@ -187,7 +187,7 @@ class StilTransformer(Transformer): @@ -187,7 +187,7 @@ class StilTransformer(Transformer):
return args[0], ([scan_in] + scan_cells + [scan_out])
def signal_groups(self, args): self._signal_groups = dict(args)
def pattern(self, args): self._calls = [c for c in args if isinstance(c, Call)]
def scan_structures(self, args): self._scan_chains = dict(args)
@ -196,7 +196,7 @@ class StilTransformer(Transformer): @@ -196,7 +196,7 @@ class StilTransformer(Transformer):
return StilFile(float(args[0]), self._signal_groups, self._scan_chains, self._calls)
grammar = r"""
GRAMMAR = r"""
start: "STIL" FLOAT _ignore _block*
_block: signal_groups | scan_structures | pattern
| "Header" _ignore
@ -240,7 +240,7 @@ grammar = r""" @@ -240,7 +240,7 @@ grammar = r"""
def parse(text):
"""Parses the given ``text`` and returns a :class:`StilFile` object."""
return Lark(grammar, parser="lalr", transformer=StilTransformer()).parse(text)
return Lark(GRAMMAR, parser="lalr", transformer=StilTransformer()).parse(text)
def load(file):

35
src/kyupy/verilog.py

@ -16,7 +16,7 @@ Instantiation = namedtuple('Instantiation', ['type', 'name', 'pins']) @@ -16,7 +16,7 @@ Instantiation = namedtuple('Instantiation', ['type', 'name', 'pins'])
class SignalDeclaration:
def __init__(self, kind, tokens):
self.left = None
self.right = None
@ -27,16 +27,15 @@ class SignalDeclaration: @@ -27,16 +27,15 @@ class SignalDeclaration:
self.basename = tokens.children[2]
self.left = int(tokens.children[0].value)
self.right = int(tokens.children[1].value)
@property
def names(self):
if self.left is None:
return [self.basename]
if self.left <= self.right:
return [f'{self.basename}[{i}]' for i in range(self.left, self.right + 1)]
else:
return [f'{self.basename}[{i}]' for i in range(self.left, self.right - 1, -1)]
return [f'{self.basename}[{i}]' for i in range(self.left, self.right - 1, -1)]
def __repr__(self):
return f"{self.kind}:{self.basename}[{self.left}:{self.right}]"
@ -57,24 +56,24 @@ class VerilogTransformer(Transformer): @@ -57,24 +56,24 @@ class VerilogTransformer(Transformer):
@staticmethod
def instantiation(args):
return Instantiation(args[0], args[1],
dict([(pin.children[0], pin.children[1]) for pin in args[2:]]))
dict((pin.children[0], pin.children[1]) for pin in args[2:]))
def input(self, args):
for sd in [SignalDeclaration('input', signal) for signal in args]:
self._signal_declarations[sd.basename] = sd
def inout(self, args):
for sd in [SignalDeclaration('input', signal) for signal in args]: # just treat as input
self._signal_declarations[sd.basename] = sd
def output(self, args):
for sd in [SignalDeclaration('output', signal) for signal in args]:
self._signal_declarations[sd.basename] = sd
def wire(self, args):
for sd in [SignalDeclaration('wire', signal) for signal in args]:
self._signal_declarations[sd.basename] = sd
def module(self, args):
c = Circuit(args[0])
positions = {}
@ -85,7 +84,7 @@ class VerilogTransformer(Transformer): @@ -85,7 +84,7 @@ class VerilogTransformer(Transformer):
pos += 1
assignments = []
for stmt in args[2:]: # pass 1: instantiate cells and driven signals
if type(stmt) is Instantiation:
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):
@ -108,7 +107,7 @@ class VerilogTransformer(Transformer): @@ -108,7 +107,7 @@ class VerilogTransformer(Transformer):
assert s1 not in c.forks, 'assignment between two driven signals'
Line(c, c.forks[s2], Node(c, s1))
for stmt in args[2:]: # pass 2: connect signals to readers
if type(stmt) is Instantiation:
if isinstance(stmt, Instantiation):
for p, s in stmt.pins.items():
n = c.cells[stmt.name]
if pin_is_output(n.kind, p): continue
@ -129,14 +128,10 @@ class VerilogTransformer(Transformer): @@ -129,14 +128,10 @@ class VerilogTransformer(Transformer):
return c
@staticmethod
def start(args):
if len(args) == 1:
return args[0]
else:
return args
def start(args): return args[0] if len(args) == 1 else args
grammar = """
GRAMMAR = """
start: (module)*
module: "module" name parameters ";" (_statement)* "endmodule"
parameters: "(" [ name ( "," name )* ] ")"
@ -167,7 +162,7 @@ def parse(text, *, branchforks=False): @@ -167,7 +162,7 @@ def parse(text, *, branchforks=False):
(see :py:func:`kyupy.sdf.DelayFile.annotation`).
: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)).parse(text)
def load(file, *args, **kwargs):

27
src/kyupy/wave_sim.py

@ -37,7 +37,7 @@ class Heap: @@ -37,7 +37,7 @@ class Heap:
if self.chunks[loc] == size:
del self.released[idx]
return loc
elif self.chunks[loc] > size: # split chunk
if self.chunks[loc] > size: # split chunk
chunksize = self.chunks[loc]
self.chunks[loc] = size
self.chunks[loc + size] = chunksize - size
@ -103,7 +103,7 @@ class WaveSim: @@ -103,7 +103,7 @@ class WaveSim:
self.cdata = np.zeros((len(self.interface), sims, 7), dtype='float32')
if type(wavecaps) is int:
if isinstance(wavecaps, int):
wavecaps = [wavecaps] * len(circuit.lines)
intf_wavecap = 4 # sufficient for storing only 1 transition.
@ -117,7 +117,7 @@ class WaveSim: @@ -117,7 +117,7 @@ class WaveSim:
# translate circuit structure into self.ops
ops = []
interface_dict = dict([(n, i) for i, n in enumerate(self.interface)])
interface_dict = dict((n, i) for i, n in enumerate(self.interface))
for n in circuit.topological_order():
if n in interface_dict:
inp_idx = self.ppi_offset + interface_dict[n]
@ -255,8 +255,7 @@ class WaveSim: @@ -255,8 +255,7 @@ class WaveSim:
def __repr__(self):
total_mem = self.state.nbytes + self.sat.nbytes + self.ops.nbytes + self.cdata.nbytes
return f'<WaveSim {self.circuit.name} sims={self.sims} ops={len(self.ops)} ' + \
f'levels={len(self.level_starts)} state_mem={hr_bytes(self.state.nbytes)} ' + \
f'total_mem={hr_bytes(total_mem)}>'
f'levels={len(self.level_starts)} mem={hr_bytes(total_mem)}>'
def get_line_delay(self, line, polarity):
return self.timing[line, 0, polarity]
@ -266,7 +265,7 @@ class WaveSim: @@ -266,7 +265,7 @@ class WaveSim:
def assign(self, vectors, time=0.0, offset=0):
nvectors = min(len(vectors) - offset, self.sims)
for i, node in enumerate(self.interface):
for i in range(len(self.interface)):
ppi_loc = self.sat[self.ppi_offset + i, 0]
if ppi_loc < 0: continue
for p in range(nvectors):
@ -321,7 +320,7 @@ class WaveSim: @@ -321,7 +320,7 @@ class WaveSim:
return self.cdata
def reassign(self, time=0.0):
for i, node in enumerate(self.interface):
for i in range(len(self.interface)):
ppi_loc = self.sat[self.ppi_offset + i, 0]
ppo_loc = self.sat[self.ppo_offset + i, 0]
if ppi_loc < 0 or ppo_loc < 0: continue
@ -386,8 +385,7 @@ class WaveSim: @@ -386,8 +385,7 @@ class WaveSim:
accs[idx] += 1
if s_sqrt2 == 0:
return values
else:
return accs
return accs
def vals(self, line, vector, times, sd=0):
return self._vals(line, vector, times, sd)
@ -464,7 +462,7 @@ def rand_gauss(seed, sd): @@ -464,7 +462,7 @@ def rand_gauss(seed, sd):
return 1.0
while True:
x = -6.0
for i in range(12):
for _ in range(12):
seed = int(0xDEECE66D) * seed + 0xB
x += float((seed >> 8) & 0xffffff) / float(1 << 24)
x *= sd
@ -541,7 +539,7 @@ def wave_eval(op, state, sat, st_idx, line_times, sd=0.0, seed=0): @@ -541,7 +539,7 @@ def wave_eval(op, state, sat, st_idx, line_times, sd=0.0, seed=0):
state[z_mem + z_cur, st_idx] = TMAX_OVL
else:
state[z_mem + z_cur, st_idx] = a if a > b else b # propagate overflow flags by storing biggest TMAX from input
return overflows
@ -565,8 +563,7 @@ class WaveSimCuda(WaveSim): @@ -565,8 +563,7 @@ class WaveSimCuda(WaveSim):
total_mem = self.state.nbytes + self.sat.nbytes + self.ops.nbytes + self.timing.nbytes + \
self.tdata.nbytes + self.cdata.nbytes
return f'<WaveSimCuda {self.circuit.name} sims={self.sims} ops={len(self.ops)} ' + \
f'levels={len(self.level_starts)} state_mem={hr_bytes(self.state.nbytes)} ' + \
f'total_mem={hr_bytes(total_mem)}>'
f'levels={len(self.level_starts)} mem={hr_bytes(total_mem)}>'
def get_line_delay(self, line, polarity):
return self.d_timing[line, 0, polarity]
@ -661,7 +658,7 @@ def reassign_kernel(state, sat, ppi_offset, ppo_offset, cdata, ppi_time): @@ -661,7 +658,7 @@ def reassign_kernel(state, sat, ppi_offset, ppo_offset, cdata, ppi_time):
if vector >= state.shape[-1]: return
if ppo_offset + y >= len(sat): return
ppo, ppo_cap, _ = sat[ppo_offset + y]
ppo, _, _ = sat[ppo_offset + y]
ppi, ppi_cap, _ = sat[ppi_offset + y]
if ppo < 0: return
if ppi < 0: return
@ -771,7 +768,7 @@ def rand_gauss_dev(seed, sd): @@ -771,7 +768,7 @@ def rand_gauss_dev(seed, sd):
return 1.0
while True:
x = -6.0
for i in range(12):
for _ in range(12):
seed = int(0xDEECE66D) * seed + 0xB
x += float((seed >> 8) & 0xffffff) / float(1 << 24)
x *= sd

4
tests/test_bench.py

@ -4,9 +4,9 @@ from kyupy import bench @@ -4,9 +4,9 @@ from kyupy import bench
def test_b01(mydir):
with open(mydir / 'b01.bench', 'r') as f:
c = bench.parse(f.read())
assert 92 == len(c.nodes)
assert len(c.nodes) == 92
c = bench.load(mydir / 'b01.bench')
assert 92 == len(c.nodes)
assert len(c.nodes) == 92
def test_simple():

4
tests/test_logic_sim.py

@ -49,7 +49,7 @@ def test_4v(): @@ -49,7 +49,7 @@ def test_4v():
assert mva[14] == 'X-XXX'
assert mva[15] == 'XXXXX'
def test_8v():
c = bench.parse('input(x, y) output(a, o, n, xo) a=and(x,y) o=or(x,y) n=not(x) xo=xor(x,y)')
s = LogicSim(c, 64, m=8)
@ -71,7 +71,7 @@ def test_8v(): @@ -71,7 +71,7 @@ def test_8v():
for i in range(64):
assert resp[i] == mva[i]
def test_b01(mydir):
c = bench.load(mydir / 'b01.bench')

7
tests/test_stil.py

@ -3,7 +3,6 @@ from kyupy import stil @@ -3,7 +3,6 @@ from kyupy import stil
def test_b14(mydir):
s = stil.load(mydir / 'b14.stuck.stil.gz')
assert 10 == len(s.signal_groups)
assert 1 == len(s.scan_chains)
assert 2163 == len(s.calls)
assert len(s.signal_groups) == 10
assert len(s.scan_chains) == 1
assert len(s.calls) == 2163

42
tests/test_wave_sim.py

@ -19,7 +19,7 @@ def test_wave_eval(): @@ -19,7 +19,7 @@ def test_wave_eval():
line_times[1, 0, 1] = 0.4
line_times[1, 1, 0] = 0.3
line_times[1, 1, 1] = 0.4
state = np.zeros((3*16, 1)) + TMAX # 3 waveforms of capacity 16
state[::16, 0] = 16 # first entry is capacity
a = state[0:16, 0]
@ -31,29 +31,29 @@ def test_wave_eval(): @@ -31,29 +31,29 @@ def test_wave_eval():
sat[2] = 32, 16, 0
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times)
assert TMIN == z[0]
assert z[0] == TMIN
a[0] = TMIN
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times)
assert TMIN == z[0]
assert z[0] == TMIN
b[0] = TMIN
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times)
assert TMAX == z[0]
assert z[0] == TMAX
a[0] = 1 # A _/^^^
b[0] = 2 # B __/^^
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times)
assert TMIN == z[0] # ^^^\___ B -> Z fall delay
assert 2.4 == z[1]
assert TMAX == z[2]
assert z[0] == TMIN # ^^^\___ B -> Z fall delay
assert z[1] == 2.4
assert z[2] == TMAX
a[0] = TMIN # A ^^^^^^
b[0] = TMIN # B ^^^\__
b[1] = 2
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times)
assert 2.3 == z[0] # ___/^^^ B -> Z rise delay
assert TMAX == z[1]
assert z[0] == 2.3 # ___/^^^ B -> Z rise delay
assert z[1] == TMAX
# pos pulse of 0.35 at B -> 0.45 after delays
a[0] = TMIN # A ^^^^^^^^
@ -61,9 +61,9 @@ def test_wave_eval(): @@ -61,9 +61,9 @@ def test_wave_eval():
b[1] = 2 # B ^^\__/^^
b[2] = 2.35
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times)
assert 2.3 == z[0] # __/^^\__
assert 2.75 == z[1]
assert TMAX == z[2]
assert z[0] == 2.3 # __/^^\__
assert z[1] == 2.75
assert z[2] == TMAX
# neg pulse of 0.45 at B -> 0.35 after delays
a[0] = TMIN # A ^^^^^^^^
@ -71,10 +71,10 @@ def test_wave_eval(): @@ -71,10 +71,10 @@ def test_wave_eval():
b[1] = 2.45
b[2] = TMAX
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times)
assert TMIN == z[0] # ^^\__/^^
assert 2.4 == z[1]
assert 2.75 == z[2]
assert TMAX == z[3]
assert z[0] == TMIN # ^^\__/^^
assert z[1] == 2.4
assert z[2] == 2.75
assert z[3] == TMAX
# neg pulse of 0.35 at B -> 0.25 after delays (filtered)
a[0] = TMIN # A ^^^^^^^^
@ -82,8 +82,8 @@ def test_wave_eval(): @@ -82,8 +82,8 @@ def test_wave_eval():
b[1] = 2.35
b[2] = TMAX
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times)
assert TMIN == z[0] # ^^^^^^
assert TMAX == z[1]
assert z[0] == TMIN # ^^^^^^
assert z[1] == TMAX
# pos pulse of 0.25 at B -> 0.35 after delays (filtered)
a[0] = TMIN # A ^^^^^^^^
@ -91,7 +91,7 @@ def test_wave_eval(): @@ -91,7 +91,7 @@ def test_wave_eval():
b[1] = 2 # B ^^\__/^^
b[2] = 2.25
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times)
assert TMAX == z[0] # ______
assert z[0] == TMAX # ______
def compare_to_logic_sim(wsim):
@ -118,7 +118,7 @@ def compare_to_logic_sim(wsim): @@ -118,7 +118,7 @@ def compare_to_logic_sim(wsim):
exp_bp = BPArray(tests_bp)
lsim.capture(exp_bp)
exp = MVArray(exp_bp)
for i in range(8):
exp_str = exp[i].replace('R', '1').replace('F', '0').replace('P', '0').replace('N', '1')
res_str = resp[i].replace('R', '1').replace('F', '0').replace('P', '0').replace('N', '1')

Loading…
Cancel
Save