A verification lead proposes a cycle-accurate model of DCRouter: it would predict every output in the exact cycle it appears, so any difference at all is a bug. Building it means re-implementing the FIFOs, the arbiter, the credit counters and the sleep timer, cycle for cycle. It will take as long as the RTL did, and it will have its own bugs. When a designer improves the arbiter, the model must change in lockstep, or every test fails.
How precise does a reference model need to be?
The obvious instinct is "as precise as possible": a more precise model catches more. But precision has three costs. It takes effort to build and maintain; it encodes implementation choices the specification never made, so legal changes fail tests (lesson 2.7); and a model as complex as the design is as likely to be wrong. The right depth is the specification's depth, rule by rule, plus just enough timing for the rules that are about time.
Depth | Predicts | Cost | Good for |
|---|---|---|---|
Functional (untimed) | Final results: which data, which values | Low | Data transformations, routing, register values |
Transaction with order | Results plus the order the specification promises | Low to medium | Packets per flow, responses per ID |
Timing-aware (approximate) | Bounds and events in time: latency limits, who was waiting when | Medium | Arbitration, performance, deadlines |
Cycle-accurate | Every output in its exact cycle | High; changes with every RTL change | Rarely: fixed timing interfaces, or a golden model from architecture |
DCRouter's testbench uses all but the last: the scoreboard is transaction-level with per-flow order; counters are functional, checked at the end; sleep, wake and arbitration need timing, and get only the timing they need.
Building lesson 5.10's arbitration checker for this course went through three versions. Each was tested on the clean DCRouter with 30 random seeds before being trusted.
Version | Model of time | Result |
|---|---|---|
1: judge each packet when its first flit leaves | Assumed the grant happens just before the first flit | False priority failures on the clean design in 17 of 30 seeds: a granted packet can wait many cycles for a credit, so the grant was much earlier than assumed |
2: also count credits from the pins | Inferred the grant time from a credit count kept by the checker | Clean design passed, but with credit bugs (BUG_9, 10, 22) the checker's count was wrong and it blamed the arbiter: real failures, wrong rule |
3: judge only packets that leave 2 cycles after the previous tail | Only where the grant time is certain at the pins: the cycle the output became free | Clean design passes all seeds; arbitration bugs caught; credit bugs left to the credit audit |
Version 3 models less than version 2 and is better. It does not guess hidden timing; it restricts itself to the moments when the pins prove when arbitration happened, which are exactly the moments inputs contend. The lesson generalises: model the timing the specification and the pins make certain, and decline to judge the rest.
Start functional: most rules are about results.
Add order where the specification promises it, by the domain it promises (lesson 5.6).
Add timing only for rules about time, as bounds rather than exact cycles.
When timing is hidden, judge only where it is observable, and say so in the checker's comments.
Validate the model across many seeds on the clean design before trusting its failures.
Practice | Purpose |
|---|---|
Transaction-level models as the default | Cheap, stable and independent of the implementation |
Separate performance checkers with bounds | Timing rules checked without a cycle-accurate model (lesson 5.9) |
Architecture models reused as references | One model of intent, often untimed or approximately timed |
Versions 1 and 2 above are what breaks: a model that assumed timing it could not see produced false failures, and a model that inferred hidden state from its own bookkeeping blamed the wrong rule when that bookkeeping was wrong. Both looked reasonable on paper and passed the first seed tried; only many seeds and the Bug Zoo exposed them.
It assumed each packet was granted just before its first flit left, but a granted packet can wait for a credit, so a high-priority packet that arrived later looked like it had been skipped.
It judges only when the grant time is certain at the pins, so it never blames the arbiter for errors in its own assumptions, and it still sees the contended moments where arbitration bugs show.
Match the reference model to the specification's depth: results, promised order, and timing only for rules about time.
Cycle-accurate models cost as much as the design and fail on legal changes.
Where timing is hidden, judge only where the pins make it certain, and validate on the clean design with many seeds.