SV采用CRT的激勵形式,而判斷驗證進度的標准也就是覆蓋率(coverage)。
覆蓋率的兩種指定形式:顯式的,直接通過SV來指定出的,如SVA,covergroup。
隱式的,在驗證過程中,隨"register move"就可以由simulator得到的,如代碼覆蓋率等。
覆蓋率類型:代碼覆蓋率---由仿真器直接提供,只能表示設計的冗余度,與spec關系不大。(toggle/expression/block)
功能覆蓋率---與spec比較來發現,design是否行為正確,需要按verification plan來比較進度。(assertion/covergroup)
斷言覆蓋率---用於檢查幾個信號之間的關系,常用在查找錯誤。
漏洞率-------同一功能驗證,運行多個seed,尋找bug
功能覆蓋率的兩個重要部分是采樣的數據和數據被采樣的時刻。數據被采樣的時刻可以是1)使用wait或@來阻塞賦值,2)使用sample的方法。采樣的數據則需要在代
碼中加入覆蓋組(Covergroup)和倉(Bin),覆蓋組可以定義在類中,程序塊,模塊中。使用覆蓋組之前必須先進行實例化。所以一般在類中使用覆蓋組時,將
覆蓋組的實例化加在類的構造函數new()中。Covergroup和Coverpoint的命名應當盡可能的明確,這樣方便檢查覆蓋率文件。
class Driver_cbs_coverage extends Driver_cbs; event trans_ready; //@event來觸發采樣
covergroup CovPort; covergroup CovPort @(trans_ready)
....... coverpoint ifc.cb.port;
endgroup endgroup
virtual task post_tx(Transaction tr);
CovPort.sample(); //顯示通過callback來回調sample函數,完成采樣
endtask
SV支持自動倉的創建,但是更多地適用於2的冪次方,因為這樣才有可能100%命中,最大的自動創建倉的數目是64。auto_bin_max限制自動創建倉的個數,SV這
時,會將值域平分在各個倉。
covergroup CovPort; covergroup CovPort;
coverpoint tr.port options.auto_bin_max = 2; //對整個covergroup有效
{options.auto_bin_max=2;} //只對此coverpoint有效 coverpoint tr.port;
endgroup endgroup
用戶自定義創建倉(bin),將coverpoint和倉分別明確的命名。
covergroup Covkind;
kind:coverpoint tr.kind{ //用kind為coverpoint命名
bins zero={0}; //自定義一個名為zero的倉,值為0
bins lo={[1:3],5}; //自定義一個名為lo的倉,值為[1:3]或5
bins hi[]={[8:$]}; //自定義$-8個倉,8個值得范圍在[8:$]
bins misc=default; //定義一個default的倉,所示所有的剩下的不關心的值
}
endgroup
為覆蓋點增加條件控制采樣時間段,關鍵字iff 。
covergroup CoverPort;
coverpoint port_value iff(!bus_if.reset);
endgroup
為枚舉類型創建倉(bin),所有枚舉類型之外的值都會被忽略,SV默認每個枚舉的值一個倉。
typedef enum{INIT, DECODE, IDLE}fsmstate_e;
fsmstate_e pstate, nstate;
covergroup cg_fsm;
coverpoint pstate;
engroup
忽略某個coverpoint的某些值,覆蓋率不在檢查該值,關鍵字ignore_bins。 illegal_bins不僅忽略某個coverpoint的值,還會報錯。
bit [2:0]low_ports_0_5; bit [2:0]low_ports_0_5;
covergroup CoverPort; covergroup CoverPort;
coverpoint low_ports_0_5{ coverpoint low_ports_0_5{
options.auto_bin_max=4; options.auto_bin_max=4;
ignore_bins hi={[6,7]}; illegal_bins hi={[6,7]};
} }
endgroup endgroup
使用cross關鍵字創建交叉覆蓋率。 //使用串聯值的方式來替換交叉覆蓋
covergroup Covport; covergroup CrossBinnames;
port:coverpoint tr.port a:coverpoint tr.a{bins a0={0}; bins a1={1};}
{bins port[] = {[0:$]};} b:coverpoint tr.b{bins b0={0}; bins b1={1};}
kind:coverpoint tr.kind ab:cross a,b {bins a0b0=binsof(a.a0)&&binsof(b.b0);
{bins zero={0}; bins a1b0=binsof(a.a1)&&binsof(b.b0);
bins lo={[1:3],5}; //注釋同上,只創建一個倉 bins b1=binsof(b.b1);}
bins hi[]={[8:$]}; ab:coverpoint{tr.a, tr.b} //用串聯值得方式來替換
bins misc=default;} {bins a0b0={2'b00};bins a1b0={2'b10};}
cross kind,port{ endgroup
ignore_bins hi=binsof(port) intersect{7}; //去除port這個coverpoint的倉7
ignore_bins md=binsof(port) intersect{0} &&
binsof(kind) intersect{[9:11]};
ignore_bins lo=binsof(kind.lo);} //去除kind這個coverpoint的lo倉
endgroup
對於單個的covergroup,它的覆蓋率是由簡單覆蓋點和交叉覆蓋點兩部分組成的,可以通過關鍵字option.weight來控制整體的覆蓋率傾向。
covergroup CovPort;
Kind:coverpoint tr.kind {bins zero={0}; option.weight=5;}
port:coverpoint tr.port {bins port={0}; option.weight=0;} //計算該covergroup的覆蓋率時,忽略該coverpoint
cross kind,port {option.weight = 10;}
endgroup
當需要編寫的覆蓋組之間十分接近時,可以寫出一個通用的覆蓋組,然后通過new函數或ref的形式來傳遞參數。
bit[2:0]port; bit[2:0]port_a,port_b;
covergroup CoverPort (int mid); covergroup CoverPort (ref bit[2:0]port, input int mid); //定義ref形式
coverpoint port{bins lo={[0:mid-1]}; coverpoint port{bins lo={[0:mid-1]};
bins hi={mid:$};}; bins hi={mid:$};};
endgroup endgroup
CoverPort cp; //定義新的covergroup CoverPort cpa, cpb; //定義新的covergroup
initial cp=new(5); //例化covergroup並傳遞參數 initial begin cpa=new(port_a,4); //例化covergroup並傳遞參數
............. cpa=new(port_b,4);
設置某個covergroup的inst_name,set_inst_name();
使用VCS等仿真工具可以追溯到每個實例的覆蓋率,但此時covergroup中應該添加聲明。
covergroup CoverLength(string comment);
coverpoint tr.length;
option.per_instance=1; //指定需要單個實例的覆蓋率
option.comment=$psprintf("%m");
/或者指定自己的注釋
option.comment = comment;
endgroup
CoverLength cp_lo = new("Low port numbers");
option.at_least,在無法有效的建立bin時,通過該設置保證bin被擊中N次后,就算是覆蓋完全。
還有兩個重要的命令:option.cross_num_print_missing = N; // 讓仿真工具給出所有的倉,柏闊那些沒有被命中的倉(默認不會報出)
option.goal=N; // 設置覆蓋組或覆蓋點的目標 如90等
在長仿真過程中:
$get_coverage:Covergroup::get_coverage()/cgInst:Covergroup()得到某個覆蓋組或者inst的coverage
$get_inst_coverage:得到特定inst的覆蓋率。