randomize()における制約のまとめページです。
SystemVerilogにおける乱数生成関数を用いたテストベンチの記述、検証において乱数への制約を適切に加えることで効率的な検証を行うことを目指します。
目次
それぞれの制約の詳細は、関連記事を参照ください。
randomize()制約:記述方法3選
制約(constraint)を記述し適用する方法の一例を以下に示します。
class内で制約記述
class Transaction;
//- 変数定義(乱数)
rand bit x;
rand bit [(8-1):0] y;
//- 制約記述
constraint c1 {
x inside {0, 1};
y inside {50, 100};
}
endclass
Transaction tr = new();
initial begin
repeat(10) begin
if(!tr.randomize()) $finish; // 乱数生成
$display("x : %d, y : %d", tr.x, tr.y);
end
$finish();
end
randomizeの対象となる変数を3,4行目でクラス内で定義しています。randを先頭に着けることで、randomizeの対象となります。
また、6~9行目で制約を記述しています。"constraint"で括りc1としている制約の名前は任意につけることができます。制約の中身に関しての詳細な説明は下で行います。
11行目でクラスをインスタンス化し、14行目のrandomize()で乱数を生成しています。
制約の後付け
class Transaction;
//- 変数定義(乱数)
rand bit x;
rand bit [(8-1):0] y;
//- 制約記述
constraint c1 {
x inside {0, 1};
}
//- クラス内宣言
constraint c2;
endclass
//- 外部制約定義
constraint Transaction::c2 {y inside {50, 100};}
Transaction tr = new();
initial begin
repeat(10) begin
if(!tr.randomize()) $finish; // 乱数生成
$display("x : %d, y : %d", tr.x, tr.y);
end
$finish();
end
soft-with:制約上書き
class Transaction;
//- 変数定義(乱数)
rand bit x;
rand bit [(8-1):0] y;
//- 制約記述
constraint c1 {
x inside {0, 1};
soft y inside {50, 100}; //- soft
}
endclass
Transaction tr = new();
initial begin
repeat(10) begin
//- 乱数生成 + 制約上書き
if(!(tr.randomize() with {y inside {0};})) $finish;
$display("x : %d, y : %d", tr.x, tr.y);
end
$finish();
end
多数の制約は同じとき一部の制約だけを変更したいような場合に用います。クラスで言うところのオーバーライドに似ています。
以下からrandomize()で用いられる制約について、まとめます。
inside:出現値(範囲)指定制約
insideを用いることで値を直接指定、もしくは値の遷移範囲を指定します。
クラス内変数定義
rand bit [(8-1):0] y;
rand bit [(8-1):0] z;
制約と実行結果
y inside {[0:99]};
z inside {0, [70:75], 100, [250:255]};
----------------------------
y : 80, z : 0
y : 35, z : 251
y : 94, z : 253
y : 2, z : 73
y : 82, z : 100
y : 36, z : 255
y : 4, z : 74
y : 79, z : 255
y : 2, z : 71
y : 7, z : 75
[y]:0~99
[x]:0, 70~75, 100, 250~55
▼詳細
dist:出現確率の重み付け制約
randomize()に置いて値が遷移する確率を指定します。ついでに値の範囲も指定できます。
上の実行例では、値の出現確率が以下になるように指定しています。
0 : 40%
1~3:60%
クラス内変数定義
rand bit [(2-1):0] x;
制約と実行結果
x dist {0:/40, [1:3]:/60};
----------------------------
[x] 0 : 40.070000 %
[x] 1 : 20.370000 %
[x] 2 : 19.460000 %
[x] 3 : 20.100000 %
x dist {0:=40, [1:3]:=60};
----------------------------
[x] 0 : 18.150000 %
[x] 1 : 27.180000 %
[x] 2 : 27.420000 %
[x] 3 : 27.250000 %
個人的には「:/」のほうが直感的なのでこちらがよく使われる気がします。
上の例では、出現率の分母が40+60で合計出現確率100に割り当てています。
「:=」の記述では、出現率の分母が40+60+60+60の合計が240となります。
▼詳細
unique:重複値を無くす制約
uniqueを用いて遷移する複数の値どうしをその名の通りそれぞれユニークにします。
クラス内変数定義
rand bit x;
rand bit [(2-1):0] y;
rand bit [(2-1):0] z;
rand bit m;
制約と実行結果
unique {x, y, z, m};
----------------------------
x : 1, y : 3, z : 2, m : 0
x : 0, y : 2, z : 3, m : 1
x : 1, y : 3, z : 2, m : 0
x : 1, y : 2, z : 3, m : 0
x : 1, y : 3, z : 2, m : 0
x : 1, y : 3, z : 2, m : 0
x : 0, y : 2, z : 3, m : 1
x : 0, y : 2, z : 3, m : 1
x : 1, y : 3, z : 2, m : 0
x : 1, y : 3, z : 2, m : 0
▼詳細
implication(->):制約間の条件追加
"->"を用いて複数の制約を関連付けます。
クラス内変数定義
rand bit x;
rand bit [(8-1):0] y;
制約と実行結果
(x == 1) -> (y < 10);
----------------------------
x : 0, y : 98
x : 1, y : 5
x : 0, y : 251
x : 0, y : 124
x : 1, y : 2
x : 1, y : 6
x : 1, y : 4
x : 1, y : 5
x : 0, y : 68
x : 1, y : 8
▼詳細
if-else:制約の条件分岐記述
if-elseを用いて、制約の記述中に条件分岐を持ち込むことができます。begin-endではなく、{ }で囲っていることに注意です。
クラス内変数定義
rand bit x;
rand bit [(8-1):0] y;
rand bit [(8-1):0] z;
制約と実行結果
if (x == 0) {
y == 0;
z inside {0};
} else {
(y > 100) & (y < 200);
z inside {[100:200]};
}
----------------------------
x : 0, y : 0, z : 0
x : 1, y : 123, z : 198
x : 0, y : 0, z : 0
x : 0, y : 0, z : 0
x : 1, y : 124, z : 147
x : 1, y : 162, z : 193
x : 1, y : 114, z : 141
x : 0, y : 0, z : 0
x : 1, y : 171, z : 124
x : 0, y : 0, z : 0
▼詳細
solve-before:値の確定順序指定制約
solve-beforeを用いることで値の出現確率を微調整することが可能です。厳密に言うと、値に対する制約のかかり方を整えるといった方が正しいかもしれません。
クラス内変数定義
rand bit x;
rand bit [(2-1):0] y;
制約と実行結果
(x == 0) -> (y == 0);
solve x before y;
----------------------------
[x, y] 0, 0 : 49.710000 %
[x, y] 0, 1 : 0.000000 %
[x, y] 0, 2 : 0.000000 %
[x, y] 0, 3 : 0.000000 %
[x, y] 1, 0 : 12.380000 %
[x, y] 1, 1 : 12.770000 %
[x, y] 1, 2 : 12.510000 %
[x, y] 1, 3 : 12.630000 %
実行結果を見るとxの値が0か1の2択から選択されるため、xが0の組と1の組でおよそ50%ずつに出現確率が分断されています。
このほか、yの値が確定してから、xの値が確定するバージョンなどについては以下の記事を参照してください。
▼詳細
foreach:配列要素へ制約追加
foreachを用いて配列の各要素に対して上記までで紹介した制約を追加できたりします。
クラス内変数定義
rand bit [(8-1):0] a[4];
制約と実行結果
foreach (a[i]) {
(a[i] < 100) -> (a[i+1] > 100);
(a[i] >= 100) -> (a[i+1] < 100);
}
----------------------------
a[0] : 50, a[1] : 127, a[2] : 66, a[3] : 195
a[0] : 73, a[1] : 254, a[2] : 97, a[3] : 123
a[0] : 69, a[1] : 213, a[2] : 20, a[3] : 244
a[0] : 66, a[1] : 148, a[2] : 45, a[3] : 172
a[0] : 25, a[1] : 157, a[2] : 31, a[3] : 172
a[0] : 71, a[1] : 131, a[2] : 5, a[3] : 158
a[0] : 16, a[1] : 217, a[2] : 30, a[3] : 177
a[0] : 52, a[1] : 230, a[2] : 30, a[3] : 243
a[0] : 20, a[1] : 248, a[2] : 99, a[3] : 204
a[0] : 6, a[1] : 208, a[2] : 81, a[3] : 243
▼詳細
以上、ありがとうございました。