a:系统函数:$random/$urandom/$urandom_range,$dist_uniform/$dist_normal/$dist_exponetial/$dist_possion/$dist_chi_square/$dist_t/$dist_erlang。注意返回值的位宽、范围。
b:randcase、randsquence实现分支选择。
c:基于对象的随机。rand/randc申明、randomize、约束:indise/dist/->/if else/foreach/soft约束。
d:标准随机函数stb::randomize();随时对任意变量进行随机化并添加约束。
1: 主要使用$urandom_range/$urandom/$random.
$urandom_randge(max,min):返回32位无符号数,包括边界。
$urandom(seed):返回32bit无符号数。
$random(seed)返回32位有符号数,可正可负。
2:randcase
3:x = 1;
1:x = 2;
2:x = 3;
endcase // x的随机权重为3:1:2.
如果权重为0,则不会随机到此条目。此外,权重还可以是任意表达式。
3:每次调用randomize都会重新随机。
randc的变量,在随机完本轮的所有值后,自动开启新周期的随机。
dist分布注意:/ =/数组中共享此权重。dist操作不能应用于randc变量。缺省值为:=1。
约束是双向的,注意概率。
约束仅支持2态值。4态会报错。
solve a before b,先解a,再解b。
子类中的约束与基类相同时,那么他会改写基类的约束。
randomize是虚方法,返回int变量,不可改写。sv中还提供pre_/post_randomize函数,可以改写。randomize……with动态修改约束。
rand_mode、constraint_mode。0表示关闭,1表示打开。默认打开。rand_mode可以关闭句柄中的所有rand变量,也可以关闭某一个变量。
4:randomzie……with。
soft约束,一般用于正常的约束,在异常包时,以后面约束的为准。
由于对象class由数据和操作组成,所以对数据的随机化一般放在一个class内。(对环境或环境的配置也可以反映在配置参数的随机化上)
一个constraint包括两部分:rand/randc变量声明,constraint约束块。其中randc会在重复之前,周期性取值,constraint约束块中的变量至少有一个rand/randc
变量,constraint约束块必须在{}内,用;来表示多个约束。约束块是一种声明性的代码,并行运行。
SV中的randomize函数有两种引用方法:
1)直接用任意一个class类型的对象引用,作用在整个class的rand/randc类型变量上。 this.randomize(var),只随机var,但是pre/post_randomize也会被调用。
obj.randomize(null),此时的randomize只是作为一个checker,检查solver是否成功,不是作为一个generator。现有值符合constraint,success返回1,failed返回0。
2)std::randomize(,,,) with {} ,其中()内的变量便是需要random的variable,with表示一些random constraint
success = std::randomize(a,b,c) with{a<b,a+b<length} ,随机化成功,返回success为1.
with约束中的变量如果与调用randomize的obj相同,需要用local::来为变量定位。
3)直接使用$urandom/$urandom_range()等函数。
constraint的引用:一般在一个initial模块或program中引用,采用assert的形式来:assert( p.randomize() );随机化失败后,返回值为0,assert将会打印log,
并退出。还有两个隐性function:pre_randomize(),post_randomize(), 可以加入非randomize变量的初始化,同时留下hook。
几种约束方式:
1) constraint longth { low < mid;
mid < high;} //关系操作符必须分开来写
2)constraint length { len == mid - low;} //约束块内不能有赋值语句,相反应该用关系运算符
3)constraint c_dist { src_dist {0:= 40, [1:3]:=60;} //:=后表示权重---相等
dst_dist {0:/ 40, [1:3]:/ 60};} //:/后表示权重---比例
4)constraint c_rang { c inside {[lo:hi]}; //inside:low-high
b inside {[10:$]}; //$可以表示边界
!(c inside {[$:30]}); } //加()可以加!表示非
5)constraint c_io { (io_space_mode) -> addr[31]==1'b1; //--->表示if
if (op==READ) len inside {[BYTE:WORD]}; } //--->if--else
6)constraint c_xy {(x==0) -> y==0; //solve..before可能改变解的概率
solve x before y;}
7)assert (t.randmize() with {addr > 50; //内嵌式的约束,addr的作用域是class这一级的,randomize的效果等价
addr < 150;} )
随机化的开关控制:
rand bit[7:0] length;
p.length.rand_mode(0); //设置包长为非随机值
约束的开关控制:
p.c_short.constraint_mode(0); //句柄+约束块+mode,控制这个约束块mode
p.constraint_mode(0); //句柄+mode,控制整个句柄的mode
对数组的约束:
1)constraint d_size {
d.size inside {[1:10]} ;
d.sum == 4'h4; } //sum的位数与数组中的数的位数相同,所以又是可能达不到想要的范围。
在实际应用中,应该多用变量来控制约束。