Bitwise toggle coverage for a bitvector

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?

In reply to albert:

class xyz ;
 
bit[31:0] address;
bit[31:0] ADDR;
 
covergroup access();
  addr : coverpoint ADDR { bins Addr[16] = {[0:address]}};  
endgroup
 
function void calc();
  access.sample();
endfunction
 
fucntion new();
  address = 'h10000; 
  access = new();
endfunction
 
task run();
 
 forever begin
    calc();
    ...
end
 
endtask
endclass

In reply to dave_59:

Hi Dave,

I need to use the ref keyword in order to achieve the behavior I want. But I see 1 bin getting created if I try to do this::

class xyz ;

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

covergroup access(ref bit[31:0] Addr);
addr : coverpoint ADDR { bins addr[16] = {[0:Addr]}};
endgroup

function void calc();
address = 'h10000;
access.sample();
endfunction

fucntion new();
access = new(address);
endfunction

task run();

forever begin
calc();

end

endtask
endclass

In reply to albert:

The value of ADDR is read when calling the covergroup’s constructor. That is when the bins for the coverpoint are created. There is no more bin creation after constructing the covergroup.

So if ADDR has the value 0 when executing the statement

 access = new(address);

Then

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

will be interpreted as

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

which creates one one bin for the value 0.

You should have gotten a warning like

** Warning: (vsim-8546) The number of values specified ‘1’ is less than the size ‘16’ of fixed-size array bin ‘Addr’ in Coverpoint ‘addr’ of Covergroup instance '/top/xyz::access '. The ‘15’ empty bins will not contribute towards coverage.

In reply to dave_59:

Hi Dave,

Thanks for the reply. Yes i did see that warning.

Actually in the function I have calculated the range of address which i want to use in my covergroup.
Basically i want to do this

memory_range : coverpoint range {bins addr = {[base_addr, final_addr]};}

which will be dependant on the size of the memory for which i have defined a function. The size and base_addr are read from registers inside the function.

function void calc();

bit [3:0] size;

register read to get size;
register read to get base_addr;
case(size)
4’b0000: begin
Max_addr = ‘h10000;
Final_addr= base_addr+max_addr;
covergroup.sample();
end

4’b0001: …….

endfunction

How should I access the base addr and final addr from the function in my covergroup?

In reply to albert:

Hi Dave,

Could you please suggest a way in which the above scenario can be achieved?

In reply to albert:

You still have not explained your situation very well. Functional coverage in SystemVerilog works by creating in set of value bins associated with a coverpoint, and a set of coverpoints or grouped within a covergroup. The bins are set up once during the covergroup’s constructor. The the covergroup repeatedly samples the values of the coverpoint, and the matching value bins are incremented with hits. You call sample() repeatedly hoping the every bin gets hot.

You need to explain what value will be repeatedly sampled and compared with the predefined set of bin values. Perhaps you need to show an example set of data that would be sampled, and explain which bins would be hit those values.

In reply to dave_59:

Hi Dave,

Thanks for the reply.

The basic idea is to create bins with the range of base address and final address.

The base address is programmed through register which is again dependant on size being programmed in another register.

So based on what size is being programmed, i have calculated the max address and final addr would be base + max.

i want to use the values inside the function (like base addr and final addr) in the covergroup.

I want to sample all the addresses which fall within that range. preferably create 16bins and have the address range split across these 16bins.

The problem i am facing now is that the base and final addr is not visible in the covergroup and only 1bin gets created as such.

In reply to albert:

Hi Dave, Can we have a function inside the coverpoint like below?

covergroup memory_access(string name) with function sample(bit[47:0] sb_addr);
mrom_erom_mmio_range : coverpoint sb_addr {

                          function bit[47:0] QUEUE[$] mem_region();

                            bit [47:0]   max_addr;
                            bit [47:0]   base_addr;
                            bit [3:0]    size;
                            bit[47:0] queue [$];
                            bit [47:0] i;
                                   
                            
                                max_addr = 48'h1000000;
                                for(i=base_addr; i<=(base_addr+max_addr); i++) begin
                                queue.push(i);
                                end
                                return queue;
                              

                          endfunction

                        bins addr = mem_region();
                        }

endgroup

function void memory_space();

        new_addr = {item.addr[5], item.addr[4], item.addr[3], item.addr[2], item.addr[1], item.addr[0]};
        memory_access.sample(new_addr);
    end

endfunction: memory_space

function new (string name, ovm_component parent);
super.new(name, parent);
memory_access = new({“memory_access_”, name()});
endfunction : new

task run();
forever begin
memory_space();
end
endtask : run

Currently on compiling this code, i see syntax error

92: token is ‘function’
function bit[47:0] QUEUE[$] mem_region();

Could you provide your input?

In reply to nisreenj:

you can use perl script also

//+vpp+ foreach my $i (0…31) {
cp_interrupting_csrmask##$i## : coverpoint m_csr_intr_mask.interrupting_csrmask[##$i##];
//+vpp+ }

it will do the for 0 to 31 just 3 steps :)

In reply to dave_59:
Thanks for sharing the solution. The problem with maximum_width is that simulator expects an equivalent type for ref formal ‘vector’ (ie. Questa will return error 8282).

However, one can override built-in sample method:


covergroup cgmaskbit(input bit [31:0] position) with function sample (bit [MAX_WIDTH-1:0] vector);
  pos: coverpoint (position & vector) !=0;
  option.per_instance = 1;
endgroup

In reply to dave_59:

Hi Dave

Do you have logic for covering of bits from toggling 1=> 0 and 0 => 1 ?