How to Implement Flexible Coverage Definitions (Part 1)

In the first part of this 3-post series, I would like to show a compact way of defining flexible coverage in SystemVerilog that adapts to a variable parameter.

Let’s consider the case where you need to cover the size of a burst, which can range between 1..max, with max being configurable within 1..N. The bins are defined as 1, 2..max-1 and max.

The first implementation that comes to mind is the following:

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] };
    bins max_items     = { max };
    illegal_bins illegal_val = default;
  }
endgroup

Even though it captures our intention, this covergroup definition is faulty. If max = 2, the several_items bin will be [2:1], which overlaps with the other two bins. When max = 1, the max_items bin will be { 1 }, which overlaps with the one_item bin. The several_items bin will be [2:0]. Not only does it overlap with the one_item and max_items bins, but it also accepts the illegal values 0 and 2, which is clearly a problem.

Solution Using the with clause

To solve this issue, the with clause will be used for the several_items and max_items bins.

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

As a consequence, the max_items bins will be created only if max >= 2, while the several_items bins will be created only if max >= 3.

The Test Module

If you want to play with the presented solution, you can use the test module 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

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

module test;
  initial begin
    cg_wrapper cgs[5];

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

      for (int size = 1; size <= max_size + 1; size++)
        cgs[max_size].size_cg.sample(size);
    end
  end
endmodule

That’s all!


Comments

Rashid August 7th, 2017 14:46:30

What solution would you recommend if “max_size” is not a static value i.e. max_size is configured during run time, for example max_size=some_register_value_after_reset?


    Horia-Răzvan Enescu August 7th, 2017 16:57:14

    Hi Rashid,

    A possible implementation would be:

    covergroup cg with function sample(int val, int max_size);
      option.per_instance = 1;
    
      val_cp: coverpoint 1 {
        bins one    = { 1 } iff (                 val == 1);
        bins middle = { 1 } iff (max_size >= 3 && val inside { [2:max_size-1] });
        bins max    = { 1 } iff (max_size >= 2 && val == max_size);
      }
    endgroup
    ...
    cg.sample(some_value, some_register_value_after_reset);

    As you only really need to know that a bin has been sampled or not, the sampled value (in this case 1) doesn’t matter as long as the sampling condition is correctly specified.
    However, you’ll need to be careful and update the code to avoid coverage holes if max_size won’t be larger that 1 or 2 in the regression.

    Horia


Leave a Comment:

Your comment will be visible after approval.

(will not be published)

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