Saturday, 16 April 2016

SystemVerilog FAQ1

What happens if I randomize variable var1 using constraint cn {0 < var1 < 100;}?
The solver considered the this constraint as (0 < var1) || (var1 < 100), so result will not be as expected.
Ex1: value 500: It is not less than 100 but it is greater than 0,
Ex2: value -1: It is not greater than 0 but it is less than 100.
To solve this issue use one of the following way,
1. Use inside operator like, constraint cn {var1 inside {[1:99]};}
          You can’t use constraint cn {var1 inside {(0:100)};} -> Wrong Syntax
2. Constraint cn {var1 >0; var1 < 100}



What are bi-directional constraints?
Constraints by-default in SystemVerilog is bi-directional. That implies that the constraint solver doesn't follow the sequence in which the constraints are specified. All the variables are looked simultaneously. Even the procedural looking constrains like if ... else ... and -> constrains, both if and else part are tried to solve concurrently.

So, all the variables are randomized simultaneously,
typedef enum {low, mid, high} AddrType;
class MyBus extends Bus;
rand bit [15:0] addr;
rand AddrType atype;
constraint addr_range {
(atype == low ) -> addr inside { [0 : 15] };
(atype == mid ) -> addr inside { [16 : 127]};
(atype == high) -> addr inside {[128 : 255]};
}
endclass
So as shown in above example, the value chosen for addr depends on atype and how it is constrained, and the value chosen for atype depends on addr and how it is constrained.



What is circular dependency?
Too many explicit variable ordering in randomization may lead to circular dependency. The LRM says that "Circular dependencies created by the implicit variable ordering shall result in an error." and "circular dependency is not allowed". But it does not put restriction on what to do if an explicit circular dependency exists.
...
int x, y, z;
constraint XYZ  {
 solve x before y;
 solve y before z;
 solve z before x;
 ....
}



What is solve...before constraint? 
By default Constraint solver tried to randomize all variables simultaneously.
In the case where the user want to specify the order in which the constraints solver shall solve the constraints, the user can specify the order via solve before construct.



What is the difference between randomize() and std::randomize() method?
Variables in an object are randomized using the randomize() class method. Every class has a built-in randomize() virtual method. However, std::randomize() is a mechanism to randomize data that do not belong to a class.
Ultimately, randomize() is a virtual method of class, so class’s variables are randomized using randomize() method while std::randomize() is used when you want to randomize variable without writing class and creating its object.



