In the first part of this 3-post series (part 2, part 3), 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!
4 Responses
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?
Hi Rashid,
A possible implementation would be:
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
The solution presented in the article might trigger overflow warnings in some simulators, even though the bins that cause the warnings are excluded anyway when their
with
expressions evaluate to 0.Other simulators will complain that the candidate value
item
is not used in thewith
expression. Section 19.5.1.1 in IEEE Std 1800-2017 leaves room for interpretation: it mandates using the nameitem
for the candidate value, but it is not clear whether its usage in the expression is also required. On the other hand, the array locator methods defined in section 7.12 (find()
,find_index()
etc.), for which thewith
clause is mandatory, do not generate any warnings if the iterator argument (nameditem
or otherwise) is not used in the expression.Here is an alternative way to implement the coverpoint, avoiding the warnings mentioned above:
burst_size: coverpoint size {
bins \1 = burst_size with (MAX >= 1 && item == 1 );
bins \2 = burst_size with (MAX >= 2 && item == 2 );
bins \3..MAX-3 = burst_size with (MAX >= 6 && item >= 3 && item = 5 && item == MAX-2);
bins \MAX-1 = burst_size with (MAX >= 4 && item == MAX-1);
bins \MAX = burst_size with (MAX >= 3 && item == MAX );
illegal_bins illegal_val = default;
}
what’ is the different between the iff and with clause in bins. They are likely the same. From LRM:
“The expression within the iff construct at the end of a bin definition provides a per-bin guard condition. If
the expression is false at a sampling point, the count for the bin is not incremented.”
with clause:
“The with clause specifies that only those values in the covergroup_range_list that satisfy the given
expression (i.e., for which the expression evaluates to true, as described in 12.4) are included in the bin”