Most application require to randomize elememts of array.Arrays are used to model payload,port connections etc.
SystemVerilog has Fixed Arrays,Dynamic arrays,queues and Associative arrays.
If an array is constrained by both size constraints and iterative constraints for constraining every element of array. The size constraints are solved first, and the iterative constraints next. In the example,size_c is solved first before element_c. As constraint element_c canot be solved without knowing the size. So there is implicit ordering while solveing this type of constraints.
This is the only approach for applying constraints to individual elements of arrays, with this approach,performance is degraded. If Payload.size() = 1000, then 1000 constraints are created by foreach. it takes much time for the solver to solve all the constraints. Another simple approach is using a task to randomize each element. This approach is 5X times faster than foreach.
EXAMPLE: class Eth_pkt_82;
randbyte Payload[] ;
constraint size_c { Payload.size() inside {[46:1500]}; }
task randomize_foreach;
foreach ( Payload[ i ] )
Payload[ i ] = 50 + $urandom % 50;// try with randomize( Payload[i]) with .....
endtask endclass
program iterative;
Eth_pkt_82 obj;
initial begin obj = new();
for(int i=0;i< 10000;i++)
begin void'(obj.randomize());
obj.randomize_foreach();
end end endprogram
In applications where some constraints are dependent on the array elements, the following may help. call the randomization function in constraints, define proper variable ordering.
EXAMPLE: class Eth_pkt;
randbyte Payload[] ;
randbyte size;
bit dummy = 1;
initial begin obj = new();
void'(obj.randomize());
for(int i=0;i< 10;i++)
begin void'(obj.randomize());
$display(" Eth_pkt.size : %d :: Payload.size() : %d ",obj.size,obj.Payload.size());
for(int j=0;j<obj.Payload.size();j++)
$write("%4d _",obj.Payload[j]);
$display("");
end end endprogram
In the above example, constraint order_c1 {solve size before dummy;} makes sure that size is randomized before function ranomize_size() is called.
If constraints are dependent on the sum of the elements of the dynamic array. The interesting elements are the new random variables which are created by current randomization call. If you are not using any techinique to get the right size after randomization sum() returns the sum of all the array elements .
Do manually in a function and use it or just use { data.sum() with (item.index < size) 1000;}There is one more bug in the above code.The sum() method returns a single value of the same type as the array element type.So the sum returns only 8 bits in this case.So a.sum() is allways less than 255 which is less than 1000 and allways the constraint is satisfied which is not what is expected.
EXAMPLE: program summ;
dynamic_array obj = new();
integer sum;
initial begin sum =0;
void'(obj.randomize());
for(int i=0;i< obj.size ;i++)
sum= sum+obj.data[i];
$display(" Sum is %d ",sum);
end endprogram
Using y.sum with (item + 32'b0) will result in a 32 bit proper sum.
program summ;
dynamic_array obj = new();
integer sum;
initial repeat(10)
begin sum =0;
void'(obj.randomize());
for(int i=0;i< obj.size ;i++)
begin sum= sum+obj.data[i];
end $display(" Sum is %d obj.sum() %d",obj.data[0],obj.data.sum());
end endprogram
Randomization donot create the objects. So when a array of objects is randomized, all the objects are pointing to null and randomization can not be done on null objets.new() has to be called to creat objects then only randomize can be done on it.So creat array of objects before calling the randomize.
EXAMPLE: class cls;
randinteger Var;
endclass
class arr_obj;
rand cls objcls [0:2];
endclass
program arr_obj_p_91;
arr_obj obj = new() ;
int i;
initial begin if(obj.randomize())
begin $display(" Randomization is done ");
for(i=0;i<3;i++)
if(obj.objcls[i] == null )
$display( " obj.objcls == null ");
else $display(" obj.objcls.Var : %d ", obj.objcls[i].Var );
end else $display(" Randomization failed ");
end endprogram RESULTS:
In the following, objects are created during the creation of arr_obj. This can also be done in pre_randomize. When dynamic arrays of objects are created, similar approach has to be taken and size of the dynamic array has to be decided before the new() is called, which makes no sense using the dynamic array of objects.
EXAMPLE: class cls;
randinteger Var;
endclass
class arr_obj;
rand cls objcls [0:2];
function new();
foreach(objcls[i])
objcls[i]=new();
endfunction
endclass
program arr_obj_p_91;
arr_obj obj = new() ;
int i;
initial begin if(obj.randomize())
begin $display(" Randomization is done ");
for(i=0;i<3;i++)
if(obj.objcls[i] == null )
$display( " obj.objcls == null ");
else $display(" obj.objcls.Var : %d ", obj.objcls[i].Var );
end else $display(" Randomization failed ");
end endprogram RESULTS:
To create queue of objects,first length of the queue has to be randomized.Then number of objects equal to length of queue.Delete the old elements in the queue.Then push each object new objects in to the queue.Lastly randomize each object.
EXAMPLE: class cls;
randinteger Var;
endclass
class q_cls;
rand cls obj[$];
randbit [2:0] length;
functionvoid pre_randomize();
length = $urandom % 20 ; // Compute the length of queue.
obj = {} ; // Delet all the elements in the queue or .delet can be used
repeat(length)
begin cls obj_loc;
obj_loc = new(); // Creat new object.
obj.Push_back(obj_loc) ; // insert it into queue.
end endfunction endclass
program q_obj_p_93;
q_cls obj = new();
initial begin if(obj.randomize())
begin $display( "Randomization done");
$write( " Length of q : %0d :::",obj.length);
for(int i ;i< obj.length;i++)
begin cls obj_temp;
obj_temp = obj.obj.Pop_front();
$write(" : %0d : ",obj_temp.Var);
end end else $display( "Randomization failed");
end endprogram RESULT:
Some application like linked list needs to generate an array of random values which are unique. foreach provides the solution,but the simples and the best solution is assign all the elements in arrat with its index and use shuffel inside a task.shuffle() randomizes the order of the elements in the array.Constraint solver is not used hear,so the preformance is better.
EXAMPLE: class List;
integer Pointer[5] ;
task randomize_unique;
foreach ( Pointer[ i ] )
Pointer[ i ] = i;
Pointer.shuffle();
endtask endclass
program Unique_rand_94;
List obj;
initial begin obj = new();
obj.randomize_unique();
for(int i=0;i< 5;i++)
begin $display(" Pointer[%0d] = %d ",i,obj.Pointer[i]);
end end endprogram RESULT: