Bitwise toggle coverage for a bitvector

Hello,

Is there a easier way in SV to define coverpoint to do a toggle coverage on every bit of a 32 bit vector. Meaning If I have a 32-bit interrupt mask vector and I just want to see if each interrupt was either masked or unmasked , I usually have to code 32 lines of code. for instance

cp_interrupting_csrmask0 : coverpoint m_csr_intr_mask.interrupting_csrmask[0];
cp_interrupting_csrmask1 : coverpoint m_csr_intr_mask.interrupting_csrmask[1];
cp_interrupting_csrmask2 : coverpoint m_csr_intr_mask.interrupting_csrmask[2];
cp_interrupting_csrmask3 : coverpoint m_csr_intr_mask.interrupting_csrmask[3];
cp_interrupting_csrmask4 : coverpoint m_csr_intr_mask.interrupting_csrmask[4];
cp_interrupting_csrmask5 : coverpoint m_csr_intr_mask.interrupting_csrmask[5];
cp_interrupting_csrmask6 : coverpoint m_csr_intr_mask.interrupting_csrmask[6];
cp_interrupting_csrmask7 : coverpoint m_csr_intr_mask.interrupting_csrmask[7];
cp_interrupting_csrmask8 : coverpoint m_csr_intr_mask.interrupting_csrmask[8];
cp_interrupting_csrmask9 : coverpoint m_csr_intr_mask.interrupting_csrmask[9];
cp_interrupting_csrmask10 : coverpoint m_csr_intr_mask.interrupting_csrmask[10];
cp_interrupting_csrmask11 : coverpoint m_csr_intr_mask.interrupting_csrmask[11];
cp_interrupting_csrmask12 : coverpoint m_csr_intr_mask.interrupting_csrmask[12];
cp_interrupting_csrmask13 : coverpoint m_csr_intr_mask.interrupting_csrmask[13];
cp_interrupting_csrmask14 : coverpoint m_csr_intr_mask.interrupting_csrmask[14];
cp_interrupting_csrmask15 : coverpoint m_csr_intr_mask.interrupting_csrmask[15];
cp_interrupting_csrmask16 : coverpoint m_csr_intr_mask.interrupting_csrmask[16];
cp_interrupting_csrmask17 : coverpoint m_csr_intr_mask.interrupting_csrmask[17];
cp_interrupting_csrmask18 : coverpoint m_csr_intr_mask.interrupting_csrmask[18];
cp_interrupting_csrmask19 : coverpoint m_csr_intr_mask.interrupting_csrmask[19];
cp_interrupting_csrmask20 : coverpoint m_csr_intr_mask.interrupting_csrmask[20];
cp_interrupting_csrmask21 : coverpoint m_csr_intr_mask.interrupting_csrmask[21];
cp_interrupting_csrmask22 : coverpoint m_csr_intr_mask.interrupting_csrmask[22];
cp_interrupting_csrmask23 : coverpoint m_csr_intr_mask.interrupting_csrmask[23];
cp_interrupting_csrmask24 : coverpoint m_csr_intr_mask.interrupting_csrmask[24];
cp_interrupting_csrmask25 : coverpoint m_csr_intr_mask.interrupting_csrmask[25];
cp_interrupting_csrmask26 : coverpoint m_csr_intr_mask.interrupting_csrmask[26];
cp_interrupting_csrmask27 : coverpoint m_csr_intr_mask.interrupting_csrmask[27];
cp_interrupting_csrmask28 : coverpoint m_csr_intr_mask.interrupting_csrmask[28];
cp_interrupting_csrmask29 : coverpoint m_csr_intr_mask.interrupting_csrmask[29];
cp_interrupting_csrmask30 : coverpoint m_csr_intr_mask.interrupting_csrmask[30];
cp_interrupting_csrmask31 : coverpoint m_csr_intr_mask.interrupting_csrmask[31];

Is there a neater way to do a toggle functional coverage bitwise for a vector.

Regards,
Nisreen

You could write a covergroup with a single coverpoint that you construct multiple times in an array generated by a for loop. (the covergroup declaration must not be embedded inside a class)

covergroup cgmaskbit(input bit [31:0] position, ref bit [31:0] vector);
  pos: coverpoint (position & vector) !=0;
  option.per_instance = 1;
endgroup

cgmaskbit cgmaskbits[32];