Are pre_randomize/post_randomize methods virtual?
No. The pre_randomize() and post_randomize() methods are not virtual. However, because they are automatically called by the randomize() method, which is virtual, so they appear to behave as virtual methods.
Below 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.
-----------------------------------------------------------------------------------------------
class Base;
function void pre_randomize;
$display(" BASE PRE_RANDOMIZATION ");
endfunction
virtual function void post_randomize;
$display(" BASE POST_RANDOMIZATION ");
endfunction
endclass
class Extend extends Base;
function void pre_randomize;
$display(" EXTEND PRE_RANDOMIZATION ");
endfunction
function void post_randomize;
$display(" EXTEND 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
//Output:
// Error-[SV-IBCMO] Illegal built-in class method override
// Built-in class method 'post_randomize' cannot be overridden 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. This is virtual function behaviour.
-----------------------------------------------------------------------------------------------
class Base;
function void pre_randomize;
$display(" BASE PRE_RANDOMIZATION ");
endfunction
function void post_randomize;
$display(" BASE POST_RANDOMIZATION ");
endfunction
endclass
class Extend extends Base;
function void pre_randomize;
$display(" EXTEND PRE_RANDOMIZATION ");
endfunction
function void post_randomize;
$display(" EXTEND 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
//Output:
// EXTEND PRE_RANDOMIZATION
// EXTEND POST_RANDOMIZATION
// EXTEND PRE_RANDOMIZATION
// EXTEND POST_RANDOMIZATION
-----------------------------------------------------------------------------------------------



Does post_randomize() is called if randomize() method is failed?
No.



How to randomize string variable?
String variable cannot be randomized directly using randomize method.
-----------------------------------------------------------------------------------------------
class rand_str;
string str;
rand int unsigned str_lngth;
rand char c[];
constraint cn_l {
str_lngth inside {[6:8]};
}
constraint cn_c {
c.size == str_lngth;
}
constraint cn_c1 {
foreach (c[i]) {
c[i] inside {[65:122]};
}
}
constraint order {
solve str_lngth before c;
}
function void post_randomize();
foreach (c[i]) begin
this.str = {str, string'(c[i])};
end
endfunction
endclass
module top();
rand_str R;
initial begin
R = new();
if (R.randomize()) begin
$display ("R.str=%s", R.str);
end
else begin
$error ("Randomization Failed");
end
end
endmodule
//Output:
// R.str=zsyF_]D
view raw rand_string.sv hosted with ❤ by GitHub
-----------------------------------------------------------------------------------------------



How to randomize real variable?
Using randomize() method we can randomize only integral data-type variables only (bit, logic, reg, wire, integer, enum, packed struct)
Here I show two ways to randomize variable of type real.
-----------------------------------------------------------------------------------------------
class rand_real_c;
rand bit [63:0] b;
real r;
function void post_randomize();
this.r = $bitstoreal(b);
endfunction
endclass
module top();
rand_real_c R;
initial begin
R = new();
if (R.randomize()) begin
$display ("R.b=%0d, R.r=%e", R.b, R.r);
end
else begin
$error ("Randomization Failed");
end
end
endmodule
//Output:
// R.b=9322325283763399790, R.r=-4.601070e-302
view raw bitstoreal_1.sv hosted with ❤ by GitHub
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
class rand_real_c;
rand integer i, j;
real r;
function void post_randomize();
this.r = $bitstoreal({i, j});
endfunction
endclass
module top();
rand_real_c R;
initial begin
R = new();
if (R.randomize()) begin
$display ("R.i=%0d,, R.j=%0d, R.r=%e", R.i, R.j, R.r);
end
else begin
$error ("Randomization Failed");
end
end
endmodule
//Output:
// R.i=727460974,, R.j=-2124444300, R.r=8.050506e-100
view raw bitstoreal_2.sv hosted with ❤ by GitHub
-----------------------------------------------------------------------------------------------




Without using randomize method or rand, generate an array of unique values?
...

int UniqVal[10];

foreach(UniqVal[i]) begin

  UniqVal[i] = i;

end

UniqVal.shuffle();




Can I use randc variable inside solve...before constraint? 
The following restrictions apply to solve...before:

1) Only random variables are allowed, that is, they shall be rand.
2) randc variables are not allowed. randc variables are always solved before any other.



Write code to generate one-hot random variable having length of 5 bit.
-------------------------------------------------------------
// Randmly generate one_hot variable having length of 5 bit
class rand_onehot #(int unsigned L = 5);
rand int unsigned a;
logic [L-1:0] one_hot;
constraint cn_1 {
a >= 0; a < L;
}
function void post_randomize();
one_hot = (1 << a);
endfunction
endclass
module top();
rand_onehot OH;
initial begin
repeat (5) begin
OH = new();
if (OH.randomize()) begin
$display ("OH.a=%0d, OH.one_hot=%b", OH.a, OH.one_hot);
end
else begin
$error ("Randomization failed");
end
end
end
endmodule
//Output:
// OH.a=1, OH.one_hot=00010
// OH.a=3, OH.one_hot=01000
// OH.a=2, OH.one_hot=00100
// OH.a=2, OH.one_hot=00100
// OH.a=1, OH.one_hot=00010
view raw one_hot.sv hosted with ❤ by GitHub

-------------------------------------------------------------



Write code to generate two-hot random variable having length of  5 bit.
-------------------------------------------------------------
// Randmly generate Two-hot (Having 2 one) variable having length of 5 bit
class rand_twohot #(int unsigned L = 5);
rand int unsigned a;
rand int unsigned b;
logic [L-1:0] two_hot;
constraint cn_1 {
a != b;
a >= 0; a < L;
b >= 0; b < L;
}
function void post_randomize();
two_hot = (1 << a) | (1 << b);
endfunction
endclass
module top();
rand_twohot TH;
initial begin
repeat (5) begin
TH = new();
if (TH.randomize()) begin
$display ("Th.a=%0d, TH.b=%0d, TH.two_hot=%b", TH.a, TH.b, TH.two_hot);
end
else begin
$error ("Randomization failed");
end
end
end
endmodule
//Output:
// Th.a=3, TH.b=4, TH.two_hot=11000
// Th.a=1, TH.b=4, TH.two_hot=10010
// Th.a=3, TH.b=1, TH.two_hot=01010
// Th.a=2, TH.b=1, TH.two_hot=00110
// Th.a=3, TH.b=4, TH.two_hot=11000
view raw two_hot.sv hosted with ❤ by GitHub

-------------------------------------------------------------




How to randomize dynamic unpacked array?
  1. Randomize size of dynamic array, it’s contents will be automatically randomized and assigned.
  2. Randomize size of dynamic array, then randomize content of dynamic array in post_randomize method.
    class ABC;
    // Dynamic array
    rand bit [7:0] data [];


    // Constraints
    constraint cc {
     // constraining size
     data.size inside {[1:10]};


     // constraining individual entry
     data[0] > 5;


     // All elements
     foreach(data[i])
     if(i > 0)
       data[i] > data[i-1];
    }
    endclass : ABC



What will be the output of following Code?
-------------------------------------------------------------
class base;
rand int a;
constraint c1 {
a > 0;
}
endclass : base
class child extends base;
constraint c2 {
a < 0;
}
endclass : child
class test;
base B;
child C;
function void abc();
C = new();
B = C;
if (!B.randomize()) begin
$error ("Randomization failed");
end
else begin
$display ("Randomization passed");
end
endfunction : abc
endclass : test
module top();
test T;
initial begin
T = new();
T.abc();
end
endmodule : top
//Output:
// Constraint failure
-------------------------------------------------------------

How to resolve it?
Need to turn off constraint of Base class.

How to turn off that constraint?
-------------------------------------------------------------
class base;
rand int a;
constraint c1 {
a > 0;
}
endclass : base
class child extends base;
constraint c2 {
a < 0;
}
endclass : child
class test;
base B;
child C;
function void abc();
C = new();
B = C;
B.c1.constraint_mode(0); // Turn OFF constraint of Base class as handld is of Base class
//B.c2.constraint_mode(0); // Using handle of Base class, can't turn OFF constraint which
// is defined in Child class even though handle of Base class
// points to object of Child class
if (!B.randomize()) begin
$error ("Randomization failed");
end
else begin
$display ("Randomization passed");
end
endfunction : abc
endclass : test
module top();
test T;
initial begin
T = new();
T.abc();
end
endmodule : top
//Output:
// Randomization passed

-------------------------------------------------------------


Write code to generate Fibonacci series of first N number using constraints.
-------------------------------------------------------------
class fibonacci;
rand int unsigned f_ary[];
rand int unsigned fibonacci_length;
constraint f_ary_size_cn {
f_ary.size() == fibonacci_length;
}
constraint f_ary_cn {
foreach (f_ary[i]) {
if (i == 0 || i == 1) {
f_ary[i] == i;
}
else {
f_ary[i] == f_ary[i-1] + f_ary[i-2];
}
}
}
endclass : fibonacci
module top();
fibonacci F;
initial begin
F = new();
if (!F.randomize() with { fibonacci_length == 10;}) begin
$fatal("Randomization failed");
end
else begin
$display("Lengh of Fibonacci series:%0d", F.fibonacci_length);
$write("Fibonaci series: ");
for (int unsigned i=0; i<F.fibonacci_length; i++) begin
if (i != F.fibonacci_length - 1) begin
$write("%0d, ", F.f_ary[i]);
end
else begin
$write("%0d\n", F.f_ary[i]);
end
end
end
end
endmodule : top
//Output:
// Lengh of Fibonacci series:10
// Fibonacci series: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34

-------------------------------------------------------------

No comments:

Post a Comment