Parametric bin assignment?

Hi , I have a binary array and I want to cover if each array element have been assigned the value one or not, something like this (syntax is not correct):


bit [9:0] arr;

covergroup my_covergroup {
  coverpoint arr {
    // assigning a bin to each array element
        bins element_0 =  arr[0] == 1; 
        bins element_1 =  arr[1] == 1; 
        bins element_2 =  arr[2] == 1; 
        bins element_3 =  arr[3] == 1; 
        bins element_4 =  arr[4] == 1; 
        bins element_5 =  arr[5] == 1; 
        bins element_6 =  arr[6] == 1; 
        bins element_7 =  arr[7] == 1; 
        bins element_8 =  arr[8] == 1; 
        bins element_9 =  arr[9] == 1; 
  }
}

meaning that the coverage will only be 100 if all array element’s values have been 1 once.
first question, what is the correct syntax ?
second question, suppose the array length is n. how can we assign parametric amount of bins like this?

In reply to Morteza_Seyedi:

For a fixed size coverpoint, you would use a wildcard bin expression

  coverpoint arr {
    // assigning a bin to each array element
        wildcard bins element_0 =  {10'b?????????1};
        wildcard bins element_1 =  {10'b????????1?};
        wildcard bins element_2 =  {10'b???????1??};
        wildcard bins element_3 =  {10'b??????1???};
        wildcard bins element_4 =  {10'b?????1????};
        wildcard bins element_5 =  {10'b????1?????};
        wildcard bins element_6 =  {10'b???1??????};
        wildcard bins element_7 =  {10'b??1???????};
        wildcard bins element_8 =  {10'b?1????????};
        wildcard bins element_9 =  {10'b1?????????};
  }
}

It would be difficult to parameterize a coverpoint for this. But what you can do is create an array of covergroups one for each bit of the array you want to cover. (untested)

covergroup cg_element (string name) with function sample(bit scalar);
  option.per_instance = 1;
  option.name = name;
  coverpoint scalar {
    bins is_set = {1};
  }
endgroup

Then you can wrap this in a parameterized class

class cover_vector#(int N);
   cg_element cg_array[N];
  function new;
     foreach(cg_array[i]) cg_array = new($sformatf("value[%0d]",i);
  endfunction
  function void sample(bit[N-1:0] value);
    foreach(cg_array[i]) cg_array.sample(value[i]);
  endfunction
endclass

In reply to Morteza_Seyedi:

There are several solutions, if you do not want to have an array of covergroups inside the wrapper class you could alternatively sample the “index” of your array only when the bit is set, I’m not sure if there are any drawbacks to this, but I could think that potentially could be more efficient than a full array of covergroups specially if you have let’s say a large number signals to cover with a large number of bits, also when reading the coverage report it can be a bit tedious traverse across all the cgs created

Also keep in mind that based your requirement you’ll get 100% coverage with a single value that has all bits set, potentially this is not exactly what you want, this article has interesting examples


class coverage_wrapper #(WIDTH = 16);
  
  covergroup bits_set_cg with function sample(bit [WIDTH-1:0] data, int index);
    option.per_instance = 1;
   
    cp_bits_set : coverpoint index iff(data[index] == 1) { //only sample when bit is set
      bins index_set[] = {[0:WIDTH-1]}; //measure the index that is set
    }
  endgroup
   
  function new();
    bits_set_cg = new();
  endfunction
  
  function void sample_bits_set_cg (bit[WIDTH-1:0] data);
    for(int i=0; i < WIDTH; i++) begin
      bits_set_cg.sample(data, i);
   	end
  endfunction
endclass


module test();
  parameter DW1 = 12;
  parameter DW2 = 16;
  bit [DW1-1:0] data_x;
  bit [DW2-1:0] data_y;
  
  
  coverage_wrapper #(.WIDTH(DW1)) cg_wrap_data_x;
  coverage_wrapper #(.WIDTH(DW2)) cg_wrap_data_y;
  
  initial begin
    cg_wrap_data_x = new();
    cg_wrap_data_y = new();
    repeat(5) begin
      if(!std::randomize(data_x)) $fatal(1, "Randomize Failed!");
      $display("data_x = %b", data_x);
      cg_wrap_data_x.sample_bits_set_cg(data_x);
      
      if(!std::randomize(data_y)) $fatal(1, "Randomize Failed!");
      $display("data_y = %b", data_y);
      cg_wrap_data_y.sample_bits_set_cg(data_y);
      
    end
    $display("cg_wrap_data_x.bits_set_cg = %0f%%", cg_wrap_data_x.bits_set_cg.get_inst_coverage());
    $display("cg_wrap_data_y.bits_set_cg = %0f%%", cg_wrap_data_y.bits_set_cg.get_inst_coverage());
  end
  
endmodule


HTH,
-R

In reply to rgarcia07:
Thanks, I tested both and found your solution more intuitive and easier to read when it comes to coverage report.