docs, fix stil unassigned, fix io_locs for busses
This commit is contained in:
1 parent
947df89434
commit
0968cb451e
6 files changed
+48
-16
No files matched your search
@@ -1,3 +1,5 @@
|
||||
# pip install sphinx sphinx-rtd-theme
|
||||
#
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
|
||||
+27
-1
@@ -291,6 +291,15 @@ class Circuit:
|
||||
|
||||
@property
|
||||
def stats(self):
|
||||
"""Generates a dictionary with the number of all different elements in the circuit.
|
||||
|
||||
The dictionary contains the number of all different kinds of nodes, the number
|
||||
of lines, as well various sums like number of combinational gates, number of
|
||||
primary I/Os, number of sequential elements, and so on.
|
||||
|
||||
The count of regular cells use their `Node.kind` as key, other statistics use
|
||||
dunder-keys like: `__comb__`, `__io__`, `__seq__`, and so on.
|
||||
"""
|
||||
stats = defaultdict(int)
|
||||
stats['__node__'] = len(self.nodes)
|
||||
stats['__cell__'] = len(self.cells)
|
||||
@@ -386,15 +395,31 @@ class Circuit:
|
||||
yield stem, region
|
||||
|
||||
def io_locs(self, prefix):
|
||||
"""Returns the indices of primary I/Os that start with given name prefix.
|
||||
|
||||
The returned values are used to index into the :py:attr:`io_nodes` array.
|
||||
If only one I/O cell matches the given prefix, a single integer is returned.
|
||||
If a bus matches the given prefix, a sorted list of indices is returned.
|
||||
Busses are identified by integers in the cell names following the given prefix.
|
||||
Lists for bus indices are sorted from LSB (e.g. `data[0]`) to MSB (e.g. `data[31]`).
|
||||
If a prefix matches multiple different signals or busses, alphanumerically sorted
|
||||
lists of lists are returned. Therefore, higher-dimensional busses
|
||||
(e.g. `data0[0], data0[1], ...`, `data1[0], data1[1], ...`) are supported as well.
|
||||
"""
|
||||
return self._locs(prefix, list(self.io_nodes))
|
||||
|
||||
def s_locs(self, prefix):
|
||||
"""Returns the indices of I/Os and sequential elements that start with given name prefix.
|
||||
|
||||
The returned values are used to index into the :py:attr:`s_nodes` array.
|
||||
It works the same as :py:attr:`io_locs`. See there for more details.
|
||||
"""
|
||||
return self._locs(prefix, self.s_nodes)
|
||||
|
||||
def _locs(self, prefix, nodes):
|
||||
d_top = dict()
|
||||
for i, n in enumerate(nodes):
|
||||
if m := re.match(fr'({prefix}.*?)((?:\d+[_\[\]])*$)', n.name):
|
||||
if m := re.match(fr'({prefix}.*?)((?:[\d_\[\]])*$)', n.name):
|
||||
path = [m[1]] + [int(v) for v in re.split(r'[_\[\]]+', m[2]) if len(v) > 0]
|
||||
d = d_top
|
||||
for j in path[:-1]:
|
||||
@@ -402,6 +427,7 @@ class Circuit:
|
||||
d = d[j]
|
||||
d[path[-1]] = i
|
||||
|
||||
# sort recursively for multi-dimensional lists.
|
||||
def sorted_values(d): return [sorted_values(v) for k, v in sorted(d.items())] if isinstance(d, dict) else d
|
||||
l = sorted_values(d_top)
|
||||
while isinstance(l, list) and len(l) == 1: l = l[0]
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ Except when bit0 differs from bit1, but bit2 (activity) is 0:
|
||||
* bit0 = 1, bit1 = 0, bit2 = 0 means ``UNKNOWN`` in 4-valued and 8-valued logic.
|
||||
* bit0 = 0, bit1 = 1, bit2 = 0 means ``UNASSIGNED`` in 4-valued and 8-valued logic.
|
||||
|
||||
2-valued logic only considers bit0, but should store logic one as ``ONE=0b011`` for interoerability.
|
||||
2-valued logic only considers bit0, but should store logic one as ``ONE=0b011`` for interoperability.
|
||||
4-valued logic only considers bit0 and bit1.
|
||||
8-valued logic considers all 3 bits.
|
||||
|
||||
|
||||
@@ -46,17 +46,12 @@ class LogicSim(sim.SimOps):
|
||||
"""
|
||||
self.c[self.pippi_c_locs] = self.s[0, self.pippi_s_locs, :self.mdim]
|
||||
|
||||
def c_to_s(self): #, responses, ff_transitions=False):
|
||||
def c_to_s(self):
|
||||
"""Capture the current values at the primary outputs and in the state-elements (flip-flops).
|
||||
|
||||
For primary outputs, the logic value is stored unmodified in the given target array.
|
||||
For flip-flops, the logic value is either stored unmodified (`ff_transitions=False`)
|
||||
or constructed from the previous state and the new state (`ff_transitions=True`).
|
||||
|
||||
:param responses: A bit-parallel storage target for the responses in a compatible shape.
|
||||
:type responses: :py:class:`~kyupy.logic.BPArray`
|
||||
:param ff_transitions: If true, calculate and store the transitions between the previous state
|
||||
(the currently assigned pattern) and the new state.
|
||||
:returns: The given responses object.
|
||||
"""
|
||||
self.s[1, self.poppo_s_locs, :self.mdim] = self.c[self.poppo_c_locs]
|
||||
if self.mdim == 1:
|
||||
|
||||
+11
-3
@@ -95,12 +95,15 @@ class StilFile:
|
||||
tests = np.full((len(interface), len(self.patterns)), logic.UNASSIGNED)
|
||||
for i, p in enumerate(self.patterns):
|
||||
for si_port in self.si_ports.keys():
|
||||
pattern = logic.mv_xor(logic.mvarray(p.load[si_port]), scan_inversions[si_port])
|
||||
pattern = logic.mvarray(p.load[si_port])
|
||||
inversions = np.choose((pattern == logic.UNASSIGNED) | (pattern == logic.UNKNOWN),
|
||||
[scan_inversions[si_port], logic.ZERO]).astype(np.uint8)
|
||||
np.bitwise_xor(pattern, inversions, out=pattern)
|
||||
tests[scan_maps[si_port], i] = pattern
|
||||
tests[pi_map, i] = logic.mvarray(p.capture['_pi'])
|
||||
return tests
|
||||
|
||||
def tests_loc(self, circuit):
|
||||
def tests_loc(self, circuit, init_filter=None, launch_filter=None):
|
||||
"""Assembles and returns a LoC scan test pattern set for given circuit.
|
||||
|
||||
This function assumes a launch-on-capture (LoC) delay test.
|
||||
@@ -112,9 +115,13 @@ class StilFile:
|
||||
for i, p in enumerate(self.patterns):
|
||||
# init.set_values(i, '0' * len(interface))
|
||||
for si_port in self.si_ports.keys():
|
||||
pattern = logic.mv_xor(logic.mvarray(p.load[si_port]), scan_inversions[si_port])
|
||||
pattern = logic.mvarray(p.load[si_port])
|
||||
inversions = np.choose((pattern == logic.UNASSIGNED) | (pattern == logic.UNKNOWN),
|
||||
[scan_inversions[si_port], logic.ZERO]).astype(np.uint8)
|
||||
np.bitwise_xor(pattern, inversions, out=pattern)
|
||||
init[scan_maps[si_port], i] = pattern
|
||||
init[pi_map, i] = logic.mvarray(p.launch['_pi'] if '_pi' in p.launch else p.capture['_pi'])
|
||||
if init_filter: init = init_filter(init)
|
||||
sim8v = LogicSim(circuit, init.shape[-1], m=8)
|
||||
sim8v.s[0] = logic.mv_to_bp(init)
|
||||
sim8v.s_to_c()
|
||||
@@ -130,6 +137,7 @@ class StilFile:
|
||||
if '_pi' in p.capture and 'P' in p.capture['_pi']:
|
||||
launch[pi_map, i] = logic.mvarray(p.capture['_pi'])
|
||||
launch[po_map, i] = logic.UNASSIGNED
|
||||
if launch_filter: launch = launch_filter(launch)
|
||||
|
||||
return logic.mv_transition(init, launch)
|
||||
|
||||
|
||||
@@ -44,12 +44,13 @@ class WaveSim(sim.SimOps):
|
||||
:param strip_forks: If enabled, the simulator will not evaluate fork nodes explicitly. This saves simulation time
|
||||
by reducing the number of nodes to simulate, but (interconnect) delay annotations of lines read by fork nodes
|
||||
are ignored.
|
||||
:param keep_waveforms: If disabled, memory of intermediate signal waveforms will be re-used. This greatly reduces
|
||||
:param c_reuse: If enabled, memory of intermediate signal waveforms will be re-used. This greatly reduces
|
||||
memory footprint, but intermediate signal waveforms become unaccessible after a propagation.
|
||||
"""
|
||||
def __init__(self, circuit, delays, sims=8, c_caps=16, c_reuse=False, strip_forks=False):
|
||||
super().__init__(circuit, c_caps=c_caps, c_caps_min=4, c_reuse=c_reuse, strip_forks=strip_forks)
|
||||
self.sims = sims
|
||||
if delays.ndim == 3: delays = np.expand_dims(delays, axis=0)
|
||||
self.delays = np.zeros((len(delays), self.c_locs_len, 2, 2), dtype=delays.dtype)
|
||||
self.delays[:, :delays.shape[1]] = delays
|
||||
|
||||
@@ -72,8 +73,8 @@ class WaveSim(sim.SimOps):
|
||||
* ``s[8]`` (P)PO sampled capture value: decided by random sampling according to a given seed.
|
||||
* ``s[9]`` (P)PO sampled capture slack: (capture time - LST) - decided by random sampling according to a given seed.
|
||||
* ``s[10]`` Overflow indicator: If non-zero, some signals in the input cone of this output had more
|
||||
transitions than specified in ``c_caps``. Some transitions have been discarded, the
|
||||
final values in the waveforms are still valid.
|
||||
transitions than specified in ``c_caps``. Some transitions have been discarded, the
|
||||
final values in the waveforms are still valid.
|
||||
"""
|
||||
|
||||
self.simctl_int = np.zeros((2, sims), dtype=np.int32)
|
||||
@@ -128,7 +129,7 @@ class WaveSim(sim.SimOps):
|
||||
self.s[3:, s_loc, vector] = wave_capture_cpu(self.c, c_loc, c_len, vector, time=time, sd=sd, seed=seed)
|
||||
|
||||
def s_ppo_to_ppi(self, time=0.0):
|
||||
"""Re-assigns the last sampled capture to the appropriate pseudo-primary inputs (PPI).
|
||||
"""Re-assigns the last sampled capture to the appropriate pseudo-primary inputs (PPI).
|
||||
Each PPI transition is constructed from its previous final value, the
|
||||
given time, and the sampled captured value of its PPO. Reads and modifies ``self.s``.
|
||||
|
||||
|
||||
Reference in new issue
Block a user