quick.gif

space2.gif

space2.gif

space2.gif

space2.gif

space2.gif

space2.gif

space2.gif

   

space.gif

   

space.gif

  ../images/main/bullet_green_ball.gif Generation And Constraints

Test generation is a process producing data layouts according to a given specification. The specifications are provided in the form of type declarations and constraints. Constraints are statements that restrict values assigned to data items by test generation.

   

space.gif

A constraint can be viewed as a property of a data item or as a relation between several data items. Therefore, it is natural to express constraints using Boolean expressions. Any valid Boolean expression in e can be turned into a constraint. Also, there are few special syntactic constructs not based on Boolean expressions for defining constraints.

   

space.gif

  ../images/main/bulllet_4dots_orange.gif Types Of Constraints

Constraints can be sub-divided according to several criteria.

   

space.gif

  • Explicit constraints : This are those declared using the keep statement or inside keeping {...} block.
  • Implicit constraints : This are those imposed by type definitions and variable declarations. Implicit constraints are always hard.
   

space.gif

  • Value constraints : This restrict the range of possible values that the generator produces for data items, and they constrain the relationship between multiple items.
  • Order constraints : This influence the sequence in which data items are generated. Generation order is important because it affects the distribution of values and the success of generation.
   

space.gif

Both value and order constraints can be hard or soft:

   

space.gif

  • Hard constraints : This (either value or order) must be met or an error is issued. This can not be over ridden.
  • Soft value constraints : This suggest default values but can be overridden by hard value constraints.
  • Soft order constraints : This suggest modifications to the default generation order, but they can be overridden by dependencies between data items or by hard order constraints.
   

space.gif

You can define constraints in many ways:

   

space.gif

  • By defining a range of legal values in the field or variable declaration
  • By defining a list size in the list declaration
  • By using one of the keep construct variations within a struct definition
  • By using a gen...keeping action within a method
   

space.gif

Example :

   

space.gif


  1 <'
  2 struct constrain_gen_ex1 {
  3   // Explicit constrains
  4   x : int[1,3,5,10..100]; // is the same as
  5   x : int; keep x in [1,3,5,10..100];
  6   // Implicit Constrains 
  7   l[20] : list of int; // is the same as l : list of int; keep l.size()==20;
  8   // Value constraints
  9   // Limits the address from 0 to 1024
 10   addr : uint[0..1k];
 11   // Read = 0 and Write = 1
 12   rd_wr: bool;
 13   // Weights for rd_wr command
 14   rd_wt: uint[0..100];
 15   wr_wt: uint[0..100];
 16   // Order of generation is different
 17   // rd_wr was declared before rd_wt and wr_wt
 18   keep gen (rd_wt, wr_wt) before (rd_wr);
 19   // Generation based on weight
 20   // Soft Constrain
 21   keep soft rd_wr == select { 
 22     wr_wt : TRUE; 
 23     rd_wt : FALSE; 
 24   }; 
 25   // Hard constraint
 26   data : uint;
 27   keep data  ! = 0xdeadbeaf;
 28 
 29   // List constraint Example
 30   payload : list of byte;
 31   keep payload.size() < 10;
 32 };
 33 '>
You could download file constrain_gen_ex1.e here
   

space.gif

   

space.gif

  ../images/main/bulllet_4dots_orange.gif Generation Order

The fields in a struct are generated one by one, starting with the first field defined and progressing through the fields in the order in which they appear in the e code. A struct item is always fully generated, including all substructs, before the next item is generated. Similarly, within a list, each item is fully generated, including all substructs, before the next item is generated. Lists are generated in ascending index order.

   

space.gif

User-defined constraints can affect generation order. A constraint for a particular item might create a dependency that requires a field to be generated before some other fields. Value constraints that induce a generation order are called unidirectional constraints.

   

space.gif


  1 <'
  2 struct constrain_gen_ex2 { 
  3   good: bool; 
  4   length: byte [1..24]; 
  5   data [length]: list of byte; 
  6   crc: uint; 
  7   keep good => crc == crc_calc(); 
  8   keep gen (length, data) before (crc); 
  9  
 10   crc_calc() : uint is { 
 11     result = pack(packing.low,length,data).crc_32(0,length); 
 12   }; 
 13 }; 
 14  
 15 extend sys { 
 16   tb : list of constrain_gen_ex2;
 17   run() is also { 
 18     print sys.tb.crc; 
 19   }; 
 20 }; 
 21 '>
You could download file constrain_gen_ex2.e here
   

space.gif

  ../images/main/bulllet_4dots_orange.gif Unidirectional Constrains

Value constraints that induce a generation order are called unidirectional constraints. For example, the keep constraint shown below requires that the "kind" field be generated first. The test generator cannot determine the value of the expression "get_size(kind)" without first generating the value of "kind".

   

space.gif


 1 type kind: [tx, rx]; 
 2 struct packet { 
 3     kind; 
 4     size: byte; 
 5     keep size == get_size(kind); 
 6 }; 
You could download file constrain_gen_ex3.e here
   

space.gif

