驗(yàn)證基礎(chǔ)-驗(yàn)證量化及覆蓋率
????????覆蓋率是衡量設(shè)計(jì)完備性的一個(gè)指標(biāo)。
????????覆蓋率工具會(huì)在仿真過程中收集信息,然后進(jìn)行后續(xù)處理并且得到覆蓋率報(bào)告,然后通過報(bào)告找出覆蓋之外的區(qū)域,接著修改現(xiàn)有測(cè)試或者創(chuàng)建新的測(cè)試來填補(bǔ)這些盲區(qū)。每一次的隨機(jī)測(cè)試我們都會(huì)得到對(duì)應(yīng)的測(cè)試結(jié)果,最后我們?cè)侔堰@些測(cè)試結(jié)果合并,就能得到最終的覆蓋率報(bào)告了。
??????覆蓋率類型
代碼覆蓋率
????????1.行覆蓋率:多少行代碼已經(jīng)被執(zhí)行過。
????????2.路徑覆蓋率:在穿過代碼和表達(dá)式的路徑中哪些已經(jīng)被執(zhí)行過。
????????3.翻轉(zhuǎn)覆蓋率:哪些單位比特變量的值為0或1.
????????4.狀態(tài)機(jī)覆蓋率:狀態(tài)機(jī)哪些狀態(tài)和狀態(tài)轉(zhuǎn)換已經(jīng)被訪問過。
????????代碼覆蓋率最終的結(jié)果用于衡量你執(zhí)行了設(shè)計(jì)中的多少代碼。未經(jīng)測(cè)試的設(shè)計(jì)代碼里可能隱藏硬件漏洞,也可能僅僅就是冗余的代碼。
????????代碼覆蓋率到達(dá)100%,并不意味著驗(yàn)證的工作已經(jīng)完成,但是代碼覆蓋率100%是驗(yàn)證工作完備性的必要條件。
斷言覆蓋率
????????斷言是用于一次性地或在一段時(shí)間對(duì)一個(gè)或者多個(gè)設(shè)計(jì)信號(hào)在邏輯或者時(shí)序上的聲明性代碼。斷言最常用于查找錯(cuò)誤,例如兩個(gè)信號(hào)是否應(yīng)該互斥,或者請(qǐng)求與許可信號(hào)之間的時(shí)序等,一旦檢查到問題,仿真就可以立即停止。
功能覆蓋率
????? ? 驗(yàn)證的目的就是確保設(shè)計(jì)在實(shí)際環(huán)境中的行為正確。功能描述文檔詳細(xì)說明了設(shè)計(jì)應(yīng)該如何運(yùn)行,而驗(yàn)證計(jì)劃則列出了相應(yīng)的功能應(yīng)該如何激勵(lì)、驗(yàn)證和測(cè)量。某個(gè)功能在設(shè)計(jì)時(shí)可能被遺漏,代碼覆蓋率不能發(fā)現(xiàn)這個(gè)錯(cuò)誤,但是功能覆蓋率可以。?
????????每一次仿真都會(huì)產(chǎn)生一個(gè)帶有覆蓋率信息的數(shù)據(jù)庫,記錄隨機(jī)游走的軌跡,把這些信息全部合并在一起就可以得到功能覆蓋率,從而衡量整體的進(jìn)展程度。
????????如果覆蓋率在穩(wěn)步增長(zhǎng),那么添加新的種子或者加長(zhǎng)測(cè)試時(shí)間即可;如果覆蓋率增速緩慢,那么需要添加額外的約束來產(chǎn)生更多“有意思”的激勵(lì);如果覆蓋率停止增長(zhǎng),然而設(shè)計(jì)某些測(cè)試點(diǎn)沒有被覆蓋到,那么需要?jiǎng)?chuàng)建新的測(cè)試;如果覆蓋率為100%但依然有新的設(shè)計(jì)漏洞,那么覆蓋率可能沒有覆蓋到設(shè)計(jì)中的某些設(shè)計(jì)功能區(qū)域。

