Home > Community > Blogs > Functional Verification > specman 9 2 preview simplifying generation with table constraints
 
Login with a Cadence account.
Not a member yet?
Create a permanent login account to make interactions with Cadence more convenient.

Register | Membership benefits
Get email delivery of the Functional Verification blog (individual posts).
 

Email

* Required Fields

Recipients email * (separate multiple addresses with commas)

Your name *

Your email *

Message *

Contact Us

* Required Fields
First Name *

Last Name *

Email *

Company / Institution *

Comments: *

Specman 9.2 Preview: Simplifying Generation With ‘Table Constraints’

Comments(0)Filed under: Functional Verification, Incisive Enterprise Simulator (IES), e, Specman, Aspect Oriented Programming, AOP, IntelliGen, IES-XL

UPDATE 9/29/2009:
Long story short, this feature did not make the 9.2 release. However, if this was of interest to you please contact us so R&D can ask you some questions about what use cases this article made you think about. Apologies for the tease.
- Team Specman

[Preface: all features in the 9.2 preview series are in Beta now. We invite you to sign-up for the beta program and give this feature a test drive!]

[Team Specman welcomes back Reuven Naveh from Specman R&D to introduce another of “his” new features developed for Specman/IES-XL 9.2.]

 

Abstract
A “Table Constraint” is a constraint which uses a special kind of data type, which can be best described as “table” or “matrix” that enables selection of a record from the table (via additional constraints if you so desire). This article will define the term “matrix” in this context, and explain how it can be used in stimulus generation.

Problem Statement
A very common generation use case is to generate a set of values not just by randomizing them (according to constraints), but also by picking their values from an existing list of items. Currently, this can be done by generating the item out of a list, using the “in list” expression:

keep my_item in list_of_items

This code / coding style does work, but down the road it can lead to problems in two respects:

  • Scalability: if the item list is large, there can be a huge performance overhead involved in the sampling of the list and choosing an item, which needs to be done in each generation of my_item in the example above.
  • Solvability: this constraint is on the item, and not on its fields. Therefore, it is impossible to add constraints on the item fields and expect them to hold.

“Table constraints” present a solution to this problem by enabling the selection of a set of variables from a list of structs as the constraints are not on the item, but on its fields.

The semantics apply to generating an item out of a list of fixed items, but it can be also used to model more sophisticated cases, which may include generating variables from given ranges, or generating specific indices of items from the table (for examples of this, refer to examples 3 & 4 below)

Table Constraints Functionality

  • The syntax of the constraint: “keep (x1,x2…xn) in sys.T”, when x1…xn are expressions, and sys.T is the path to a list which serves as the “table”. There should be a 1-to-1 mapping between x1…xn and the element type of T (in number and types), otherwise if this is violated a load time error will be issued.
  • The expressions x1…xn need to be “atomic” expressions, i.e. generative variables, inputs, or constants. For example, it is possible to write “keep (x,read_only(y),100) in sys.T” but not “keep (x+f(),y-100,x==y) in sys.T”.
  • The in-table expression can also appear in compound constraints, with no restriction. For example, the constraint “keep b => (x==y or (x,y) in sys.T)” is OK..
  • The “table” is not an input to the constraint, but will be sampled once, during the buildup phase of the Constrained Field Set (CFS). Therefore, it is recommended to populate the tables at the beginning of sys.pre_generate() method.

 

Use Model / Examples

Example 1 (simplest case)

<’
struct S {
 a:bool;
 x:uint;
 y:uint;
 keep a => x
};
 

extend sys {
 !T:list of S;
 pre_generate()is first {
  for i from 1 to 10000 {
    var s:S;
    gen s;
    T.add(s);
   };
 };

  x:uint;
 y:uint;
 keep (TRUE,x,y) in sys.T;

 check() is also {
   check that x
<y;
 };
};
'>

Example 2 (more complex generation)

<’
type short_addr_t:uint(bits:18);
type long_addr_t:uint(bits:36);
struct addr_translator_s {
 input_addr:short_addr_t;
  output_addr:long_addr_t;
};
extend sys {
 !T:list of addr_translator_s;
 pre_generate() is first {
   //build the table here from a file };
 first_addr:short_addr_t;
 second_addr:long_addr_t;
 max_addr:long_addr_t;
 keep first_addr[17:9] == 0;
 keep first_addr + second_addr < max_addr;
 keep (first_addr,second_addr) in sys.T;
};
‘>

Example 3
This example demonstrates a problem in which we want a set of variables to belong to specific “cubes”, e.g., have x in [1..10], y in [100.200] and z in [1000..2000], or x in [100..200], y in [10..50] and z in [1..5]. This is done in the example by using the same syntax, but with translating the ranges to their min and max values.

<’
struct cube_3d {
min1:uint; max1:uint; min2:uint; max2:uint; min3:uint; max3:uint;
};
extend sys {
 !T:list of cube_3d;
pre_generate() is first {
//read the table from file
};
//the real output of the test
x:uint; y:uint; z:uint;
//auxiliary fields, used to pick the ranges from the table
minx:uint; maxx:uint; miny:uint; maxy:uint; minz:uint; maxz:uint;

//constraints…
keep x>=minx and x<=maxx;
keep y>=miny and y<=maxy;
keep z>=minz and z<=maxz;
keep (minx,maxx,miny,maxy,minz,maxz) in sys.T;
};
‘>

 

Example 4
In this example the generative variables are not fields of the table’s items, but their indices in the table. This is done by simply adding the indices as fields to the table item. The example models a problem with can describes as “keep l1[index1].l2[index2] < 100”. This example also demonstrates how to translate a table which is originally based on nested lists.

 

<’
struct l1_packet {
 l2:list of l2_packet;
};
struct l2_packet {
 size:uint;
 keep soft size == select {10:[1..99]; 90:others};
};
struct table_item {
 ind1:uint;
 ind2:uint;
 size:uint;
};
extend sys {
 !l1:list of l1_packet;
pre_generate() is first {
  gen l1;
  var tmp:table_item;
  for each using index (ind1) in l1 {
    for each using index (ind2) in it.l2 {
      tmp = new table_item with {
          .ind1 = ind1;
          .ind2 = ind2;
          .size = it.size;
      };
    };
  };
 };
 index1:uint;
 index2:uint;
 size:uint;
 keep size < 100;
 keep (index1,index2,size) in sys.T;
};
‘>

I hope you find this feature as helpful as the Named Constraints I described in my last post, and I invite you to send me any questions or feedback by posting a comment below, or relayed via Team Specman. 


Happy Coding!

Reuven Naveh
Specman R&D

Comments(0)

Leave a Comment


Name
E-mail (will not be published)
Comment
 I have read and agree to the Terms of use and Community Guidelines.
Community Guidelines
The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.