FA-88886 / Digital logic simulation / Open access
Output events pending after the last stimulus are lost · case 01
The final output transition is missing whenever it matures after the last input change.
ROOT CAUSE
The event loop ends with the last input change and never drains the pending queue.
VERIFIED REPAIR
Append a far-future sentinel so every pending output event matures before returning.
Unsuccessful approach: A sentinel at the time of the last input only drains events that have already matured.
Case contract
Input [gate, rise_delay, fall_delay, v0, events]; gate is 'buf' or 'not', events are time-sorted [t, v] input changes. Output starts at f(v0) (not reported). Each input change schedules f(v) at t + rise_delay when f(v)==1 else t + fall_delay, and cancels every pending output event (inertial delay). Pending events maturing at or before the next input time are committed first. Report [time, value] only when the output value changes; all pending events are committed after the last input.
Why this case matters
Event-driven simulators filter pulses narrower than a gate delay; getting cancellation, polarity and flushing right determines the waveform.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(*args):
gate, dr, df, v0, events = args
f = (lambda v: 1 - v) if gate == 'not' else (lambda v: v)
out = f(v0)
q = []
res = []
for t, v in events:
while q and q[0][0] <= t:
at, nv = q.pop(0)
if nv != out:
out = nv
res.append([at, nv])
if v is None:
break
q.clear()
nv = f(v)
q.append([t + (dr if nv == 1 else df), nv])
return res
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('pulse shorter than inertial delay is filtered', ['buf', 4, 4, 0, [[10, 1], [12, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [21, 0]]], [[12, 1], [25, 0]]), ('inverter uses output polarity for delay', ['not', 2, 6, 0, [[10, 1], [30, 0]]], [[16, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [10, 0]]], [[12, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[1, 1]]], [[5, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [21, 0]]], [[25, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [41, 1]]], [[15, 1], [20, 0], [46, 1]])], [('pulse shorter than inertial delay is filtered', ['buf', 5, 5, 0, [[10, 1], [13, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [22, 0]]], [[12, 1], [26, 0]]), ('inverter uses output polarity for delay', ['not', 2, 7, 0, [[10, 1], [30, 0]]], [[17, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [11, 0]]], [[13, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[2, 1]]], [[6, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [22, 0]]], [[26, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [42, 1]]], [[15, 1], [20, 0], [47, 1]])], [('pulse shorter than inertial delay is filtered', ['buf', 6, 6, 0, [[10, 1], [14, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [23, 0]]], [[12, 1], [27, 0]]), ('inverter uses output polarity for delay', ['not', 2, 8, 0, [[10, 1], [30, 0]]], [[18, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [12, 0]]], [[14, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[3, 1]]], [[7, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [23, 0]]], [[27, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [43, 1]]], [[15, 1], [20, 0], [48, 1]])], [('pulse shorter than inertial delay is filtered', ['buf', 7, 7, 0, [[10, 1], [15, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [24, 0]]], [[12, 1], [28, 0]]), ('inverter uses output polarity for delay', ['not', 2, 9, 0, [[10, 1], [30, 0]]], [[19, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [13, 0]]], [[15, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[4, 1]]], [[8, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [24, 0]]], [[28, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [44, 1]]], [[15, 1], [20, 0], [49, 1]])], [('pulse shorter than inertial delay is filtered', ['buf', 8, 8, 0, [[10, 1], [16, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [25, 0]]], [[12, 1], [29, 0]]), ('inverter uses output polarity for delay', ['not', 2, 10, 0, [[10, 1], [30, 0]]], [[20, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [14, 0]]], [[16, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[5, 1]]], [[9, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [25, 0]]], [[29, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [45, 1]]], [[15, 1], [20, 0], [50, 1]])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| pulse shorter than inertial delay is filtered | [] | [] | Passed |
| wide pulse passes with rise and fall delays | [[12, 1]] | [[12, 1], [25, 0]] | Failed |
| inverter uses output polarity for delay | [[16, 0]] | [[16, 0], [32, 1]] | Failed |
| redundant input event produces no output edge | [] | [[12, 0]] | Failed |
| final pending event is committed | [] | [[5, 1]] | Failed |
| inverter glitch cancelled | [] | [[25, 1]] | Failed |
| output matures exactly at next input change | [[15, 1], [20, 0]] | [[15, 1], [20, 0], [46, 1]] | Failed |
SHA-256 / a662a64935611bfc13c0da4195c2405f1f284497607ca9940fcde20d1e1d73ce
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(*args):
gate, dr, df, v0, events = args
f = (lambda v: 1 - v) if gate == 'not' else (lambda v: v)
out = f(v0)
q = []
res = []
for t, v in events + [[events[-1][0], None]]:
while q and q[0][0] <= t:
at, nv = q.pop(0)
if nv != out:
out = nv
res.append([at, nv])
if v is None:
break
q.clear()
nv = f(v)
q.append([t + (dr if nv == 1 else df), nv])
return res
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('pulse shorter than inertial delay is filtered', ['buf', 4, 4, 0, [[10, 1], [12, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [21, 0]]], [[12, 1], [25, 0]]), ('inverter uses output polarity for delay', ['not', 2, 6, 0, [[10, 1], [30, 0]]], [[16, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [10, 0]]], [[12, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[1, 1]]], [[5, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [21, 0]]], [[25, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [41, 1]]], [[15, 1], [20, 0], [46, 1]])], [('pulse shorter than inertial delay is filtered', ['buf', 5, 5, 0, [[10, 1], [13, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [22, 0]]], [[12, 1], [26, 0]]), ('inverter uses output polarity for delay', ['not', 2, 7, 0, [[10, 1], [30, 0]]], [[17, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [11, 0]]], [[13, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[2, 1]]], [[6, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [22, 0]]], [[26, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [42, 1]]], [[15, 1], [20, 0], [47, 1]])], [('pulse shorter than inertial delay is filtered', ['buf', 6, 6, 0, [[10, 1], [14, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [23, 0]]], [[12, 1], [27, 0]]), ('inverter uses output polarity for delay', ['not', 2, 8, 0, [[10, 1], [30, 0]]], [[18, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [12, 0]]], [[14, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[3, 1]]], [[7, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [23, 0]]], [[27, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [43, 1]]], [[15, 1], [20, 0], [48, 1]])], [('pulse shorter than inertial delay is filtered', ['buf', 7, 7, 0, [[10, 1], [15, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [24, 0]]], [[12, 1], [28, 0]]), ('inverter uses output polarity for delay', ['not', 2, 9, 0, [[10, 1], [30, 0]]], [[19, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [13, 0]]], [[15, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[4, 1]]], [[8, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [24, 0]]], [[28, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [44, 1]]], [[15, 1], [20, 0], [49, 1]])], [('pulse shorter than inertial delay is filtered', ['buf', 8, 8, 0, [[10, 1], [16, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [25, 0]]], [[12, 1], [29, 0]]), ('inverter uses output polarity for delay', ['not', 2, 10, 0, [[10, 1], [30, 0]]], [[20, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [14, 0]]], [[16, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[5, 1]]], [[9, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [25, 0]]], [[29, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [45, 1]]], [[15, 1], [20, 0], [50, 1]])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| pulse shorter than inertial delay is filtered | [] | [] | Passed |
| wide pulse passes with rise and fall delays | [[12, 1]] | [[12, 1], [25, 0]] | Failed |
| inverter uses output polarity for delay | [[16, 0]] | [[16, 0], [32, 1]] | Failed |
| redundant input event produces no output edge | [] | [[12, 0]] | Failed |
| final pending event is committed | [] | [[5, 1]] | Failed |
| inverter glitch cancelled | [] | [[25, 1]] | Failed |
| output matures exactly at next input change | [[15, 1], [20, 0]] | [[15, 1], [20, 0], [46, 1]] | Failed |
SHA-256 / dfefc22cb90318c0fb9a21b3bc8729d2a72e0758c5d0c4525579548e7369d594
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(*args):
gate, dr, df, v0, events = args
f = (lambda v: 1 - v) if gate == 'not' else (lambda v: v)
out = f(v0)
q = []
res = []
for t, v in events + [[10 ** 9, None]]:
while q and q[0][0] <= t:
at, nv = q.pop(0)
if nv != out:
out = nv
res.append([at, nv])
if v is None:
break
q.clear()
nv = f(v)
q.append([t + (dr if nv == 1 else df), nv])
return res
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('pulse shorter than inertial delay is filtered', ['buf', 4, 4, 0, [[10, 1], [12, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [21, 0]]], [[12, 1], [25, 0]]), ('inverter uses output polarity for delay', ['not', 2, 6, 0, [[10, 1], [30, 0]]], [[16, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [10, 0]]], [[12, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[1, 1]]], [[5, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [21, 0]]], [[25, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [41, 1]]], [[15, 1], [20, 0], [46, 1]])], [('pulse shorter than inertial delay is filtered', ['buf', 5, 5, 0, [[10, 1], [13, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [22, 0]]], [[12, 1], [26, 0]]), ('inverter uses output polarity for delay', ['not', 2, 7, 0, [[10, 1], [30, 0]]], [[17, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [11, 0]]], [[13, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[2, 1]]], [[6, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [22, 0]]], [[26, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [42, 1]]], [[15, 1], [20, 0], [47, 1]])], [('pulse shorter than inertial delay is filtered', ['buf', 6, 6, 0, [[10, 1], [14, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [23, 0]]], [[12, 1], [27, 0]]), ('inverter uses output polarity for delay', ['not', 2, 8, 0, [[10, 1], [30, 0]]], [[18, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [12, 0]]], [[14, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[3, 1]]], [[7, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [23, 0]]], [[27, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [43, 1]]], [[15, 1], [20, 0], [48, 1]])], [('pulse shorter than inertial delay is filtered', ['buf', 7, 7, 0, [[10, 1], [15, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [24, 0]]], [[12, 1], [28, 0]]), ('inverter uses output polarity for delay', ['not', 2, 9, 0, [[10, 1], [30, 0]]], [[19, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [13, 0]]], [[15, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[4, 1]]], [[8, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [24, 0]]], [[28, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [44, 1]]], [[15, 1], [20, 0], [49, 1]])], [('pulse shorter than inertial delay is filtered', ['buf', 8, 8, 0, [[10, 1], [16, 0]]], []), ('wide pulse passes with rise and fall delays', ['buf', 2, 4, 0, [[10, 1], [25, 0]]], [[12, 1], [29, 0]]), ('inverter uses output polarity for delay', ['not', 2, 10, 0, [[10, 1], [30, 0]]], [[20, 0], [32, 1]]), ('redundant input event produces no output edge', ['buf', 1, 2, 1, [[5, 1], [14, 0]]], [[16, 0]]), ('final pending event is committed', ['buf', 4, 4, 0, [[5, 1]]], [[9, 1]]), ('inverter glitch cancelled', ['not', 4, 4, 1, [[10, 0], [12, 1], [25, 0]]], [[29, 1]]), ('output matures exactly at next input change', ['buf', 5, 5, 0, [[10, 1], [15, 0], [45, 1]]], [[15, 1], [20, 0], [50, 1]])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| pulse shorter than inertial delay is filtered | [] | [] | Passed |
| wide pulse passes with rise and fall delays | [[12, 1], [25, 0]] | [[12, 1], [25, 0]] | Passed |
| inverter uses output polarity for delay | [[16, 0], [32, 1]] | [[16, 0], [32, 1]] | Passed |
| redundant input event produces no output edge | [[12, 0]] | [[12, 0]] | Passed |
| final pending event is committed | [[5, 1]] | [[5, 1]] | Passed |
| inverter glitch cancelled | [[25, 1]] | [[25, 1]] | Passed |
| output matures exactly at next input change | [[15, 1], [20, 0], [46, 1]] | [[15, 1], [20, 0], [46, 1]] | Passed |
SHA-256 / 1ebee7a5486716e88dd2c30db51d1a01b4d600a97674fb1d7e90483329d0d274
Verification & scope
A deterministic bounded teaching model of one simulator rule set; the contract is stipulated and is not a claim of conformance to any HDL standard or commercial simulator. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:51:12.290848+00:00.
Case digest / 764f8d65708ba7eebfeada9340595ea155a709feaf56110ccc2230cd8ff82868