foreach (cgmaskbits[i]) cgmaskbits[i] = new(1'b1<<i,m_csr_intr_mask.interrupting_csrmask);

In reply to dave_59:

Hello Dave,

I used your solution and it works like Jelly Bean.

This mechanism will help the the verif community a lot.

Thanks Again,
Nisreen

In reply to nisreenj:

Dave,

I would like to use this approach inside a class, but if I understand your example correctly the covergroup declaration cannot be embedded in the class. How do I create something similar inside a class?

Pseudo code:

class my_coverage extends uvm_subscriber #(apb_seq_item);
:
covergroup output_en_cg (input bit position, ref bit vector);
  encoding: coverpoint (('1b1<<position & vector) !=0)
              {
               bins hit = {1};
               }
               option.per_instance = 1;
endgroup: output_en_cg

output_en_cg g1[16];
:

function new(string name = "my_coverage", uvm_component parent = null);
  super.new(name, parent);
  foreach (g1[i]) begin
    g1[1] = new(i, output_enable_reg[15:0]);
  end
endfunction
endclass

My example code doesn’t compile (no surprise). Ideas?

In reply to paulegan:

Paul,You can simply move the covergroup declaration outside of the class. The covergroup does not reference any members of the class directly, you pass them in as constructor arguments. You did not show the declaration of output_en_reg.

In reply to dave_59:

I am trying to construct an array of covergroups in order to sample slices of a parameterized vector as follows:

module checker {
  clk,
  reset, 
  sig
}
parameter WIDTH = 32;
input clk;
input reset;
input [WIDTH-1:0] sig;

// Declare generic covergroup
covergroup CG (ref reg _cp) @ (posedge clk);
  option.per_instance = 1;
  CP: coverpoint _cp;
endgroup 

//Instantiate covergroup
CG cg[32];
for (int i=0; i < WIDTH; i=i+1) begin
  cg[i] = new(sig[i]);
end
endmodule

This line:

CG cg[32]

Is causing the following compiler error: Syntactically this identifier appears to begin a datatype but it does not refer to a visible datatype in the current scope.

I guess I need to declare the covergroup outside the module, but I’m not sure what that would look like. Can anyone provide an example of what that looks like in my case?

In reply to k8:

Your tool does not yet support arrays of covergroups.

In reply to shalom:

Use generate + cover property (SVA) to get this easily done.

Ajeetha, CVC

In reply to ajeetha:

Can you give an example of using cover property with generate? How can I create a parameterized number of bins using cover property?

Thanks

In reply to dave_59:

Hi Dave,

 In your original solution you mentioned, (the covergroup declaration must not be embedded inside a class). Could you explain what you meant by this ?

where do you define the covergroup definition then ? (lets say you have class extended from uvm_subscriber and you get the transaction from an analysis port)

Madhu

In reply to mseyunni:

Put the covergroup declaration in front of the class definition. This means that all coverpoint expressions must be passed in as arguments to the covergroup.

In reply to dave_59:

Hi Dave,

Thanks. I have not understood why you chose the type of the argument for covergroup to be ref. Can you explain ?

Madhu

In reply to mseyunni:

Page 519 of the 1800-2012 LRM

In reply to dave_59:

Hi Dave,

I am new to coverage and also i might not have understood the question correctly.

But i was thinking can we use your code inside the class in following manner without using ref in the argument .

class coverage ;

bit [31:0] vector;

covergroup cg_active_tag_bit(input bit [31:0] position);
  pos: coverpoint (position & vector) !=0;
  option.per_instance = 1;
endgroup : cg_active_tag_bit

cg_active_tag_bit cg_active_tag_bits[32];

function new(); 
foreach (cg_active_tag_bits[i]) cg_active_tag_bits[i] = new(1'b1 << i);
endunction

function sample(input value);
this.vector =value;
foreach (cg_active_tag_bits[i]) cg_active_tag_bits[i].sample();
endfunction

endclass

Please correct me if am wrong.
Thanks in advance
rakshith

In reply to raku:

rakshith,

The problem is when you declare a covergroup inside a class, it is implicitly declared as a covergroup variable with the same name as the covergroup. Therefore you cannot use the covergroup name as a type to declare another covergroup variable or, in this case, an array of covergroup variables.

Dave

In reply to dave_59:

Hello Dave, thanks it works well!
because the covergroups declaration is outside the class, i can use parameter to determine the width:

   covergroup mask (input bit [MASK_WIDTH-1:0] position ,ref bit [MASK_WIDTH-1:0] vector);
            mask_cp : coverpoint (position & vector) !=0;
            option.per_instance = 1;
            //option.comment = "";
   endgroup

but if i would like to make it be more flexible, i mean the width will get different value each time, so then a constant parameter is not good for me.
i thought to do it by the factory registration, like that:

`ovm_field_int (m_mask_width, OVM_ALL_ON)

but with this way my covergroups will not recognize it.
how can i declare my covergroups like that?

thanks for your help
Racheli

In reply to racheli kaplan:

You can define your covergroup using a maximum width, and then use a for-loop instead of a foreach-loop to create a covergroup for each bit.

In reply to dave_59:

Hi Dave,

I am trying to execute this piece of code but it results in only one bin getting created(with address all 0’s) instead of 16. could you suggest what might be going wrong here? basically the address value assigned in the function is not seen by the covergroup. Is there any other way i could do this?

Code is as follows:

class xyz ;

bit[31:0] address;
bit[31:0] ADDR;

covergroup access();

addr : coverpoint ADDR { bins Addr[16] = {[0:address]}};  

endgroup

function void calc();

address = 'h10000;
access.sample();

endfunction

fucntion new();

access = new();

endfunction

task run();

 forever begin
    calc();
end

endtask



In reply to albert:

The value of address it read when calling the covergroup’s constructor. That is when the bins for the coverpoint are created.

In reply to dave_59:

Could you suggest a way this could be done to get 16 bins instead of just 1?