制約(constraint)の一つdistを用いて、randomize()による乱数生成における出現確率の重みづけを行います。
ちなみに、distは配分(Distribution)の略のらしいです。
distにおける":/"と":="の違いは?
毎度微妙に違いが分からなくなる2つの記述方法について、簡潔にまとめておきます。
重みをレンジに配分する":/"
":/"では重みづけをレンジ(一定間隔)に平等に配分します
個人的にこちらの方がより直感的だと思うので、こちらを用いることが多いです。
【制約】
0:/40, [1,3] :/60
【配分】
0:40/100 = 40 %
1:20/100 = 20 %
2:20/100 = 20 %
3:20/100 = 20 %
上記ように制約を記述すると、出現頻度の配分はこのようになります。実際に1万回試行してみた結果が以下です。
▼1万回実行した結果:
x dist {0:/40, [1:3]:/60};
----------------------------
[x] 0 : 40.070000 %
[x] 1 : 20.370000 %
[x] 2 : 19.460000 %
[x] 3 : 20.100000 %
各要素に重みづけを行う":="
":="では各要素に重みづけを行います。
【制約】
0:=40,[1,3] :=60
【配分】
0:40/220 = 18.18...%
1:60/220 = 27.27...%
2:60/220 = 27.27...%
3:60/220 = 27.27...%
上記のように制約を記述すると、出現頻度はこのように分配されます、220=40+60×3です。実際に1万回試行してみた結果が以下です。
▼1万回実行した結果:
x dist {0:=40, [1:3]:=60};
----------------------------
[x] 0 : 18.150000 %
[x] 1 : 27.180000 %
[x] 2 : 27.420000 %
[x] 3 : 27.250000 %
双方とも合計値は100でなくても大丈夫です。
dist":/"で出現確率を指定
まず、シンプルに合計が100になるように割り当ててみた例を以下に示します。
":/"重みづけ:SystemVerilog
class Transaction;
rand bit x;
rand bit [(2-1):0] y;
// random constraint
constraint c1 {
x dist {0:/70, 1:/30};
y dist {0:/10, [1:3]:/90};
}
endclass
Transaction tr = new();
real x0 = 0; real x1 = 0;
real y0 = 0; real y1 = 0; real y2 = 0; real y3 = 0;
initial begin
repeat(10000) begin
if(!tr.randomize()) $finish;
if (tr.x == 0) x0++; else x1++;
if (tr.y == 0) y0++; if (tr.y == 1) y1++; if (tr.y == 2) y2++; if (tr.y == 3) y3++;
end
//- result dist
$display("[x] 0 : %f %%", (x0/10000)*100);
$display("[x] 1 : %f %%", (x1/10000)*100);
$display("[y] 0 : %f %%", (y0/10000)*100);
$display("[y] 1 : %f %%", (y1/10000)*100);
$display("[y] 2 : %f %%", (y2/10000)*100);
$display("[y] 3 : %f %%", (y3/10000)*100);
$finish();
end
":/"重みづけ:実行結果
x dist {0:/70, 1:/30};
y dist {0:/10, [1:3]:/90};
----------------------------
[x] 0 : 70.130000 %
[x] 1 : 29.870000 %
[y] 0 : 10.140000 %
[y] 1 : 29.930000 %
[y] 2 : 30.080000 %
[y] 3 : 29.850000 %
":/"重みづけ:合計100以外の実行結果
次に合計100以外(140)で割り当ててみます。yの値については、上の合計100%になるように割り当てた場合とおよそ同じ重みづけとなるようにしています。
x dist {0:/70, 1:/70};
y dist {0:/14, [1:3]:/126};
----------------------------
[x] 0 : 49.910000 %
[x] 1 : 50.090000 %
[y] 0 : 10.900000 %
[y] 1 : 29.750000 %
[y] 2 : 29.610000 %
[y] 3 : 29.740000 %
合計140として、yの値の出現率が1つ目の例とおよそ同じになるようになるようにすると、{0:/14, [1:3]:/126}のように値を計算して設定する必要があります。
小数点以下の細かな調整が必要など、事情がない限りは合計100で割り当てるので問題ありません。
dist":="で出現確率を指定
":="重みづけ:SystemVerilog
class Transaction;
rand bit x;
rand bit [(2-1):0] y;
// random constraint
constraint c1 {
x dist {0:=70, 1:=30};
y dist {0:=10, [1:3]:=90};
}
endclass
Transaction tr = new();
real x0 = 0; real x1 = 0;
real y0 = 0; real y1 = 0; real y2 = 0; real y3 = 0;
initial begin
repeat(10000) begin
if(!tr.randomize()) $finish;
if (tr.x == 0) x0++; else x1++;
if (tr.y == 0) y0++; if (tr.y == 1) y1++; if (tr.y == 2) y2++; if (tr.y == 3) y3++;
end
$display("[x] 0 : %f %%", (x0/10000)*100);
$display("[x] 1 : %f %%", (x1/10000)*100);
$display("[y] 0 : %f %%", (y0/10000)*100);
$display("[y] 1 : %f %%", (y1/10000)*100);
$display("[y] 2 : %f %%", (y2/10000)*100);
$display("[y] 3 : %f %%", (y3/10000)*100);
$finish();
end
":="重みづけ:実行結果
x dist {0:=70, 1:=30};
y dist {0:=10, [1:3]:=90};
----------------------------
[x] 0 : 70.130000 %
[x] 1 : 29.870000 %
[y] 0 : 3.590000 %
[y] 1 : 31.940000 %
[y] 2 : 33.150000 %
[y] 3 : 31.320000 %
以下のように1, 2, 3の値それぞれが30%ずつの出現率を持つというように記載すれば、合計の出現率を100%にすることが可能です。
":="合計100%にする割り当てかたの例
x dist {0:=70, 1:=30};
y dist {0:=10, [1:3]:=30};
----------------------------
[x] 0 : 70.130000 %
[x] 1 : 29.870000 %
[y] 0 : 10.080000 %
[y] 1 : 29.880000 %
[y] 2 : 30.060000 %
[y] 3 : 29.980000 %
これはこれで、[1:3]の記述中で均等に割り当たる重みを直接指定できるので場合によっては便利ではあります。