FAILURE MAP
← Case archive

FA-88871 / Digital logic simulation / Open access

Rise or fall delay chosen from the input edge · case 01

An inverter output falls after the rise delay and rises after the fall delay.

Verified by executionVariant 1 · 7 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The delay is selected by the input transition direction rather than by the output value being driven.

THE FAILURE

The delay is selected by the input transition direction rather than by the output value being driven.

Unsuccessful approach: Inverting the polarity test for every gate fixes inverters but breaks buffers.

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 + [[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 v == 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 fixtureActualExpectedOutcome
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[[12, 0], [36, 1]][[16, 0], [32, 1]]Failed
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 / 2845ea9602fc2c76a5d8656c94d15b16c804159b78982e702ce6dca5fe95746c

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 + [[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 (v == 1) != (gate == 'buf') 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 fixtureActualExpectedOutcome
pulse shorter than inertial delay is filtered[][]Passed
wide pulse passes with rise and fall delays[[14, 1], [23, 0]][[12, 1], [25, 0]]Failed
inverter uses output polarity for delay[[12, 0], [36, 1]][[16, 0], [32, 1]]Failed
redundant input event produces no output edge[[11, 0]][[12, 0]]Failed
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 / d76ada32a121bd0620af40176943a1054536d213a6f0be27a2573ee274895269

HELD IN THE MEMBER ARCHIVE

The verified repair and its recorded checks are member-only.

This mechanism has 7 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.

Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.

Member access is invitation-based. Sign in with your invited account to inspect the repair.

Sign in to the archive ↗

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 / 228a1ac1f249876b3fb5adb11e25f6c0b026b8d469976d3e022432fdd5e791b5