Choosing bins
Choose bins that match the specification: single values, ranges and arrays for what must happen, ignore_bins for what cannot, and illegal_bins for what must never.
- Lesson
- C3
- Time
- 25 min
- Runs on
- Coverage build
- Check
- 5 questions
A length coverpoint with automatic bins sat at 50% for a whole project, and the team learned to ignore it. Half of its 16 bins were lengths the specification forbids, 0 and 9 to 15, which no legal packet could ever hit. When a real hole appeared later, the number did not move, because nobody looked at a figure that was "always 50".
One column per sample. The 8 bins for forbidden lengths can never fill, so 50% is the ceiling.
Bins say what must happen
Each bin is a claim from the test plan: "this must happen at least once". So choose bins from the specification, not from the width of the field. For packet lengths, the design treats a single beat, a short burst and a long burst differently, and those are the cases worth counting.
| Bin declaration | Bins created | Covered when |
|---|---|---|
bins one = {1}; | 1 | length 1 is sampled |
bins short_ = {[2:4]}; | 1 | any of 2, 3 or 4 is sampled |
bins each[] = {[1:8]}; | 8, one per value | each value separately |
bins part[2] = {[1:8]}; | 2: lengths 1-4 and 5-8 | any value in each part |
bins even[] = {[1:8]} with (item % 2 == 0); | 4: 2, 4, 6, 8 | each even value |
bins other = default; | 1, not counted in coverage | any value no other bin takes |
The common forms of a bin. The brackets after the name decide how many bins one line creates.
The brackets are the detail people misread. bins short_ = {[2:4]} is one bin, covered by any of its three values. bins short_[] = {[2:4]} is three bins, each covered only by its own value.
How fine should bins be?
Bins that are too coarse hide holes. The example's coarse coverpoint has a single bin for lengths 1 to 8, so it reads 100% even for stimulus that never sends a packet longer than 4 beats.
Bins that are too fine create work that tells you nothing. If the design treats lengths 5, 6, 7 and 8 the same way, four separate bins demand four times the stimulus for no extra confidence. The right size is the one where each bin is a case the design actually handles differently.
Ask of each bin which bug its hole would hide. If no bug comes to mind, the bin is probably too fine; if several very different bugs do, it is probably too coarse.
Explicit bins also document the model. A reviewer reading bins long_ = {[5:8]} sees the specification's long burst directly, while 16 automatic bins say nothing about what matters.
A bin can also demand several hits before it counts: option.at_least = 4; inside a coverpoint means each of its bins needs 4 samples. That suits cases that must happen repeatedly, such as a buffer filling up more than once.
The limits of a range deserve attention. The shortest and longest legal packets are where boundary bugs live, so many models give lengths 1 and 8 bins of their own on top of the classes.
A wildcard bin matches values by pattern, such as wildcard bins even = {4'b???0};, where ? matches either bit value. It is handy for flag fields, where only some bits matter.
Values left out of the total
Two kinds of bin remove values from the coverage total. ignore_bins says a value does not matter, or cannot happen, so it is excluded and nobody waits for it. illegal_bins says a value must never occur, so it is also excluded, and a sample that hits it is a run-time error.
| Kind of bin | Counted in coverage? | If a sample hits it |
|---|---|---|
bins | yes | the bin is covered |
ignore_bins | no | nothing happens |
illegal_bins | no | a run-time error is reported |
bins x = default | no | counted in x, outside the total |
How each kind of bin affects the coverage total.
Use illegal_bins sparingly. It turns the coverage model into a checker, and a checker belongs in the scoreboard or an assertion, where its failure is reported with context. It is useful as a last line of defence for values that would mean the stimulus itself is broken, such as a packet length of 0.
Same stimulus, different answers
The example samples the same lengths into four coverpoints. With legal stimulus over every length, the automatic bins read 50% and the other three read 100%.
With stimulus that never exceeds 4 beats, the model with one bin per length reads 50%, the model with three classes reads 66.67%, and the coarse model still reads 100%. Only the last one hides the hole completely, which is why every bin must correspond to a case from the plan.
The illegal_bins in len_classes does a quiet job as well. If the generator ever produced a length of 0 or 9, the run would stop at once and name the value, long before a scoreboard noticed anything odd.
Name bins after what they mean, such as one, short_ and long_. The names appear in every coverage report, and a reader should understand a hole without opening the code.
Try it
Automatic bins top out at 50%, because 8 of the 16 values are illegal. The illegal_bins in len_classes never fires, because every packet is legal. When long packets are missing, each and classes both show the hole; coarse cannot.
Add ignore_bins never = {0, [9:15]}; to len_auto and predict its new percentage.
all lengths: auto 50.00% each 100.00% classes 100.00% coarse 100.00% lengths 1-4: each 50.00% classes 66.67% coarse 100.00%Check yourself
Remember
- Make each bin a case the specification treats differently; avoid automatic bins over illegal values.
bins b = {...}is one bin covered by any listed value;bins b[] = {...}is one bin per value.- Bins that are too coarse hide holes; bins that are too fine add work without adding confidence.
ignore_binsexcludes values that cannot or need not happen;illegal_binsalso makes a hit an error.- A
defaultbin collects the rest and is not counted in coverage.