Expressions like "get_size(kind)" are treated like constants within the context of a constraint Boolean expression. That is, any parameters in these expressions are first generated, the operation is performed on the generated values, and the returned value can be used to constrain other generatable items in the constraint Boolean expression. In the example above, the field "size" is constrained by return value of "get_size(kind)".

   

space.gif

A unidirectional constraint can cause a runtime contradiction error if it selects a value for a parameter that turns out to conflict with a subsequent constraint. In the example below, the first constraint is unidirectional for b, c, and d because of the multiplication operator. Thus the generator first selects a value for b from the range [0..16], then selects a value for c from the range [0..4], and for d from the range [0..1]. Finally, the generator applies the constraint (a + 3*b + 12*c + 48*d) == 48. Most of the time this constraint results in a contradiction error because the values for three of the integers are selected before the constraint defining the required relationship between the integers is applied.

   

space.gif


  1 a: uint; 
  2 b: uint; 
  3 c: uint; 
  4 d: uint; 
  5 // Usually results in a contradiction error 
  6 keep a + 3*b + 12*c + 48*d == 48; 
  7 keep a <= 48; 
  8 keep b <= 16; 
  9 keep c <= 4; 
 10 keep d <= 1; 
You could download file constrain_gen_ex4.e here
   

space.gif

In some cases you can rewrite the constraints to avoid the contradiction error. To avoid the contradiction illustrated above, for example, you need define the generation order so that the integers in the multiplication expressions (d, c, and b) are generated before a. You also must define each integer based only on constants and the values of the previously generated integers. Modifying the constraints in this manner avoids the contradiction error. To change the distribution of values (50% of the time d is 1 and a, b, and c are all 0), you can either add keep soft select constraints or you can constrain one of the other integers (a, b, or c) to a constant, and then constrain the others based only on constants and products of previously generated integers.

   

space.gif


 1 d: uint; 
 2 keep d <= 1; 
 3 c: uint; 
 4 keep c <= (48 - 48*d)/12; 
 5 b: uint; 
 6 keep b <= (48 - 48*d - 12*c)/3; 
 7 a: uint; 
 8 keep a + 3*b + 12*c + 48*d == 48; 
You could download file constrain_gen_ex5.e here
   

space.gif

Unidirectional constraints can also cause a constraint cycle, which results in a runtime contradiction error. A constraint cycle occurs when two or more unidirectional constraints impose conflicting requirements on the generation order. For example, the first constraint shown below requires that the "kind" field be generated first. The second constraint, however, requires that the "size" field be generated first.

   

space.gif


 1 type kind: [tx, rx]; 
 2 struct packet { 
 3     kind; 
 4     size: byte; 
 5     keep size == get_size(kind); 
 6     keep kind == get_kind(size);    // Constraint cycle 
 7 }; 
You could download file constrain_gen_ex6.e here
   

space.gif

Sometimes it is useful to be able to continue a test even if constraint cycles exists.

   

space.gif

To identify the source of a constraint contradiction, you can use the collect gen and show gen commands to collect and view the order in which items are generated. The show gen command brings up the generation debugger so you can view information about how ranges were reduced by constraints during generation.

   

space.gif

   

space.gif

  ../images/main/bulllet_4dots_orange.gif Constraining Lists

There are several ways that you can constrain a list or its elements.

   

space.gif

  • List Size : You can constrain the list size of a field either by using a size expression in a field declaration or by using a keep constraint.
  • List Item : You can constrain an individual item in a list of scalar items using the keep constraint.
  • Item in List : You can constrain a list to keep a specific item in the list.
  • One List to Another List : You can constrain one list to contain the same items as another list, using the keep constraint.
   

space.gif


  1 <'
  2 struct constrain_gen_ex9 {
  3   // Define a list
  4   payload : list of bytes;
  5   // Soft constraint the size of list
  6   keep soft payload.size < 64K;
  7   // Constraint first byte = 0
  8   keep payload[0] == 0;
  9 
 10   // Example for Item in list
 11   magic_byte: uint; 
 12   keep magic_byte == 100; 
 13   keep magic_byte in payload;
 14 
 15   // Example for One List to Another List
 16   payload2 : list of bytes;
 17   keep payload2 == payload;
 18 };
 19 '>
You could download file constrain_gen_ex8.e here
   

space.gif

  ../images/main/bulllet_4dots_orange.gif Constraining Bit Slices

You can use the bit slice operator in constraints to achieve a variety of purposes. A simple example is using the bit slice operator to constrain the fields of a CPU instruction.

   

space.gif


 1 <'
 2 struct cpu_env { 
 3   instr: uint (bits: 16); 
 4   keep instr[15:13] == 0b100; 
 5   keep instr[12:8] == 0b11001; 
 6   keep instr[7:0] == 0b00001111; 
 7 }; 
 8 '>
You could download file constrain_gen_ex7.e here
   

space.gif

   

space.gif

   

space.gif

   

space.gif

space2.gif

space2.gif

space2.gif

space2.gif

space2.gif

  

Copyright © 1998-2014

Deepak Kumar Tala - All rights reserved

Do you have any Comment? mail me at:deepak@asic-world.com