← Design Verification Interviews

Interview Question · Code Reading

A Covergroup Inside a Collector Class

L1 JuniorL2 Mid-Levelfunctional coverageclassessampling

The Question

The interviewer asks

This collector receives lengths 1, 2, 3 and 4. What coverage does it report, and why?

systemverilog
class len_collector;
  int len;
  covergroup cg;
    cp: coverpoint len { bins b[] = {[1:4]}; }
  endgroup
  function new(); cg = new(); endfunction
  function void write(int t);
    cg.sample();
    len = t;
  endfunction
endclass
// The test calls write(1), write(2), write(3), write(4).
Reveal the Model Answer

It reports 75%. write() calls sample() before it updates len, so each sample sees the previous length. The first sample sees 0, which has no bin, and the length 4 is never sampled. Pass the value in instead: declare covergroup cg with function sample(int l); and call cg.sample(t). The constructor is also the right place for cg = new(), because an embedded covergroup must be built there.

Each Sample Sees the Previous Length
0123callwrite(1)write(2)write(3)write(4)len when sample() runs0123bin hitnoneb[1]b[2]b[3]with sample(int l)b[1]b[2]b[3]b[4]3 of 4 bins: 75.00; the fix reaches 100.00

One column per call. Because sample() runs before len = t, the length 4 is never sampled.

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Junior)

A good junior answer walks through the four calls and finds the off-by-one. It rewrites the covergroup so sample() takes the length as an argument.

Cross-Questions

Where the interviewer goes next. Open a node to practise that follow-up.

WhyWhat IfProve ItCompareScale It

  1. A Covergroup Inside a Collector Class
  2. WhyWhy Pass Values to SampleL1 Junior

    Why do many teams prefer with function sample(...) over coverpoints that read class members?

    Reveal the Model Answer

    The arguments say exactly what is sampled and when. There is no ordering rule between updating members and calling sample(). The same covergroup can be sampled from any place that has the values. A monitor callback or an assertion action block both work. It also keeps the covergroup independent of the class layout.

    Self-Check

    Tick each key point you covered in your answer.

    Buzzword Without Mechanism

    "Sample arguments are only syntax sugar."

    They change what the covergroup depends on. Member-based coverpoints depend on the state of the object at the moment of sampling.

    Source Mehta, SystemVerilog Assertions and Functional Coverage (3rd ed.), §27.4 (PDF p503)

  3. What IfAn Embedded Covergroup That Was Never BuiltL1 JuniorL2 Mid-Level

    Asked if they move cg = new() out of the constructor

    What if someone moves cg = new() into a configure() method, or forgets it entirely?

    Reveal the Model Answer

    Moving it does not compile. The standard allows an embedded covergroup to be assigned only in its class's new method, and the coverage build says exactly that. Forgetting it does compile. Then the covergroup never exists, and the first sample() call stops the run with a null pointer error. A collector that never samples just reports nothing for that group.

    Self-Check

    Tick each key point you covered in your answer.

    Spec Misquote

    "Build the covergroup later, when the test configures coverage."

    The language rule ties an embedded covergroup to the constructor. To make coverage optional, guard the sample() calls with an enable flag instead.

    Source IEEE 1800-2017 §19.4

    Missed Corner

    "A missing covergroup shows up as 0% in the report."

    An instance that was never created may not appear at all. A merged report can then look complete with that group simply absent.

    Source Mehta, SystemVerilog Assertions and Functional Coverage (3rd ed.), §26.13 (PDF p467)

  4. CompareEmbedded vs Standalone CovergroupsL1 JuniorL2 Mid-Level

    Compare a covergroup embedded in a class with one declared in a package and created by the class.

    Reveal the Model Answer

    An embedded covergroup can read the class's local and protected members directly, and it is one instance per object. A covergroup declared in a package takes its inputs as arguments. Several classes can then create it, and a class can hold an array of them. Use embedded for one collector class; use a package covergroup when several components share the model.

    Embedded in a classDeclared in a package
    InputsReads the class's members directlyTakes arguments
    InstancesOne per object, built in newAny number; arrays are fine
    Shared by several classesNoYes

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "Embedded covergroups can't see protected members, so you must make them public."

    An embedded covergroup is inside the class, so it can use local and protected members without breaking encapsulation.

    Source Mehta, SystemVerilog Assertions and Functional Coverage (3rd ed.), §26.13 (PDF p466)

  5. Scale ItA Covergroup Inside the Transaction ClassL2 Mid-LevelL3 Senior

    A teammate embeds the covergroup in the transaction class, and the test creates a million transactions. What happens?

    Reveal the Model Answer

    Each transaction object builds its own covergroup instance in its constructor. That is a million covergroup instances, each sampled once or twice, and memory and run time grow with them. Put covergroups in components that live for the whole run, such as a coverage collector, and pass each transaction to them.

    Self-Check

    Tick each key point you covered in your answer.

    What Interviewers Listen For (Senior)

    A good senior answer turns this into a review rule. Covergroups live in components that last the whole run, never in transactions or sequences.

    Misconception

    "The covergroup is shared by all objects of the class, like a static member."

    An embedded covergroup is an instance member. Each object that runs its constructor creates its own instance.

    Source IEEE 1800-2017 §19.4

  6. Prove ItSolve 7.5.8: Two Coverpoints for the FIFOSimulator-graded

    Show it, don't just say it: this Silicon Lab problem is graded by the simulator.

    Open Problem 7.5.8

What People Get Wrong

Common wrong answers and why they fail. Run It shows the wrong belief failing on a real simulator.

Misconception

"The covergroup reads the length that just arrived."

A covergroup reads its variables when sample() runs, not when write() was called. The twin samples before the update and misses length 4.

Run It

The interview collector, fed lengths 1 to 4.

RUNVerilator (coverage build) · simulator service
Edit the code, then run it
Expected: length coverage=75.00 after lengths 1 to 4 FAIL: sample() ran before len was updated, so it saw the previous length and never saw 4
See the Fix
class len_collector;
  covergroup cg with function sample(int l);   // the fix: pass the value in
    cp: coverpoint l { bins b[] = {[1:4]}; }
  endgroup
  function new(); cg = new(); endfunction
  function void write(int t);
    cg.sample(t);
  endfunction
endclass
module tb;
  initial begin
    len_collector col = new();
    for (int i = 1; i <= 4; i++) col.write(i);
    $display("length coverage=%0.2f after lengths 1 to 4", col.cg.get_coverage());
    if (col.cg.get_coverage() < 100.0) $display("FAIL: sample() ran before len was updated, so it saw the previous length and never saw 4");
    else $display("PASS: with function sample(int l) the covergroup sees each length as it arrives");
  end
endmodule

Prints: length coverage=100.00 after lengths 1 to 4 PASS: with function sample(int l) the covergroup sees each length as it arrives

Spec Misquote

"Construct the covergroup in a build step, like other members."

Only the class's new may assign an embedded covergroup. The coverage build refuses to compile an assignment anywhere else.

Source IEEE 1800-2017 §19.4

Half-Truth

"Just swap the two lines and move on."

Swapping fixes this bug. A sample argument also removes the hidden ordering rule for the next person who edits write().

Learn It, Then Prove It