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); };
};

'>

Thursday, 24 June 2010

Cadence's Labs on Cloud

Have you ever wanted to try out any Cadence tools or VIPs evaluation without going through the process of getting evaluation licenses, software download and installation and all that logistic stuff? Now you can do all that without all that hassles. Cadence has tied with Xuropa for their cloud computing platform so that all you need is high speed broadband for any Cadence tools/VIPs evaluation.

Using Xuropa Online Labs, you can run an evaluation using the Incisive Enterprise simulator, following instructions for a self-paced demo. All the software runs on Xuropa servers, and there is nothing to purchase, license, install, download, or upload.

You can read more about it at at Cadence's Community Blog Post

Saturday, 8 May 2010

Generic/Parameter support in Mixed HDL Hierarchy Code Generator

I hope this small utility is helpful. I've thought one small enhancement to it. Now, you can select whether you need VHDL Generic or Verilog Parameterized examples code by selecting the checkbox. Please feel free to comment/enhancement. You can visit http://www.sandipgor.com/hdl_gen.html

Friday, 9 April 2010

Mixed HDL Hierarchy Code Generator

Sometime back, I wanted to experiment Specman environment with Mixed HDL (Verilog + VHDL) design. I wanted to have a simple 4 level hierarchical design with simple port connections. It took some time for me to build it as I need to refer VHDL and Verilog syntax. That time one thought came to my mind to have simple utility which can build this env very quickly so that I don't need to invest time to clean up the compilation errors.

Keeping this simple requirement in mind, I decided to build such a simple online tool which can be used by everybody.

I've created one Javascript based tool which can generate Mixed HDL Hierarchical design.Its link is http://www.sandipgor.com/hdl_ gen.html

I've tried to keep it simple. You can use "Add VHDL" and "Add Verilog" buttons to add VHDL or Verilog instance into hierarchy. "Level Up" and "Level Down" buttons can be used to increase/decrease current level where you want to add instances. Finally "Generate" button can be used to dump the hierarchical HDL code into the two text box placed right side of the window. I've also kept "Clear Code" and "Clear Hierarchy" buttons to clean up the relevent data. "Undo" button is useful to undo the last change. Remember, there is no "Redo" button though.

I hope you will find it useful. Please feel free to use it.

Any suggestion/feedback is welcome.

Friday, 10 July 2009

DigitalVerification Blog is noticed by Verification Community

I am glad and thankful to the verification community for appreciating my small contribution towards the verification world. This blog has been noticed by Cadence Team Specman and recoginized as useful resource.
ChipDesignMag.com also recognized this blog saying "if you live and breathe in this world, here’s an additional resource"
I'll keep posting and contributing to the verification world.

Thursday, 25 June 2009

IntelliGen - Introduction

IntelliGen is around for quite a while, but I've observed that most of the Specman users are less interested in/aware of it. Probably they are very comfortable with old generation engine known as PGen. Even I am quite comfortable with PGen and I am used to think generation in PGen way. But, when I went through IntelliGen, it also looked conviencing. But it will take some time to penetrate and Cadence has to push it hard so that people start thinking about generation IntelliGen way. :)

IntelliGen is a new generation engine introduced in Specman 6.1 version onwards. It is a new generation engine which uses different generation algorithm from Specman's original generation engine PGen. Though PGen remains default generation engine, user can switch to IntelliGen by setting a configuration flag before loading any code.

Specman>config gen -default_generator=IntelliGen

IntelliGen is easier to use as there is no generation dependencies on the fields declaration order. In PGen, fields which are declared first are generated first unless there are specific generation order mentioned using "keep gen before" or "readonly()". With a new and powerful debugger, its very easy to debug generation errors for IntelliGen. The messages which are displayed when any generation errors occur are more informative than whatever is displayed for PGen. Cadence also claims that performance can be increased by 2 to 5 times compared to PGen. IntelliGen solves some constraint more logically and intelligently compared to PGen. We will see all these in few examples.

  • Generation Order Independence
In the code shown below, we want to generate addr based on addr_hi_lo value. So you put constraint over addr_hi_lo and addr. But since addr is declared first, it will be generated first in PGen generation engine. Due to that, there are very little chance that it is either equal to addr_hi or addr_lo. So, either of the constraint on addr_hi_lo does not satisfy and PGen will not be able to solve it. Though the constraint is bidirectional, since addr is declared first, it is generated first and that makes constraint unidirectional.
Same code will not cause any generation error if IntelliGen is used because, there is not generation dependency on declaration order.