????????完備的覆蓋率測(cè)量結(jié)果和漏洞增長(zhǎng)曲線,可以幫助確認(rèn)設(shè)計(jì)是否被完整地驗(yàn)證過。A.如果代碼覆蓋率低,但功能覆蓋率高,這說明驗(yàn)證計(jì)劃不完整可能有部分功能點(diǎn)沒被列入驗(yàn)證計(jì)劃。B.如果代碼覆蓋率高,但功能覆蓋率低,這說明即使測(cè)試平臺(tái)很好地執(zhí)行了設(shè)計(jì)的所有代碼,但測(cè)試沒有把設(shè)計(jì)定位到所有感興趣的狀態(tài)上。
????????一般在公司里都會(huì)要求代碼覆蓋率和功能覆蓋率都要達(dá)到95%以上。
覆蓋組
????????覆蓋組(covergroup)與類(class)相似,一次定義后便可以多次實(shí)例化。它含有覆蓋點(diǎn)、選項(xiàng)、形式參數(shù)和可選觸發(fā)(trigger)。一個(gè)覆蓋組包含了一個(gè)或多個(gè)數(shù)據(jù)點(diǎn),全都在同一時(shí)間采集。covergroup可以定義在類中,也可以定義在?interface?或者?module?中,它可以采樣任何可見的變量,例如程序變量、接口信號(hào)或者設(shè)計(jì)端口。
????????一個(gè)類里可以包含多個(gè)covergroup,當(dāng)你擁有多個(gè)獨(dú)立的 covergroup 時(shí),每個(gè)covergroup 可以根據(jù)需要自行使能或者禁止。covergroup 必須要被例化才可以用來收集數(shù)據(jù)。

????????如果覆蓋組定義在類里,實(shí)例化時(shí)可以使用最初的名字,例如上面這個(gè)例子中展現(xiàn)的,申明了CovPort為covergroup后,就直接對(duì)它進(jìn)行了new(),實(shí)際上我們知道這只是聲明該變量為covergroup類型并不是聲明對(duì)象。除此種特殊的例化方式,通常使用的是下面這種:

????????因?yàn)閏overgroup是可以例化多次的,如果采用直接把CovPort作為實(shí)例名例化,那就不能例化第二次了,而采用下面這種聲明一個(gè)別的對(duì)象為CovPort類型(也即covergroup類型)顯然可以例化多次,改個(gè)聲明對(duì)象名字即可。
????????上面的代碼,在采樣的時(shí)候,采用的是CovPort.sample()(調(diào)用sample()函數(shù))的方式進(jìn)行采樣,這是第一種采樣方式,還有第二種就是采取阻塞的方式wait或者@實(shí)現(xiàn)事件上的阻塞,當(dāng)遇到什么事件的時(shí)候再進(jìn)行采樣。
數(shù)據(jù)采樣
????????當(dāng)你在 coverpoint 指定采樣一個(gè)變量或表達(dá)式時(shí),SV會(huì)創(chuàng)建很多的倉(bin)來記錄每個(gè)數(shù)值被捕捉到的次數(shù)。這些bin是衡量功能覆蓋率的基本單位。
????????covergroup 中可以定義多個(gè)coverpoint,coverpoint中可以自定義多個(gè)cover bin或者SV幫助自動(dòng)定義多個(gè)cover bin。
????????為了計(jì)算一個(gè)coverpoint上的覆蓋率,首先需要確定可能數(shù)值的個(gè)數(shù),這也被稱為域。
????????※ 覆蓋率就是采樣值的數(shù)目除以bin的數(shù)目。例如一個(gè)3bit變量的域是0:7,正常情況下會(huì)自動(dòng)分配8個(gè)bin。如果仿真過程中有7個(gè)值被采樣到,那么最終該coverpoint的覆蓋率為7/8。
????????※ 所有的coverpoint的覆蓋率最終構(gòu)成一個(gè)covergroup的覆蓋率。所有的covergroup的覆蓋率構(gòu)成了整體的覆蓋率。
????????如果采樣變量的域范圍過大而又沒有指定bin,那么系統(tǒng)會(huì)默認(rèn)分配64個(gè)bin,將值域范圍平均分配個(gè)這64個(gè)bin,例如一個(gè)16bit變量有65536個(gè)可能值,所以64個(gè)bin中的每一個(gè)都覆蓋了1024個(gè)值。用戶可以通過covergroup的選項(xiàng)auto_bin_max來指定自動(dòng)創(chuàng)建bin的最大數(shù)目。實(shí)際操作中自動(dòng)創(chuàng)建bin的方法并不實(shí)用,建議用戶自行定義bin:

注意coverpoint定義使用{}而不是begin-end。大括號(hào)的結(jié)尾沒有分號(hào),和end一樣。


對(duì)于hi,會(huì)分配8個(gè)bin。lo是一個(gè)bin,misc也是一個(gè)bin。左邊是bin的名稱,中間是bin里的數(shù)據(jù)被采樣了多少次,右邊意思是這個(gè)至少要收集多少次。上面這個(gè)結(jié)果來看,總共有11個(gè)bin,只有一個(gè)bin沒有被收集到,那么它最終的覆蓋率就是10/11。
條件覆蓋率
????????可以使用關(guān)鍵詞 iff 給 coverpoint 添加條件。

