Showing posts with label Coverage. Show all posts
Showing posts with label Coverage. Show all posts

Wednesday, 29 February 2012

Automatic Coverage Weight Calculator Utility

If you want to get Specman coverage number in linear fashion (i.e. coverage numbers = (total buckets hit) / (total buckets in valid space) ), then you need to set the weight of individual items and coverage groups properly. Updating the code for proper weights to each item and cover group is tedious and error prone task. Maintaining the code is also a problem. What if you can do it automatically by using Coverage API? I hope people, who are looking such kind of solution will benefit from this post.

Specman overall coverage grade is calculated in hierarchical manner by default. It means that coverage is calculated from leaf level to the top level in following manner. I've assumed that weight is not set manually and default weight value 1 is applied here.

  1. Individual item grade is calculated by dividing buckets hit by total bucket for that item.
  2. Individual cover group grade is calculated by dividing total of all items grade by total number of items
  3. Overall coverage grade is calculated by dividing total of all cover groups graade by total number of cover groups

Take a look at the following example code.

<'
extend sys
{
config : config_s;
};
struct config_s
{
a : uint(bits: 3);
b : uint(bits: 3);
c : bool;
event cov1_e;
event cov2_e;
cover cov1_e is
{
item a using ignore = (a in [0, 1, 7, 8]);
item b using ignore = (b in [0, 1, 7, 8]);
cross a, b using
ignore =
(a in [2] and b in [4]) or
(a in [4] and b in [2] );
};
cover cov2_e is
{
item a using ignore = (a in [0, 1, 7, 8]);
item c using ignore = (c == TRUE);
cross a, c;
};
keep soft a == select
{
40 : 2;
10 : 3;
40 : 4;
10 : 5;
10 : 6;
};
keep soft b == select
{
40 : 2;
10 : 3;
40 : 4;
10 : 5;
10 : 6;
};
keep soft c == TRUE;
run() is also
{
for i from 1 to 10
{
gen a; gen b; gen c;
emit cov1_e;
emit cov2_e;
outf ("a=%d b=%d c=%s\n", a, b, c);
};
};
};
'>


When you run the above code with Intelligen with seed 1, Specman generates following combinations of a, b and c.

a=4 b=4 c=TRUE
a=4 b=4 c=TRUE
a=4 b=3 c=TRUE
a=2 b=2 c=TRUE
a=6 b=2 c=TRUE
a=2 b=4 c=TRUE
a=2 b=2 c=TRUE
a=2 b=4 c=TRUE
a=2 b=2 c=TRUE
a=4 b=6 c=TRUE

Let's analyze the coverage now.

ItemHitValid SpaceGrade
a3560.00% (hit/valid space)
b4580.00% (hit/valid space)
cross_a_b52321.74% (hit/valid space)

So, cov1_e cover group's grade = (grade of item a*weight + grade of item b*weight + grade of item cross_a_b*weight)/3 = 1.6174/3 = 53.91 %

ItemHitValid SpaceGrade
a3560.00% (hit/valid space)
c11100.00% (hit/valid space)
cross_a_c3560.00% (hit/valid space)

So, cov2_e cover group's grade = (grade of item a + grade of item c + grade of item cross_a_c)/3 = 2.20/3 = 73.33 %

So, overall grade = (cov1_e grade + cov2_grade)/2 = 1.2725/2 = 63.62 %

But, if you need the linear coverage, it should be
(Total number of hit buckets) / (Total number of buckets in valid space) = ((3+4+5) + (3+1+3))/((5+5+23) + (5+1+5)) = 43.18 %

This can be achieved by adjusting the weitage of individual item and cover group. If you set the weight of each item equal to the total number of valid buckets, linear coverage is achieved. Let's see how it works.

ItemHitValid SpaceWeightGrade
a35560.00 % (hit/valid space)
b45580.00 % (hit/valid space)
cross_a_b5232321.74 % (hit/valid space)

So, cov1_e cover group's grade = (grade of item a*weight + grade of item b*weight + grade of item cross_a_b*weight)/(weight of a + weight of b + weight of cross_a_b) = (3 + 4 + 5) / (5 + 5 + 23) = 36.36 %

ItemHitValid SpaceWeightGrade
a35560.00 % (hit/valid space)
c11180.00 % (hit/valid space)
cross_a_c35521.74 % (hit/valid space)

So, cov2_e cover group's grade = (grade of item a*weight + grade of item c*weight + grade of item cross_a_c*weight)/(weight of a + weight of c + weight of cross_a_c) = (3 + 1 + 3) / (5 + 1 + 5) = 63.64 %

