Tutorials ARRAY RANDOMIZATION

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;
constraint size_c { Payload.size() inside {[46:1500]}; }
foreach ( Payload[ i ] )
Payload[ i ] = 50 + \$urandom % 50;// try with randomize( Payload[i]) with .....
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;
rand byte size;
bit dummy = 1;

constraint dummy_c { dummy == randomize_size();}
constraint size_c { size inside {[10:100]};}
constraint order_c1 {solve size before dummy;}
constraint order_c2 {solve dummy before Payload;}

function bit randomize_size();
randomize_size = 1;
return randomize_size;
endfunction

endclass

program iterative_88;
Eth_pkt obj;

initial
begin
obj = new();
void'(obj.randomize());
for(int i=0;i< 10;i++)
begin
void'(obj.randomize());
\$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 .

EXAMPLE:
class dynamic_array_89;
rand byte size;
rand byte data[];
constraint size_c { data.size() == size; size >= 0; }
constraint sum_c { data.sum() < 1000;}
endclass

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.

EXAMPLE:
class dynamic_array;
rand integer size;
rand reg [7:0] data[];
constraint sum_c { data.sum() == data;}
constraint size_c { data.size() == size; size >1000 ;size < 2000; }

endclass

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,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;
rand integer 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:

# Randomization is done
# obj.objcls == null
# obj.objcls == null
# obj.objcls == null

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;
rand integer 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:

Randomization is done
obj.objcls.Var : 733126180
obj.objcls.Var : -119008195
obj.objcls.Var : 342785185

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;
rand integer Var;
endclass

class q_cls;
rand cls obj[\$];
rand bit [2:0] length;

function void 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:

Randomization done
Length of q : 6 ::: : 1474208060 : : -1098913923 : : 816460770 : : 41501707 : : -1179418145 : : -212817600 :

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 ;

foreach ( Pointer[ i ] )
Pointer[ i ] = i;
Pointer.shuffle();
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:

Pointer = 2
Pointer = 1
Pointer = 3
Pointer = 0
Pointer = 4

Using foreach in global constraints in the following way wont work currently. as the . operator(dot) is not supported in foreach in LRM currently.

EXAMPLE:
class parent;
rand byte a[0:9];
endclass

class child_96;
rand parent P;
rand byte a[0:9];
constraint Not_supported { foreach(P.a[i]) P.a[i] == a[i];}
endclass

The correct way to write the above constraint is
constraint Supported { foreach(a[i]) a[i] == P.a[i];}

 << PREVIOUS PAGE TOP NEXT PAGE >> 