Thursday, February 19, 2009

Automated coverage closure

Nusym tool does automated coverage closure. It automatically directs the random constraints so as to target coverage points.It automates the process of going between coverage goals and determining what constraints to modify, then modifying the constraint to achive the coverage goal. When we hit bug in random scenario we generally re-play the sequence to fix the bug , but with Nusym's verification tool the same bug is reproduced just at the point of bug , the long sequence of random transaction need not be reproduced to hit the bug. The tool supports both VERA and Systemverilog languages for automatic coverage closure.

Sunday, February 15, 2009

Randomization of scalar variables -- System Verilog

In VERA/NTB to randomize a set of variables we need to have variables in the class add constraints/ in-line constraints to randomize the variables. More over the variables have to be of type rand or randc Assume we have a requirement to randomize a set of variables outside a class with a set of constraints. We have the option of using random(),urandom() or urandom_range() and randomize the variables separately. When we use the above listed random methods we can not randomize a variable based on another variable.

System verilog has an option of randomizing scalar variables out side a class with constraints.

Example

integer a,b,c;
void'( std::randomize(a,b,c) with { a==b;b>0;c==10; } );

The above construct generates random values for a,b,c the constraint is provided in line. The variables a,b,c are out side the class scope.

Saturday, February 14, 2009

Coverage grading

What is coverage grading ?

Coverage grading is an option used to rank the test cases based on the number of functional coverage points hit by the individual test case. Grading option can be used to analyze and remove redundant test cases which is targeting the same functionality. This will help to optimize the regression run and save simulation time.

In random test run scenario it also helps in identifying the random seeds which provides maximum coverage.It will be a good idea to go for functional coverage grading when the verification environment and test cases are frozen and suitable functional coverage numbers are achieved. if your test bench is constantly in development and changing ,using the same seed that gave you good coverage before may not do so again since the randomization may have been affected by the changes in the source code.

Command to generate functional coverage grading in VCS is

urg -dir ( *.vdb ) -grade -metric group

Sunday, February 8, 2009

functional coverage

Code coverage metrics such as line coverage, fsm coverage, expression coverage, block coverage, toggle coverage and branch coverage is extracted automatically by the code coverage tool it gives us the picture of which sections of the RTL have been executed. Root cause analysis can be done on the code coverage holes and suitable test case can be added to cover the RTL functionality.Code coverage has a draw back of not identifying missing features in the RTL. There is no automatic way of getting the correlation between the functionality to be tested and the implementation of the functionality.Lot of manual effort has to put in to get this correlation.

Functional coverage is the determination of how much functionality of the design has been exercised by the verification environment. Functional coverage is a user defined coverage which maps every functionality to be tested (defined in the test plan) to a coverage point. When ever the functionality to be tested is hit in the simulation the functional coverage point is automatically updated. Functional coverage report can be generated which gives us the summary of how many coverage points where hit. Functional coverage metrics can be used as a feedback path to measure the progress of a verification effort.

Adding functional coverage to a verification environment involves three steps.

1. Identifying the functional coverage and cross coverage points.
( directly maps to your test plan )
2. Implementing the functional coverage monitors.
3. Running simulation to collect the functional coverage and functional coverage analysis.

Methodology of identifying functional coverage points and cross coverage points can be explained with a simple USB2.0 Bulk transfer example.


12 diffrent axis have been identified for a simple USB 2.0 bulk transfer. Total no of basic coverage points for this functional coverage group is 34 coverage points. Now we need to get the cross coverage points. So what is a cross coverage point ? Cross coverage is the valid combinations of the identified axis for example one cross coverage point can be

HS(speed) --> IN(direction) -->ACK(response) -->SMALL(length) --> No (data toggle error)

--> No (crc error) -->No ( pid error) --> SMALL (No of tokens per uframe)

--> No ( token error) --> ODD (payload) --> OFF (ping token)

We need to identify all the cross coverage points for this functional coverage group. Each of the cross coverage point is an test scenario. The way to find all the cross coverage point is to simply cross all the axis which will give you all the possible combinations, now eliminate the invalid combinations. Eliminating the invalid cross can be done using ignore construct or bad state construct in VERA/NTB.

example :: finding the cross coverage points for Axis1 and Axis2 alone. ( In the actual scenario all the axis should be taken in to account). possible cross coverage points

HS --> IN, HS -->OUT , FS --> IN , FS-->OUT

4 cross coverage points have been identifyed by crossing Axis 1 and Axis 2.

Now the identified functional coverage / cross coverage points need to be implemented in VERA/NTB/SV as a coverage group and integrated to the verification environment.

Saturday, February 7, 2009

Fine-grain process control -- System Verilog

In Vera/NTB the user has very limited control to the threads/process spawned by fork ..join construct . We have constructs like wait_child() to wait for all the threads to complete. terminate() to kill all threads spawned. What was missing in VERA/NTB was the fine-grain process control which will allow the user to selectively suspend,resume,wait and kill the spawned threads.

System Verilog has a build in process class which can be used for fine-grain process control.This process class is a good addition in system verilog and provides fine-grain process control which was not available in VERA/NTB. The prototype of the process class is as follows.



class process;
enum state { FINISHED, RUNNING, WAITING, SUSPENDED, KILLED };
static function process self();
function state status();
task kill();
task await();
task suspend();
task resume();
endclass

Objects of type process are created internally when processes are spawned. Users cannot create objects of type process; attempts to call new shall not create a new process, and instead result in an error. The process class cannot be extended. Attempts to extend it shall result in a compilation error.

The self() function returns a handle to the current process, that is, a handle to the process making the call. The status() function returns the process status, as defined by the state enumeration:



  • FINISHED Process terminated normally.

  • RUNNING Process is currently running (not in a blocking statement).

  • WAITING Process is waiting in a blocking statement.

  • SUSPENDED Process is stopped awaiting a resume.

  • KILLED Process was forcibly killed (via kill or disable).

The await() task allows one process to wait for the completion of another process. It shall be an error to call this task on the current process, i.e., a process cannot wait for its own completion.


The suspend() task allows a process to suspend either its own execution or that of another process. If the process to be suspended is not blocked waiting on some other condition, such as an event, wait expression, or a delay then the process shall be suspended at some unspecified time in the current time step.

The resume() task restarts a previously suspended process.


The kill() task terminates the given process and all its sub-processes, that is, processes spawned using fork statements by the process being killed.


Usage example for the process class


task do_n_way( int N );
process job[1:N];
for ( int j = 1; j <= N; j++ )
fork
automatic int k = j;
begin job[j] = process::self(); ... ; end
join_none
for( int j = 1; j <= N; j++ ) // wait for all processes to start
wait( job[j] != null );
job[1].await(); // wait for first process to finish
for ( int k = 1; k <= N; k++ ) begin
if ( job[k].status != process::FINISHED )
job[k].kill();
end
endtask