So, overall grade = (cov1_e grade*weight + cov2_grade*weight)/(weight of cov1_e + weight of cov2_e) = (12+7)/(33+11) = 43.18%

This number looks linear as we can see we've calculated the coverage based on the number of buckets hit divided by total number of bucket for whole of the coverage space. So, setting the weight of the items based its number of buckets, it gives us the correct result.

Setting the weight manually is tedious process as you need to check the exact number of valid buckets of each item and coverage groups by keeping ignores and ranges into the mind. And even you do that, if you want to change the coverage model again, you might need to calculate the valid space again which is tedious and error prone. So, why not automate it using Coverage API calls?

You can use this small utility which uses coveage API to change the weight of all the items and cover group. It gives you the linear overall grade which is total number of buckets hit in valid coverage space divided by total number of buckets in valid coverage space. This utility can also be used in the post processing of coverage database. This utility uses coverage API to recursively parse the whole coverage space of a given unit which can be sys. It counts the total number of buckets of each item and coverage group and uses covers.set_weight() to set the weight of items and cover groups recursively.

You can use it after loading the linear_coverage.e. It defines a specman command using "define as" macro. Example is given below

Specman>load linear_coverage.e
Specman>adjust weight sys (for whole coverage space)
Specman>adjust weight config_s (for coverage space defined in config_s struct)


I hope this will help you. Your comments and thoughts are welcome.

-------------------------------------------
liner_coverage.e
-------------------------------------------
<'
define "adjust weight " as {
sys.adjust_weight = new;
sys.adjust_weight.main("<1>");
};

struct cover_info
{
item_name : string;
num_of_buckets: uint;
weight : uint;
};

struct bucket_cover_struct like user_cover_struct
{
collect: bool; // flag to skip specific item
cover_info : list (key: item_name) of cover_info;

main(items: string) is
{
if scan_cover(items) == 0 {
error("Adjust Weight Error: no cover items matching ", items," exist");
};
};

scan_bucket() is
{
if ((collect) and (cross_level == sub_items.size()-1)) then
{
var full_item_name := appendf ("%s.%s.%s", struct_name, group_name, item_name);
if (status in [hole, normal])
{
if cover_info.key_exists(full_item_name)
{
cover_info.first(.item_name == full_item_name).num_of_buckets = cover_info.first(.item_name == full_item_name).num_of_buckets + 1;
}
else
{
var temp_cov_info : cover_info = new;
temp_cov_info.item_name = full_item_name;
temp_cov_info.num_of_buckets = 1;
cover_info.add(temp_cov_info);
};
};
};
};

// Output a line of text for item:
end_item() is
{
if collect then
{
var full_item_name := appendf ("%s.%s.%s", struct_name, group_name, item_name);
var num_of_buckets := cover_info.first(.item_name == full_item_name).num_of_buckets;
outf ("%s - %d (weight=%d)\n", full_item_name, num_of_buckets, item_weight);
covers.set_weight(full_item_name, num_of_buckets, FALSE);
};
};

start_group() is
{
collect = (struct_name != "session");//skip session struct
if collect then
{
outf ("\n------------------------------------\n");
};
};

end_group() is
{
if collect then
{
var group_total : uint;
for each (cov_info) in (cover_info)
{
group_total = group_total + cov_info.num_of_buckets;
};
outf ("------------------------------------\n");
outf ("Group and Total Buckets ---> %s - %d (weight=%d)\n", group_name, group_total, group_weight);
covers.set_weight(appendf("%s.%s", struct_name, group_name), group_total, FALSE);
outf ("------------------------------------\n");
cover_info.clear();
};
};
};

// Define an instance of bucket_cover_struct:
extend sys
{
!adjust_weight: bucket_cover_struct;
init() is also { adjust_weight = new; };
setup() is also { set_config(cover, show_sub_holes, TRUE); };
};

'>

Friday, 14 December 2007

Are You Reporting Wrong Coverage Number?

If you are not giving weight to your items in your coverage groups, the overall functional coverage number you get on Specman coverage report might be wrong. Let me explain it using an example. Take a look at following code.

<'
struct coverage_example
{
event cover_e;
a : bool;
b : uint (bits: 2);
cover cover_e is
{
item a;
item b;
cross a, b;
};
run() is also
{
emit cover_e;
};
};
extend sys
{
cov_ex : coverage_example;
keep soft cov_ex.a == TRUE;
keep soft cov_ex.b == 0;
};
'>

