有些情況下,constraint不能簡單用一行來表達(dá),而是需要復(fù)雜的計算,如果都寫到constraint block內(nèi)部就比較復(fù)雜,而且很亂,這時候可以調(diào)用functions來約束隨機(jī)變量。在constraint內(nèi)調(diào)用function就稱為”function in constraints”。它的格式如下:
constraint constraint_name { rand_var == function_call(arguments...); }
- function的定義寫在constraint block之外,它內(nèi)部包含了對arguments的處理。
- 在調(diào)用randomize()的時候,function會先被求解,function的返回值將會作為state variables去參與接下來的求解。
不過在使用function in constraints有以下幾點需要注意:
- 在constraint內(nèi)部調(diào)用的function不能包含output或ref類型的arguments,但是const ref是允許的;
- 在constraint內(nèi)部調(diào)用的function應(yīng)該是automatic類型的;
- 在constraint內(nèi)部調(diào)用的function不能修改constraints,例如調(diào)用rand_mode或constraint_mode方法;
- Function會先被求解,也就是它的返回值會被當(dāng)作state variables。因此,function的arguments和其它rand variables會隱含建立求解order關(guān)系(有一點點類似solve…before…),arguments會先求解,解完之后作為傳入function得到返回值作為state variables,最后再求解其它rand variables。另外,如果隱含約束關(guān)系會造成求解循環(huán)依賴,那么仿真器將會報錯;
順便提一下state variables的概念,它是constraint guards的一種,我們可以把它理解成常數(shù)(constants),也就是它的值是固定的了,不會發(fā)生變化,不會創(chuàng)建constraint。
接下來看個例子來加深印象。
代碼1如下:
class packet;
rand int length, size, add;
constraint const_c { /*solve length before size;*/ length == calc(size, add); }
constraint const_d { size inside {1, 2, 3, 4, 5, 6, 7, 8}; }
constraint const_e { add inside {1, 0}; }
function int calc(int _s, int _m);
if ( _m )
return ( 100 + 2**_s + _s);
else
return ( 100 - 2**_s - _s);
endfunction: calc
endclass
module top;
initial begin
packet pkt;
pkt = new();
repeat(3) begin
pkt.randomize();
$display("length = %0d, size = %0d, add=%0d",pkt.length, pkt.size, pkt.add);
end
end
endmodule
使用Cadence Xcelium 20.09運(yùn)行結(jié)果如下:
xcelium > run
length = 120, size = 4, add=1
length = -35, size = 7, add=0
length = 80, size = 4, add=0
xmsim: *W,RNQUIE: Simulation is complete.
結(jié)果分析:
上面例子在const_c constraint block里使用了函數(shù)calc,block給calc傳遞的實參是size和add,因此systemverilog會先求解size和add變量的值,然后再去計算calc的返回結(jié)果,這時size, add以及calc()函數(shù)的返回值都當(dāng)作state variables,最終再去求解length變量的值。
但如果將代碼1里第4行的/ solve length before size; /注釋打開,也就是如下代碼2:
class packet;
rand int length, size, add;
constraint const_c { solve length before size; length == calc(size, add); }
constraint const_d { size inside {1, 2, 3, 4, 5, 6, 7, 8}; }
constraint const_e { add inside {1, 0}; }
function int calc(int _s, int _m);
if ( _m )
return ( 100 + 2**_s + _s);
else
return ( 100 - 2**_s - _s);
endfunction: calc
endclass
module top;
initial begin
packet pkt;
pkt = new();
repeat(3) begin
pkt.randomize();
$display("length = %0d, size = %0d, add=%0d",pkt.length, pkt.size, pkt.add);
end
end
endmodule
那么使用Cadence Xcelium 20.09運(yùn)行結(jié)果變成如下所示:
xcelium > run
xmsim: *W,RNDSVB: These solve/before constraints are circular:
0. length - > size
constraint const_c { solve length before size; length == calc(size, add); } (./testbench.sv,4)
1. size - > length
( because of an implicit solve..before for random function-call arguments ): constraint const_c { solve length before size; length == calc(size, add); } (./testbench.sv,4)
pkt.randomize();
|
xmsim: *W,SVRNDF (./testbench.sv,22|18): The randomize method call failed. The unique id of the failed randomize call is 0.
Observed simulation time : 0 FS + 0
結(jié)果分析:
這是因為solve length before size與cacl()函數(shù)創(chuàng)造的隱含求解order約束沖突了。(Circular dependencies)
-
Verilog語言
+關(guān)注
關(guān)注
0文章
113瀏覽量
8206 -
求解器
+關(guān)注
關(guān)注
0文章
77瀏覽量
4505
發(fā)布評論請先 登錄
相關(guān)推薦
評論