????????如果在采樣(sample函數(shù))的時(shí)候,使用了iff,那么收集覆蓋率的時(shí)候,既要滿足sample()進(jìn)行采樣,也要滿足iff后面的條件,才會(huì)對(duì)其進(jìn)行采樣。還可以使用start和stop函數(shù)來控制covergroup各個(gè)獨(dú)立實(shí)例的開啟和關(guān)閉,如果關(guān)閉了,哪怕設(shè)了采樣sample函數(shù),也不會(huì)真的采樣。
翻轉(zhuǎn)覆蓋率
????????coverpoint 也可以用來記錄變量從A值到B值的跳轉(zhuǎn)情況。還可以確定任何長(zhǎng)度的翻轉(zhuǎn)次數(shù)。

????記錄t1值從0翻轉(zhuǎn)到1或者2或者3的次數(shù),但凡這三個(gè)事件有一個(gè)發(fā)生,bin里面記錄的次數(shù)就會(huì)加1。
忽略的bin

????????三比特變量low_ports_0_5最初的范圍是0:7。ignore_bins 排除掉最后兩個(gè)倉,即不考慮6和7的采樣值,從而把采樣范圍縮小到0:5.所以這個(gè)組的總體覆蓋率是采樣到的倉數(shù)除以總倉數(shù),這里總倉數(shù)時(shí)是6。
非法的bin
????????有些采樣值不僅應(yīng)該被忽略而且如果出現(xiàn)還應(yīng)該報(bào)錯(cuò)。
????????這種情況可以在測(cè)試平臺(tái)中監(jiān)測(cè),也可以使用illegal_bins對(duì)特定的bin進(jìn)行標(biāo)示。

如果出現(xiàn)6,7不單不能出現(xiàn),而且如果出現(xiàn)了就會(huì)報(bào)錯(cuò)。
交叉覆蓋率
????????coverpoint 是記錄單個(gè)變量或者表達(dá)式的觀測(cè)值。如果想記錄某一時(shí)刻,多個(gè)變量之間值的組合情況,需要使用交叉(cross) 覆蓋率。

排除部分cross bin
????????比如上面的例子,假設(shè)kind有16個(gè)bin,port有8個(gè)bin,那么cross之后,它們之間就會(huì)產(chǎn)生8*16=128個(gè)bin,數(shù)量很多,為了減少bin的數(shù)量,我們可以采用ignore的方式來清除那些我們不關(guān)心的cross bin。

????????如上面的例子,port共有8個(gè)bin,kind共有11個(gè)bin。在聲明兩個(gè)變量的交叉覆蓋率的時(shí)候,忽略了很多的交叉情況,比如當(dāng)port 里值為7時(shí),不考慮和 kind 的 bin 交叉的情況,以及 port 里值為0且 kind 里值為9-11的時(shí)候,也不考慮這種情況的交叉 bin 等。
????????但是隨著cross覆蓋率越來越精細(xì),更合適的方式是不使用自動(dòng)分配的cross bin,而是自己聲明自己感興趣的cross bin。
????????假如有兩個(gè)隨機(jī)變量a,b。它們帶著三種感興趣的狀態(tài){a==0,b==0}\{a==1,b==0}和{b==1}。

選擇自己感興趣的點(diǎn)做交叉覆蓋。
覆蓋選項(xiàng)
????????如果對(duì)一個(gè)covergroup 例化多次,那么默認(rèn)情況下SV會(huì)將所有實(shí)例的覆蓋率加權(quán)合并到一起,如果需要單獨(dú)列出每個(gè)covergroup實(shí)例的覆蓋率,需要設(shè)置覆蓋選項(xiàng)。

這樣設(shè)置option后,每個(gè)實(shí)例的覆蓋率都會(huì)單獨(dú)計(jì)算。
????????如果有多個(gè)covergroup實(shí)例,可以通過參數(shù)來對(duì)每一個(gè)實(shí)例傳入單獨(dú)的注釋。這些注釋最終會(huì)顯示在覆蓋率數(shù)據(jù)的總結(jié)報(bào)告中。

????????covergroup 方法:sample()采樣、get_coverage()/get_inst_coverage():獲取覆蓋率,返回0-100的real數(shù)值。set_inst_name(string):設(shè)置coverage的名稱、start()/stop():使能或者關(guān)閉覆蓋率的收集。
覆蓋率分析
????????使用?$get_coverage()?可以得到總體的覆蓋率。
????????也可以使用 covergroup_inst.get_inst_coverage( )?來獲取單個(gè) covergroup 實(shí)例的覆蓋率。
????????如果覆蓋率水平在一段時(shí)間之后沒有提高,那么這個(gè)測(cè)試就應(yīng)該停止。重啟新的隨機(jī)種子或者測(cè)試可能有望提高覆蓋率,重新限定隨機(jī)的約束也能對(duì)提高覆蓋率有所幫助。