One can generate the fields of a struct on-the-fly by calling the gen action from a TCM or a method.[1] The gen action generates a random value for the instance of the item specified in the expression and stores the value in that instance, while considering all relevant constraints at the current scope on that item or its children. Constraints defined in a scope above the scope from which the gen action is executed are ignored. It is possible to generate values for particular struct instances, fields, or variables during simulation (on-the-fly generation) with the gen action. It is not possible to use the gen action to generate units. The syntax for the gen action is as follows:
[1] Although the gen action is introduced in the chapter on TCMs, it can also be called from non-TCM methods or constructs.
gen gen-item [keeping {[it].constraint-bool-exp; ...}];
Additional constraints can be applied to a particular instance of the item by use of the keeping keyword. This constraint applies for that instance in addition to all other constraints applicable to the item from its original struct definition. The fields of the gen action are shown in Table 8-3 below.
gen-item | A generatable item. If the expression is a struct, it is automatically allocated, and all fields under it are generated recursively, in depth-first order. |
constraint-bool-exp | A simple or a compound boolean expression. |
Example 8-7 uses the gen action within a TCM called gen_next() to create packets to send to the DUT. A constraint within the gen action keeps len with a range of values. A constraint defined at a lower scope level, packet, is also applied when the gen action is executed, keeping the size of the data field equal to the len field. The constraint defined at the sys level keep sp.next_packet.len == 4; is not considered because it is not at the current scope of the gen action.
Example shows the use of a gen action. <' extend sys { event event_clk is rise('~/top/clk')@sim; //define clock event sp: send_packet; //Instantiate send_packet keep sp.next_packet.len == 4; //constraint on sp.next_packet.len }; struct packet { //Define packet struct len: int [0..10]; kind: [normal, control, ack]; data: list of int; keep me.data.size() == len; }; struct send_packet { //Struct to send the packet. num_of_packets_to_send: int [0..20]; //Series of packets !next_packet: packet; //A packet instance with do-not-generate gen_next() @sys.event_clk is { //Define TCM gen num_of_packets_to_send; // Random loop delimiter for i from 0 to num_of_packets_to_send - 1 do { wait ([100]*cycle); gen next_packet keeping { // gen the packet .len in [5..10]; //additional constraint on len .kind in [normal, control]; //constraint on kind //This will generate a packet with len in 5..10 instead //of 0..10 and kind will be either normal or control //but not ack. }; //end of gen action }; //end of for loop }; //end of gen_next() TCM run() is also { start gen_next(); //Start the TCM at time 0. }; }; '>