de-lint and repr improvements
This commit is contained in:
1 parent
c12a30328c
commit
ff4de6d782
14 files changed
+114
-126
No files matched your search
@@ -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:
|
||||
outer = self
|
||||
|
||||
def make_launcher(func):
|
||||
class Launcher(object):
|
||||
class Launcher:
|
||||
def __init__(self, funcc):
|
||||
self.func = funcc
|
||||
|
||||
|
||||
+6
-6
@@ -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):
|
||||
[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):
|
||||
: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):
|
||||
|
||||
@@ -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:
|
||||
"""
|
||||
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:
|
||||
"""
|
||||
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:
|
||||
|
||||
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:
|
||||
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.
|
||||
"""
|
||||
|
||||
+3
-3
@@ -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:
|
||||
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:
|
||||
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
|
||||
@@ -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')
|
||||
|
||||
+9
-9
@@ -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):
|
||||
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):
|
||||
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):
|
||||
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)
|
||||
|
||||
+10
-14
@@ -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:
|
||||
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:
|
||||
|
||||
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:
|
||||
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):
|
||||
return DelayFile(name, cells)
|
||||
|
||||
|
||||
grammar = r"""
|
||||
GRAMMAR = r"""
|
||||
start: "(DELAYFILE" ( "(SDFVERSION" _NOB ")"
|
||||
| "(DESIGN" "\"" NAME "\"" ")"
|
||||
| "(DATE" _NOB ")"
|
||||
@@ -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):
|
||||
|
||||
+17
-17
@@ -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:
|
||||
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:
|
||||
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:
|
||||
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):
|
||||
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):
|
||||
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"""
|
||||
|
||||
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):
|
||||
|
||||
+15
-20
@@ -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:
|
||||
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):
|
||||
@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):
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
(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):
|
||||
|
||||
+12
-15
@@ -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:
|
||||
|
||||
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:
|
||||
|
||||
# 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:
|
||||
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:
|
||||
|
||||
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:
|
||||
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:
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
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
|
||||
|
||||
+2
-2
@@ -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():
|
||||
|
||||
@@ -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():
|
||||
|
||||
for i in range(64):
|
||||
assert resp[i] == mva[i]
|
||||
|
||||
|
||||
|
||||
def test_b01(mydir):
|
||||
c = bench.load(mydir / 'b01.bench')
|
||||
|
||||
+3
-4
@@ -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
|
||||
+21
-21
@@ -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():
|
||||
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():
|
||||
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():
|
||||
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():
|
||||
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():
|
||||
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):
|
||||
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')
|
||||
|
||||
Reference in new issue
Block a user