<'
define addr_hi 0xFF;
define addr_lo 0x05;
type addr_kind : [LO, HI];
extend sys
{
addr : list of uint (bits: 8);
addr_hi_lo : addr_kind;
keep addr.size() == 10;
keep for each in (addr)
{
addr_hi_lo == HI => it == addr_hi;
addr_hi_lo == LO => it == addr_lo;
};
post_generate() is also { print addr; };
};
'>

Results with PGen:

*** Error: Contradiction:
A contradiction has occurred when generating sys-@0.addr_hi_lo :
Previous constraints reduced its range of possible values,
then the following constraint contradicted these values:
addr_hi_lo == LO => it == addr_lo; at line 20 in @temp
Reduced: sys-@0.addr_hi_lo into []
To see details, reload and rerun with "collect gen"

Results with IntelliGen:

addr = (10 items, dec):
5 5 5 5 5 5 5 5 5 5 .0

  • Better Solvability
Further to that, IntelliGen takes good care of soft and soft select constraints. When soft select constraints are added for a field which already has soft constraint defined previously, PGen will ignore all the previously defined soft constraints even there are no contradiction between soft and soft select constraints. Whereas IntelliGen takes care of both constraints as long as they do not contradict. If they contradict, then IntelliGen ignores soft constraint over soft select. Take a look at the following example and results generated using PGen and IntelliGen.
<'
type addr_kind : [LO, HI, OTHERS];
struct operation_s
{
addr_hi_lo : addr_kind;
keep soft addr_hi_lo in [HI, LO];
};
extend operation_s
{
keep soft addr_hi_lo == select
{
10 : LO;
80 : OTHERS;
10 : HI;
};
};
extend sys
{
op : list of operation_s;
keep op.size() == 10;
post_generate() is also { print op; };
};

Results with PGen:

op =
item type addr_hi_lo

0. operation* OTHERS
1. operation* OTHERS
2. operation* OTHERS
3. operation* OTHERS
4. operation* HI
5. operation* OTHERS
6. operation* OTHERS
7. operation* HI
8. operation* HI
9. operation* OTHERS

Results with IntelliGen:

op =
item type addr_hi_lo

0. operation* LO
1. operation* LO
2. operation* HI
3. operation* HI
4. operation* LO
5. operation* HI
6. operation* HI
7. operation* LO
8. operation* LO
9. operation* LO

  • Better Distribution
Because of improved constraint solving ability, IntelliGen gives better distribution of generated values within the range.
<'
define addr_hi 0xFF;
define addr_lo 0x05;
type op_kind : [LO, HI, OTHERS];
struct operation_s
{
addr : uint (bits: 8);
op_hi_lo : op_kind;
keep op_hi_lo == HI => addr == addr_hi;
keep op_hi_lo == LO => addr == addr_lo;
keep op_hi_lo == OTHERS => addr in [addr_lo+1..addr_hi-1];
};
extend sys
{
op : list of operation_s;
keep op.size() == 10;
post_generate() is also { print op; };
};

Results with PGen:

op =
item type addr op_hi_lo

0. operation* 0x57 OTHERS
1. operation* 0x12 OTHERS
2. operation* 0x80 OTHERS
3. operation* 0xbe OTHERS
4. operation* 0x7f OTHERS
5. operation* 0x64 OTHERS
6. operation* 0x0f OTHERS
7. operation* 0xab OTHERS
8. operation* 0x6e OTHERS
9. operation* 0xcd OTHERS

Results with IntelliGen:

op =
item type addr op_hi_lo

0. operation* 0xff HI
1. operation* 0xc3 OTHERS
2. operation* 0xff HI
3. operation* 0x05 LO
4. operation* 0x05 LO
5. operation* 0x05 LO
6. operation* 0x1d OTHERS
7. operation* 0x6a OTHERS
8. operation* 0x1a OTHERS
9. operation* 0xff HI


  • Better Debug Information
