1. 前言
通常說的覆蓋率有兩種類型:code coverage(代碼覆蓋率)和functional coverage(功能覆蓋率)。代碼覆蓋率是使用EDA工具自動從設計代碼里提取出來的,功能覆蓋率是用戶指定的,用于衡量測試設計意圖和功能進展。因此,功能覆蓋率有兩個關鍵點:
- 它是用于指定的,而不是根據設計代碼自動推測生成的;
- 它是基于設計需求,獨立于實際設計代碼和結構;
覆蓋率主要由覆蓋率組(covergroup)、覆蓋率點(coverage point)、交叉覆蓋率(cross coverage)、覆蓋率選項(coverage option)和覆蓋率方法(coverage method)組成的。
2. covergroup
Covergroup用于構建覆蓋率模型,它將覆蓋率模型和規范封裝起來,內部可以包含以下組件:
- 用于coverage point同步和采樣的時鐘事件;
- Coverage points;
- Cross coverage;
- 可選的參數;
- Coverage options
Covergroup是用戶定義的類型,可以定義在package、module、program、interface、checker或class里面。類似于class,covergroup可以在多處地方調用new()構造函數例化。如下所示,covegroup name是cg,通過new()構造函數,創建了cg的例化cg_inst。
covergroup cg; ... endgroup
cg cg_inst = new;
covergroup可以通過new(xx)構造函數傳遞參數進去,參數的類型只能是ef(會被處理成const ref)或input,而不能時output或inout。
可以通過@event或sample()方法來指定coverage何時采樣。Covergroup可以包含一個或多個coverage points。Coverage point可以覆蓋一個變量或一個表達式。Coverage point內部可以包含一組bins(倉),用于采集values或value transitions。用于采集value 集合的bin稱為state bins,用于采集value transitions的bin稱為transition bins。
也可以將coverage group嵌入到class定義中,這是一種常見的做法,它提供了一種簡單的方式去覆蓋類中的屬性,可以保護類的封裝性,這種方式稱作embedded covergroup declaration。
3. coverage point
Coverpoint表達式(包括iff condition)的采樣是發生在covergroup被采樣的時候。Coverpoint會創建一個層次化范圍且可選的labeled。如果有使用label,那么該label就是coverage point的名字。該名字也可以用于cross coverage 和訪問coverpoint中的方法。如果沒有指定label且coverpoint只和一個單一變量關聯,那么該變量名可以是coverpoint的名字,其它情況,由工具實現定義,但該自動生成的名字只是用于coverpoint報告,不能被其它地方語言引用。
Coverpoint bin將一個name和count與一組value或value transition 序列聯系起來,當一個bin指定的value或value transition 序列每一次滿足時,相應的count加1。每一個bins的后面都可以跟著iff construct來指定該bins是否滿足采樣條件,如果是false,那么count肯定不會增加的。Transition bin在每一個sample中,最多只能增加1,不管同時有幾個hit同一個bins。
bins允許對于給定范圍列表的每一個value創建一個獨立的bin,可以在bin name后面加上[]就可以了,或者如果要把給定范圍列表分配到幾個bin內,可以在[]里加上正整數expression。如果bins的固定個數小于values的指定個數,那么盡力采用均分,無法均分,最后一個全部兜著。如果bins的個數大于values的指定個數,那么有一些bins將會是空的。
bins允許對于范圍列表創建一個單一的bin,也就是bin name的等號后面使用{}指定一組values。
對于范圍列表,允許使用[ expression : $ ] or [ $ : expression ]。
如果沒有指定bins的話,coverpoint bin會自動創建,創建的最大個數為auto_bin_max(coverage option)指定的。
default可以用于替代沒有被顯式定義的bins中指定的其它值,對于coverpoint覆蓋率的計算不考慮default bin,同樣的,cross coverage也不考慮default。default sequence用于替代沒有被顯式定義的transition bins中指定的其它transition值。defualt或者defualt sequence bin不能被顯式ignored。如果一個bins被指定為ignore_bins且被指定為default或defualt sequence,那么會報錯的。
Wildcard bin使得所有的X、Z或?可以被當作0或1。如下:
wildcard bins g12_15 = { 4'b11?? };
如果采樣值有1100、1101、1110和1111,那么g12_15命中的次數就增加。
Wildcard bins也可以用于separate bins,例如:
wildcard bins g12_15_array[] = { 4'b11?? };
上述會創建1100、1101、1110和1111這4個bin。
Wildcard bins也可以用于transition bins,例如:
wildcard bins T0_3 = (2'b0x => 2'b1x);
每當有下面的value transitions,T0_3 bin的計數會增加,有點類似于(0,1=>2,3)方法。
00 => 10、00 => 11、01 => 10、01 => 11
3.1. Transition bins的指定方式
value1(range_list1) => value2(range_list2):表示value1的下一次sample要是value2;如果有用到range_list,那么SV會拓展range_list里的值其它值進行轉換,比如:
1,5 => 6, 7
那么它的效果相當于:( 1=>6 ), ( 1=>7 ), ( 5=>6 ), ( 5=>7 )
trans_item [* repeat_range ]: 表示trans_item要重復repeat_range次,比如:
3 [* 5]
上述等價于:3=>3=>3=>3=>3
還可以指定重復的范圍,比如:
3 [* 3:5]
上述等價于:( 3=>3=>3 ), ( 3=>3=>3=>3 ), ( 3=>3=>3=>3=>3 )
trans_item [-> repeat_range],或trans_item [= repeat_range]:表示trans_item出現個數,中間不管有什么其它值。比如:
3 [-> 3]
上述等于:...=>3...=>3...=>3,(...)代表任何不包含值為3的轉換。在比如:
1 => 3 [ -> 3] => 5
上述等于:1...=>3...=>3...=>3 =>5
4. cross coverage
Coverage group可以指定在兩個或多個coverpoints或變量之間進行cross coverage。如果指定的是變量,那么SV會隱式地幫它定義一個coverpoint,然后再參與到cross。因此cross coverage的輸入本質上只有coverpoint。另外expression不能直接用于cross中,只能先將expression定義成coverpoint,然后再用cross。
Cross coverage提供了一個可選的label,該label會為cross中定義的bins創建一個層次化范圍。Cross coverage也可用iff來選擇是否在該次統計coverage。
對于coverpoint中定義為default、ignored或illegal的bins,在cross中不會創建bins的。Cross coverage只允許用同一個coverage group中的coverage points進行cross,引用其它group的coverpoint將會導致編譯錯誤。
除了cross自動生成的bins之外,SV允許用戶定義指定的cross coverage bins。可以使用bin select 方式來定義用戶自定義的bins。用戶自定義cross bins和自動生成 bins可以在同一個cross中生成的。只要沒有被用戶定義的cross bin截斷的其它自動生成bins都會保持。如下例子:
int i,j;
covergroup ct;
??? coverpoint i { bins i[] = { [0:1] }; }
??? coverpoint j { bins j[] = { [0:1] }; }
??? x1: cross i,j;
??? x2: cross i,j {
??????? bins i_zero = binsof(i) intersect { 0 };
??? }
endgroup
x1 cross的結果為:
<i[0],j[0]>
<i[1],j[0]>
<i[0],j[1]>
<i[1],j[1]>
x2 cross的結果為:
i_zero? // user-specified bin for <i[0],j[0]> and <i[0],j[1]>
<i[1],j[0]>? // an automatically generated bin that is retained
<i[1],j[1]>? // an automatically generated bin that is retained
binsof語法產生它里面表達式的bins,該表達式可以是coverage point(顯式)或單個變量(隱式生成coverpoint),或coverpoint bin。生成的結果bins可以進一步選擇,通過intersect語法來選擇或排除某些bins的值。Bins值的選擇可以使用逗號分隔來選取多個,因此可以選擇1個value、一個范圍value、也可以范圍值。例如:
[ $ : value ] => The set of values less than or equal to value
[ value : $ ] => The set of values greater or equal to value
bins的選擇可以和其它bins的的選擇進行邏輯運算(&&, ||)來進一步選擇的。
5. coverage option
Coverage options可以用于控制covergroup、coverpoint和cross的行為。有兩種options類型:一種用于指定covergroup instance的行為,另一種用于指定covergroup type的行為。如果對于同樣option,指定多個值會報錯的。
5.1 Covergroup instance options
下表為instance-specific covergroup options及其描述。這些options可以在初始化instance-specific options時指定不同的值。這些初始化option value只影響對應的instance。
Instance-specific options可以在covergroup定義的時候set進去。在covergroup定義時設置這些options的語法如下:
option.member_name = expression;
每一個covergroup、coverpoint或corss內部都自帶有option這個成員變量。covergroup定義時,內部的option賦值語句是在該covergroup例化時生效的。per_instance和get_inst_coverage options只能在covergroup定義時設置。auto_bin_max和detect_overlap options只能在covergroup和coverpoint定義時生效。其它的instance-specific options可以在covergroup例化之后,通過賦值來設置的。下表總結了instance options在不同語法層次(covergroup、coverpoint或cross)的總結。所有的instance options可以在covergroup層次指定。除了weight、goal、comment和per_instance options,所有其它options在covergroup設置后,也作為該covergroup內部所有coverpoints和crosses的相應options的默認值。當然獨立的coverpoints或crosses可以覆蓋這些默認值。weight、goal、comment和per_instance options在covergroup層次設置時,不會影響更低層次(coverpoint和cross)相應options的默認值。
5.2 Covergroup type options
下表列出的options描述covergroup type整體的屬性。它們就像是class中的static data members一樣,對于所有的instances都起作用的。
上述提到的covergroup type options可以在covergroup定義時設置,語法如下:
type_option.member_name = constant_expression;
type_option是每個covergroup、coverpoint和cross內建的static 成員。不同instances不能對type_options賦不同的值。這些options只能在初始化時通過常數表達式來設置。Strobe type option只能在covergroup定義時設置,其它type options可以在仿真進行中賦值,通過::方式來的。如下:
covergroup gc @(posedge clk) ;
??? a : coverpoint a_var;
??? b : coverpoint b_var;
endgroup
...
// Set the comment for all covergroups of type "gc"
gc::type_option.comment = "Here is a comment for covergroup g1";
// Set the weight for coverpoint "a" of all covergroups of type gc
gc::a::type_option.weight = 3;
gc g1 = new;
下表列出了不同層次的type options可以是否被設置。covergroup層次的設置不影響到底下層次的設置。
6. coverage method
covergroup提供了一些coverage方法,這些方法可以在任何時刻被調用:
get_coverage()返回type coverage,它包含了所有該type例化出來的coverage累積,它是static方法,可以用::操作符和.操作符來引用。get_inst_coverage()返回指定instance的coverage,它只能對應的instance有關聯,不是static方法,因此只能用.操作符。另外,covergroup里的sample()函數其實可以使用with關鍵字來override的。
SV提供了以下的系統方法去幫助管理覆蓋率數據收集:
- $set_coverage_db_name ( filename ):設置覆蓋率數據庫的文件名,在仿真運行結束時將覆蓋率信息保存到該數據庫中。
- $load_coverage_db ( filename ):從給定的文件名加載所有coverage group類型的累積覆蓋率信息。
- $get_coverage ( ):返回0~100范圍內所有coverage group類型的總體覆蓋率的實數。這個數字是按照前面描述的方法計算的。
7. coverage computation
關于覆蓋率的計算,請看這篇文章《Systemverilog覆蓋率的合并和計算方式_覆蓋率merge-CSDN博客》。