Member 'Downloads' section will be deprecated from Jan 1, 2020.
4 minutes reading time (816 words)

Inheritance of covergroups

uvm_message_anatomy

Object oriented programming has a feature called inheritance that allows child classes to inherit members from its parent class without having to redeclare them in the child class. It's a great way to reuse existing code, and to make changes to testbenches without touching the base class structure. A covergroup is a System Verilog keyword that allows the user to declare and define the variables to be sampled for functional coverage. In this post, I'll just share what simulation results tell us about how inherited covergroups behave and how their coverage numbers are affected.

To start with, let us define a parent class A with covergroup cgA.

 
class A;
  rand bit[3:0] var1;
 
  covergroup cgA;
    option.per_instance = 1;
    coverpoint var1 {
          bins each[16] = {[0:$]};
    }
  endgroup
 
  function new ();
      cgA = new;
  endfunction
endclass
 

Next we'll declare a child class called B from A and have another covergroup for the new variable. Note that we are attempting to cross between a coverpoint declared in the parent class's covergroup cgA with the new variable.

 
class B extends A;
  rand bit[3:0] var2;
 
  covergroup cgB(); 
    option.per_instance = 1;
    coverpoint var2 {
          bins all = {[0:$]};
      }
    cross cgA.var1, var2; 
  endgroup
 
  function new ();
    super.new();
    cgB = new;
  endfunction
endclass
 

The code should compile well because cgA is defined in B because of inheritance. In the testbench we'll simply randomize the variables and call the sample() method and finally display the coverage. We'll try out a few things here, and observe how coverage changes.

Trial 1

In this case, we'll simply randomize A and B and sample only A.

 
module tb;
  A a;
  B b;
  initial begin
    a = new();
    b = new();
 
    for (int i = 0;i < 5; i++) begin
      a.randomize();
      b.randomize();
      a.cgA.sample();
    end
 
    $display ("A.cgA get_coverage = %0.2f %%   get_inst_coverage = %0.2f %%", a.cgA.get_coverage(), a.cgA.get_inst_coverage());
    $display ("B.cgA get_coverage = %0.2f %%   get_inst_coverage = %0.2f %%", b.cgA.get_coverage(), b.cgA.get_inst_coverage());
    $display ("B.cgB get_coverage = %0.2f %%   get_inst_coverage = %0.2f %%", b.cgB.get_coverage(), b.cgB.get_inst_coverage());
 
  end
endmodule
 

var1 gets randomized to 4 out of the 16 possible values and hence coverage is expected to be 25%. The instance a also gets an instance coverage of 25% since it has only one covergroup.

Simulation Log
ncsim> run
a.var1=0xf b.var1=0xd b.var2=0xe
a.var1=0xf b.var1=0xf b.var2=0xe
a.var1=0x2 b.var1=0xa b.var2=0x5
a.var1=0x9 b.var1=0xd b.var2=0x3
a.var1=0xe b.var1=0x3 b.var2=0xd
A.cgA get_coverage = 25.00 %   get_inst_coverage = 25.00 %
B.cgA get_coverage = 25.00 %   get_inst_coverage = 0.00 %
B.cgB get_coverage = 0.00 %    get_inst_coverage = 0.00 %
ncsim: *W,RNQUIE: Simulation is complete.

Trial 2

In this case, we'll try sampling cgA from both A and B. The only difference is what goes into the for loop when compared to the previous code.

 
    for (int i = 0;i < 5; i++) begin
      a.randomize();
      b.randomize();
      $display ("a.var1=0x%0h b.var1=0x%0h b.var2=0x%0h", a.var1, b.var1, b.var2);
      a.cgA.sample();
      b.cgA.sample();
    end
 

Firstly, note that both a and b instance coverage becomes 25%. Why a got 25% was seen in the example above. Now, b gets 25% because both variables var1 and var2 covers 4 out of the 16 possible values.

Secondly, look at the overall coverage. Covergroup A.cgA gets 43.75% because var1 hits 7 (f, 2, 9, e, d, a, 3) values out of the 16 possible values and hence gets 43.75%.

Simulation Log
ncsim> run
a.var1=0xf b.var1=0xd b.var2=0xe
a.var1=0xf b.var1=0xf b.var2=0xe
a.var1=0x2 b.var1=0xa b.var2=0x5
a.var1=0x9 b.var1=0xd b.var2=0x3
a.var1=0xe b.var1=0x3 b.var2=0xd
A.cgA get_coverage = 43.75 %   get_inst_coverage = 25.00 %
B.cgA get_coverage = 43.75 %   get_inst_coverage = 25.00 %
B.cgB get_coverage = 0.00 %    get_inst_coverage = 0.00 %
ncsim: *W,RNQUIE: Simulation is complete.

Trial 3

Now we'll sample cgB also along with the other covergroup.

 
    for (int i = 0;i < 5; i++) begin
      a.randomize();
      b.randomize();
      $display ("a.var1=0x%0h b.var1=0x%0h b.var2=0x%0h", a.var1, b.var1, b.var2);
      a.cgA.sample();
      b.cgA.sample();
      b.cgB.sample();
    end
 

As expected, cgB now reports a value greater than zero. The cross between cgA and var2 yields 62.5% which can be explained as follows. var1 has 16 bins and var2 has one bin, and the cross between the two should give 16 bins (16 x 1), out of which 4 are covered and yields 25% for the cross. The other bin which is for var2 is covered 100% and the average of both coverages give 62.5%.

Simulation Log
ncsim> run
a.var1=0xf b.var1=0xd b.var2=0xe
a.var1=0xf b.var1=0xf b.var2=0xe
a.var1=0x2 b.var1=0xa b.var2=0x5
a.var1=0x9 b.var1=0xd b.var2=0x3
a.var1=0xe b.var1=0x3 b.var2=0xd
A.cgA get_coverage = 43.75 %   get_inst_coverage = 25.00 %
B.cgA get_coverage = 43.75 %   get_inst_coverage = 25.00 %
B.cgB get_coverage = 62.50 %   get_inst_coverage = 62.50 %
ncsim: *W,RNQUIE: Simulation is complete.

In short, covergroups are also inherited by a child class in addition to variables and methods, and it should be possible to cross coverpoints belonging to two different covergroups within the base and child classes.

Maybe some simulators support this and some do not. Post your comments below !

HDL routines for error injection
Stressing the interconnect for performance bugs

Related Posts

 

Comments 3

Guest - Edison Yu on Thursday, 15 November 2018 18:16

Your result is wierd!? you can't use get_inst_coverage without option.per_instance = 1

Your result is wierd!? you can't use get_inst_coverage without option.per_instance = 1
Admin on Thursday, 15 November 2018 19:50

Thanks for noting that, the code has been corrected.

Thanks for noting that, the code has been corrected.
Guest - Veera on Tuesday, 09 July 2019 21:55

Is it possible to do ignore bins for cross coverage between two different cover groups?

bins c1 : cross a1.a, b iff (a1.a !=0);

Similar to this above...

Is it possible to do ignore bins for cross coverage between two different cover groups? bins c1 : cross a1.a, b iff (a1.a !=0); Similar to this above...
Already Registered? Login Here
Guest
Thursday, 12 December 2019

You consent to our cookies if you continue to use our website. To know more about cookies, see our privacy policy. I accept cookies from this site.

Agree