How to Implement Flexible Coverage Definitions (Part 2)

In part 1 of this 3-post series (part 3), I presented a way of defining flexible coverage definitions in SystemVerilog using the with clause.

In this second post, I will show a way of achieving the same flexibility for transition coverage. As SystemVerilog’s grammar doesn’t allow us to use the with clause for defining transition bins, we will be using the coverpoint coverage option called weight.

The example given in part 1 will be enhanced with transitions for the burst size from any of the three bins to any of the three bins, for a total of 9 possible transitions.

Solution using option.weight

Although more commonly used for defining cross-coverage, option.weight gives us a way to exclude coverpoints from the computation of the total coverage score. This feature can be used to our advantage.

Let’s define three coverpoints: one for max = 1, one for max = 2 and one for max >= 3. Depending on the value of max, only one of the three coverpoints will have the weight equal to 1. The weight of the other two coverpoints will be 0, so they will be excluded from the coverage computation. The covergroup’s total coverage grade will be equal to the coverage grade of the coverpoint which has the weight equal to 1.

I provide you a working example below:

class cg_wrapper;
  covergroup size_cg(int max) with function sample(int size);
    option.per_instance = 1;
    type_option.merge_instances = 1;

    burst_size: coverpoint size {
      bins one_item      = { 1 };
      bins several_items = { [2:max-1] } with (max >= 3);
      bins max_items     = { max }       with (max >= 2);
      illegal_bins illegal_val = default;
    }
  endgroup

  covergroup size_transitions_cg(int max) with function sample(int size);
    option.per_instance = 1;
    type_option.merge_instances = 1;

    max_burst_size_one: coverpoint size iff (max == 1) {
      option.weight = (max == 1);
      bins one_to_one = (1 => 1);
    }

    max_burst_size_two: coverpoint size iff (max == 2) {
      option.weight = (max == 2);
      bins all_to_all[] = (1, 2 => 1, 2);
    }

    max_burst_size_three_or_more: coverpoint size iff (max >= 3) {
      option.weight = (max >= 3);
      bins one_to_one         = (1         => 1);
      bins one_to_several     = (1         => [2:max-1]);
      bins one_to_max         = (1         => max);
      bins several_to_one     = ([2:max-1] => 1);
      bins several_to_several = ([2:max-1] => [2:max-1]);
      bins several_to_max     = ([2:max-1] => max);
      bins max_to_one         = (max       => 1);
      bins max_to_several     = (max       => [2:max-1]);
      bins max_to_max         = (max       => max);
    }
  endgroup

  function new(int max_size);
    size_cg = new(max_size);
    size_cg.set_inst_name($sformatf("size_cg_max_size_%0d", max_size));

    size_transitions_cg = new(max_size);
    size_transitions_cg.set_inst_name($sformatf("size_transitions_cg_max_size_%0d", max_size));
  endfunction
endclass

module test;
  initial begin
    int size;
    int max_size;
    cg_wrapper cgs[5];

    foreach (cgs[i]) begin
      max_size = i + 1;
      cgs[i] = new(max_size);

      repeat (1000) begin
        void'(std::randomize(size) with { size inside { [1:max_size] }; });
        cgs[i].size_cg.sample(size);
        cgs[i].size_transitions_cg.sample(size);
      end
    end
  end
endmodule

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Subscribe to our newsletter

Do you want to be up to date with our latest articles?