Closing holes
Read a coverage report, decide whether each hole is a stimulus gap or a model mistake, and close the real holes with constraints aimed at them.
- Lesson
- C7
- Time
- 25 min
- Runs on
- Coverage build
- Check
- 5 questions
A team needed its last two coverage holes closed before tape-out and tripled the length of every random test. A week of simulation later, the holes were still open. Both holes needed a single-beat packet, which the random stimulus produced in only a few percent of packets, and more of the same stimulus could not change that.
The example: ten random packets leave two holes, and one packet aimed at each closes them.
Read the report before adding stimulus
A coverage report lists every bin with its hit count. The total says how far you are; the empty bins say where to go. Start every closure effort from the list of holes, not from the percentage.
| Cross cell | Hits | Status |
|---|---|---|
| READ / one | 0 | hole |
| READ / short | 2 | covered |
| READ / long | 1 | covered |
| WRITE / one | 0 | hole |
| WRITE / short | 2 | covered |
| WRITE / long | 4 | covered |
| CONFIG / one | 1 | covered |
| CONFIG / short, long | - | ignored: impossible |
The cross after 10 random packets in the example, as a report would show it. Coverage 90.48%.
Each hole has one of three causes, and each cause has its own fix. The case may be impossible, in which case the model is wrong and the cell needs an ignore_bins. The case may be possible but rare under the current stimulus, which calls for aimed constraints. Or the stimulus may never produce it at all, because of a constraint or a missing feature, which is a bug in the testbench.
Why more random stimulus is slow
Random stimulus covers likely cases quickly and rare cases slowly. When the constraints allow 17 combinations of kind and length with equal chance, a single-beat READ is one of them, so it appears in about 1 packet in 17. Common cells fill in the first few dozen packets, and the last rare one can take hundreds more.
Holes that close in some seeds and stay open in others are a warning sign. A bin that depends on luck should be made reliable with a dist before the model is called complete.
Module 5 showed how solve order and weights shape those chances. The coverage report tells you which chances need changing; the constraints are how you change them.
Aim constraints at the holes
The direct fix is a packet aimed at each hole: randomize() with { kind == WRITE; len == 1; } produces exactly the missing combination, while every other field stays random and legal. The example finds the holes, aims one packet at each, and reaches 100%.
For holes that should appear naturally in every regression, change the distribution instead, with a dist such as len dist {1 := 3, [2:4] :/ 3, [5:8] :/ 3}, which makes single beats as common as each burst class. A dist keeps the stimulus random while moving the probabilities toward the cases the model asks for.
List the holes
Read the empty bins from the report, not just the total.
Classify each hole
Impossible: fix the model with
ignore_bins. Possible: decide whether it is rare or unreachable.Aim or reweight
Rare: adjust a
dist. Needed now: aim a packet with an inline constraint. Unreachable: find the constraint or feature that blocks it.Rerun and recheck
Confirm the hole is closed and that no check failed on the new stimulus.
A closed hole must be checked
A hole is closed only when the scoreboard has checked the packet that filled it. Aimed stimulus that reaches a bin while the checker is disconnected closes nothing, so keep every aimed packet inside the normal checked flow.
Aimed packets are directed tests in disguise, so keep them few. Each one should name the hole it closes, in a comment or a message, so a later reader knows why it exists. After closing holes, rerun with several new seeds to check that the total stays at 100% without the aimed packets doing all the work.
Record how each hole was closed. A dist change helps every future regression, while a one-off aimed packet must stay in the test list, or the next change to the constraints can quietly reopen the hole.
Sometimes the honest answer is that a case is not worth covering, for example a combination the product will never use. Then remove it from the model in a review, with the reason written next to the ignore_bins, never by quietly lowering the goal.
Count holes across the whole regression, not just per test. Merged coverage over every seed is what a sign-off review looks at, and it shows which holes no seed ever reached.
Try it
Ten random packets leave the two single-beat cells for READ and WRITE empty. The second round reads the holes from its own hit table and aims one packet at each, with an inline constraint on kind and length class.
Change repeat (10) to repeat (100) and predict whether round 1 still finds holes. The example keeps its own hit table because the coverage build cannot report a single bin's count; a simulator's coverage report lists the same cells.
round 1: 10 random packets, 90.48%, holes: READ/one WRITE/one round 2: aimed packets added, 100.00%, holes: noneCheck yourself
Remember
- Start closure from the list of empty bins, not from the total.
- Classify each hole: impossible (fix the model), rare (reweight), or unreachable (fix the testbench).
- Aim a packet at a hole with an inline constraint, or reweight with
distso every run reaches it. - A hole is closed only when the stimulus that filled it was also checked.