在進行驗證已編寫過的模塊時,我們往往需要一些隨機的測試方法來檢測隱藏的漏洞。
sv相比於verilog而言,在隨機化上則是非常有力,有許多關於隨機化的操作。
===================================================
一 隨機數據:
一般而言隨機化的操作都是需要封裝成為類的。
class Bus;
rand bit[15:0] addr;
rand bit[31:0] data;
constraint word_align {addr[1:0] == 2’b0;}
endclass
這是個簡單的例子,只要在類的數據類型前加上了rand或者randc,那么只要對這個類的實例化
對象調用randomize()方法,這些帶有rand與randc的數據類型則是會被隨機化。
但往往隨機化並非完全的隨機化,很多時候需要有一定的限制,所以還需要使用constraint語句
構造約束條件。
其中約束有很多種:
(1)表達式約束:
constraint word_align {addr[1:0] == 2’b0; data < 32 }
(2)條件約束:
class MyBus extends Bus;
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
條件約束可以使用->的方式也可以使用if-else的方式。只有當先前的條件滿足時才可以進行后面的約束。
(3)嵌套約束:
task exercise_bus (MyBus bus);
int res;
// EXAMPLE 1: restrict to low addresses
res = bus.randomize() with {atype == low;};
// EXAMPLE 2: restrict to address between 10 and 20
res = bus.randomize() with {10 <= addr && addr <= 20;};
// EXAMPLE 3: restrict data values to powers-of-two
res = bus.randomize() with {data & (data - 1) == 0;};
endtask
在randomize()方法后使用with { } 加入約束的條件。
(4)權重約束:
x dist { [100:102] := 1, 200 := 2, 300 := 5} // 其中在:=前的每個元素的權重值都為:=后的值
x dist { [100:102] :/ 1, 200 :/ 2, 300 :/ 5} // 其中在:/前的每個元素平分:/后的權重值
二 隨機序列:
randsequence ( main )
main : first second done ; // 從main處順序執行 first second done
first : add | dec ; // 執行add 或者 dec
second : pop | push ;
done : { $display("done"); } ;
add : { $display("add"); } ;
dec : { $display("dec"); } ;
pop : { $display("pop"); } ;
push : { $display("push"); } ;
endsequence
三 決策樹:
randcase 3 : x = 1; // :前的值為相應的權重 1 : x = 2; 4 : x = 3; 6 : randcase 4 : x = 4 ; 5 : x = 5 ; endcase endcase
CONTRAINT 約束
本篇主要介紹一些 systemverilog 中的 constraint。
我們可以用> < >= <=等符號來對變量進行簡單的約束, 注意的是當要把某個變量設為定值時, 需要使用==符號。
比如下面的例子:
1 |
class myClass; |
那么運行的結果就是:
1 |
source ../edaTools/cadence/INCISIV131/tools/inca/files/ncsimrc |
2. inside 表達式
(1) 也可以使用inside關鍵字申明變量的范圍或者申明變量只能取某些特定的值, 比如:
1 |
constraint my_range { typ > 32; |
(2) 如果加上符號!表示變量不在某個范圍內
1 |
rand bit [2:0] typ; |
3. 權重分布
當在隨機化變量的時候, 需要某些值出現的更加頻繁一些。 就可以用關鍵字dist進行權重的約束。
:=表示的是, 對於指定范圍的值, 權重都一樣, 比如 [1:5]:=50;表示的是 [1:5] 范圍的任何一個值, 其權重都是 50;
:/表示的是, 對於指定范圍的值, 權重均分, 比如 [1:5]:=50;表示的是 [1:5] 范圍的任何一個值, 其權重都是 10;
1 |
rand bit [2:0] typ; |
上面約束表示的含義是: 0 的權重是 20, 6 是 40, 7 是 10, 1:5 中的每個數都是 50. 總共 320, 那么選擇 0 的概率就是 20/320
1 |
rand bit [2:0] typ; |
這個約束表示的含義就不同了, 選中 0 的概率就是 20/100
4. 多重約束
多重約束存在時, 取的是交集:
1 |
class myClass; |
比如上面的例子, val 的值被約束在了 [10, 12)
5. implication 約束
implication 約束使用的符號是->, 代表的是某兩個或者多個變量之間的關系。 有些類似於if - else申明。
1 |
class ABC; |
上面例子的運行結果為:
1 |
ncsim> run |
