随机方法
在类中声明的随机变量,需要伴随着类句柄调用方法randomize(),这是SV类的内建方法:
virtual function int randomize();
如果随机化成功则会返回1,如果失败则会返回0。
注意:
- 对象的例化和随机化是两件事,需要分布调用new()函数和randomize()函数。随机化之前,要先对对象完成例化。
- 在类中,被声明为随机属性的变量,只有被随机化以后,才能具备随机值。单纯的对象例化并不会带来随机值,只是它们的默认值,或者new()函数中被赋予的初值。
示例:
class Simpl eSum;
rand bit [7:0]x,y,z;
constraint c {z ==x + y;}
endclass
SimpleSum p = new;
int success = p.randomize() ;
if (success == 1 ) ...
内嵌约束(with)
上一节的软约束例子中,在对象例化时,添加了临时的外部约束
内嵌约束:在调用类方法randomize()时可以伴随着with来添加额外的约束。
示例:
class SimpleSum;
rand bit [7:0] x,y,z;
//c约束块,要求z为x和y之和
constraint c {z ==x + y;}
endclass
task InlineConstraintDemo(SimpleSum p) ;
int success;
//句柄p在随机化对象时,添加了内嵌约束,要求z=x+y的同时,x大于y
success = p.randomize() with {x > y;};
endtask
//如果两个约束都是硬约束,为了避免随机化失败,
//内嵌约束不应该与约束块c发生冲突
内嵌约束(指向模糊)
有的时候,内嵌约束中使用的变量 可能会出现指向模糊的问题。
同名的变量处在不同的域中,可能会出现指向模糊的情况 。
示例:
//C1 C2中都有变量x
//C2中的任何doit,也有输入参数x
class C1;
rand integer x ;
endclass
class C2 ;
integer x ;
integer y;
task doit(C1 f, integer x, integer z);
int result;
//在随机化句柄f指向的C1对象时,添加的内嵌约束中的x,有指向模糊的问题。
//这需要确定x到底是哪个域中的变量。
//实际上,这个x会被编译器理解为C1对象的成员变量。
result = f.randomize () with {x < y + z; };
endtask
endclass
内嵌约束(指向明确)
使得随机化函数指向的变量尽量明确。
同名的变量处在不同的域中,可能会出现指向模糊的情况。
解决方法:
- 在内嵌约束中指明参与的对象成员变量。 例如 with(x) {x > y}
- 指明约束块中,哪些变量来自对象之外的域。例如with( x > local::x)
在内嵌约束中指明参与的对象成员变量
示例:
class C;
rand integer x;
endclass
function int F(C obj, integer y);
//随机化C对象时,通过内嵌约束with的()中指明了
//内嵌约束块中的变量,哪些来自C对象的成员变量;而不在参数列表里面的变量即为C对象以外的变量
F= obj.randomize() with (x){ x < y; };
endfunction
指明约束块中,哪些变量来自对象之外的域(local域指向)
通过local::的域索引方式来明确随机变量的指向
即local::指向的变量会在包含randomize()方法的域中。
示例:
class C;
rand integer x;
endclass //在约束块中,x < local::x
function int F(C obj,integer x) ; //第一个 x指向C对象的成员变量
F = obj.randomize() with { x < local::x; };//local::x,指向C对象以外的域
endfunction
控制随机化和约束块
除了可以更灵活添加内嵌约束,提高公共约束的复用率之外,还可以在随机化对象之前,控制随机化和约束块。
随机控制—rand_mode()
rand_mode可以用来使能或者禁止成员变量的随机属性。
(rand_modeSV对域的预定义方法 )
当随机数被禁止时,它会同未声明为随机变量的普通变量一样,不会参与到随机化过程当中。
从以下两个函数声明可以看到,rand_mode使用范围:
- 可以就单个随机变量调用其rand_mode。【可以禁止/使能某个对象的成员变量随机模式】
- 可以对整个对象调用rand_mode来控制其中所有的随机变量。【可以禁止/使能整个对象的成员变量随机模式】
使能某一个成员变量的随机属性的前提:这个成员变量之前已经被声明为随机属性 。
task object[.random_variable]:: rand_mode( bit on_off ) ;
function int object.random_variable::rand_mode() ;
示例:
class Packet;
rand integer source_value,dest_value;
... other declarations
endclass
int ret;
Packet packet_a = new;
//rand_mode(O)。关闭对象中的所有变量,禁止整个对象的成员变量随机模式
packet_a.rand_mode(O) ;
、、 ...其他代码
//使能source_value
packet_a.source_value.rand_mode(1);
ret = packet_a.dest_value.rand__mode() ,
约束控制—constraint_mode ()
类似于随机模式控制,类的约束块都可以单个控制或者全部控制。
task object[.constraint_identifier]::constraint_mode(bit on_off );
function int object.constraint_identifier::constraint_mode();
constraint_mode( )
- 通过约束控制函数来使能或者关闭某些约束块。
- 调用函数获取某个约束块当前状态
示例:
//Packet类中的约束块 filter1 ,可以通过句柄 索引 约束块
//并且利用函数constraint_mode ()来关闭或者使能约束块
//被关闭的约束块,在接下来对象进行随机化的时候,将不会影响对象成员的随机化。
class Packet;
rand integer source_value ;
constraint filter1 { source_value > 2 *m; }
endclass
function integer toggle_rand( Packet p ) ;
if ( p.filter1.constraint_mode () )
p.filter1.constraint_mode (0) ;
else
p.filter1.constraint_mode (1) ;
toggle_rand = p.randomize () ;
endfunction
内嵌变量控制
在使用类的随机化函数randomize()时,如果伴有参数,那么只会随机化参数列表里面的这些变量,而其余变量无论是否之前被声明为随机属性(rand/randc),都将不会参与到随机化当中。
示例:
class CA;
rand byte x,y;
byte v,w;
constraint c1 { x < v && y > w;};
endclass
CA a = new;
a.randomize();//随机化变量:x,y
a.randomize( x );//随机化变量:x
a.randomize( v, w );//随机化变量: v,w
a.randomize( w, x );//随机化变量:w,x
//注意
//最后一个randomize()函数指明了w和x参与随机化,但是随机化时的约束块仍然需要被满足
//只有这样,随机化才算成功