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:
|
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 __getitem__(self, name): return self.timers[name]
|
||||||
def __repr__(self): return '{' + ', '.join([f'{k}: {v}' for k, v in self.timers.items()]) + '}'
|
def __repr__(self): return '{' + ', '.join([f'{k}: {v}' for k, v in self.timers.items()]) + '}'
|
||||||
def __add__(self, t):
|
def __add__(self, t):
|
||||||
|
|||||||
+19
-3
@@ -356,6 +356,19 @@ class LogicSim2V(sim.SimOps):
|
|||||||
Storage locations are indirectly addressed.
|
Storage locations are indirectly addressed.
|
||||||
Data for line `l` is in `self.c[self.c_locs[l]]`.
|
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)
|
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.
|
"""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 = np.full(self.c.shape[-1], 0, dtype=np.uint8)
|
||||||
fault_mask2[:len(fault_mask)] = fault_mask
|
fault_mask2[:len(fault_mask)] = fault_mask
|
||||||
fault_mask = fault_mask2
|
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):
|
def c_to_s(self):
|
||||||
"""Captures the results of the combinational portion into ``self.s_result``.
|
"""Captures the results of the combinational portion into ``self.s_result``.
|
||||||
@@ -424,9 +437,11 @@ class LogicSim2V(sim.SimOps):
|
|||||||
|
|
||||||
|
|
||||||
@numba.njit
|
@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]:
|
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)]
|
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]
|
if op == sim.BUF1: c[o0]=c[i0]
|
||||||
elif op == sim.INV1: c[o0] = ~c[i0]
|
elif op == sim.INV1: c[o0] = ~c[i0]
|
||||||
elif op == sim.AND2: c[o0] = c[i0] & c[i1]
|
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
|
c[o0] = c[o0] & ~fault_mask
|
||||||
elif fault_model == 1:
|
elif fault_model == 1:
|
||||||
c[o0] = c[o0] | fault_mask
|
c[o0] = c[o0] | fault_mask
|
||||||
else:
|
elif fault_model == 2:
|
||||||
c[o0] = c[o0] ^ fault_mask
|
c[o0] = c[o0] ^ fault_mask
|
||||||
|
c_dirty[o0] = 1
|
||||||
|
|
||||||
|
|
||||||
class LogicSim4V(sim.SimOps):
|
class LogicSim4V(sim.SimOps):
|
||||||
|
|||||||
Reference in new issue
Block a user