When any generation error occurs, IntelliGen issues elaborated generation error message which is very useful to pin point the problematic area of the code. Look at the below code.
<'
type addr_kind : [LO, HI, OTHERS];
struct operation_s
{
addr_hi_lo : addr_kind;
keep addr_hi_lo in [HI, LO];
};
extend sys
{
op : list of operation_s;
keep op.size() == 10;
keep for each in (op)
{
index in [0] => it.addr_hi_lo == LO;
index in [1..8] => it.addr_hi_lo == OTHERS;
index in [9] => it.addr_hi_lo == HI;
};
post_generate() is also { print op; };
};
'>

Error Message with PGen:

*** Error: ERR_GEN_OR_WITH_NO_GEN_ALT: After static analysis, the following constraint
consists of non-enforceable constraints only:
index in [1..8] => it.addr_hi_lo == OTHERS; at line 19 in @temp

Error Message with IntelliGen:

*** Error: Contradiction when generating sys

No set of values exists for:
op[0x0..0xffffffff].addr_hi_lo

that obey the constraints:
keep addr_hi_lo in [0x0..0x1] at line 7 in @temp ,
index in [0x1..0x8] => it.addr_hi_lo == OTHERS at line 19 in @temp

with the input:
index = 0x1

By now, you might have realized the improvement of IntelliGen over PGen. I hope this is useful basic information about IntelliGen. I'll cover IntelliGen Technical Concepts in my next post.

Monday, 15 June 2009

Specman/Verification Books

Specman Books

Design Verification with e
Author : Samir Palnitkar
ISBN 0131413090
Publisher Prentice Hall Professional Technical Reference
Publish Date Auguts, 2003
Page 416
Preview
 
The e-Hardware Verification Language
Author : Sasan Iman and Sunita Joshi
ISBN 1402080239
Publisher Kluwer Academic Publishers
Publish Date May, 2004
Page 349
Preview
 
Aspect-Oriented Programming with the e Verification Language: A Pragmatic Guide for Testbench Developers
Author : David Robinson
ISBN 0123742102
Publisher Morgan Kaufmann Publishers
Publish Date August, 2007
Page 244
Preview
 

Verification Books

Metric Driven Design Verification: An Engineer's and Executive's Guide to First Pass Success
Author : Hamilton B. Carter; Shankar G. Hemmady
ISBN 0387381511
Publisher Springer Verlag
Publish Date May, 2007
Page 361
Preview
 
Writing Testbenches: Functional Verification of HDL Models
Author : Janick Bergeron
ISBN 1402074018
Publisher Kluwer Academic Publishers
Publish Date February, 2003
Page 512
Preview
 
Effective Functional Verification: Principles and Processes
Author : Srivatsa Vasudevan
ISBN 0387286012
Publisher Springer Verlag
Publish Date June, 2006
Page 256
Preview
 
Principles of Functional Verification
Author : Andrea S. Meyer
ISBN 0750676175
Publisher Newnes
Publish Date November, 2003
Page 240
Preview
 

SystemVerilog Books

Step-by-step Functional Verification with SystemVerilog and OVM
Author : Sasan Iman
ISBN 0981656218
Publisher Hansen Brown Publishing
Publish Date May, 2008
Page 520
Preview
 
SystemVerilog for Verification: A Guide to Learning the Testbench Language Features
Author : Spear, Chris
ISBN 0387270361
Publisher Springer
Publish Date June, 2007
Page 429
Preview
 
Verification Methodology Manual For Systerm Verilog
Author : Andy Nightingale, Alan Hunter, Eduard Cerny and Janick Bergeron
ISBN 0387255389
Publisher Springer-Verlag New York Inc
Publish Date 2005
Page 503
Preview
 
Writing Testbenches Using SystemVerilog
Author : Janick Bergeron
ISBN 0387292217
Publisher Springer-Verlag New York Inc
Publish Date 2006
Page 412
Preview
 
A Practical Guide for System Verilog Assertions
Author : Srikanth Vijayaraghavan and Meyyappan Ramanathan
ISBN 0387260498
Publisher Springer Verlag
Publish Date 2005
Page 334
Preview
 
Hardware Verification With SystemVerilog: An Object-oriented Framework
Author : Mike Mintz and Robert Ekendahl
ISBN 0387717382
Publisher Springer
Publish Date May, 2007
Page 314
Preview