DDR · Module 33
Bring-Up Review Checklist
The first gate whose subject has an order. Nine items asked of a bring-up plan before it runs and a log after it ran, each about whether a step's evidence supports what a later step assumed — including the assumption ledger no plan has.
Five gates reviewed a design. This one reviews a plan, and a plan can be wrong in a way no step in it is wrong.
33.5 §24 named the difference: every gate so far could be run in any order and would find the same defects. Bring-up cannot. A bring-up is a sequence in which each step's evidence is the ground the next step stands on — so the reviewable object is not a step, it is a relation between steps.
What does this step establish, what does the next step assume, and is the second contained in the first?
Chapter 28.7 owns the method. This chapter owns the review of its output. That boundary is unusually sharp here and §3 states it in full, because 28.7 is the most complete chapter this track has on the subject: it owns the staged order, the gate, the one-variable rule, configuration provenance, evidence capture before recovery, minimal reproducer reduction, proving a repair, and the ledger that records all of it.
DERIVED: a project can hold every one of those and still fail this gate, because 28.7's artifacts are things you build and this chapter's items are things you check. A ledger can exist and record the wrong entries. A gate can be defined and establish nothing. An experiment can change one variable by name and four by consequence. Nine items, and each one is a question you ask of a document somebody already wrote.
And one item has no counterpart anywhere in the track. 28.7 §3 supplies the table of what each gate does and does not establish. It does not supply the checker — the thing that takes every stage's establishes set and every later stage's assumes set and reports the difference. §14 is that checker, and in the weak build it finds six assumptions no gate ever established.
1. How To Use This Chapter
Each of the nine review items answers the same eight questions.
| Facet | What it settles |
|---|---|
| Under review | the plan entry, log entry, or gate definition being examined |
| Invariant at risk | which later step's evidence becomes worthless if it is wrong |
| Where it lives | the plan document, or the run log's row |
| Evidence to demand | the record that should already exist |
| What escapes | the investigation that starts from a false premise |
| How DV proves it | an injected failure at a named stage, and a check that the plan detects it there |
| Telemetry | what the log must carry for this item to be checkable |
| Misleading evidence | a bring-up that reached the last stage |
The eighth facet is the same at every gate in this module and here it has a specific and expensive form. DERIVED: a bring-up that completed is the single most reassuring artifact an engineering organisation produces, and completion is compatible with every defect in this chapter. Seven of the nine weak builds below reach the final stage. CURRICULUM-DERIVED from 28.7 §1, whose framing of bring-up as “making the suspect list short by construction” carries the corollary this gate lives on: a bring-up that reached stage 10 with a gate that established nothing has a suspect list that is long and believed to be short.
2. The One-Sentence Model
A bring-up review is sound when every gate's pass criterion is a positive observation rather than the absence of a failure, when the stage order is a topological sort of a declared dependency relation, when every experiment's changed-variable set is the transitive closure rather than the edit count, when every configuration read-back is compared against an independently derived value rather than against what was written, when every recorded observable is classified by whether recovery destroys it, when every reduction step carries its own re-confirmation, when every repair is proved by a revert as well as by a pass, when a failing stage produces a classified result rather than a halt, and when no stage assumes more than some earlier gate established — and “bring-up completed” is bit 0.
3. What This Chapter Owns
This is the narrowest ownership statement in the module, and it needs to be, because 28.7 owns the subject.
| Ground | Owner |
|---|---|
| The staged bring-up order and the gate at each stage | 28.7 §2, 28.7 §3 |
| What each gate establishes and does not establish — the table | 28.7 §3 |
| The one-variable rule, and the compound actions that violate it | 28.7 §4 |
| Configuration provenance as a bring-up artefact | 28.7 §5 |
| Evidence capture before recovery | 28.7 §10 |
| Minimal reproducer reduction during bring-up | 28.7 §11 |
| The bring-up ledger, and testing it | 28.7 §12, 28.7 §14 |
| Proving a repair | 28.7 §15 |
| The dependency structure of the training searches | 21.5 §2 |
| The diagnostic ledger that preserves the earliest reliable evidence | 28.1 |
| Interpreting a failure that has already happened | 28.1, 28.4 |
| Reviewing a bring-up plan before it runs and a log after it ran | this chapter |
Six of this chapter's nine items are reviews of a mechanism 28.7 owns, and in each case the review's contribution is an instrument 28.7 does not build. DERIVED: 28.7 states a rule and gives the reasoning; this chapter builds the thing that checks whether the rule was followed, on an artifact.
| 28.7 owns the rule | This chapter builds the checker |
|---|---|
| §3's establishes / does-not-establish table | §14's unestablished-assumption difference |
| §4's change one variable | §8's transitive closure over a declared dependency map |
| §5's provenance record with a read-back row | §9's independence test on the read-back's comparand |
| §10's capture before recovering | §10's classification of observables by what recovery destroys |
| §11's reduction technique | §11's per-step re-confirmation record |
| §15's proof of a repair | §12's revert test — the negative control |
And three items have no rule in 28.7 to check against, which is why they are stated as rules here. §6's requirement that a gate's criterion be a positive observation; §7's requirement that the order be a topological sort of a declared relation rather than a list; §13's requirement that a failing stage produce a classified result rather than a halt. DERIVED: all three are about the plan's form, and 28.7 is about its content.
4. Teaching-Model Boundary And Source Discipline
Every SystemVerilog block below models a bring-up artifact — a plan, a log, a ledger — rather than hardware. None of them is synthesisable in spirit, and several would be a script in practice.
DERIVED: the models are written in SystemVerilog anyway, and deliberately. A plan expressed as data can be checked by the same properties as a design, and the point this chapter makes about six of nine items is that the checker already exists as a pattern — an exhaustive classification, a transitive closure, an independence test, a positive control. CURRICULUM-DERIVED from 28.7 §14, which already tests its ledger in SystemVerilog: this chapter extends that treatment to the plan.
| Claim class | What it means here | Example below |
|---|---|---|
| Structural | a real mechanism, or a documented rule of this track | 28.7's stages and its gate table; 21.5's dependency order |
| Curriculum-derived | follows from a cited chapter | every pass criterion |
| Derived | computed in this chapter from the models below | every gap figure in §16 |
| Illustrative | a chosen number or scenario that makes a mechanism visible | stage counts, experiment counts, timestamps |
The stage set used throughout is 28.7 §2's, taken as given and not re-derived. DERIVED: this chapter never argues about what the stages should be — it argues about whether a given plan's stages establish what its later stages assume, which is a property of the plan rather than of the stage list. Where a stage is named below it is named to make an example concrete.
No external source was consulted and no network tool was used.
5. Why an Order Can Be Wrong When No Step Is
This is the first gate in the module whose subject has a structure, and the structure is where the defects live.
CURRICULUM-DERIVED from 21.5 §2, whose one-sentence model this chapter inherits at a larger scale: the order is determined by which observable each step requires, not by which direction it trains. And from 28.7 §1: “LOCALIZE BEFORE CORRECTING becomes stage before localizing. A staged system localizes itself.”
DERIVED: if a staged system localizes itself, then a mis-staged system mis-localizes itself — and does so silently, because localisation is an inference from an order rather than a measurement.
| The defect | Every step is | And yet |
|---|---|---|
| a gate that passes on a non-event | individually correct | it establishes nothing, so every later inference is unfounded |
| a stage before its prerequisite | individually correct | it may pass for a reason that will not hold later |
| a compound variable called one | individually correct | the suspect list after a failure is four items, not one |
| a read-back compared to the write | individually correct | it confirms the write path and not the value |
| an observable destroyed by recovery | individually correct | the recorded value is post-recovery and read as pre |
| a reduction with one confirmation | individually correct | the minimal reproducer may be a different failure |
| a repair proved by a pass | individually correct | something else may have changed at the same time |
| a stage that halts on failure | individually correct | one run yields one fact where it could have yielded five |
| an assumption no gate established | individually correct | and there is no single step to point at |
Nine rows, and in every one the word individually is doing the work. DERIVED: each defect is a relation — between a criterion and what it licenses, between two stages, between a change and its consequences, between a value and its comparand, between an observation and a reset, between two reductions, between a repair and its cause, between a failure and the plan, between an assumption and a gate. A review that examines steps finds none of them.
And that is why this chapter's items are asked of documents rather than of hardware. CURRICULUM-DERIVED from 28.7 §3's framing — “a gate is a statement with a stated limit” — and the relation this gate checks is between a statement's limit and the next statement's premise.
6. Review Item 1 — Is This Gate's Pass Criterion an Observation or the Absence of a Failure?
| Facet | Content |
|---|---|
| Under review | every stage gate's pass criterion, as written in the plan |
| Invariant at risk | a gate that passes licenses a specific later assumption |
| Where it lives | the plan's criterion column |
| Evidence to demand | per gate: the observable, its expected value, and what a pass licenses |
| What escapes | a stage passed with nothing established, and ten stages of inference on top |
| How DV proves it | run the stage on a dead system; a non-event criterion still passes |
| Telemetry | the observed value, recorded — not the verdict |
| Misleading evidence | the gate passed, and the plan says passing means the stage is good |
CURRICULUM-DERIVED from 28.7 §3, which owns the establishes table and supplies this item's most expensive instance: a calibration done implemented as !busy reads true from reset, so a stage-2 gate that checks only done lets an entire uncalibrated PHY through.
28.7 records that as a fact about a gate. This item is the rule the fact implies, and it is about the criterion's form rather than its content. DERIVED: a criterion of the form nothing failed is satisfied by a system that did nothing, and a criterion of the form X was observed to equal V is not. The test is mechanical: can the criterion be satisfied by an inert system?
// ROBUST PLAN MODEL: every gate carries an OBSERVABLE, an EXPECTED
// VALUE, and the assumption a pass licenses. A gate with no observable
// cannot be constructed.
package gate_criterion_pkg;
typedef enum int {
K_POSITIVE, // "X was observed to equal V"
K_NONEVENT // "no error was reported" -- the defect
} kind_e;
typedef struct {
int stage;
string observable; // the signal or register READ
int expect_lo; // the value range that constitutes a pass
int expect_hi;
kind_e kind;
string licenses; // what a later stage may now assume
} gate_t;
// ILLUSTRATIVE, over 28.7 section 2's stages, taken as given.
gate_t PLAN[] = '{
'{1, "trcd_reg_readback", 14, 14, K_POSITIVE, "timing counts applied"},
'{2, "calib_committed_val", 1, 4095, K_POSITIVE, "calibration converged"},
'{3, "gate_window_width", 4, 64, K_POSITIVE, "read path has margin"},
'{4, "first_txn_data", 1, 4095, K_POSITIVE, "one address works"},
'{5, "sweep_mismatches", 0, 0, K_POSITIVE, "map self-consistent"},
'{6, "lanes_carrying_data", 64, 64, K_POSITIVE, "every lane carried data"},
'{7, "refresh_deadline_max", 1, 7800, K_POSITIVE, "refresh deadlines met"},
'{8, "idle_gap_txn_ok", 1, 1, K_POSITIVE, "long gaps survive"},
'{9, "freq_bin_margin", 2, 64, K_POSITIVE, "this bin has margin"}
};
endpackage
module gate_criterion (
input logic clk,
input logic rst_n,
input logic eval,
input logic [3:0] stage_id,
input logic [15:0] observed,
input logic error_reported,
output logic gate_pass,
output logic gate_licensed,
output logic [3:0] nonevent_gates,
output logic [3:0] inert_system_passes
);
import gate_criterion_pkg::*;
// The inert-system test, computed once over the plan rather than run.
// A gate whose criterion is a non-event passes on a dead system, and
// the count of such gates is the review finding.
always_comb begin
nonevent_gates = 4'd0;
foreach (PLAN[i]) if (PLAN[i].kind == K_NONEVENT) nonevent_gates++;
// A POSITIVE gate whose expected range INCLUDES the reset value is
// also inert-passable -- the subtler half of the same defect, and
// the reason `expect_lo` is 1 rather than 0 on five rows above.
inert_system_passes = nonevent_gates;
foreach (PLAN[i])
if ((PLAN[i].kind == K_POSITIVE) && (PLAN[i].expect_lo == 0)
&& (PLAN[i].expect_hi != 0))
inert_system_passes++;
end
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
gate_pass <= 1'b0; gate_licensed <= 1'b0;
end else if (eval) begin
// A pass requires the OBSERVED VALUE to be in range. The absence
// of an error is necessary and never sufficient.
gate_pass <= (observed >= 16'(PLAN[stage_id-1].expect_lo))
&& (observed <= 16'(PLAN[stage_id-1].expect_hi))
&& !error_reported;
// The licence is granted only by a positive gate. This is the
// link section 14's ledger consumes.
gate_licensed <= (PLAN[stage_id-1].kind == K_POSITIVE)
&& (observed >= 16'(PLAN[stage_id-1].expect_lo))
&& (observed <= 16'(PLAN[stage_id-1].expect_hi));
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK PLAN: criteria written as non-events.
//
// gate_t PLAN[] = '{
// '{1, "", 0, 0, K_NONEVENT, "timing counts applied"},
// '{2, "calib_done", 1, 1, K_POSITIVE, "calibration converged"},
// '{3, "", 0, 0, K_NONEVENT, "read path has margin"},
// ... };
//
// gate_pass <= !error_reported; // <-- the defect
// gate_licensed <= gate_pass;
//
// CONTRACT VIOLATED: 28.7 section 3's requirement that a gate be a
// statement with a stated limit. A non-event has no limit because it
// has no statement.
//
// WHY IT SURVIVES: every criterion is TRUE of a working system. "No
// errors during the register write phase" is a real property of a good
// bring-up, and a plan full of them describes a successful bring-up
// accurately. It just cannot distinguish one from an inert system.
//
// Note row 2 in particular: it is K_POSITIVE and still inert-passable,
// because `calib_done` implemented as `!busy` reads 1 from reset --
// 28.7 section 3's most expensive row, reproduced exactly.
//
// TRACE (ILLUSTRATIVE, 9 stages, run twice: once on a working system
// and once on a system held in reset with no clock to the PHY):
// working system:
// robust: 9 of 9 pass, 9 of 9 licensed
// weak: 9 of 9 pass, 9 of 9 licensed IDENTICAL
// inert system (PHY in reset):
// robust: stage 1 observed 0, expect 14..14 -> FAIL at stage 1.
// gates licensed: 0
// weak: no errors are reported by a PHY that is not running, so
// every K_NONEVENT gate passes and `calib_done` reads 1:
// 9 of 9 PASS. Bring-up "completes" on a dead PHY.
//
// gap: robust 0 of 9 licensed on an inert system; weak 9 of 9.
// nonevent_gates: robust 0, weak 5. inert_system_passes: robust 0,
// weak 6 (the five non-events plus `calib_done`).The gap is nine gates passing on a PHY that is not running, and the experiment that finds it costs nothing. DERIVED: run the plan against a system held in reset. Every gate that passes is a gate that establishes nothing, and the count is the finding. CURRICULUM-DERIVED from 33.4 §10's positive-control matrix — this is the same idea applied to a plan rather than to a checker, and it is cheaper, because an inert system requires no injection.
The subtler half of the defect is row 2, and it is why positive is not the whole criterion. DERIVED: calib_done is a positive observable with an expected value of 1, and it reads 1 from reset — so a positive criterion whose expected range includes the reset value is inert-passable too. CURRICULUM-DERIVED from 28.4 §1 via 28.7 §3: the pass criterion is therefore positive and excluding the reset value, which is what expect_lo = 1 encodes on five of the robust plan's nine rows.
And the misleading evidence is the strongest available: the plan is a true description of a good bring-up. DERIVED: every non-event criterion in the weak plan is a genuine property of a working system. The plan is not wrong about what success looks like; it is unable to distinguish success from absence, and those are different failures of a document.
7. Review Item 2 — Is the Stage Order a Topological Sort of a Declared Relation, or a List?
| Facet | Content |
|---|---|
| Under review | the plan's stage sequence |
| Invariant at risk | no stage runs before a stage it depends on |
| Where it lives | the plan's order, and the dependency relation it does or does not declare |
| Evidence to demand | the dependency relation, declared separately from the order |
| What escapes | a stage that passes for a reason that will not hold once its prerequisite runs |
| How DV proves it | permute the order and check the plan rejects illegal permutations |
| Telemetry | the relation, and a validation result on the order |
| Misleading evidence | the order is the one that has always worked |
CURRICULUM-DERIVED from 21.5 §2, which owns the principle: the order is determined by which observable each step requires. And from 28.7 §2, which supplies a stage order for a DDR subsystem.
Both give an order. Neither gives a relation — and the review question is which one the plan in front of you has. DERIVED: an order is a sequence somebody wrote; a relation is a set of constraints from which orders can be derived and against which one can be validated. A plan with an order and no relation cannot be checked, cannot be safely modified, and cannot explain why it is what it is.
// ROBUST PLAN MODEL: the relation is declared and the order is
// VALIDATED against it, so the order becomes a derived artifact.
module stage_order_check #(
parameter int NST = 9
)(
input logic clk,
input logic rst_n,
input logic validate,
// the plan's proposed order: order[k] = the stage run k-th
input logic [3:0] order [0:NST-1],
output logic order_legal,
output logic [3:0] violations,
output logic [3:0] first_violating_slot,
output logic relation_declared
);
// DEPENDS[a][b] = 1 means stage a requires stage b to have passed.
// ILLUSTRATIVE over 28.7 section 2's stages. This matrix IS the artifact
// the item demands; its absence is the finding.
localparam bit DEPENDS [1:NST][1:NST] = '{
// 1 2 3 4 5 6 7 8 9
'{ 1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0 }, // 1 registers
'{ 1'b1,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0 }, // 2 calibration
'{ 1'b1,1'b1,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0 }, // 3 training
'{ 1'b1,1'b1,1'b1,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0 }, // 4 first txn
'{ 1'b1,1'b1,1'b1,1'b1,1'b0,1'b0,1'b0,1'b0,1'b0 }, // 5 addr sweep
'{ 1'b1,1'b1,1'b1,1'b1,1'b0,1'b0,1'b0,1'b0,1'b0 }, // 6 all lanes
'{ 1'b1,1'b1,1'b1,1'b1,1'b0,1'b0,1'b0,1'b0,1'b0 }, // 7 refresh
'{ 1'b1,1'b1,1'b1,1'b1,1'b0,1'b0,1'b1,1'b0,1'b0 }, // 8 idle/power
'{ 1'b1,1'b1,1'b1,1'b1,1'b1,1'b1,1'b1,1'b1,1'b0 } // 9 frequency
};
always_comb relation_declared = 1'b1;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
order_legal <= 1'b0; violations <= '0; first_violating_slot <= '0;
end else if (validate) begin
automatic bit done_before [1:NST];
automatic int v = 0;
automatic int firstv = 0;
for (int s = 1; s <= NST; s++) done_before[s] = 1'b0;
for (int k = 0; k < NST; k++) begin
automatic int st = int'(order[k]);
// Every dependency of `st` must already be marked done.
for (int d = 1; d <= NST; d++) begin
if (DEPENDS[st][d] && !done_before[d]) begin
v++;
if (firstv == 0) firstv = k + 1;
end
end
done_before[st] = 1'b1;
end
violations <= 4'(v);
first_violating_slot <= 4'(firstv);
order_legal <= (v == 0);
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK PLAN: an order with no relation.
//
// // bringup_plan.md
// // 1. Program registers
// // 2. Check calibration done
// // 3. First transaction <-- before training
// // 4. Run training
// // 5. Address sweep
// // ...
// // (no dependency matrix; no validation; the order is prose)
//
// CONTRACT VIOLATED: 21.5 section 2 -- the order is determined by which
// observable each step requires. Here it is determined by what is
// quickest to try.
//
// WHY IT SURVIVES: stage 3 before stage 4 OFTEN WORKS. A first
// transaction at a low frequency with default delays can succeed on a
// short channel before any training has run -- and when it does, the
// team has a passing stage 3 and a reason to believe the read path is
// good. The order is then never questioned, because it worked.
//
// TRACE (ILLUSTRATIVE, the order above):
// robust validator on that order:
// slot 3 runs stage 4 (first txn) with stage 3 (training) not done
// -> violations 3 (first txn requires 1, 2, 3; 3 is missing)
// first_violating_slot = 3, order_legal = 0. REJECTED before
// anybody powers a board.
// weak: no validator exists. The plan runs.
//
// and what the passing stage 3 establishes:
// on a SHORT channel: the transaction succeeds untrained, stage 3
// passes, and the team believes the read path has margin. It has
// a default delay that happens to land inside a wide eye.
// on a LONG channel: the transaction fails, and the suspect list
// is the whole read path -- because training, the thing that
// would have made it work, has not run and is not suspected.
//
// gap: 3 order violations, detected in the plan review at zero cost,
// versus an investigation that starts with a false premise. And the
// short-channel case is worse than the long-channel case, because it
// passes.The short-channel case is the finding, and it is worse than the failure. DERIVED: an untrained first transaction that succeeds establishes that a default delay landed inside the eye on this board — and the plan records it as the read path works. CURRICULUM-DERIVED from 28.7 §3's table: one transaction matched establishes “one address, one pattern, one lane set works” and nothing about other addresses — and running it before training narrows even that, to one board.
The relation is the artifact, and its absence is a complete finding on its own. DERIVED: a plan with a declared relation can be validated in milliseconds, permuted safely, and explained; a plan with only an order can do none of the three. And the relation is nine rows of a matrix — CURRICULUM-DERIVED from 21.5 §2, which derives a legal order from a dependency structure for four training searches and therefore establishes the method this item asks a plan to apply at the subsystem scale.
And the misleading evidence has a specific and hard-to-argue form: the order has always worked. DERIVED: an order that has always worked on the boards a team owns is evidence about those boards. CURRICULUM-DERIVED from 22.3 §3: channel properties belong to board and package design, so always worked is a statement whose scope is a set of channels nobody enumerated.
8. Review Item 3 — Is the Changed-Variable Set the Transitive Closure, or the Edit Count?
| Facet | Content |
|---|---|
| Under review | every experiment in the log that claims a single change |
| Invariant at risk | the suspect list after a result has the size the log says it has |
| Where it lives | the log's changed column |
| Evidence to demand | the closure, computed from a declared consequence map |
| What escapes | a four-item suspect list believed to be one item, for the rest of the investigation |
| How DV proves it | change a compound variable and check the closure is reported, not the edit |
| Telemetry | the closure size per experiment |
| Misleading evidence | the log says one field was edited, and one field was edited |
CURRICULUM-DERIVED from 28.7 §4, which owns the rule and its hardest part: “change one thing” is “a goal that requires decomposition rather than discipline alone”, and its table lists six common actions of which “not one is a single variable.”
28.7 gives the table and the technique — change the compound variable, and decompose if the result is surprising. This item builds the thing that makes the closure visible before the result is surprising. DERIVED: a log that records the edit rather than the closure produces a suspect list whose size is wrong in the direction that makes an investigation converge on the wrong thing.
// ROBUST LOG MODEL: the closure is computed from a declared consequence
// map, so "one variable" becomes a measured quantity.
module one_variable_audit #(
parameter int NV = 10
)(
input logic clk,
input logic rst_n,
input logic experiment,
input logic [NV-1:0] edited, // what the operator changed
output logic [NV-1:0] closure, // what actually changed
output logic [3:0] edit_count,
output logic [3:0] closure_count,
output logic is_one_variable,
output logic [7:0] experiments_logged,
output logic [7:0] experiments_truly_single
);
// CONSEQUENCE[a][b] = 1 means changing a also changes b.
// ILLUSTRATIVE, and every row is taken from 28.7 section 4's table.
// 0 frequency 1 timing counts 2 calib validity 3 channel behaviour
// 4 rank count 5 loading 6 termination 7 address space
// 8 address map 9 burst width
localparam bit CONSEQ [0:NV-1][0:NV-1] = '{
'{1'b0,1'b1,1'b1,1'b1,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}, // frequency
'{1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}, // timing counts
'{1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}, // calib validity
'{1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}, // channel
'{1'b0,1'b0,1'b0,1'b0,1'b0,1'b1,1'b1,1'b1,1'b0,1'b0}, // rank count
'{1'b0,1'b0,1'b0,1'b1,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}, // loading
'{1'b0,1'b0,1'b0,1'b1,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}, // termination
'{1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}, // address space
'{1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}, // address map
'{1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0} // burst width
};
function automatic logic [NV-1:0] close(logic [NV-1:0] seed);
logic [NV-1:0] cur = seed;
logic [NV-1:0] nxt;
// Transitive closure by iteration to a fixed point. NV passes is
// sufficient and the bound matters: a single pass misses
// frequency -> channel -> nothing, but rank -> loading -> channel
// needs two.
for (int it = 0; it < NV; it++) begin
nxt = cur;
for (int a = 0; a < NV; a++)
if (cur[a])
for (int b = 0; b < NV; b++)
if (CONSEQ[a][b]) nxt[b] = 1'b1;
if (nxt == cur) break;
cur = nxt;
end
return cur;
endfunction
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
closure <= '0; edit_count <= '0; closure_count <= '0;
is_one_variable <= 1'b0;
experiments_logged <= '0; experiments_truly_single <= '0;
end else if (experiment) begin
automatic logic [NV-1:0] c = close(edited);
closure <= c;
edit_count <= 4'($countones(edited));
closure_count <= 4'($countones(c));
// The definition the item enforces: one variable means the
// CLOSURE has one member, not the edit.
is_one_variable <= ($countones(c) == 1);
experiments_logged <= experiments_logged + 1'b1;
if ($countones(c) == 1)
experiments_truly_single <= experiments_truly_single + 1'b1;
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK LOG: the edit count.
//
// // bringup_log.csv
// // exp,changed,result
// // 14,"freq 1600->1866",fail
// // 15,"rank 1->2",fail
// // 16,"addr map RBC->BRC",pass
// // and the review note: "experiments 14-16 each changed one thing"
//
// edit_count <= $countones(edited);
// is_one_variable <= ($countones(edited) == 1); // <-- the defect
//
// CONTRACT VIOLATED: 28.7 section 4 -- not one of its six listed actions
// is a single variable.
//
// WHY IT SURVIVES: the log is TRUE. One field was edited. The operator
// did change one thing, in the only sense available at a keyboard. The
// error is that the suspect list is derived from the edit, and nothing
// in the log says otherwise.
//
// TRACE (ILLUSTRATIVE, 20 experiments; three shown):
// exp 14, edited = {frequency}
// robust: closure = {frequency, timing counts, calib validity,
// channel behaviour} -> closure_count 4,
// is_one_variable 0
// weak: edit_count 1, is_one_variable 1
// exp 15, edited = {rank count}
// robust: closure = {rank, loading, termination, address space,
// channel behaviour} -> 5, is_one_variable 0
// (channel arrives via loading AND termination -- two
// paths, which is why the closure needs iteration)
// weak: 1
// exp 16, edited = {address map}
// robust: closure = {address map} -> 1, is_one_variable 1. This
// one genuinely IS a single variable.
// weak: 1 AGREE
//
// over 20 experiments:
// robust: experiments_truly_single = 12 of 20
// weak: claimed 20 of 20
//
// gap: 8 experiments whose suspect list is 4 or 5 items and whose log
// says 1. And the investigation that follows exp 14 will compare a
// 1600 run against an 1866 run and attribute the difference to
// frequency, when three other things moved with it.The gap is eight of twenty, and exp 15 shows why the closure needs iteration rather than a lookup. DERIVED: changing the rank count reaches channel behaviour through two paths — loading and termination — so a single-pass consequence lookup finds four members and the fixed point finds five. A consequence map applied once is not a closure, and the difference is exactly the kind of quiet under-count this item exists to catch.
And exp 16 is in the trace deliberately, because an item that flags everything is useless. DERIVED: switching the address map is genuinely one variable by this map, and both builds agree. CURRICULUM-DERIVED from 28.7 §4, whose table lists the address map as changing “which bank each address hits, row-hit rate, bank parallelism” — all consequences for performance and none for correctness, which is why a correctness bring-up's consequence map has an empty row there and a performance investigation's would not. DERIVED: the map is relative to what is being brought up, and the plan must say which.
The pass criterion is the closure size in the log, per experiment. DERIVED: one column, computed rather than typed — and a log that has it makes 28.7's decomposition unnecessary in eight of twenty cases, because the decomposition has already been done.
9. Review Item 4 — Is This Read-Back Compared Against an Independently Derived Value?
| Facet | Content |
|---|---|
| Under review | every configuration read-back in the provenance record |
| Invariant at risk | the read-back's comparand is independent of the write |
| Where it lives | the comparison, not the read |
| Evidence to demand | the derivation chain, and the value it produces, held separately from the write |
| What escapes | a read-back that confirms the access path and says nothing about the value |
| How DV proves it | corrupt the derivation and check the read-back still agrees |
| Telemetry | the derived value, the written value and the read value — three columns |
| Misleading evidence | the read-back matched, which is what a correct configuration looks like |
CURRICULUM-DERIVED from 28.7 §5, which owns configuration provenance as a bring-up artefact and specifies its six links — including both a conversion row with an explicit rounding direction and a readback row — and states stage 1's gate as “every row's readback matches its conversion.”
28.7 specifies the artifact correctly. This item is the review question about how a project implements the comparison — and the defect is that the read-back is compared against the variable the write used rather than against the conversion. DERIVED: those two are the same value in a correct system, which is why the substitution is invisible, and they are the same value in a system whose conversion is wrong, which is why it matters.
// ROBUST PROVENANCE MODEL: the comparand is derived INDEPENDENTLY of
// the write path, from the device figure, in this module.
module config_readback #(
parameter int NROW = 6
)(
input logic clk,
input logic rst_n,
input logic check,
// the device figure and its condition, from the datasheet row
input logic [15:0] spec_ns_x100, // ILLUSTRATIVE: ns * 100
input logic [15:0] spec_min_nck, // the max(nCK, ns) form's nCK part
input logic [15:0] clk_period_x100, // ns * 100
// the value the driver actually wrote, and what the register reads
input logic [15:0] written_value,
input logic [15:0] read_value,
output logic row_ok,
output logic [15:0] derived_value,
output logic write_path_ok,
output logic value_correct,
output logic [3:0] rows_confirmed,
output logic [3:0] rows_write_only
);
// The derivation. 28.7 section 5 requires the rounding DIRECTION to be
// stated, and 28.2 section 10 establishes it: a minimum time requirement
// rounds UP. A ceiling is written explicitly so a reviewer can see it.
function automatic logic [15:0] derive();
logic [31:0] ns_cycles;
// ceil(spec_ns / clk_period), in hundredths to avoid a divide by a
// fraction.
ns_cycles = (32'(spec_ns_x100) + 32'(clk_period_x100) - 32'd1)
/ 32'(clk_period_x100);
// max(nCK, ns) form: the larger of the two constraints binds.
return (ns_cycles > 32'(spec_min_nck)) ? 16'(ns_cycles) : spec_min_nck;
endfunction
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
row_ok <= 1'b0; derived_value <= '0;
write_path_ok <= 1'b0; value_correct <= 1'b0;
rows_confirmed <= '0; rows_write_only <= '0;
end else if (check) begin
automatic logic [15:0] d = derive();
derived_value <= d;
// TWO separate facts, because they answer different questions and
// collapsing them is the item.
write_path_ok <= (read_value == written_value); // the path works
value_correct <= (read_value == d); // the value is right
row_ok <= (read_value == d) && (read_value == written_value);
if ((read_value == d) && (read_value == written_value))
rows_confirmed <= rows_confirmed + 1'b1;
else if (read_value == written_value)
// The path works and the value is wrong: this is the state the
// weak build reports as a pass.
rows_write_only <= rows_write_only + 1'b1;
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK PROVENANCE: the comparand is the write.
//
// // config_check.c
// // for (each row) {
// // write_reg(row.addr, row.value);
// // if (read_reg(row.addr) != row.value) // <-- the defect
// // fail("readback mismatch");
// // }
// // and the provenance table's `conversion` and `readback` columns
// // are both populated from `row.value`.
//
// CONTRACT VIOLATED: 28.7 section 5's stage-1 gate -- the readback must
// match the CONVERSION, not the write.
//
// WHY IT SURVIVES: it catches everything a read-back is usually
// expected to catch -- a wrong address, a locked register, a
// write-only shadow, a bus fault. It is a genuinely useful check. It
// simply cannot see an error in the conversion, and the conversion is
// where 28.2's hardest bugs live.
//
// TRACE (ILLUSTRATIVE, tRCD at two frequencies; spec 13.75 ns,
// min 8 nCK):
// 1600 MT/s, clk_period 1.25 ns:
// correct: ceil(13.75 / 1.25) = 11; max(11, 8) = 11
// the driver's code uses a FLOOR: 13.75 / 1.25 = 11.0 exactly,
// so floor gives 11 too.
// robust: derived 11, written 11, read 11 -> row_ok 1
// weak: read == written -> pass IDENTICAL
// -- 28.2 section 10's point exactly: a floor is invisible wherever the
// division is exact.
// 1866 MT/s, clk_period 1.071 ns:
// correct: ceil(13.75 / 1.071) = ceil(12.83) = 13; max(13, 8) = 13
// the driver's FLOOR gives 12.
// robust: derived 13, written 12, read 12
// -> write_path_ok 1, value_correct 0, row_ok 0. FAIL,
// and it names WHICH of the two facts failed.
// weak: read == written -> PASS. Stage 1's gate is satisfied with
// tRCD programmed one cycle short.
//
// over 6 provenance rows at the higher bin:
// robust: rows_confirmed 2, rows_write_only 4 -> 4 conversions wrong
// weak: 6 of 6 pass
//
// gap: 4 of 6 timing counts are one cycle short and stage 1 passes.
// And the failure that follows is a timing violation at stage 4 or
// later, whose suspect list does not include stage 1 because stage 1
// passed.The gap is four of six timing counts short by one cycle with stage 1 passing, and the mechanism is the one 28.2 §10 already named. DERIVED: the floor and the ceiling agree wherever the division is exact, so a rounding defect is invisible at one frequency bin and appears at the next — and the weak read-back is invisible at every bin, because it never computes either.
The item's contribution is the split into two facts, and the split is what makes the finding actionable. DERIVED: write_path_ok and value_correct answer different questions, and the weak build reports their conjunction as the first one. A failure that reports the path works and the value is wrong points at the derivation; a failure that reports mismatch points at the bus. CURRICULUM-DERIVED from 33.2 §9's denominator-independence item: the same defect shape — a comparand derived from the thing it is supposed to check — relocated from a utilisation register into a bring-up script.
And the cost of the fix is a function, which is the reason this item is in the cheap half of §15's ordering. DERIVED: the derivation is six lines and it is already written down in the provenance table's conversion column — 28.7 §5 requires that column to exist. The finding is almost always that the column exists as documentation and the check uses the variable.
10. Review Item 5 — Which of These Recorded Observables Does Recovery Destroy?
| Facet | Content |
|---|---|
| Under review | every observable in the capture list, against the recovery action taken |
| Invariant at risk | a recorded value was read before anything that changes it |
| Where it lives | the capture list, and the recovery script's first line |
| Evidence to demand | per observable: sticky, volatile, or reset-cleared |
| What escapes | a post-recovery value read as a pre-failure value, for the whole investigation |
| How DV proves it | recover, then read; compare against the pre-recovery capture |
| Telemetry | a per-observable survival class, in the capture list itself |
| Misleading evidence | the capture ran, and it captured everything on the list |
CURRICULUM-DERIVED from 28.7 §10, which owns evidence capture before recovery and names it “the rule most often broken under time pressure.” And from 28.1's diagnostic ledger, which preserves the earliest reliable evidence.
Both own the rule. This item is the classification that tells you whether following the rule was possible for each observable — because “capture before recovery” assumes the capture happened first, and in a real failure some of the list is already gone. DERIVED: an observable cleared by the functional reset that the failure itself triggered was destroyed before any operator acted, so no discipline recovers it — only a design change does.
// ROBUST CAPTURE MODEL: each observable carries a survival class, and
// the ledger reports which recorded values are trustworthy.
package recovery_survival_pkg;
typedef enum int {
S_STICKY, // survives reset; latched on first occurrence
S_VOLATILE, // changes continuously; a read is a sample
S_RESET_CLEARED // destroyed by the reset recovery uses
} surv_e;
typedef struct {
string name;
surv_e surv;
} obs_t;
// ILLUSTRATIVE capture list of twelve observables.
obs_t LIST[] = '{
'{"first_err_code", S_STICKY},
'{"first_err_addr", S_STICKY},
'{"err_count", S_STICKY},
'{"training_bitmap", S_RESET_CLEARED},
'{"committed_delay", S_RESET_CLEARED},
'{"calib_fail_case", S_RESET_CLEARED},
'{"queue_occupancy", S_VOLATILE},
'{"refresh_debt", S_VOLATILE},
'{"bank_open_map", S_VOLATILE},
'{"temp_sensor", S_VOLATILE},
'{"mode_regs", S_STICKY},
'{"phy_lock_status", S_RESET_CLEARED}
};
endpackage
module recovery_survival_map (
input logic clk,
input logic rst_n,
input logic capture_done, // the capture completed
input logic recovery_started,
input logic classify,
output logic [3:0] trustworthy,
output logic [3:0] lost_to_recovery,
output logic [3:0] sampled_only,
output logic capture_preceded_recovery
);
import recovery_survival_pkg::*;
logic captured_first;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
captured_first <= 1'b0; capture_preceded_recovery <= 1'b0;
trustworthy <= '0; lost_to_recovery <= '0; sampled_only <= '0;
end else begin
// The ordering fact, recorded rather than assumed -- 28.7 section 10's
// rule turned into a bit.
if (capture_done && !recovery_started) captured_first <= 1'b1;
capture_preceded_recovery <= captured_first;
if (classify) begin
automatic int t = 0, l = 0, s = 0;
foreach (LIST[i]) begin
case (LIST[i].surv)
// Sticky values are trustworthy whether or not capture won
// the race: that is what sticky MEANS.
S_STICKY: t++;
// Reset-cleared values are trustworthy ONLY if the capture
// preceded recovery. Otherwise the recorded value is the
// post-reset value wearing a pre-failure label.
S_RESET_CLEARED: if (captured_first) t++; else l++;
// Volatile values are a SAMPLE even when captured first.
// They are not lost; they are weaker than they look.
S_VOLATILE: s++;
default: ;
endcase
end
trustworthy <= 4'(t);
lost_to_recovery <= 4'(l);
sampled_only <= 4'(s);
end
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK CAPTURE: one list, no classes.
//
// // capture.sh -- run this when it fails
// // dump_regs > capture.txt # all twelve observables
// // reset_phy # then recover
// // and the ledger records all twelve as "captured at 14:22:07"
//
// CONTRACT VIOLATED: nothing in 28.7 section 10 -- the capture DOES precede
// the recovery in this script. The defect is that the ledger reports
// twelve trustworthy values when four are samples and, in the common
// case where the failure itself triggered a reset, four more are gone.
//
// WHY IT SURVIVES: the script is correct and the discipline was
// followed. Somebody wrote the capture, put it before the recovery,
// and ran it. Every value in capture.txt is a real register read.
//
// TRACE (ILLUSTRATIVE, the twelve observables above):
// case A -- operator-initiated recovery, capture ran first:
// robust: trustworthy 8 (4 sticky + 4 reset-cleared, captured
// first), lost 0, sampled_only 4,
// capture_preceded_recovery 1
// weak: "12 captured"
// gap: 4 volatile values presented as state when they are samples.
// case B -- the failure triggered an automatic PHY reset, and the
// capture ran afterwards:
// robust: captured_first 0 -> trustworthy 4 (sticky only),
// LOST 4, sampled_only 4
// weak: "12 captured" -- and `training_bitmap` reads all zeros,
// which 28.1 section 2 says is consistent with five different
// causes. The investigation now has a bitmap signature
// that is an artefact of the reset.
//
// gap: in case B, 4 of 12 recorded values are post-recovery values
// read as pre-failure state, and one of them is the single most
// misleading signature in the track.Case B is the finding, and the misleading value is the worst one it could have been. DERIVED: an all-zeros training bitmap produced by the recovery reset is indistinguishable from an all-zeros bitmap produced by the failure — CURRICULUM-DERIVED from 28.1 §2, which records that such a bitmap is consistent with “a dead lane, a stuck classifier, a mis-programmed sweep range, an unfinished prerequisite step, and a genuine margin failure” — five causes, one signature, and case B adds a sixth that is not a failure at all.
And the S_VOLATILE class is this item's second contribution, because it is a weakness rather than a loss. DERIVED: queue occupancy captured before recovery is a real, trustworthy read — of one instant. A ledger that lists it beside first_err_code implies both are state, and only one is. CURRICULUM-DERIVED from 30.10 §12's variety 9 — evidence cleared by its own reset — and this item's classification is the artifact that makes variety 9 visible at capture time rather than at analysis time.
The pass criterion is a column, and the review finding is almost always its absence. DERIVED: three classes, twelve rows, and the classification is a property of the design rather than of the failure — so it can be written once, before bring-up, and 28.7 §10's rule then becomes checkable instead of aspirational.
11. Review Item 6 — Does Every Reduction Step Carry Its Own Re-Confirmation?
| Facet | Content |
|---|---|
| Under review | the reduction log for a minimal reproducer |
| Invariant at risk | every intermediate case still reproduces the original phenomenon |
| Where it lives | the reduction log's per-step result column |
| Evidence to demand | one confirmation record per step, with the observed signature |
| What escapes | a minimal reproducer of a different failure, investigated as the original |
| How DV proves it | reduce past the point of reproduction and check the log rejects the step |
| Telemetry | per-step: the change, the result, and the signature observed |
| Misleading evidence | the minimal case fails, and the original failed |
CURRICULUM-DERIVED from 28.7 §11, which owns minimal reproducer reduction applied during bring-up rather than after. 28.7 owns the technique. This item is the review question about the log it produces, and the question is about signature identity rather than about failure.
DERIVED: a reduction is a sequence of changes each of which must preserve the phenomenon, and fails is not the phenomenon — it is a category containing many phenomena. A reduction confirmed only by continued failure can walk from one failure to another without any step looking wrong.
// ROBUST REDUCTION LOG: each step records the signature, and a step
// that changes the signature is REJECTED and backed out.
module reduction_confirmation #(
parameter int MAXSTEP = 12
)(
input logic clk,
input logic rst_n,
input logic step,
input logic [7:0] sig_observed, // the failure's signature
input logic reproduced,
input logic [7:0] baseline_sig, // the ORIGINAL signature
output logic [3:0] steps_accepted,
output logic [3:0] steps_rejected,
output logic [3:0] steps_signature_drift,
output logic chain_intact,
output logic [7:0] current_sig
);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
steps_accepted <= '0; steps_rejected <= '0;
steps_signature_drift <= '0; chain_intact <= 1'b1;
current_sig <= '0;
end else if (step) begin
current_sig <= sig_observed;
if (!reproduced) begin
// Stopped reproducing: back the step out. This is the case
// everybody handles.
steps_rejected <= steps_rejected + 1'b1;
end else if (sig_observed != baseline_sig) begin
// Still fails, DIFFERENT signature. This is the case nobody
// handles, and it is the item.
steps_rejected <= steps_rejected + 1'b1;
steps_signature_drift <= steps_signature_drift + 1'b1;
chain_intact <= 1'b0;
end else begin
steps_accepted <= steps_accepted + 1'b1;
end
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK REDUCTION LOG: confirm at the end.
//
// // reduce.sh
// // remove_requester 3; remove_requester 2; disable_refresh;
// // narrow_addr_range; single_bank; single_lane
// // run_test # and if it still fails, we have a minimal case
// //
// steps_accepted <= steps_accepted + 1; // every step accepted
// chain_intact <= reproduced; // checked once, at the end
//
// CONTRACT VIOLATED: 28.7 section 11 -- reduction during bring-up requires
// confirmation during reduction. The script's logic is sound if
// "fails" identifies the phenomenon, and it does not.
//
// WHY IT SURVIVES: it produces a small failing case, quickly, and a
// small failing case is genuinely valuable. Nobody notices the swap
// because both the original and the final case fail.
//
// TRACE (ILLUSTRATIVE, 8 reduction steps; baseline_sig = 0x41, a
// read-data mismatch on lane 17 under refresh):
// step 1 remove requester 3 repro 1 sig 0x41 -> accept
// step 2 remove requester 2 repro 1 sig 0x41 -> accept
// step 3 disable refresh repro 1 sig 0x08 -> the failure
// still happens, and it is now a TIMING violation with no
// refresh in the picture. Different phenomenon.
// robust: signature drift -> REJECT, back out, chain_intact 0.
// The reduction continues from step 2 with refresh on.
// weak: accept. Refresh is now out of the reproducer, and the
// original failure -- which required refresh -- is gone.
// steps 4-8 reduce the NEW failure: narrow the range, one bank, one
// lane. All reproduce 0x08.
// final: a six-line reproducer that fails 0x08 every time.
//
// robust: steps_accepted 2, steps_rejected 6, signature_drift 1,
// chain_intact 0 -- and it says WHICH step broke the chain
// weak: steps_accepted 8, chain_intact 1, "minimal reproducer found"
//
// gap: the weak build delivers a clean, small, reliably-failing
// reproducer of a failure that is not the one being investigated.
// The original -- a lane-17 mismatch under refresh -- has no
// reproducer at all, and the team believes it has one.The gap is a reproducer of the wrong failure, delivered clean and small, and step 3 is the whole finding. DERIVED: disabling refresh removed the condition the original failure required and exposed a second, independent failure that the same test also detects. Both cases fail. Only one of them is the bug.
And the reason this is worse than a failed reduction is that it succeeds. DERIVED: a reduction that stops reproducing is loud — the step is backed out and the log shows it. A reduction that drifts signature is silent and produces a better artifact: smaller, faster, more reliable. CURRICULUM-DERIVED from 28.7 §1's rule that the first observed error is not necessarily the first causal error — and this item is its reduction-time form: the last observed error is not necessarily the one you started with.
The pass criterion is a signature column, and what counts as a signature is the design decision this item forces. DERIVED: fails is one bit and cannot serve; a signature must carry enough to distinguish phenomena — the error class, the lane or bank, and the condition present. CURRICULUM-DERIVED from 28.1 §2's eleven bitmap signatures, which is exactly such a vocabulary: a project that has adopted 28.1's signature set already has this item's column and needs only to record it per step.
12. Review Item 7 — Was This Repair Proved by a Revert as Well as by a Pass?
| Facet | Content |
|---|---|
| Under review | every claimed repair in the log |
| Invariant at risk | the repair is the cause of the pass |
| Where it lives | the repair's evidence: one run, or three |
| Evidence to demand | the reproducer passing with the fix, failing without it, and a stated mechanism |
| What escapes | a repair that is not the fix, and a real defect still present |
| How DV proves it | revert the change and require the failure to return |
| Telemetry | three results per repair, not one |
| Misleading evidence | it was failing, we changed something, it passes |
CURRICULUM-DERIVED from 28.7 §15, which owns proving a repair against the reproducer. This item adds one experiment that 28.7's proof does not require and that nothing else in the track requires either: the revert.
DERIVED: a reproducer passing with the fix establishes that the system now works. It does not establish that the fix is why — and in a bring-up, where several people change several things, the alternative explanations are numerous and mundane. A board was reseated. A different part was fitted. An unrelated commit landed. The revert is the negative control, and it is the same instrument 33.4 §10 demanded of a checker, applied to a claim.
// ROBUST REPAIR LOG: three facts per repair, and a verdict that
// requires all three.
module repair_proof #(
parameter int NREP = 8
)(
input logic clk,
input logic rst_n,
input logic submit,
input logic repro_passes_with_fix,
input logic repro_fails_without_fix, // the REVERT test
input logic regression_still_passes,
input logic [7:0] mechanism_len, // 0 = no mechanism stated
output logic repair_proved,
output logic [3:0] proved_count,
output logic [3:0] unproved_count,
output logic [3:0] no_revert_count,
output logic [3:0] coincidence_count
);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
repair_proved <= 1'b0; proved_count <= '0; unproved_count <= '0;
no_revert_count <= '0; coincidence_count <= '0;
end else if (submit) begin
// All four, and the revert is not optional.
automatic bit ok = repro_passes_with_fix
&& repro_fails_without_fix
&& regression_still_passes
&& (mechanism_len != 8'd0);
repair_proved <= ok;
if (ok) proved_count <= proved_count + 1'b1;
else unproved_count <= unproved_count + 1'b1;
// The two diagnostic sub-counts, because "unproved" is not
// actionable and these are.
if (!repro_fails_without_fix && repro_passes_with_fix) begin
// Passes with the fix AND passes without it: the fix is not
// the cause. Something else changed.
coincidence_count <= coincidence_count + 1'b1;
end
if (mechanism_len == 8'd0)
no_revert_count <= no_revert_count + 1'b1;
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK REPAIR LOG: one fact.
//
// // bringup_log.csv
// // repair,result
// // "increase tRP by 1", "reproducer passes"
// // "re-run training", "reproducer passes"
// // "disable write CRC", "reproducer passes"
// //
// repair_proved <= repro_passes_with_fix; // <-- the defect
//
// CONTRACT VIOLATED: 28.7 section 15's proof of a repair, weakened to its
// necessary condition.
//
// WHY IT SURVIVES: the reproducer really does pass. Under schedule
// pressure a passing reproducer is the definition of done, and asking
// to break it again on purpose reads as obstruction.
//
// TRACE (ILLUSTRATIVE, 8 repairs submitted during one bring-up):
// repair A "increase tRP by 1"
// with fix: pass. without fix: FAIL. regression: pass.
// mechanism: "tRP was floored; 28.2 section 10 requires ceiling" -> PROVED
// repair B "re-run training"
// with fix: pass. without fix: PASS. -> the failure had already
// stopped reproducing before the repair. A board had been reseated
// that morning.
// robust: coincidence_count++, repair_proved 0
// weak: PROVED. And the real defect -- an intermittent connector
// -- is now closed as "fixed by retraining".
// repair C "disable write CRC"
// with fix: pass. without fix: FAIL. regression: FAIL (CRC
// coverage lost). mechanism: none stated.
// robust: repair_proved 0 -- it is a WORKAROUND, correctly
// classified, and the regression failure is recorded
// weak: PROVED
// repairs D-H: 3 proved, 2 coincidences
//
// robust: proved 5 of 8, coincidences 2, no mechanism 1
// weak: 8 of 8 proved
//
// gap: 3 of 8 repairs are not repairs -- two coincidences and one
// undocumented workaround that costs a regression. And repair B is
// the expensive one: an intermittent connector is now a closed
// ticket, and it will come back.Repair B is the finding, and it is the reason the revert is not pedantry. DERIVED: the reproducer passed without the fix, so the fix explains nothing — and the actual cause, an intermittent connector, is now recorded as resolved. CURRICULUM-DERIVED from 28.7 §1's rule that a passing retry does not explain the first attempt: this is that rule applied one level up, to a passing repair rather than a passing retry.
Repair C is the second-order finding and it is a classification rather than an error. DERIVED: disabling write CRC makes the reproducer pass, fails the regression, and states no mechanism — which is a workaround, and a workaround honestly labelled is a legitimate bring-up action. The defect is not the workaround; it is calling it a repair, because a repair closes an investigation and a workaround does not. CURRICULUM-DERIVED from 22.4, which owns write CRC: its loss is a coverage change with its own consequences, and those belong in the ledger.
The pass criterion is three results and a sentence, and the revert is the cheap one. DERIVED: the revert costs one run of a reproducer that is already minimal — and it is the only one of the four that distinguishes a repair from a coincidence. In this trace it found two of eight.
13. Review Item 8 — Does a Failing Stage Produce a Classified Result, or a Halt?
| Facet | Content |
|---|---|
| Under review | the plan's behaviour when a stage gate fails |
| Invariant at risk | one failing run yields every fact it could have yielded |
| Where it lives | the plan's failure branch — or its absence |
| Evidence to demand | per stage, the defined branch on failure and the facts still collectable |
| What escapes | a run that produced one word — blocked — where it could have produced five facts |
| How DV proves it | fail a middle stage and count the facts the plan still gathers |
| Telemetry | a classified failure record, plus the results of the stages still run |
| Misleading evidence | stopping on failure is careful, and continuing sounds reckless |
CURRICULUM-DERIVED from 28.7 §9, which owns a stage gate failing, and from 28.1 §4's failure-domain split — six domains that a failure must be classified into before it can be investigated.
Both chapters handle a failure that has happened. This item is about the plan's obligation, and it is a form question: does the plan say what to do, or does it end? DERIVED: a plan whose failure behaviour is undefined halts by default, and a halt converts a run into a single bit.
The subtlety is that continuing is not always right, and the item does not say it is. DERIVED: some stages' failures genuinely invalidate everything downstream — that is §14's subject — and the correct branch for those is to stop. The item's requirement is that the plan say which, per stage, and gather the facts that remain collectable either way.
// ROBUST PLAN MODEL: a failure is classified, the facts still available
// are gathered, and the branch is declared per stage.
package failure_as_result_pkg;
// 28.1 section 4's six failure domains, taken as given.
typedef enum int { D_SEARCH, D_OBSERVE, D_CONFIG, D_STALE,
D_ORDER, D_MARGIN } domain_e;
typedef enum int { B_STOP, // downstream evidence would be void
B_CONTINUE, // downstream stages remain valid
B_SKIP_DEPS // skip dependents, run independents
} branch_e;
typedef struct {
int stage;
branch_e on_fail;
int facts_still_collectable;
} stage_policy_t;
// ILLUSTRATIVE, and the branch on each row is a JUDGEMENT the plan
// must record rather than a rule this chapter supplies.
stage_policy_t POLICY[] = '{
'{1, B_STOP, 2}, // wrong timing counts void everything
'{2, B_STOP, 3}, // an uncalibrated PHY voids everything
'{3, B_SKIP_DEPS, 4}, // training failed: 28.1's bitmap is still data
'{4, B_SKIP_DEPS, 3},
'{5, B_CONTINUE, 4}, // map inconsistent: lanes and refresh still valid
'{6, B_CONTINUE, 3},
'{7, B_CONTINUE, 4},
'{8, B_CONTINUE, 2},
'{9, B_CONTINUE, 3}
};
endpackage
module failure_as_result (
input logic clk,
input logic rst_n,
input logic stage_failed,
input logic [3:0] failed_stage,
input logic [2:0] observed_domain,
output logic [2:0] branch_taken,
output logic [3:0] facts_gathered,
output logic classified,
output logic [3:0] stages_still_run
);
import failure_as_result_pkg::*;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
branch_taken <= '0; facts_gathered <= '0;
classified <= 1'b0; stages_still_run <= '0;
end else if (stage_failed) begin
automatic stage_policy_t p = POLICY[failed_stage-1];
// The classification is mandatory. An unclassified failure is
// 28.1's five-causes-one-signature problem by construction.
classified <= (observed_domain <= 3'(D_MARGIN));
branch_taken <= 3'(p.on_fail);
// The facts the failing stage can still yield -- 28.1's bitmap,
// a partial sweep result, a per-lane map -- are gathered whether
// or not the plan continues.
facts_gathered <= 4'(p.facts_still_collectable);
case (p.on_fail)
B_STOP: stages_still_run <= 4'd0;
B_SKIP_DEPS: stages_still_run <= 4'd9 - failed_stage - 4'd1;
default: stages_still_run <= 4'd9 - failed_stage;
endcase
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK PLAN: halt, unclassified.
//
// // run_bringup.sh
// // for stage in 1..9; do
// // run_stage $stage || { echo "BLOCKED at stage $stage"; exit 1; }
// // done
//
// CONTRACT VIOLATED: nothing 28.7 states as a rule. The script is
// careful, conventional, and the safest-looking thing to write.
//
// WHY IT SURVIVES: stopping on failure is correct for stages 1 and 2,
// and those are the stages that fail most often early in a bring-up.
// By the time a stage-5 failure happens, the script's behaviour is
// established practice.
//
// TRACE (ILLUSTRATIVE, stage 5 fails -- an address-map inconsistency):
// robust: classified into D_CONFIG; branch B_CONTINUE;
// facts_gathered 4 (the sweep's mismatch pattern, the first
// mismatching address, the bit position, the stride);
// stages_still_run 4 -> lanes, refresh, idle and frequency
// all execute and all pass.
// Result: the team knows the failure is config-domain, has
// a mismatch pattern, and knows four later stages are clean.
// The suspect list is the address map alone.
// weak: "BLOCKED at stage 5". One fact.
// Result: the suspect list is stages 5 through 9.
//
// gap: 9 facts versus 1, from the same run on the same hardware.
// And the expensive part is not the facts -- it is that the weak
// run's suspect list includes four subsystems that the robust run
// proved clean in the same afternoon.The gap is nine facts against one from the same run, and the expensive half is the suspect list rather than the facts. DERIVED: the robust run proved lanes, refresh, idle behaviour and the frequency bin clean while the address map was still broken — so the suspect list is one item. The weak run's suspect list is five subsystems, and narrowing it will cost another day of the same hardware time.
This is 28.7 §1's thesis measured. CURRICULUM-DERIVED: bring-up is “making the suspect list short by construction”, and a halt is the one plan behaviour that makes it long by construction — it declines the information that would have shortened it.
And the plan's per-stage branch is a judgement this chapter deliberately does not make for you. DERIVED: rows 1 and 2 of the robust policy stop, and stopping is right there — CURRICULUM-DERIVED from 28.7 §3: wrong timing counts or an uncalibrated PHY void every downstream gate's meaning. The item's requirement is that the plan record the branch and its reason per stage, so that a reviewer can disagree with a specific row rather than with a script.
14. Review Item 9 — Does Any Stage Assume More Than Some Earlier Gate Established?
| Facet | Content |
|---|---|
| Under review | the whole plan, as a relation between what gates establish and what stages assume |
| Invariant at risk | every assumption in the plan is licensed by an earlier gate |
| Where it lives | between two rows of the plan — which is why no step review finds it |
| Evidence to demand | two columns: per stage, what it establishes and what it assumes |
| What escapes | an entire bring-up resting on a premise nothing ever checked |
| How DV proves it | compute the difference; every unlicensed assumption is a finding |
| Telemetry | the unestablished-assumption set, published with the plan |
| Misleading evidence | every gate passed, and every stage's own logic is sound |
This is the item 33.5 §24 promised and the one with no counterpart in the track. CURRICULUM-DERIVED from 28.7 §3, which supplies the establishes / does not establish table and states its purpose exactly: a bring-up that reaches stage 10 “needs to know, when something fails, exactly what each earlier gate did and did not establish.”
28.7 supplies the table. It does not supply the difference. DERIVED: the table tells you what each gate establishes; the finding requires comparing that against what each later stage assumes, and the assumption side is not written down anywhere in a normal plan. This item's whole contribution is to require the second column and subtract.
// ROBUST PLAN MODEL: establishes-sets and assumes-sets, and the
// difference computed. The difference is the review's output.
module assumption_ledger #(
parameter int NST = 9,
parameter int NFACT = 12
)(
input logic clk,
input logic rst_n,
input logic audit,
input logic [NST-1:0] gate_passed,
output logic [NFACT-1:0] established,
output logic [NFACT-1:0] unlicensed,
output logic [3:0] unlicensed_count,
output logic [3:0] first_unlicensed_stage,
output logic plan_sound
);
// The twelve facts a DDR bring-up's stages reason about. ILLUSTRATIVE
// set, chosen to cover 28.7 section 3's eight rows plus four the table's
// "does not establish" column implies.
// 0 access path 1 timing counts correct 2 calib started
// 3 calib converged 4 setting committed 5 window is wide
// 6 one address works 7 map self-consistent 8 map matches geometry
// 9 every lane carried data 10 every lane has margin
// 11 refresh deadlines met
localparam bit ESTABLISHES [1:NST][0:NFACT-1] = '{
'{1'b1,1'b1,0,0,0,0,0,0,0,0,0,0}, // 1 registers + provenance
'{0,0,1'b1,1'b1,0,0,0,0,0,0,0,0}, // 2 calibration
'{0,0,0,0,1'b1,0,0,0,0,0,0,0}, // 3 training: COMMITTED, not wide
'{0,0,0,0,0,0,1'b1,0,0,0,0,0}, // 4 first transaction
'{0,0,0,0,0,0,0,1'b1,0,0,0,0}, // 5 sweep: self-consistent only
'{0,0,0,0,0,0,0,0,0,1'b1,0,0}, // 6 lanes: carried data only
'{0,0,0,0,0,0,0,0,0,0,0,1'b1}, // 7 refresh
'{0,0,0,0,0,0,0,0,0,0,0,0}, // 8 idle/power: establishes none
'{0,0,0,0,0,0,0,0,0,0,0,0} // 9 frequency: none beyond itself
};
// What each stage ASSUMES. This is the column a normal plan lacks.
localparam bit ASSUMES [1:NST][0:NFACT-1] = '{
'{0,0,0,0,0,0,0,0,0,0,0,0}, // 1
'{1'b1,1'b1,0,0,0,0,0,0,0,0,0,0}, // 2
'{1'b1,1'b1,1'b1,1'b1,0,0,0,0,0,0,0,0}, // 3
'{1'b1,1'b1,0,1'b1,1'b1,0,0,0,0,0,0,0}, // 4
'{1'b1,1'b1,0,0,1'b1,0,1'b1,0,0,0,0,0}, // 5
'{1'b1,1'b1,0,0,1'b1,0,1'b1,0,0,0,0,0}, // 6
'{1'b1,1'b1,0,0,1'b1,0,1'b1,0,0,0,0,0}, // 7
'{1'b1,1'b1,0,0,1'b1,0,1'b1,0,0,0,0,1'b1}, // 8
// Stage 9 is the interesting row: a frequency sweep assumes MARGIN,
// and no gate establishes margin. That is the finding.
'{1'b1,1'b1,0,0,1'b1,1'b1,1'b1,0,1'b1,1'b1,1'b1,1'b1}
};
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
established <= '0; unlicensed <= '0; unlicensed_count <= '0;
first_unlicensed_stage <= '0; plan_sound <= 1'b0;
end else if (audit) begin
automatic bit [NFACT-1:0] est = '0;
automatic bit [NFACT-1:0] unl = '0;
automatic int cnt = 0;
automatic int firsts = 0;
for (int s = 1; s <= NST; s++) begin
// Before running stage s, check its assumptions against what
// the gates BEFORE it established.
for (int f = 0; f < NFACT; f++) begin
if (ASSUMES[s][f] && !est[f]) begin
unl[f] = 1'b1;
cnt++;
if (firsts == 0) firsts = s;
end
end
// Then add what stage s establishes, but only if its gate passed.
if (gate_passed[s-1])
for (int f = 0; f < NFACT; f++)
if (ESTABLISHES[s][f]) est[f] = 1'b1;
end
established <= est;
unlicensed <= unl;
unlicensed_count <= 4'(cnt);
first_unlicensed_stage <= 4'(firsts);
plan_sound <= (cnt == 0);
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK PLAN: no assumes column.
//
// // bringup_plan.md has an "establishes" note per stage, copied
// // from 28.7 section 3's table, and no "assumes" column at all. The
// // review consists of reading each stage's note and agreeing.
//
// CONTRACT VIOLATED: none stated anywhere. 28.7 section 3 requires the
// establishes column and does not require the other one, because its
// subject is a gate and this item's subject is the relation.
//
// WHY IT SURVIVES: every stage's own reasoning is sound, every gate
// passes, and the establishes notes are correct and cited. There is no
// row to object to. The defect is in a column that does not exist.
//
// TRACE (ILLUSTRATIVE, all nine gates passing):
// robust audit: established after stage 8 =
// {access path, timing counts, calib started, calib converged,
// setting committed, one address works, map self-consistent,
// lanes carried data, refresh deadlines met} -- 9 of 12
// unlicensed, found at stage 9:
// fact 5 window is wide -- 28.1 section 5: a committed
// setting at the centre of a
// one-tap window passes every
// digital check
// fact 8 map matches geometry -- 28.7 section 3: a clean sweep
// establishes self-consistency,
// not agreement with the device
// fact 10 every lane has margin -- 28.7 section 3: lanes carried
// data; margin is not shown
// plus three more that stage 9 assumes and that stages 1-8 establish
// only for the PREVIOUS frequency bin -- 28.4 section 5's staleness.
// unlicensed_count = 6, first_unlicensed_stage = 9, plan_sound = 0
// weak: nine gates, nine passes, plan complete.
//
// gap: six assumptions that no gate established, and three of the six
// are margin -- the quantity 28.1 and 28.7 both say a digital gate
// cannot see. A frequency sweep is exactly the activity that consumes
// margin, so stage 9 is where the plan's unlicensed premises are
// spent.The gap is six unlicensed assumptions and the concentration is the finding: three of the six are margin. DERIVED: every one of stages 1 through 8 establishes a functional fact, and stage 9 — the frequency sweep — is the first stage that consumes margin. CURRICULUM-DERIVED from 28.1 §5 via 28.7 §3: a committed setting at the centre of a one-tap window passes every digital check, so setting committed and window is wide are different facts and only the first has a gate.
And the plan has no row to object to, which is what makes this item structurally different from the other eight. DERIVED: every stage's establishes note is correct and cited; every gate passes; and the defect is a column that does not exist. CURRICULUM-DERIVED from 28.7 §3, which requires the establishes side because its subject is a gate — this item's subject is the relation, and a relation needs both sides.
The remedy is a gate, not a note — and naming it is the item's practical output. DERIVED: three of the six unlicensed facts are margin, and margin has a measurement — 21.4's grid width, 20.5's window figures. So the finding converts into one new stage between 8 and 9 whose gate is a measured window width, which is exactly 33.3 §11's range-adequacy instrument used as a bring-up gate. A review that produces a missing stage has produced more than a verdict.
15. The Review Assembled
Cost-ordered. DERIVED from §19's table. Every item at this gate is answered from a document, so the ordering is by how much of the document has to exist first.
| # | Item | Question, in one line | Cost | What it needs |
|---|---|---|---|---|
| 1 | §6 Gate criteria | Can any gate here be satisfied by an inert system? | minutes | read the criterion column |
| 2 | §7 Order | Is there a dependency relation, separate from the order? | minutes | look for a matrix; absence is the finding |
| 3 | §12 Repair proof | Does any repair record a revert result? | minutes | one column of the log |
| 4 | §13 Failure branch | Does the plan say what to do when a stage fails? | minutes | read the plan's failure section |
| 5 | §9 Read-back comparand | Is the read-back compared to the conversion or to the write? | minutes | read two lines of a script |
| 6 | §10 Recovery survival | Which captured observables does the recovery reset destroy? | hours | a three-class map of the observables |
| 7 | §11 Reduction signatures | Does each reduction step record a signature? | hours | a signature vocabulary |
| 8 | §8 Variable closure | Per experiment, is the closure size recorded? | hours | a declared consequence map |
| 9 | §14 Assumption ledger | Does any stage assume more than an earlier gate established? | days | an assumes column nobody has written |
Five of nine take minutes and all five are answered by reading a column that is either there or is not. DERIVED: a gate criterion that names no observable, an order with no relation, a repair log with no revert column, a plan with no failure section, a read-back compared to its own write. A reviewer with the plan, the log, and twenty minutes finds five of nine findings before touching hardware.
And that ordering inverts the usual intuition about bring-up review, which is worth stating because it changes when the review should happen. DERIVED: items 1, 2, 4 and 9 are answerable before bring-up starts, because their subject is the plan. Items 3, 5, 6, 7 and 8 need the log. CURRICULUM-DERIVED from 28.7 §5, which makes the same argument about provenance: building the record before stage 1's gate is “cheaper and more valuable” than treating it as a debugging afterthought. Four of this chapter's nine items are the same trade — a plan review that costs an hour and cannot be done later.
Item 9 is last and most expensive for one reason: the column it needs does not exist in any plan this chapter has described. DERIVED: the establishes side is 28.7 §3's table and can be copied; the assumes side has to be written, stage by stage, by somebody willing to say out loud what each stage takes for granted. That is the artifact, and writing it is the work.
16. Quantitative Reasoning
| Item | Quantity | Robust | Weak | Gap | Provenance |
|---|---|---|---|---|---|
| §6 | gates licensed on an inert system | 0 of 9 | 9 of 9 | 6 inert-passable criteria | DERIVED, ILLUSTRATIVE plan |
| §7 | order violations detected | 3, before power-on | 0 | a passing stage that proves one board | DERIVED |
| §8 | experiments truly single-variable | 12 of 20 | claimed 20 of 20 | 8, closures of 4 and 5 | DERIVED from 28.7 §4's table |
| §9 | provenance rows with a correct value | 2 of 6 | 6 of 6 "pass" | 4 counts one cycle short | DERIVED, ILLUSTRATIVE bins |
| §10 | recorded values that are trustworthy | 4 of 12 (case B) | claimed 12 | 4 lost, 4 samples | DERIVED |
| §11 | reduction steps preserving the phenomenon | 2 accepted, 1 drift flagged | 8 accepted | a reproducer of a different bug | DERIVED |
| §12 | repairs actually proved | 5 of 8 | 8 of 8 | 2 coincidences, 1 workaround | DERIVED |
| §13 | facts from one failing run | 9 | 1 | suspect list 1 vs 5 subsystems | DERIVED |
| §14 | unlicensed assumptions | 0 | 6 | 3 of the 6 are margin | DERIVED from 28.7 §3, 28.1 §5 |
Sort the nine by what the weak artifact said and this gate's signature appears — it is different from every gate before it.
| Item | The weak artifact recorded | And it was |
|---|---|---|
| §6 | nine gates passed | true |
| §7 | stages 1–5 passed in order | true |
| §8 | one field edited per experiment | true |
| §9 | every read-back matched | true |
| §10 | twelve observables captured | true |
| §11 | eight reduction steps, still failing | true |
| §12 | the reproducer passes with the fix | true |
| §13 | blocked at stage 5 | true |
| §14 | every stage's establishes note is correct | true |
DERIVED: all nine weak artifacts are factually accurate, and that is this gate's defining property. At 33.5's gate the numbers were correct and about the wrong thing; here the records are correct and license the wrong conclusion.
The mechanism is uniform: in every row, the record states a fact and omits its limit. Nine gates passed — of criteria that an inert system satisfies. One field edited — with four consequences. Twelve captured — of which four were destroyed. The reproducer passes — and also passed without the fix. CURRICULUM-DERIVED from 28.7 §3's formulation, which this gate turns into a review rule: “a gate is a statement with a stated limit” — DERIVED: and so is every other bring-up record, which is why nine items reduce to one question about the limit.
And the numbers cluster in a way worth noting: seven of nine gaps are a count that should have been smaller. Nine gates instead of zero, twenty experiments instead of twelve, twelve observables instead of four, eight steps instead of two, eight repairs instead of five. DERIVED: every weak build over-reports the amount of established knowledge, and none of them under-reports it — so a bring-up's recorded confidence is systematically higher than its actual confidence, and the bias has a direction.
17. What the Assertions Prove
// ---- Section 6: gate criteria. The obligation is on the PLAN, so the
// property is over the plan's data rather than over a design's signals.
property p_no_inert_passable_gate;
@(posedge clk) disable iff (!rst_n) inert_system_passes == '0;
endproperty
assert property (p_no_inert_passable_gate)
else $error("a gate can be satisfied by a system that is not running");
property p_licence_requires_a_positive_observation;
@(posedge clk) disable iff (!rst_n)
gate_licensed |-> gate_pass;
endproperty
assert property (p_licence_requires_a_positive_observation)
else $error("a gate granted a licence without passing");
// And the two-sided companion -- 30.3 section 9's variety 8: a plan of
// nothing but refusals satisfies the property above.
property p_working_system_passes;
@(posedge clk) disable iff (!rst_n)
(eval && all_observables_nominal) |=> gate_pass;
endproperty
assert property (p_working_system_passes)
else $error("a gate rejected a nominal system: the criterion is too strict");
// ---- Section 7: stage order.
property p_order_is_topological;
@(posedge clk) disable iff (!rst_n)
(validate && order_legal) |-> (violations == '0);
endproperty
assert property (p_order_is_topological)
else $error("an order was declared legal with dependency violations");
property p_relation_exists;
@(posedge clk) disable iff (!rst_n) relation_declared;
endproperty
assert property (p_relation_exists)
else $error("the plan has an order and no dependency relation");
// ---- Section 8: the closure. The property that a single EDIT does not
// license a single-variable claim.
property p_single_variable_means_closure;
@(posedge clk) disable iff (!rst_n)
is_one_variable |-> (closure_count == 4'd1);
endproperty
assert property (p_single_variable_means_closure)
else $error("an experiment was logged as one variable with a larger closure");
property p_closure_contains_the_edit;
@(posedge clk) disable iff (!rst_n)
experiment |=> ((closure & $past(edited)) == $past(edited));
endproperty
assert property (p_closure_contains_the_edit)
else $error("the closure omits a variable that was edited");
property p_closure_is_a_fixed_point;
@(posedge clk) disable iff (!rst_n)
experiment |=> (closure_count >= edit_count);
endproperty
assert property (p_closure_is_a_fixed_point)
else $error("the closure is smaller than the edit set");
// ---- Section 9: the read-back's comparand. TWO properties, because the
// whole item is that these are different facts.
property p_value_checked_against_derivation;
@(posedge clk) disable iff (!rst_n)
row_ok |-> (read_value == derived_value);
endproperty
assert property (p_value_checked_against_derivation)
else $error("a provenance row passed without matching its conversion");
property p_write_path_and_value_are_separate;
@(posedge clk) disable iff (!rst_n)
(check && (read_value == written_value) && (read_value != derived_value))
|=> (write_path_ok && !value_correct);
endproperty
assert property (p_write_path_and_value_are_separate)
else $error("a wrong value with a working write path was not distinguished");
// ---- Section 10: recovery survival.
property p_reset_cleared_needs_capture_first;
@(posedge clk) disable iff (!rst_n)
(classify && !capture_preceded_recovery) |=> (lost_to_recovery != '0);
endproperty
assert property (p_reset_cleared_needs_capture_first)
else $error("reset-cleared observables were reported trustworthy after recovery");
property p_volatile_is_never_trustworthy_state;
@(posedge clk) disable iff (!rst_n)
classify |=> (trustworthy + lost_to_recovery + sampled_only == 4'd12);
endproperty
assert property (p_volatile_is_never_trustworthy_state)
else $error("the survival classification does not account for every observable");
// ---- Section 11: reduction. The signature, not the failure.
property p_step_accepted_only_on_same_signature;
@(posedge clk) disable iff (!rst_n)
(step && reproduced && (sig_observed == baseline_sig))
|=> (steps_accepted == $past(steps_accepted) + 1'b1);
endproperty
assert property (p_step_accepted_only_on_same_signature)
else $error("a reduction step was accepted with a drifted signature");
property p_signature_drift_breaks_the_chain;
@(posedge clk) disable iff (!rst_n)
(step && reproduced && (sig_observed != baseline_sig)) |=> !chain_intact;
endproperty
assert property (p_signature_drift_breaks_the_chain)
else $error("signature drift did not break the reduction chain");
// ---- Section 12: the repair. The revert is a CONJUNCT, which is the item.
property p_repair_requires_a_revert;
@(posedge clk) disable iff (!rst_n)
repair_proved |-> (repro_fails_without_fix && repro_passes_with_fix
&& regression_still_passes && (mechanism_len != '0));
endproperty
assert property (p_repair_requires_a_revert)
else $error("a repair was proved without all four facts");
property p_coincidence_is_classified;
@(posedge clk) disable iff (!rst_n)
(submit && repro_passes_with_fix && !repro_fails_without_fix)
|=> (coincidence_count == $past(coincidence_count) + 1'b1);
endproperty
assert property (p_coincidence_is_classified)
else $error("a coincidence was not distinguished from a repair");
// ---- Section 13: failure as a result.
property p_failure_is_classified;
@(posedge clk) disable iff (!rst_n)
stage_failed |=> classified;
endproperty
assert property (p_failure_is_classified)
else $error("a stage failed and was not classified into a failure domain");
property p_facts_gathered_on_failure;
@(posedge clk) disable iff (!rst_n)
stage_failed |=> (facts_gathered != '0);
endproperty
assert property (p_facts_gathered_on_failure)
else $error("a failing stage gathered no facts");
property p_stop_only_where_policy_says;
@(posedge clk) disable iff (!rst_n)
(stage_failed && (branch_taken == 3'd0)) |=> (stages_still_run == '0);
endproperty
assert property (p_stop_only_where_policy_says)
else $error("the branch taken does not match the stage's declared policy");
// ---- Section 14: the assumption ledger. The whole-plan property, and the
// only one here whose antecedent is an audit rather than an event.
property p_no_unlicensed_assumption;
@(posedge clk) disable iff (!rst_n)
audit |=> (unlicensed_count == '0);
endproperty
assert property (p_no_unlicensed_assumption)
else $error("a stage assumes a fact no earlier gate established");
property p_established_requires_a_passing_gate;
@(posedge clk) disable iff (!rst_n)
(audit && (gate_passed == '0)) |=> (established == '0);
endproperty
assert property (p_established_requires_a_passing_gate)
else $error("facts were marked established with no gate passing");
// ---- COVERS. Each on the dimension its defect scales with.
// Section 6: the INERT SYSTEM run. The dimension is the system's state,
// and running the plan on working hardware a thousand times never
// reaches it -- 31.2 section 14's coverage-dimension rule.
cover property (@(posedge clk) disable iff (!rst_n)
eval && !all_observables_nominal && gate_pass);
// Section 7: an ILLEGAL permutation offered to the validator. Without
// it, p_order_is_topological is satisfied by never validating.
cover property (@(posedge clk) disable iff (!rst_n)
validate && (violations != '0));
// Section 8: an experiment whose closure EXCEEDS its edit set. A log
// of only atomic changes never reaches it.
cover property (@(posedge clk) disable iff (!rst_n)
experiment && (closure_count > edit_count));
// Section 9: a frequency bin where the division is INEXACT -- 28.2
// section 10's point. At an exact bin floor and ceiling agree and the
// cover is uninformative.
cover property (@(posedge clk) disable iff (!rst_n)
check && (derived_value != written_value));
// Section 10: capture AFTER recovery. The dimension is the recovery's
// trigger -- operator or automatic -- and it belongs to the failure.
cover property (@(posedge clk) disable iff (!rst_n)
classify && !capture_preceded_recovery);
// Section 11: signature DRIFT with continued failure. A reduction that
// either holds or stops never reaches it.
cover property (@(posedge clk) disable iff (!rst_n)
step && reproduced && (sig_observed != baseline_sig));
// Section 12: a repair whose revert PASSES -- the coincidence. A log
// that never reverts cannot produce it.
cover property (@(posedge clk) disable iff (!rst_n)
submit && repro_passes_with_fix && !repro_fails_without_fix);
// Section 13: a failure at a stage whose policy is CONTINUE. A bring-up
// that only ever fails at stages 1 and 2 never reaches it.
cover property (@(posedge clk) disable iff (!rst_n)
stage_failed && (branch_taken == 3'd1));
// Section 14: an audit with EVERY gate passing and unlicensed
// assumptions remaining -- the state the weak plan is in.
cover property (@(posedge clk) disable iff (!rst_n)
audit && (gate_passed == '1) && (unlicensed_count != '0));
// And the positive companion: an audit that finds NONE, so
// p_no_unlicensed_assumption is not satisfied by never auditing.
cover property (@(posedge clk) disable iff (!rst_n)
audit && (unlicensed_count == '0));Reviewed against the twelve varieties, and three are worth recording.
Variety 8 — safety cannot see conservatism — forced p_working_system_passes, and this is the first gate in the module where the conservative direction is the plan's default. DERIVED: p_no_inert_passable_gate is satisfied by a plan whose gates reject everything, and a plan that never passes is not obviously absurd — it looks rigorous. CURRICULUM-DERIVED from 30.3 §9: the two-sided pair is mandatory wherever a one-sided property admits a do-nothing solution.
Variety 6 governs three properties whose antecedents are project activities — validate, submit, audit — and the pattern is now familiar. CURRICULUM-DERIVED from 33.4 §18, which found the same shape: in a project that never validates an order, never reverts a repair, and never audits assumptions, all three properties are green and vacuous. DERIVED: the three covers on those antecedents are the only thing distinguishing the plan is sound from nobody checked, and that is the same finding one gate later.
And variety 12 appears in a new place: p_closure_is_a_fixed_point constrains the mechanism and says nothing about the consequence map's completeness. DERIVED: a CONSEQ matrix of all zeros makes every experiment single-variable and satisfies every property here. CURRICULUM-DERIVED from 33.4 §15: the fix is a bound with a width — here, a requirement that the consequence map contain at least the six rows 28.7 §4 enumerates — and that requirement is a document, exactly as the variety predicts.
18. Mutation Testing
Baseline first: all twenty-one assertions pass and all ten covers are non-zero.
| # | Mutation | Killed by | Survived? |
|---|---|---|---|
| M1 | §6: one gate's kind set to K_NONEVENT | p_no_inert_passable_gate | killed |
| M2 | §6: gate_licensed <= gate_pass | p_no_inert_passable_gate | killed* |
| M3 | §6: every gate's expected range emptied | p_working_system_passes | killed |
| M4 | §7: order_legal <= 1'b1 unconditionally | p_order_is_topological, by one cover | killed |
| M5 | §7: drop the DEPENDS matrix | p_relation_exists | killed |
| M6 | §8: closure computed with one pass | p_single_variable_means_closure, by one cover | killed |
| M7 | §8: closure returns edited unchanged | p_single_variable_means_closure | killed* |
| M8 | §9: row_ok <= (read_value == written_value) | p_value_checked_against_derivation | killed |
| M9 | §9: derivation uses floor instead of ceiling | p_value_checked_against_derivation, by one cover | killed |
| M10 | §10: S_RESET_CLEARED rows counted trustworthy | p_reset_cleared_needs_capture_first | killed |
| M11 | §10: drop S_VOLATILE from the accounting | p_volatile_is_never_trustworthy_state | killed |
| M12 | §11: accept on reproduced alone | p_step_accepted_only_on_same_signature, by one cover | killed |
| M13 | §12: drop the revert conjunct | p_repair_requires_a_revert | killed |
| M14 | §12: mechanism_len defaulted to 1 | nothing | SURVIVES |
| M15 | §13: facts_still_collectable all set to 1 | nothing | SURVIVES |
| M16 | §13: every policy set to B_STOP | nothing | SURVIVES |
| M17 | §14: ASSUMES matrix emptied | nothing | SURVIVES |
| M18 | §14: established seeded to all-ones | p_established_requires_a_passing_gate | killed |
DERIVED: fourteen of eighteen killed, four survived — and the two marked killed* are conditional kills that deserve stating rather than hiding.
Both conditional kills are killed on a realistic plan and unkillable on the robust one, and the reason is the same in each case: the robust artifact does not contain the condition that exposes them. M2 makes a licence follow a pass. On a plan of nine positive gates, pass and licence are the same predicate, so M2 changes nothing and no property can see it; it is caught by p_no_inert_passable_gate the moment a single K_NONEVENT gate exists. DERIVED: that is a finding about the robust plan rather than about the mutation — the pass/licence distinction earns its keep only on a plan that has at least one non-event criterion, which is exactly the plan a review is handed.
M7 is the mirror. Returning edited unchanged satisfies p_closure_is_a_fixed_point trivially, because the closure then equals the edit set. It is caught by p_single_variable_means_closure only on an experiment whose true closure is larger — and the cover on closure_count > edit_count is what guarantees the regression contains one. DERIVED: both rows are the same lesson about mutation harnesses: a mutation that is invisible on the robust artifact is not a coverage gap, it is evidence that the robust artifact is unrepresentative of what will be reviewed.
The four genuine survivors are M14, M15, M16 and M17, and all four are variety 12. A default mechanism string, a uniform fact count, a uniformly conservative branch policy, and an empty assumes matrix. Every mechanism stays correct, every property passes, and the instrument is destroyed in each case.
M17 is the worst of the four and it deserves naming. Emptying the ASSUMES matrix makes unlicensed_count zero and plan_sound true for every plan — DERIVED: the item designed to find unlicensed assumptions reports none when its own input is empty, which is indistinguishable from a sound plan. CURRICULUM-DERIVED from 33.4 §15's variety 12 and 33.5 §18's M18: this is the third gate in a row where the instrument's input is the thing that must be independently established, and the pattern is now a result rather than an observation.
M16 is the interesting one because the mutation makes the plan more conservative. Setting every stage's branch to B_STOP satisfies p_stop_only_where_policy_says perfectly and reduces every failing run to one fact. DERIVED: it is §13's weak build, arrived at by making the policy stricter — CURRICULUM-DERIVED from 30.3 §9's variety 8: safety cannot see conservatism, and here the conservatism is in a document rather than in a timing comparison.
And four mutations are killed only by a cover — M4, M6, M9 and M12. M9's is the sharpest and the most specific to this subject: a floor instead of a ceiling is invisible at any frequency bin where the division is exact, so the cover on derived_value != written_value is what forces an inexact bin into the run. CURRICULUM-DERIVED from 28.2 §10 via 28.7 §5: the dimension is the frequency bin, and bringing up one bin repeatedly never reaches it.
19. Baseline Defects Found Before Mutation
Each of the nine weak artifacts run against the robust property set, before any mutation.
| Item | Weak artifact caught by | At what cost |
|---|---|---|
| §6 | p_no_inert_passable_gate | nothing — count the criteria with no observable |
| §7 | p_relation_exists | nothing — the matrix is absent |
| §8 | p_single_variable_means_closure | a consequence map somebody must write |
| §9 | p_value_checked_against_derivation | nothing — read two lines |
| §10 | p_reset_cleared_needs_capture_first | a survival class per observable |
| §11 | p_step_accepted_only_on_same_signature | a signature vocabulary |
| §12 | p_repair_requires_a_revert | nothing — the column is absent |
| §13 | p_failure_is_classified | nothing — the plan has no branch |
| §14 | p_no_unlicensed_assumption | an assumes column somebody must write |
DERIVED: five of nine are found by noticing that a column is absent, and four need a column to be written first. That is a cleaner split than any other gate in this module, and it is the split that tells a project what to do.
The five absences are a twenty-minute review. The four constructions are the deliverables.
| Item | The artifact to build | Written once, or per run? |
|---|---|---|
| §8 | a consequence map over the configuration space | once — 28.7 §4's table is the seed |
| §10 | a survival class per observable | once — it is a property of the design |
| §11 | a signature vocabulary | once — 28.1 §2's eleven signatures are the seed |
| §14 | an assumes set per stage | once — and 28.7 §3 supplies the other half |
DERIVED: all four are written once, none is per-run, and three of the four have a starting point already in this track. CURRICULUM-DERIVED from 28.7 §4's six compound actions, 28.1 §2's eleven bitmap signatures, and 28.7 §3's eight-row establishes table. So the cost of passing this gate is four documents, and three of them are extensions of tables this curriculum has already built.
Two items need a stimulus rather than a document, and both stimuli are states a bring-up will not produce on purpose.
| Item | The stimulus | Why a normal bring-up never reaches it |
|---|---|---|
| §6 | the plan run against an inert system | nobody runs a bring-up on hardware held in reset |
| §9 | a frequency bin where the division is inexact | the first bin brought up is usually a round one |
DERIVED: §6's is free and nobody does it. CURRICULUM-DERIVED from 33.4 §10's positive-control matrix — an inert-system run is a positive control for a plan, it costs one board-hour, and it is the single highest-yield experiment in this chapter: it found six inert-passable criteria out of nine.
20. Silicon Observability
Bring-up happens on silicon, so this section reads as a diagnosis of the record from the symptom.
| Item | The later symptom | What it says about the plan |
|---|---|---|
| §6 | a failure at stage 7 whose cause is in stage 2's subsystem | a stage-2 gate that established nothing |
| §7 | a stage that passed on one board and fails on the next | a stage run before its prerequisite |
| §8 | an investigation that converges and then un-converges | a suspect list sized from an edit count |
| §9 | a timing violation at the second frequency bin only | a read-back compared against its own write |
| §10 | a training bitmap of all zeros in every capture | an observable destroyed by the recovery reset |
| §11 | a minimal reproducer nobody can connect to the original report | a reduction confirmed by failure alone |
| §12 | a closed defect that returns after three weeks | a repair proved without a revert |
| §13 | a bring-up schedule with long blocked intervals | a plan that halts instead of branching |
| §14 | a system that passes bring-up and fails at the top frequency bin | margin assumed and never established |
Three rows are diagnostic, and each points at one item.
§12: a closed defect that returns. DERIVED: a repair proved by a pass alone closes a ticket without establishing causation, so an intermittent cause is recorded as fixed and recurs on its own schedule. CURRICULUM-DERIVED from 28.7 §1's rule that a passing retry does not explain the first attempt. The recurrence interval is the intermittent cause's interval and has nothing to do with the repair, which is why the pattern is recognisable.
§14: bring-up passes and the top frequency bin fails. DERIVED: every functional gate passed and no gate measured margin, so the plan's unlicensed assumptions are all spent in the one stage that consumes margin. CURRICULUM-DERIVED from 28.1 §5 via 28.7 §3: a committed setting at the centre of a one-tap window passes every digital check. This is the single most predictable escape in this chapter, because the stage ordering makes it arrive last.
§9: a violation at the second bin only. DERIVED: the first bin's division was exact, so floor and ceiling agreed and the provenance check passed — CURRICULUM-DERIVED from 28.2 §10. A defect that appears when a frequency changes and disappears when it changes back is a rounding defect until proven otherwise.
And one row is about a schedule rather than a signal: §13's. DERIVED: a bring-up log with long blocked intervals is evidence about the plan's failure behaviour, not about the hardware — and it is visible to anyone reading the schedule, without any access to the system. That makes it the only item in this chapter whose symptom is observable by a project manager.
21. Common Wrong Answers
-
“Bring-up completed, so the system is good.” Seven of the nine weak artifacts reach the final stage. CURRICULUM-DERIVED from 28.7 §1: bring-up is making the suspect list short by construction, and a completed bring-up with gates that established nothing has a long suspect list believed to be short.
-
“All nine gates passed.” §6: nine gates passed on a PHY held in reset. Five criteria were non-events and a sixth —
calib_done— reads 1 from reset. The test is one question: can this criterion be satisfied by a system that is not running? -
“The gate is positive — it checks that
doneis high.” A positive criterion whose expected value includes the reset value is inert-passable too. CURRICULUM-DERIVED from 28.4 §1 via 28.7 §3:doneas!busyreads true from reset, so the criterion must be positive and exclude the reset value. -
“Our stage order is the one that has always worked.” On the boards you own. §7: a first transaction before training succeeds on a short channel and establishes that a default delay landed inside one board's eye. CURRICULUM-DERIVED from 22.3 §3: channel properties are board design's, so always worked has an unenumerated scope.
-
“We have a documented stage order.” An order is not a relation. DERIVED: a plan with a declared dependency matrix can be validated, permuted and explained; one with only an order can do none of the three — CURRICULUM-DERIVED from 21.5 §2, which derives an order from a relation rather than asserting one.
-
“We changed one thing between runs.” §8: eight of twenty experiments had a closure of four or five. CURRICULUM-DERIVED from 28.7 §4: of six common bring-up actions, “not one is a single variable” — and changing the frequency moves the timing counts, the calibration's validity and the channel with it.
-
“We looked up the consequences in the table.” Once is not a closure. §8's exp 15: the rank count reaches channel behaviour through two paths, so a single-pass lookup finds four members and the fixed point finds five.
-
“The read-back matched, so the configuration is correct.” §9: matched what. CURRICULUM-DERIVED from 28.7 §5: the read-back must match the conversion. Compared against the write, it confirms the access path and cannot see a rounding error.
-
“The timing counts were right at 1600, so the arithmetic is right.” CURRICULUM-DERIVED from 28.2 §10: a floor is invisible wherever the division is exact. §9: four of six counts are one cycle short at the next bin, and stage 1 passes.
-
“We captured everything before recovering.” §10 case B: the failure triggered the reset, so four observables were gone before anyone acted. And
training_bitmapreads all zeros — CURRICULUM-DERIVED from 28.1 §2: a signature consistent with five causes, plus a sixth that is the recovery itself. -
“Queue occupancy is in the capture, so we know the state at failure.” A volatile observable captured before recovery is a real read of one instant. DERIVED: listing it beside a sticky first-error register implies both are state, and only one is.
-
“The minimal reproducer still fails, so it is the same bug.” §11 step 3: disabling refresh removed the condition the original failure needed and exposed a second failure the same test detects. Fails is a category, not a phenomenon.
-
“The reduction gave us a smaller, more reliable case.” Smaller and more reliable is what signature drift produces. DERIVED: a reduction that stops reproducing is loud and gets backed out; one that drifts signature is silent and yields a better-looking artifact.
-
“The reproducer passes with the fix, so the fix works.” §12 repair B: it also passed without the fix. CURRICULUM-DERIVED from 28.7 §1: a passing retry does not explain the first attempt — and a passing repair does not either, without a revert.
-
“Reverting a fix to break the system again is a waste of hardware time.” It is one run of a reproducer that is already minimal, and in §12's trace it found two coincidences in eight repairs. It is the only one of the four facts that distinguishes a repair from a change that happened at the same time.
-
“Disabling write CRC fixed it.” It is a workaround, and the label matters. DERIVED: a repair closes an investigation and a workaround does not — CURRICULUM-DERIVED from 22.4, which owns write CRC: its loss is a coverage change with consequences that belong in the ledger.
-
“Stopping on the first failure is the careful thing to do.” §13: nine facts versus one from the same run, and the robust run proved four subsystems clean while the address map was broken. DERIVED: a halt makes the suspect list long by construction, which is the opposite of the method's purpose.
-
“Then the plan should always continue.” No — rows 1 and 2 of §13's policy stop, and stopping is right there. CURRICULUM-DERIVED from 28.7 §3: wrong timing counts or an uncalibrated PHY void every downstream gate. The requirement is that the plan record the branch and its reason per stage.
-
“Every stage's establishes note is correct and cited.” §14: and six assumptions still have no gate. DERIVED: there is no row to object to, because the defect is a column that does not exist — the assumes side, which 28.7 §3 does not require because its subject is a gate rather than the relation.
-
“Training passed, so the read path has margin.” Training establishes that a setting was committed. CURRICULUM-DERIVED from 28.1 §5 via 28.7 §3: a committed setting at the centre of a one-tap window passes every digital check — and three of §14's six unlicensed assumptions are margin.
-
“The address sweep was clean, so the map is right.” CURRICULUM-DERIVED from 28.7 §3: a clean sweep establishes that the map is self-consistent over that sweep, not that it matches the device's geometry. A consistently wrong map sweeps clean.
-
“We will review the bring-up when it is done.” Four of the nine items are answerable before it starts, and item 9 cannot be answered later — DERIVED: once a bring-up has completed, every unlicensed assumption has been silently confirmed by the completion, and the plan review's finding has been converted into confidence.
22. Self-Check
- A stage gate's criterion reads “no errors during register programming.” State the test that decides whether it establishes anything, and say what the test costs.
- A gate checks that
calib_doneis 1. It is a positive criterion. Why is it still inert-passable, and which chapter owns the mechanism? - A plan lists nine stages in order and has no dependency matrix. Name three things the plan cannot do, and say which one matters most when somebody proposes reordering it.
- A first transaction runs before training and passes. State precisely what it establishes, and say why the passing case is worse than the failing one.
- A log records “exp 14: freq 1600→1866” as one variable. Give the closure, and name the two-path case that makes a single lookup insufficient.
- A bring-up script writes each register then reads it back and compares. What does the comparison establish, what does it not, and at which frequency bin will the gap first appear?
- A capture script runs before the recovery and dumps twelve registers. Classify the twelve, and say which single recorded value is the most misleading and why.
- A reduction log shows eight accepted steps and a final case that fails reliably. Give the one column that is missing, and say what a fails result cannot distinguish.
- A repair's evidence is “the reproducer passes.” Name the three missing facts, and say which one distinguishes a repair from a coincidence.
- A bring-up log reads “BLOCKED at stage 5” for a failing address sweep. How many facts were available from that run, and how large is the suspect list in each case?
- Every gate in a plan passes and every establishes note is correct. Explain how six assumptions can still be unlicensed, and name the three that are margin.
- Four mutations survived this chapter's property set. Group them, name the variety, and say what the third consecutive gate finding it implies about instruments generally.
23. The Residual Risk
What this gate cannot catch, stated plainly — and one limit is now a pattern rather than an observation.
It cannot validate its own inputs. M17 emptied the assumes matrix and the item reported a sound plan; M15 flattened the fact counts; M14 defaulted the mechanism string. DERIVED: every item here consumes a document, and a document that is empty or uniform satisfies every property. CURRICULUM-DERIVED from 33.4 §15 and 33.5 §18: this is the third consecutive gate whose instrument depends on an input that nothing inside engineering establishes, and the chain has not changed — a mechanism by a property, a quantity by a bound, a bound by an objective, and the objective by a requirement.
It cannot supply the judgement in §13's branch policy. Which stages' failures void downstream evidence is a real engineering decision, and this chapter deliberately declines to make it. DERIVED: the item requires only that the decision be recorded per stage with a reason — so a plan with nine wrong branches and nine stated reasons passes item 8, and the review's finding is then about a specific row rather than about the form.
It cannot tell you that a consequence map or a signature vocabulary is complete. §8's CONSEQ and §11's signature set are both finite descriptions of an open space. CURRICULUM-DERIVED from 27.1's completeness argument for a specification written by someone else: an unenumerable domain cannot be covered by enumeration, and both artifacts are enumerations. DERIVED: the best available check is that they contain at least what this track has already documented — 28.7 §4's six actions and 28.1 §2's eleven signatures — which is a lower bound and not a completeness claim.
It cannot recover evidence that the failure itself destroyed. §10's classification makes the loss visible; it does not prevent it. CURRICULUM-DERIVED from 30.10 §12's variety 9: an observable cleared by the reset that recovery requires is gone before any discipline applies, and the only remedy is a sticky register added before tapeout — which is 33.1's gate, not this one.
And it cannot establish that the stages themselves are the right stages. Every item is relative to a stage set, and the stage set here is 28.7 §2's. DERIVED: a plan whose nine stages are internally consistent, correctly ordered, fully licensed and completely instrumented can still omit a subsystem entirely — and §14's audit would report it sound, because a fact nobody assumes is never unlicensed.
The honest summary: this gate's nine items decide whether a plan's records support what its later steps assume. It cannot decide whether the stages were the right stages, whether the documents it consumes are complete, or whether the branch judgements recorded in them are correct.
24. Where This Goes
This gate reviewed a plan that was followed. The next gate reviews what happens when a plan has run out and the system is still wrong.
Chapter 33.7 reviews debug. The question changes from does this record support what the next step assumed to does this evidence support the conclusion somebody drew from it — and the shift is from a relation between steps to a relation between an observation and an inference, which has no order to lean on.
| From here | What 33.7 must settle |
|---|---|
| §11's signature drift | When is a signature evidence, and when is it a verdict? |
| §10's destroyed observables | What can you conclude from evidence you know is post-recovery? |
| §14's unlicensed assumptions | How do you attribute a failure to a layer before you can discriminate within it? |
The first row is the one to carry forward, and it is the sharpest boundary in the two chapters. DERIVED: §11 treated a signature as an identity — a label that says whether two failures are the same phenomenon — and that is all a reduction needs. A debug uses the same signature as evidence about a cause, which is a much stronger reading of the same bits. CURRICULUM-DERIVED from 28.4 §2's standing rule, which the next gate inherits as its first principle: “A FAILURE SIGNATURE IS EVIDENCE, NOT A VERDICT. A done flag is a signature. So is a converged result. Neither is a statement about margin.”
So the next gate opens where this one's item 6 stops. DERIVED: this chapter required that a signature be recorded so two failures can be told apart. It never asked what a signature licenses — and 28.1 §2 has already measured the answer for the hardest case: five causes, one signature, and nothing in the bitmap distinguishes them. 33.7's first item is therefore the one this chapter had no need for: given a signature, what is the set of causes consistent with it, and what single experiment reduces that set fastest?
Continue learning
Related tutorials
- Related topic
Architecture Review Checklist
The first of eight pre-tapeout gates. Eight review items asked of a controller architecture before RTL exists, each one a question whose pass criterion is a named mechanism rather than an intention — and whose weak build produces a document that reads as thorough.
- Related topic
RTL Review Checklist
Nine questions drawn from the eighteen documented defects this track already carries. Every finding is code that is legal, lint-clean, passes a nominal test and is wrong — and five of the nine are decided by reading a port list.
- Related topic
PHY Review Checklist
A PHY's correctness lives in registers whose contents were measured rather than written, so every item is a question about provenance: what measured this, against what, when, and what happens when that measurement stops being true.
- Related topic
Verification Review Checklist
The gate that reviews the environment rather than the design. Nine items on configuration reach, antecedent publication, scale-vacuity, model independence and checker liveness — and it opens a twelfth variety the eleven-item taxonomy does not cover.
Standards & specifications
- Governing standard
- JEDEC JESD79 (DDR SDRAM)(opens JEDEC Solid State Technology Association in a new tab)
Defines the DDR SDRAM device itself — signals, command encoding, mode registers, timing parameters and the initialisation sequence — one document per generation. Memory-controller microarchitecture, address-mapping policy, PHY training algorithms and board-level design are not specified by it.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the DDR curriculum.
