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的位數與數組中的數的位數相同,所以又是可能達不到想要的范圍。
在實際應用中,應該多用變量來控制約束。