If you load above code, issue a test command and see the coverage report, it will show you 28%, which is wrong in fact. Specman calculates the overall coverage numbers hierarchical. For the above code, it calculates as following.

For item a:
total bucket = 2
total hit = 1
So, coverage number = 50%

For item b:
total bucket = 4
total hit = 1
So, coverage number = 25%

For cross a, b:
total bucket = 4*2 = 8
total hit = 1
So, coverage number = 12.5%

For Overall:
total bucket = 3 (item a, item b and cross a,b)
total hit = (50 + 25 + 12.5) = 87.5
So, coverage number = 29.166% (87.5/3)

But, in fact, it should be calculated as following.

Total bucket in the coverage group = 2 + 4 + 8 = 14
Total hit = 1 + 1 + 1 = 3
So, overall coverage should be (3*100/14 = 21.4285%)

This wrong calculation can be avoided by doing following modification in the code. See highlighted "green" code below.

<'
struct coverage_example
{
event cover_e;
a : bool;
b : uint (bits: 4);
cover cover_e is
{
//Weight is total number of buckets
item a using weight=2;
item b using weight=4;
cross a,b using weight=8;
};
run() is also
{
emit cover_e;
};
};
extend sys
{
cov_ex : coverage_example;
keep soft cov_ex.a == TRUE;
keep soft cov_ex.b == 0;
};
'>

But, all the time, applying weight to every item is not possible, as some code may be imported from third party vendor or some code might be read-only to the user. Also whenever the number of buckets change, user needs to update the weight of particular item. This might not be feasible sometimes.

To avoid this, there is a utility called bucket_counter which was delivered by Clemens Mueller from Cadence. This e code will report total number of buckets in each item and total number of bucket hits. This simple utility will help you calculate the exact number of functional coverage you have.

Please click here to download the code.

Just load the ecode along with your environment and read the coverage file. Then issue "sys.report_buckets()". It will report total number of buckets in each item, and total number of hits, as shown below.

Valid Space size for item a is 2 buckets
Valid Space size for item b is 4 buckets
Valid Space size for item cross__a__b is 8 buckets
total coverage buckets: 14
total coverage buckets hit: 3

Wednesday, 12 December 2007

Cover "check that" and "expect" statement

If you want to write a checker coverage grid, Cadence Specman team has come up with a solution to put "check that" and "expect" statement in the coverage grid.

Please find this shareware at following link. This works for Specman 6.0 onwards.

http://sandipgor.googlepages.com/shr_chkcov_1.1.tar.gz

Friday, 7 December 2007

100% functional coverage is not enough

Let me address this age old question once again. As we all know that 100% functional coverage does not mean bug free design, but it surely adds to the confidence of the designer. It is one of the criteria for verification completion. So, what are the other criteria people use for their verification completion. Most of us will answer that 100% code coverage achievement and few of us will also add that closing all the pending review items derived from verification review. But is it enough? We still feel that it is not enough. Deep inside our hearth, we still feel the need of some more testing/verification.

Well, this feeling will be there because of the nature of the verification task. But, let me come to the technical aspect of the 100% functional coverage. If we ask our self, what is the functional coverage, we will be scratching our head to find exact wordings to explain the functionality. Let me try to explain it in my words. For me, Functional Coverage Points are nothing but the measure of all possible combinations of inputs which can be applied to the design. So, in our functional coverage grid, we always cover all the input stimulus parameters and we assume that the output behaviour will be checked somewhere else in the verification environment. So, 100% functional coverage means we have stimulated the design with all possible stimulus. But this does not guarantee that all outputs and behaviors of the design are checked. So, 100% functional coverage does not mean bug free design. But, if we also have one more coverage grid which could be checker coverage grid, then, we can definitely say that we have applied all possible combinations of inputs and we have also checked all possible combinations of outputs. Even we need co-relation between these two grids. I mean, for each functional coverage point (one possible combination input), there should be at lease one checker coverage point (one possible output checker). And for each checker coverage point, there should be at least one functional coverage point. Thus co-relating these two grids will definitely help to improve the confidence in the design.

So, in my opinion, verification completion declaration should be based on following criteria.

1) All test cases passed.
2) 100% Code Coverage (of course with some waivers)
3) 100% Functional Coverage (and again, with some waivers)
4) 100% Checker Coverage
5) Correlation between Functional Coverage Grid and Checker Coverage Grid.