SystemVerilog has randomize(),pre_randomize() and post_randomize() built-in functions for randomization. Calling randomize() causes new values to be selected for all of the random variables in an object. To perform operations immediately before or after randomization,pre_randomize() and post_randomize() are used.
Randomize()
Every class has a virtual predefined function randomize(), which is provided for generating a new value.Randomization function returns 1 if the solver finds a valid solution. We cannot override this predefined function. It is strongly recommended to check the return value of randomize function. Constraint solver never fails after one successful randomization, if solution space is not changed. For every randomization call, check the return value, solver may fail due to dynamically changing the constraints.In the following example, there is no solution for Var < 100 and Var > 200,so the randomization fails.
The best way to check status of randomization return value is by using assertion.
assert(obj.randomize());
EXAMPLE: program Simple_pro_13;
class Simple;
randinteger Var;
constraint c1 { Var <100;}
constraint c2 { Var >200;}
endclass initial begin Simple obj = new();
if(obj.randomize())
$display(" Randomization sucsessfull : Var = %0d ",obj.Var);
else $display("Randomization failed");
end endprogram
RESULTS:
# Randomization failed
If randomize() fails, the constraints are infeasible and the random variables retain their previous values. In the following example, For the first randomization call there is a solution. When the constraints are changed, the randomization failed. Simulation results show that after randomization failed, random variables hold their previous values.
EXAMPLE: program Simple_pro_14;
class Simple;
randinteger Var;
integer MIN = 20 ;
constraint c { Var < 100 ; Var > MIN ; }
endclass Simple obj;
initial begin obj = new();
if(obj.randomize())
$display(" Randomization successful : Var = %0d ",obj.Var);
else $display("Randomization failed: Var = %0d ",obj.Var);
obj.MIN = 200;
$display(" MIN is changed to fail the constraint");
if(obj.randomize())
$display(" Randomization sucsessfull : Var = %0d ",obj.Var);
else $display(" Randomization failed : Var = %0d",obj.Var);
end endprogram RESULTS:
# Randomization sucsessfull : Var = 87 # MIN is changed to fail the constraint. # Randomization failed : Var = 87
Pre_randomize And Post_randomize
Every class contains pre_randomize() and post_randomize() methods, which are automatically called by randomize() before and after computing new random values. When randomize() is called,it first invokes the pre_randomize() then randomize() finally if the randomization is sucesusful only post_randomize is invoked.
These methods can be used as hooks for the user to perform operations such as setting initial values and performing functions after assigning random variables.
Overriding of pre_randomize and post_randomize functions is allowed by child class. If parent class functions are not called when overriding pre_randomize() and post_randomize functions, parent class function definations will be omitted.
EXAMPLE: class Base;
functionvoid pre_randomize;
$display(" BASE PRE_RANDOMIZATION ");
endfunction functionvoid post_randomize;
$display(" BASE POST_RANDOMIZATION ");
endfunction endclass
program pre_post_16;
Base B = new();
Extend_1 E1 = new();
Extend_2 E2 = new();
initial begin void'(B.randomize());
void'(E1.randomize());
void'(E2.randomize());
end endprogram
In the extended class EXTEND_1, when overiding the builtin functions, parent class functions are not called. In the extended class EXTEND_2, super.methods are called which invokes the parent class methods also.
RESULTS:
# BASE PRE_RANDOMIZATION # BASE POST_RANDOMIZATION # EXTEND_1 PRE_RANDOMIZATION # EXTEND_1 POST_RANDOMIZATION # BASE PRE_RANDOMIZATION # EXTEND_2 PRE_RANDOMIZATION # BASE POST_RANDOMIZATION # EXTEND_2 POST_RANDOMIZATION
The pre_randomize() and post_randomize() methods are not virtual. However, because they are automatically called by the randomize() method, which is virtual, they appear to behave as virtual methods. This example demonstrates that these functions are not virtual but simulation results show that, it executed extended class definition functions. Extended class object is created and assigned to base class object. Calls to pre_randomize and post_randomize calls in object B ,executed the extended class definitions.
EXAMPLE: class Base;
functionvoid pre_randomize;
$display(" BASE PRE_RANDOMIZATION ");
endfunction virtualfunctionvoid post_randomize;
$display(" BASE POST_RANDOMIZATION ");
endfunction endclass
program pre_post_17;
Base B ;
Extend E = new();
initial begin B = E ;
void'(B.randomize());
void'(E.randomize());
end endprogram
RESULTS:
There should be compilation error.
In the above example compilation error is due to the declaration of post_randmoize() function as virtual. By removing the virtual keyword for the post_randomize() function, calling the randomize() function by parent and child class, both will execute functions of child class only. Which is a virtual function behaviour.
EXAMPLE: class Base;
functionvoid pre_randomize;
$display(" BASE PRE_RANDOMIZATION ");
endfunction functionvoid post_randomize;
$display(" BASE POST_RANDOMIZATION ");
endfunction endclass
If the class is a derived class and no user-defined implementation of pre_randomize() and post_randomize() exists, then pre_randomize() and post_randomize() will automatically invoke super.pre_randomize() and super.post_randomize() respectively.
EXAMPLE: class Base;
functionvoid pre_randomize;
$display(" BASE PRE_RANDOMIZATION ");
endfunction functionvoid post_randomize;
$display(" BASE POST_RANDOMIZATION ");
endfunction endclass
class Extend extends Base;
endclass
program pre_post_19;
Extend E = new();
initial void'(E.randomize());
endprogram
RESULTS:
# BASE PRE_RANDOMIZATION # BASE POST_RANDOMIZATION
EXAMPLE: class Base;
functionvoid pre_randomize;
$display(" BASE PRE_RANDOMIZATION \n");
endfunction functionvoid post_randomize;
$display(" BASE POST_RANDOMIZATION \n");
endfunction endclass
program pre_post;
Base B;
Extend E = new();
initial begin B = E;
if(B.randomize())
$display(" randomization done \n");
end endprogram
RESULTS:
BASE PRE_RANDOMIZATION EXTENDED PRE_RANDOMIZATION EXTENDED POST_RANDOMIZATION randomization done
Results show that, if extended class is having new definition, explicitly super.pre_ or post_ has to be called.
super.pre_randomize() is called in extended class, but super.post_randomize() is not called in above example. See the difference in results.
If a class A instance is in Class B,To randomize class A by calling the randomize function of class B,Class A instance has to be declared as rand variable.
EXAMPLE: class A;
randinteger Var;
endclass
class B;
rand A obj_1 = new() ;
A obj_2 = new();
endclass
program a_b_20;
B obj=new();
initial begin obj.obj_1.Var = 1;
obj.obj_2.Var = 1;
repeat(10)
begin void'(obj.randomize());
$display(" Var1 = %d ,Var2 = %d ",obj.obj_1.Var,obj.obj_2.Var );
end end endprogram
Look at the results. Variable of obj_2 is not randomized. Only variable of obj_1 which is declared as rand is ranomized.
Upon calling the randomize method of B object which contains rand A object, First B prerandomize is called, then A prerandomize method is called, then B is randomized, if a solution was found, new values are assigned to the random A objects.If solution was found, for each random object that is a class instance it's post_randomize method is called. That means if randomization is successful next B postrandomize, next A postrandomize functions are called. Upon calling B randomize function this is sequence it follow.
EXAMPLE: class A;
randinteger Var;
functionvoid pre_randomize;
$display(" A PRE_RANDOMIZATION ");
endfunction functionvoid post_randomize;
$display(" A POST_RANDOMIZATION ");
endfunction endclass
class B;
rand A obj_a;
function new();
obj_a = new();
endfunction functionvoid pre_randomize;
$display(" B PRE_RANDOMIZATION ");
endfunction functionvoid post_randomize;
$display(" B POST_RANDOMIZATION ");
endfunction endclass
program pre_post_21;
B obj_b = new();
initial void'(obj_b.randomize());
endprogram
RESULTS:
# B PRE_RANDOMIZATION # A PRE_RANDOMIZATION # B POST_RANDOMIZATION # A POST_RANDOMIZATION
If randomization failed for obj_a, then post_randomize of obj_a and post_randomize of obj_b won't be called, and randomization will fail for obj_b also.
EXAMPLE: class A;
randbit [2:0] Var;
constraint randge_c { Var > 2 ; Var < 2;}
functionvoid pre_randomize;
$display(" A PRE_RANDOMIZATION ");
endfunction functionvoid post_randomize;
$display(" A POST_RANDOMIZATION ");
endfunction endclass
class B;
rand A obj_a;
functionvoid pre_randomize;
$display(" B PRE_RANDOMIZATION ");
endfunction functionvoid post_randomize;
$display(" B POST_RANDOMIZATION ");
endfunction function new();
obj_a = new();
endfunction endclass
program pre_post_22;
B obj_b = new();
initial void'(obj_b.randomize());
endprogram
RESULTS:
# B PRE_RANDOMIZATION # A PRE_RANDOMIZATION
Disabling Random Variable
The random nature of variables declared as rand or randc can be turned on or off dynamically. To change the status of variable which is declared as rand or randc to state variable, built in rand_mode() method is used. State variables are not randomized by randomize() mehod. By default all rand and randc variables are active. When called as a task, the arguments to the rand_mode method determines the operation to be performed. If the arguments is 0, then all the variables declared as rand and randc will become non random i.e all random variables treated as state variables. IF argument is 1, then all variables declares as rand and randc will be randomized.
EXAMPLE: class rand_mo;
randinteger Var1;
randinteger Var2;
endclass
program rand_mo_p_23;
rand_mo obj = new();
initial begin void'(obj.randomize());
$display(" Var1 : %d Var2 : %d ",obj.Var1,obj.Var2);
obj.rand_mode(0); // Var1 and Var2 will be treated as State variables.
void'(obj.randomize());
$display(" Var1 : %d Var2 : %d ",obj.Var1,obj.Var2);
obj.rand_mode(1); // // Var1 and Var2 will be treated as random variables.
void'(obj.randomize());
$display(" Var1 : %d Var2 : %d ",obj.Var1,obj.Var2);
end endprogram
A compiler error shall be issued if the specified variable does not exist within the class hierarchy or eventhough it exists but not declared as rand or randc. The following example illustrates the second case.
EXAMPLE: class rand_mo;
randinteger Var1;
integer Var2;
endclass
In the above example, Var2 is state variable. If the random variable is an object handle, only the mode of the object is changed, not the mode of random variables within that object.
EXAMPLE: class rand_var;
randinteger Var2;
endclass class rand_mo;
randinteger Var1;
rand rand_var rv;
function new();
rv = new();
endfunction endclass
Randomization does not depend on life time of variable. Even if a variable is static,randomization is specfic to object.So rand_mode() on static variable,only switches off the randomization on the variable of that object.This is true for dist and randc.
In the following example, Var1 is static and Var2 is automatic.Var1 and Var2 in obj_2 are made nonrandom using rand_mode(0).Var1 and Var2 in obj_1 are getting randomized.The only difference between Var1 and Var2 is that new random value for Var1 is appreas on both objects.
EXAMPLE: class A;
randstaticinteger Var1;
randinteger Var2;
endclass
program A_p_27;
A obj_1 = new;
A obj_2 = new;
initial begin obj_2.Var1.rand_mode(0);
obj_2.Var2.rand_mode(0);
repeat(2)
begin void'(obj_1.randomize());
void'(obj_2.randomize());
$display("obj_1.Var1 : %d ,obj_1.Var2 : %d : obj_2.Var1 : %d ,obj_2.Var2 : %d :",obj_1.Var1,obj_1.Var2,obj_2.Var1,obj_2.Var2);
end end endprogram
Random variables declared as static are shared by all instances of the class in which they are declared. Each time the randomize() method is called, the variable is changed in every class instance.
Randomizing Nonrand Varible
All the variables(randc, rand and nonrandom variables) randomization nature can be changed dynamically. Using rand_mode() rand and randc varibles changes its nature. The random nature of variables which are not declared as rand or randc can also be randomized dynamically. When the randomize method is called with no arguments, it randomizes the variables which are declared as rand or randc,so that all of the constraints are satisfied. When randomize is called with arguments, those arguments designate the complete set of random variables within that object, all other variables in the object are considered state variables.
EXAMPLE: class CA;
randbyte x, y;
byte v, w;
constraint c1 { x < v && y > w ;}
endclass
program CA_p_28;
CA a = new;
initial begin a.x = 10;a.y = 10;a.v = 10;a.w = 10;
$display(" x : %3d y : %3d : v : %3d : w : %3d ",a.x,a.y,a.v,a.w);
void'(a.randomize()); // random variables: x, y state variables: v, w
$display(" x : %3d y : %3d : v : %3d : w : %3d ",a.x,a.y,a.v,a.w);
void'(a.randomize(x)); // random variables: x state variables: y, v, w
$display(" x : %3d y : %3d : v : %3d : w : %3d ",a.x,a.y,a.v,a.w);
void'(a.randomize(v,w)); // random variables: v, w state variables: x, y
$display(" x : %3d y : %3d : v : %3d : w : %3d ",a.x,a.y,a.v,a.w);
void'(a.randomize(w,x)); // random variables: w, x state variables: y, v
$display(" x : %3d y : %3d : v : %3d : w : %3d ",a.x,a.y,a.v,a.w);
end endprogram
RESULTS:
# x : 10 y : 10 : v : 10 : w : 10 # x : -71 y : 96 : v : 10 : w : 10 # x : -37 y : 96 : v : 10 : w : 10 # x : -37 y : 96 : v : -22 : w : 80 # x : -90 y : 96 : v : -22 : w : -41
In above example x and y are rand variables, v and w are state variables. When a.randomize() is called, all rand varibles are randomized and state variables are hold the same value. When a.randomize(w) is called, only w is considered as rand variable and all others as state varibles. Here w is in constraint block so it has to satisfy the constraints. v,y and x also are state variables now, they also need to satisfy the constraint else it fails.
Replacing the class variables, with its hierarchical result also should result same.
EXAMPLE: program CA_p_29;
CA a = new;
initial begin a.x = 10;a.y = 10;a.v = 10;a.w = 10;
$display(" x : %3d y : %3d : v : %3d : w : %3d ",a.x,a.y,a.v,a.w);
void'(a.randomize()); // random variables: x, y state variables: v, w
$display(" x : %3d y : %3d : v : %3d : w : %3d ",a.x,a.y,a.v,a.w);
void'(a.randomize( a.x )); // random variables: x state variables: y, v, w
$display(" x : %3d y : %3d : v : %3d : w : %3d ",a.x,a.y,a.v,a.w);
void'(a.randomize( a.v, a.w )); // random variables: v, w state variables: x, y
$display(" x : %3d y : %3d : v : %3d : w : %3d ",a.x,a.y,a.v,a.w);
void'(a.randomize( a.w, a.x )); // random variables: w, x state variables: y, v
$display(" x : %3d y : %3d : v : %3d : w : %3d ",a.x,a.y,a.v,a.w);
end endprogram
RESULTS:
# x : 10 y : 10 : v : 10 : w : 10 # x : -71 y : 96 : v : 10 : w : 10 # x : -37 y : 96 : v : 10 : w : 10 # x : -37 y : 96 : v : -22 : w : 80 # x : -90 y : 96 : v : -22 : w : -41
If you are not interested to satisfy the constraints in constraint block, instead of switching off the constraint block, just randomize the variables using scope randomize() function. Scope randomize provide the ability to randomize class variables also along with non class variables.
EXAMPLE: program CA_p_30;
integer x,y,v,w;
initial begin x = 10;y = 10;v = 10;w = 10;
$display(" x : %3d y : %3d : v : %3d : w : %3d ",x,y,v,w);
randomize( x ); // random variables: x state variables: y, v, w
$display(" x : %3d y : %3d : v : %3d : w : %3d ",x,y,v,w);
randomize(v,w ); // random variables: v, w state variables: x, y
$display(" x : %3d y : %3d : v : %3d : w : %3d ",x,y,v,w);
randomize(w,x ); // random variables: w, x state variables: y, v
$display(" x : %3d y : %3d : v : %3d : w : %3d ",x,y,v,w);
end endprogram
RESULTS:
# x : 10 y : 10 : v : 10 : w : 10 # x : -826701341 y : 10 : v : 10 : w : 10 # x : -826701341 y : 10 : v : 541037099 : w : -457978538 # x : 978699393 y : 10 : v : 541037099 : w : -683182079