DCRouter's BUG_21 stops input 3 from waking the router. In lesson 4.10 the random hunt caught it through its scoreboard: after 40,000 cycles with flits still undelivered, the run reported "flits still pending" at 439,965 ns. Lesson 5.3 adds a one-line assertion that any valid input wakes the router in the next cycle; with the same stimulus it fails at 39,985 ns, naming the rule and the input. Same bug, same traffic: one check reported a symptom at the end, the other the cause at the moment it happened.
Should a rule be checked locally where it applies, or end to end at the outputs?
One obvious answer is "end to end": compare final outputs with a reference model, and every bug that matters shows up there. It does, eventually, as a symptom: a missing packet, a hang, a wrong counter, far from the cause. The other obvious answer, "assert everything locally", turns every rule into a cycle-level property, including rules about data transformations that are much easier to state as "this packet should come out". Each approach is good at different rules.
Local assertion | End-to-end scoreboard | |
|---|---|---|
Checks | A rule at the place and cycle it applies | The final result against a reference |
Fails | At the cause, in the cycle it happens | At the effect, often much later |
Debug | Points at the rule and the signals | Points at a wrong output; the cause must be traced back |
Best for | Protocol and timing rules, relations between signals, illegal states | Data transformations, routing, ordering, end results |
Survives redesign | If written on stable interfaces | Yes, if the reference is at the specification's level |
Misses | Rules that need a model of the whole function | Masked or hidden state (lesson 3.3); timing rules with no data effect |
Rule | Check | Why |
|---|---|---|
R3 whole packets, per-flow order | Scoreboard | A statement about results: which packets arrive where, in what order |
R5, R8 out_err on faulty tails | Scoreboard, plus an assertion that out_err appears only with out_last | Which packets are faulty is data; where the flag may appear is a local rule |
R1 disabled port never ready | Assertion | A relation between configuration and one signal, every cycle |
R7 credits | Sink overrun check plus a credit audit | A count the sink can see, and hidden state the audit exposes |
R9, R10 counters | End-of-test register reads | Results accumulated over the whole test |
R13 sleep and wake | Assertions | Timing rules with no data of their own: a wake that never comes only shows as a hang |
R6 arbitration | A dedicated checker (lesson 5.10) | Needs a model of who was waiting when |
End to end for what the specification states as results: data, routing, order, counts.
Locally for what it states as relations or timing: handshakes, illegal combinations, deadlines.
Both for important rules: the assertion finds the cause fast; the scoreboard confirms the result.
Neither alone is complete: lesson 5.10 needs scoreboard, assertions and an arbitration checker together.
Practice | Purpose |
|---|---|
Protocol assertion checkers on every interface | Local rules checked everywhere, reused across projects |
Scoreboards per data path | End-to-end correctness against a reference model |
Designer assertions inside blocks | Internal rules checked at their source (lesson 3.4) |
A team (illustrative) relied on an end-to-end scoreboard alone for a bus bridge. A handshake bug held valid high for one cycle too long, so a beat was sometimes accepted twice downstream. The scoreboard saw a duplicated transfer thousands of cycles later and reported a data mismatch at the output. It took two days to trace back to the handshake; a one-line assertion on valid and ready would have failed in the cycle it happened.
It is a timing rule with no data of its own; a scoreboard only sees its effect, much later, as missing or late packets.
It is a statement about results across many cycles and packets; a reference model and scoreboard express it directly.
Local assertions check relations and timing where they apply, and fail at the cause.
Scoreboards check results end to end against a reference, and survive redesign.
Use both: results end to end, relations and timing locally, and both for important rules.