一
随机验证来找bug,但是随机并不是所有,模块和系统验证差别挺大的。
随机是产生随机的数据,
想,要随机的是什么
测试向量,数据可以组合。
随机测试带来的额外负担是复杂度会提高,
绿色环保可回收的二次使用代码。
通过系统函数std::randomize()对变量完成随机化。
$urandom()生成一个32bit的无符号随机数。$urandom_range(max,min)生成区间的数。
SV中,硬件中,产生随机数不是完全的free,不是完全的不受任何控制。时序等。
软件
硬件上,约束,有时序,硬件的功能要求。需要载体,区容纳变量以及之间的约束,载体就是类。 在SV里,载体只能类。若想把随机的变量裹在一块,而且想要每次随机他们的时候添加一些约束,那么只能是类(mod做不到,if也是,package等都做不到只有类能做到)。类可以在声明变量时,把变量声明为随机的属性,用rand和randc表示(任何整型的变量都可以声明为rand)。
句柄也可以声明。、
例——随机数可以由系统函数$urandom()获得;可以对动态数组做随机化;随机化时可以指定变量的随机数值范围;SV不支持对实数类型做随机化,消耗大;
二
声明句柄,例化,做随机化。三个独立的过程。
mod里边不能用rand
要随机化结构体struct,结构体如果想要随机里边的成员。那么如果想要随机化结构体,结构体里面的成员要声明rand。
失去控制,失去了数和数之间的约束。
随机句柄的嵌套,一层一层。给句柄加rand。class A里的随机句柄指向class B,class B里的随机句柄指向class C,class C里有若干个变量。然后去随机化class A的对象时,不但会随机化class A里的变量,还会随机化里边句柄指向class B对象里的句柄成员,进一步随机化class B里的随机句柄所指向的class C对象里的变量。
random为每次随机化时rand,从扑克里抽一张牌,下次随机化时重新拿一踏扑克再抽;
randomc表示random cycle的意思randc,下次初始化还是拿第一踏的扑克牌。
带有随机变量的简单类
class Packet;
//random variables
rand bit [31:0] src, dst, data[8];
randc bit[ 7:0] kind;
//limite the values for src
constraint c{src > 10;
src < 15;}
endclass
Packet p;
initial begin
p = new(); //Create a packet
if(!p.randomize())
$finish;
transmit(p);
end
如果上面的句柄p未调用randomize()函数,那么p.src应是夺少?
0 间于[0:(2^32-1)] 间于[11:14] 32'hFFFFFFFF
三
随机约束
约束块
想要放约束,最好的容器就是类,结构体里不能放约束。要产生随机数,伴随着固定的约束,放到类里。 ——约束块constraint。
两个赋值
uniquecase是case的选项不能有重合。再constraint里表示四个变量随机化初始值不同。
箭头。箭头可以触发事件。
foreach轮询,循环,在constraint也可用,在其中选一个。
硬约束,软约束。没有soft就是硬约束;当俩约束有冲突时,随机化失败。
软约束满足不满足都行,硬约束必须满足。 一旦有冲突,follow硬约束。
class SimpleSum;
rand bit [7:0] x, y
bit [7:0] z;
constraint c {z == x + y;}
endclass
//打印出来xyz结果都为0
/*如果把xyz都放到randomize函数里,虽然z没有rand属性,但是z指定了randomize。
所以结果应该是xyz都randomize;如果是randomize(z)就只有z被指定randmize。*/
module tb8;
class simplesum;
rand bit[7:0] x, y;
bit[8:0] z;
constraint cstr {
z == x + y;
}
endclass
initial begin
simplesum ss = new();
repeat(10) begin
if(ss.randomize()) $display("x=%d, y=%d, z=%d", ss.x, ss.y, ss.z);
else $error("randomize failure!");
end
end
endmodule
z没有参与到rand里,不会随机化。所以z的值是0,且在constraint限制中,所以xy(无符号值)只能是0。 x = y = z = 0
就近,就句柄近,就这个类的近。
module tb9;
class packet1;
rand bit[7:0] x;
constraint cstr {soft x == 5;}
endclass
//1.就近原则,x == x此时跳到class packet1里,x = 5。
//2.如果用{x == local::x;};时,x = 30
//3.如果想让其等于packet2里的x = 10。应{x == local::this.x;};
class packet2;
bit[7:0] x = 10;
function int get_rand_x(input bit[7:0] x = 20); //默认参数
packet1 pkt = new();
pkt.randomize with {x == x;};
return pkt.x;
endfunction
endclass
initial begin
packet2 pkt = new();
$display("pkt.x = %0d ", pkt.get_rand_x(30)); //传的参数值
end
endmodule
上述代码,的例子。
local在constrint,local表示所处当前文本/域要索引x。见上述代码,local(默认参数和真正传进来的参数,不传参数就成20了)和local.this(local到class这里了,x=20,当前所在域上下文就是class packet2了,加个this即可=10。)。
显然BCD
四
控制——随机控制,约束。 随机和约束的部分可分开。随机可控制变量,在randomize过程中是否参与到随机化。
rand_mode可以使能/禁止随机变量,前提是变量要拿rand声明。
可用rand_mode来声明哪些参与否随机化。
class Packet;
rand integer source_value, dest_value;
... other declarations
endclass
int ret;
Packet packet_a = new;
//Turn off all var in object
packet_a.rand_mode(0); //对于整个类,packet_a这个句柄,packet里的变量都不参与randmize。就是让整个声明为rand变量的不参与到随机化里。(randmize前,关掉所有变量的随机化)
//...other code
//Enable source_value
packet_a.source_value.rand_mode(1); //随机化之前,打开里面单独的变量
ret = packet_a.dest_value.rand_mode();
//等同于
packet_a.randmize(source_value)
上述为随机化的控制。
task object[.constraint_identifier]::constraint_mode(bit on_off
function int object.constraint_identifier::constraint_mode();)
约束的控制可通过constraint_mode打开。即把整个类的所有约束块通过constraint_mode打开/关闭。指定类的某个约束块,调用其constraint_mode,打开/关闭约束块。 所以在每次randmize之前要使能一个,关闭一个,randmize才能有效,才能找到一个可解的值。
class Packet;
rand integer source_value;
constraint filter1 { source_value > 2 * m; }
endclass
//传进来一个句柄,如果constraint_mode是打开的,就关掉。反之则反。
function integer toggle_rand( Packet p ); //toggle翻转
if( p.filter1.constraint_mode() )
p.filter1.constraint_mode(0);
else
p.filter1.constraint_mode(1);
toggle_rand = p.randomize(); //然后再做一个randomize
endfunction
除了之前看到的,randomize指定变量以外,若想使能/失能某些变量的随机属性,或使能/失能类里边的约束块,都可通过rand_mode或constraint_mode。
内嵌变量控制。
例题——a.randomize(v, w)可能产生的随机数...
class CA;
rand byte x, y;
byte v, w;
constraint c1 { x < v && y > w; };
endclass
CA a = new;
a.randomize(); //random var:x, y ///v = 0,w = 0所以x<0,y<0
a.randomize( x ); //random var:x ///y=8'h49,v=0,w=0所以y>w,x=8'hda<0
a.randomize( v, w );//random var:v, w ///x=8'hda,y=8'h49,x<v=8'h74 && y>w=8'hd3
a.randomize( w, x );//random var:w, x
不管randomize怎样,constraint必须满足。 首先randomize()了xy,那么默认vw为0,且为满足constraint,所以x < 0,y > 0;再randomize( x ),那y v=0 w=0不变,且第一次randomize仍有效;第三次就randomize( v, w ),xy不变。
注释值由仿真生成,打断点得出值。如下图: