我們知道virtual來修飾子函數,可以讓基類的指針指向擴展類,從而利用基類中的virtual函數可以復用擴展類中的同名函數。但是constrain呢?本小結就來詳細說明一下constrain。
我們通過一個例子來簡單聲明一下:
情況一:
class bird;
rand bit [1:0] src;
rand bit [1:0] drc;
constraint src_stim{src ==3;}
constraint drc_stim{drc ==1;};
endclass
class parrot extends bird;
constraint drc_stim{drc ==2;};
endclass
program ex6_14_tb;
bird A;
parrot B;
initial begin
A = new();
B = new();
assert(A.randomize());
$display("A:src=%0d,drc=%0d",A.src,A.drc);
assert(B.randomize());
$display("A:src=%0d,drc=%0d",A.src,A.drc);
end
endprogram
打印結果是:
A:src=3,drc=1
B:src=3,drc=2
- 如果B extends A的話,那么約束其實是可以重寫和繼承的。
情況二:
class bird;
rand bit [1:0] src;
rand bit [1:0] drc;
constraint src_stim{src ==3;}
constraint drc_stim{drc ==1;};
endclass
class parrot extends bird;
constraint drc_stim{drc ==2;};
endclass
program ex6_14_tb;
bird A;
parrot B;
initial begin
A = new();
B = new();
A = B;
assert(A.randomize());
$display("A:src=%0d,drc=%0d",A.src,A.drc);
assert(B.randomize());
$display("A:src=%0d,drc=%0d",A.src,A.drc);
end
endprogram
打印結果:
A:src=3,drc=2
B:src=3,drc=2
- constrain,類似於virtual task,基類=擴展類;
- 如果改成B = A,即擴展類=基類,那么編譯就會報錯!!
情況三:
class bird;
rand bit [1:0] src;
rand bit [1:0] drc;
constraint src_stim{src ==3;}
constraint drc_stim{drc > 1;
drc < 6;};
endclass
class parrot extends bird;
constraint drc_stim{drc ==2;};
endclass
program ex6_14_tb;
bird A;
parrot B;
initial begin
A = new();
B = new();
assert(A.randomize() with {drc ==3;});
$display("A:src=%0d,drc=%0d",A.src,A.drc);
assert(B.randomize());
$display("A:src=%0d,drc=%0d",A.src,A.drc);
end
endprogram
打印結果:
A:src=3,drc=3
B:src=3,drc=2
-
randomize() with {} 是求解drc>1;drc<6;以及drc == 3的交集;
-
如果with里面的東西與原來的約束沒有交集的話,那么會顯示約束求解錯誤。
那么比如說我就有這樣的需求呢?有兩種解決方案:
方案一:class bird; rand bit [5:0] src; rand bit [5:0] drc; constraint src_stim{src ==3;} constraint drc_stim{ drc > 1; soft drc < 6;}; //****************** endclass class parrot extends bird; constraint drc_stim{drc ==2;}; endclass program ex6_14_tb; bird A; parrot B; initial begin A = new(); B = new(); assert(A.randomize() with {drc ==7;}); $display("A:src=%0d,drc=%0d",A.src,A.drc); assert(B.randomize()); $display("A:src=%0d,drc=%0d",A.src,A.drc); end endprogram
打印結果:
A:src=3,drc=7
B:src=3,drc=2
- 用soft來修飾約束,這樣當with的約束和內部約束有沖突的時候,我們是以with里面的約束為准。
方案二:
class bird;
rand bit [5:0] src;
rand bit [5:0] drc;
constraint src_stim{src ==3;}
constraint drc_stim{
drc > 1;
drc < 6;};
endclass
class parrot extends bird;
constraint drc_stim{drc ==2;};
endclass
program ex6_14_tb;
bird A;
parrot B;
initial begin
A = new();
B = new();
A.drc_stim.constraint_mode(0); //*****************//
assert(A.randomize() with {drc ==7;});
$display("A:src=%0d,drc=%0d",A.src,A.drc);
assert(B.randomize());
$display("A:src=%0d,drc=%0d",A.src,A.drc);
end
endprogram
打印結果:
A:src=3,drc=7
B:src=3,drc=2
- constraint_mode來關閉對應的約束,然后with里面的約束是最終的約束。