simple incremental sim using dirty flags
This commit is contained in:
1 parent
c90bc89522
commit
53309f9e59
2 files changed
+20
-4
No files matched your search
@@ -111,7 +111,7 @@ class Timer:
|
||||
|
||||
|
||||
class Timers:
|
||||
def __init__(self, t={}): self.timers = defaultdict(Timer) | t
|
||||
def __init__(self, t={}): self.timers: dict[str, Timer] = defaultdict(Timer) | t
|
||||
def __getitem__(self, name): return self.timers[name]
|
||||
def __repr__(self): return '{' + ', '.join([f'{k}: {v}' for k, v in self.timers.items()]) + '}'
|
||||
def __add__(self, t):
|
||||
|
||||
+19
-3
@@ -356,6 +356,19 @@ class LogicSim2V(sim.SimOps):
|
||||
Storage locations are indirectly addressed.
|
||||
Data for line `l` is in `self.c[self.c_locs[l]]`.
|
||||
"""
|
||||
self.c_dirty = np.full(self.c_len, 1, dtype=np.uint8)
|
||||
"""Marker for logic values that have changed recently for use in incremental simulation.
|
||||
|
||||
A node n will be evaluated by `c_prop()` if and only if at least one of its inputs is marked dirty (`c_dirty[c_locs[n.ins[i]]] == 1`).
|
||||
If a node is evaluated, its output is marked dirty.
|
||||
By default, this array is all-1, therefore every node is evaluated every time by `c_prop()`.
|
||||
Enable incremental simulation by setting this array to all-0, change signal values in `c` and set `c_dirty` to 1 for all changed signals.
|
||||
Next call to `c_prop()` will only evaluate nodes that read from the changed signals.
|
||||
To restore the original simulation state, revert the signal value changes in `c`, and call `c_prop()` again.
|
||||
Caveats:
|
||||
- Injected changes that are located downstream of other changes will have no effect.
|
||||
- Only works with `c_reuse=False` (default).
|
||||
"""
|
||||
self.s_assign = np.zeros((self.s_len, self.sims), dtype=np.uint8)
|
||||
"""Logic values assigned to the ports and flip-flops of the circuit.
|
||||
|
||||
@@ -390,7 +403,7 @@ class LogicSim2V(sim.SimOps):
|
||||
fault_mask2 = np.full(self.c.shape[-1], 0, dtype=np.uint8)
|
||||
fault_mask2[:len(fault_mask)] = fault_mask
|
||||
fault_mask = fault_mask2
|
||||
c_prop_2v_cpu(self.ops, self.c_locs, self.c, int(fault_line), fault_mask, int(fault_model))
|
||||
c_prop_2v_cpu(self.ops, self.c_locs, self.c, self.c_dirty, int(fault_line), fault_mask, int(fault_model))
|
||||
|
||||
def c_to_s(self):
|
||||
"""Captures the results of the combinational portion into ``self.s_result``.
|
||||
@@ -424,9 +437,11 @@ class LogicSim2V(sim.SimOps):
|
||||
|
||||
|
||||
@numba.njit
|
||||
def c_prop_2v_cpu(ops, c_locs, c, fault_line, fault_mask, fault_model):
|
||||
def c_prop_2v_cpu(ops, c_locs, c, c_dirty, fault_line, fault_mask, fault_model):
|
||||
for op, o0l, i0l, i1l, i2l, i3l in ops[:,:6]:
|
||||
o0, i0, i1, i2, i3 = [c_locs[x] for x in (o0l, i0l, i1l, i2l, i3l)]
|
||||
if fault_line < 0 or o0l != fault_line: # fault injection forces node evaluation
|
||||
if not (c_dirty[i0] | c_dirty[i1] | c_dirty[i2] | c_dirty[i3]): continue
|
||||
if op == sim.BUF1: c[o0]=c[i0]
|
||||
elif op == sim.INV1: c[o0] = ~c[i0]
|
||||
elif op == sim.AND2: c[o0] = c[i0] & c[i1]
|
||||
@@ -466,8 +481,9 @@ def c_prop_2v_cpu(ops, c_locs, c, fault_line, fault_mask, fault_model):
|
||||
c[o0] = c[o0] & ~fault_mask
|
||||
elif fault_model == 1:
|
||||
c[o0] = c[o0] | fault_mask
|
||||
else:
|
||||
elif fault_model == 2:
|
||||
c[o0] = c[o0] ^ fault_mask
|
||||
c_dirty[o0] = 1
|
||||
|
||||
|
||||
class LogicSim4V(sim.SimOps):
|
||||
|
||||
Reference in new issue
Block a user