本記事はSystem Verilogのcovergroupの説明シリーズです。全体でかなりボリュームがあるため、以下に分割しています。上から順番に読んでいただくことをお勧めします。
本記事ではSystem Verilogのcovergroupについて、他の一連の記事で触れることのできなかった項目について説明します。
配列に対するカバレッジ
ここでは配列に対するカバレッジの取り方を説明します。
以下の3 bitのlogicの配列であるdatのカバレッジを考えます。配列であるdatのそれぞれの要素のカバレッジを見ます。配列なのでcoverpointの対象として直接指定することはできません。
localparam DAT_WIDTH = 3;
rand logic [DAT_WIDTH - 1:0] dat [$];
対応するには、まずsample functionをオーバーライドして、datの一つの要素についてのcoverpointを作成します。sample functionはcovergroupが初めから持っているfunctionです。オーバーライドすることでサンプル時の動作を変更することができます。
covergroup cg with function sample(logic [DAT_WIDTH - 1:0] v);
option.per_instance = 1;
cp: coverpoint v; // Automatic bins auto[0] ... auto[7]
endgroup
そして、sampleメソッドを呼ぶときは、配列の要素方向にループさせます。
foreach (dat[i]) begin
cg.sample(dat[i]);
end
これで配列の要素に対してのカバレッジを取ることができます。全体のプログラム例は以下の通りです。
class MyTest;
localparam DAT_WIDTH = 3;
rand logic [DAT_WIDTH - 1:0] dat [$];
covergroup cg with function sample(logic [DAT_WIDTH - 1:0] v);
option.per_instance = 1;
cp: coverpoint v; // Automatic bins auto[0] ... auto[7]
endgroup
function new();
cg = new;
endfunction
function void run();
randomize() with {dat.size() inside {[10:20]};};
foreach (dat[i]) begin
$display("i = %d, dat = 0x%h", i, dat[i]);
cg.sample(dat[i]);
end
endfunction
endclass
program top;
initial begin
MyTest myTest;
myTest = new;
myTest.run();
end
endprogram
EDA Playgroundにソースコードがありますので、WEB browserから各自実行して結果を確かめることができます。実行後にダウンロードされるファイルの中のcov.txtがカバレッジリポートになります。
[covergroup to array] (https://www.edaplayground.com/x/4xeW)
functionの戻り値へのcoverpoint
functionの戻り値はlogicのベクタだけど、coverageはenumとして取りたい場合があります。特に困るのがenumの要素数とlogicベクタの要素数が一致していない場合です。以下の例だとenumでは3通りの値しかとらないのに、logic [1:0]では4通りの値になります。coverpointをlogicとして扱うと、使用しない値はignore_binでいちいち指定しないと絶対にカバーされないbinが生成されてしまいます(本例では3が絶対にカバーされない値)。
typedef enum logic [1:0] {ZERO, ONE, TWO} reg_t;
class RegClass;
reg_t v;
function logic [1:0] get;
return v;
endfunction
endclass
対応は簡単で、coverpointで指定する時に対象の型にキャスティングするだけです。
covergroup cg;
cp: coverpoint reg_t'(regClass.get());
endgroup
UVMのRAL(Register Abstraction Layer)はget()での戻り値はデフォルトでは64ビットになっています。例えenable/disableのような1ビットのフィールドに対しても64ビット幅でデータが返ってきてしまいます。このようなモードビットのために、汎用のtypedefを定義しておくとcoverpointの定義が少し楽になります。
typedef enum logic {FALSE, TRUE} boolean_t;
covergroup cg;
cp1: coverpoint uvm_reg_field_class.get(); // This coverpoint will generate bins for 64 bit space
cp2: coverpoint boolean_t'(uvm_reg_field_class.get()); // Bin will be just FALSE and TRUE
endgroup
以下がサンプルプログラム全体です。
typedef enum logic [1:0] {ZERO, ONE, TWO} reg_t;
class RegClass;
rand reg_t v;
function logic [1:0] get;
return v;
endfunction
endclass
class MyTest;
RegClass regClass;
covergroup cg;
option.per_instance = 1;
cp1: coverpoint regClass.get();
cp2: coverpoint reg_t'(regClass.get());
endgroup
function new();
cg = new;
regClass = new;
endfunction
function void run();
regClass.randomize();
cg.sample();
endfunction
endclass
program top;
initial begin
MyTest myTest;
myTest = new;
myTest.run();
end
endprogram
以下がカバレッジレポートです。logic [1:0]をそのままcoverpointにしたcpではbinが4通りできていますが、reg_tにキャスティングした結果をcoverpointにしたcp2では、bin数は3になっています。
COVERGROUP COVERAGE
===============================================================
| Covergroup | Hits | Goal / | Status |
| | | At Least | |
===============================================================
| TYPE /MyTest/cg | 29.166% | 100.000% | Uncovered |
===============================================================
| INSTANCE <UNNAMED1> | 29.166% | 100.000% | Uncovered |
|----------------------------|---------|----------|-----------|
| COVERPOINT <UNNAMED1>::cp1 | 25.000% | 100.000% | Uncovered |
|----------------------------|---------|----------|-----------|
| bin auto[0] | 1 | 1 | Covered |
| bin auto[1] | 0 | 1 | Zero |
| bin auto[2] | 0 | 1 | Zero |
| bin auto[3] | 0 | 1 | Zero |
|----------------------------|---------|----------|-----------|
| COVERPOINT <UNNAMED1>::cp2 | 33.333% | 100.000% | Uncovered |
|----------------------------|---------|----------|-----------|
| bin auto[ZERO] | 1 | 1 | Covered |
| bin auto[ONE] | 0 | 1 | Zero |
| bin auto[TWO] | 0 | 1 | Zero |
===============================================================
EDA Playgroundにソースコードがありますので、WEB browserから各自実行して結果を確かめることができます。実行後にダウンロードされるファイルの中のcov.txtがカバレッジリポートになります。
[covergroup type cast] (https://www.edaplayground.com/x/5YWL)
参考文献
"19 Functional coverage". 1800-2017 - IEEE Standard for SystemVerilog--Unified Hardware Design, Specification, and Verification Language. pp.553-590.