An erratum that changes nothing is tuition unpaid: the next chip repeats the bug, pays the workaround cost again, and adds its own entries beside it. The loop closes only when each erratum becomes a rule the next chip cannot forget: a design requirement, a checklist row, or a verification test that fails if the bug returns. This lesson runs the loop for the NanoSoC errata and states what the next chip inherits. Its one job is the feedback; it closes the section and the course's signoff story.
Each erratum maps to one of three inheritances. Design rules change the RTL contract: every new status register uses set-wins write-1-to-clear, every control write preserves unrelated enables, every job-start clears all terminal flags. Checklist rows change the integration review: the driver-rule audit joins the evidence matrix, the spare-select tie-off audit joins the ECO review, the errata sheet ships with the headers. Verification tests change the regression: the error-then-success sequence, the clear-against-event race, and the start-while-busy case become permanent top-level tests that fail if the behaviour returns. The script below counts the NanoSoC loop: four sources (ERR-001, ERR-004, the clear-versus-set race and the gated-clock hang) converted into seven inherited items, three rules, two tests and two checklist rows, none left as prose advice.
# The feedback loop: every erratum becomes a rule, a test or a
# checklist row, each with an owner. Items are illustrative.
errata = ["ERR-001", "ERR-004"]
loop = [ # source, kind, what the next chip inherits, owner
("ERR-001", "checklist", "driver-rule audit in evidence matrix", "integrator"),
("ERR-004", "rule", "job-start clears all terminal flags", "rtl owner"),
("ERR-004", "test", "error-then-success sequence permanent", "verification owner"),
("ERR-004", "rule", "control writes preserve enables", "rtl owner"),
("W1C-race", "rule", "set-wins W1C on all new status bits", "rtl owner"),
("W1C-race", "test", "clear-against-event race test", "verification owner"),
("gated-clock", "checklist", "bridge-watchdog and busy-guard proof with every gating change", "integrator"),
]
def audit(loop, errata):
bad = []
for src, kind, text, owner in loop:
if kind not in ("rule", "test", "checklist"):
bad.append((src, "kind"))
if not owner:
bad.append((src, "no owner"))
sources = {item[0] for item in loop}
for e in errata:
if e not in sources:
bad.append((e, "never inherited"))
return bad
assert audit(loop, errata) == []
count = {k: sum(1 for item in loop if item[1] == k)
for k in ("rule", "test", "checklist")}
assert count == {"rule": 3, "test": 2, "checklist": 2}, count
assert len(loop) == 7
# the audit must be able to fail: an unowned item and an unlooped erratum
assert audit(loop + [("ERR-004", "rule", "x", "")], errata) == [("ERR-004", "no owner")]
assert audit(loop, errata + ["ERR-007"]) == [("ERR-007", "never inherited")]
print("PASS: 7 inherited items, 3 rules, 2 tests, 2 checklist rows, every erratum covered")The next chip's plan quotes the inherited items by identifier: which rules, which tests, which rows.
No erratum closes with prose advice alone: advice without an owner and a test is a wish.
The escape-rate table improves because the granting bar references these rules, not because the count was reset.
At the next chip's first integration review, run the inherited tests against the new RTL before anything else: they are the cheapest failures the project will ever find. Any inherited test that cannot run on the new design is itself an erratum in the loop, and gets a rule that tests stay portable. The memory-map contract lessons carry the same message for headers and decode.
# not-run: the loop card pinned to the next kickoff wall
every erratum -> one rule, one test, or one checklist row, with an owner
ERR-004 -> start clears all flags; error-then-success test permanent
W1C-race -> set-wins W1C everywhere; clear-against-event test permanent
gated-clock -> bridge-watchdog and busy-guard proof with every clock-gating changeYes: the ECO fixes this chip, while the rule, test or row stops the next one. The silicon plan and the loop entry are different fields, and both must be filled.