randomize()における制約(constraint)の一つ、insideによる制約の活用方法についてまとめます。
SystemVerilogでinsideというメンバシップ演算子が追加されていますが、ここで取り上げているのは乱数における制約についてとなります。
insideによりrandomize()により生成される乱数に制限をかけることができます。
これを用いることで本来回路中に"入力される可能性のない値"の組み合わせ検証について試行する必要がなくなるため無駄を省けます。
insideで乱数で出現する値を直接指定
以下は制約により生成する値を直接指定する場合の例です。
8行目~10行目でx, y, zという変数に対して、制約を追加しています。
直接値指定:SystemVerilog
class Transaction;
rand bit x;
rand bit [(8-1):0] y;
rand bit [(8-1):0] z;
logic [(8-1):0] a = 255;
// random constraint
constraint c1 {
x inside {0, 1};
y inside {70, 122, a}; // 変数指定
z inside {10, 100, 1000}; // 1000は取れない値
}
endclass
//- Instance
Transaction tr = new();
initial begin
repeat(10) begin
if(!tr.randomize()) $finish; // 乱数生成
$display("x : %d, y : %d, z : %d", tr.x, tr.y, tr.z);
end
$finish();
end
直接値指定:実行結果
x inside {0, 1};
y inside {70, 122, a(=255)};
z inside {10, 100, 1000};
----------------------------
x : 1, y : 122, z : 10
x : 1, y : 122, z : 100
x : 0, y : 122, z : 100
x : 1, y : 70, z : 10
x : 1, y : 255, z : 100
x : 0, y : 122, z : 10
x : 1, y : 122, z : 10
x : 1, y : 255, z : 100
x : 1, y : 70, z : 10
x : 1, y : 255, z : 100
また、10行目では8bitのレジスタz(最大値255)に対して、ランダムに取ることのできる値として1000を指定しています。ツールにもよるかもしれませんが、シミュレーション実行時に特にエラーとして通知されることはなく、実行結果を見ると指定が無いものとして10と100だけが制約として認識されていることが分かります。
insideで乱数の遷移する範囲を指定
上の例では、randomize()で出現する値を直接指定していましたが、以下では、値の範囲を指定しています。
範囲指定:SystemVerilog
class Transaction;
rand bit [(8-1):0] y;
rand bit [(8-1):0] z;
// random constraint
constraint c1 {
y inside {[0:99]};
z inside {0, [70:75], 100, [250:255]};
}
endclass
//- Instance
Transaction tr = new();
initial begin
repeat(10) begin
if(!tr.randomize()) $finish;
$display("y : %d, z : %d", tr.y, tr.z);
end
$finish();
end
範囲指定:実行結果
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
実装の7行目のように、範囲指定と値指定を組み合わせることも可能です。
insideで乱数の遷移する範囲の排他的な指定
指定した値"以外"として乱数に制約を掛けるには以下のように記述します。
排他的に制限:SystemVerilog
class Transaction;
rand bit [(8-1):0] y;
rand bit [(8-1):0] z;
// random constraint
constraint c1 {
!(y inside {[10:255]});
!(z inside {[0:99], [200:255]});
}
endclass
//- Instance
Transaction tr = new();
initial begin
repeat(10) begin
if(!tr.randomize()) $finish;
$display("y : %d, z : %d", tr.y, tr.z);
end
$finish();
end
排他的に制限:実行結果
!(y inside {[10:255]});
!(z inside {[0:99], [200:255]});
----------------------------
y : 6, z : 162
y : 3, z : 139
y : 2, z : 104
y : 5, z : 163
y : 1, z : 184
y : 2, z : 138
y : 7, z : 144
y : 6, z : 182
y : 8, z : 147
y : 2, z : 117
出現する値の範囲より、出現しない値の範囲が大きい場合には便利です。
randomize()制約一覧
参考:
・https://verificationguide.com/systemverilog/systemverilog-constraint-inside/