房地產(chǎn)網(wǎng)站制作seo搜索引擎優(yōu)化
文章目錄
- 1.0 覆蓋率前言
- 1.1 覆蓋率類型
- 1.2 覆蓋策略及覆蓋組
- 1.3 覆蓋率數(shù)據(jù)采樣
- 1.3.1 bin的創(chuàng)建與使用
- 1.3.2 條件覆蓋率
- 1.3.3 翻轉覆蓋率
- 1.3.4 wildcard覆蓋率
- 1.3.5 忽略bin與非法bin
- 1.4 交叉覆蓋率
- 1.4.1 排除部分cross bin
- 1.4.2 精細化交叉覆蓋率
- 1.4.3 單個實例的覆蓋率
- 1.4.4 注釋
- 1.4.5 覆蓋率次數(shù)限定與目標
- 1.4.6 covergroup方法總結
- 1.4.7 案例
1.0 覆蓋率前言
覆蓋率是用來衡量設計驗證完備性。隨著測試逐步覆蓋各種合理的組合,覆蓋率用來衡量測試進行的程度。覆蓋率工具會在仿真過程中收集信息,然后進行后續(xù)處理并且得到覆蓋率報告。通過報告找出覆蓋盲區(qū),然后修改現(xiàn)有test或者創(chuàng)建新的test來填補這些盲區(qū)。
覆蓋率反饋環(huán)路:
帶約束的隨機測試與定向測試這兩種環(huán)路一直迭代,直到達到要求
收集覆蓋率:最簡單的辦法就是改變隨機種子seed,就可以反復運行同一個隨機測試平臺來產(chǎn)生新的激勵。每一次仿真都會產(chǎn)生一個帶有覆蓋率信息的數(shù)據(jù)庫,將這些信息全部合并在一起就可以得到功能覆蓋率。
1.1 覆蓋率類型
-
代碼覆蓋率:直接去檢查RTL Code
代碼覆蓋率衡量的是測試對于硬件設計描述的“實現(xiàn)”究竟測試得有多徹底,而非針對驗證計劃。
- line coverage:所有行是否都運行到
- paths coverage:所有路徑是否以cover到
- toggle coverage:所有變量都有過0,1翻轉
- FSM coverage:狀態(tài)機中所有狀態(tài)都已運行到
很多的仿真工具都帶有代碼覆蓋率工具,而得到的最終結果就是檢測對設計代碼運行程度的衡量。代碼覆蓋率最終的結果用于衡量所有testcase執(zhí)行了設計中的多少代碼。 關注點在設計代碼RTL的分析上,而不是測試平臺。
未經(jīng)測試的設計代碼里可能隱藏硬件漏洞,也可能是冗余代碼。
代碼覆蓋率達到了100%,并不意味著驗證的工作已經(jīng)完成,但代碼覆蓋率100%是驗證工作完備性的必要條件
-
功能覆蓋率:
驗證的目的: 確保設計在實際環(huán)境中的行為正確。功能描述文檔詳細說明了設計應該如何運行,而驗證計劃則列出了相應的功能應該如何激 勵、驗證和測量。功能覆蓋率是和功能設計緊密相連的,而代碼覆蓋率則是衡量設計的實現(xiàn)情況。若某個功能在設計中被遺漏,代碼覆蓋率不能發(fā)現(xiàn)這個錯誤,但是功能覆蓋率可以。
-
斷言覆蓋率
斷言:用于一次性地或在一段時間內(nèi)核對兩個或兩個以上設計信號之間關系的聲明性代碼。斷言覆蓋率可以測量某斷言被觸發(fā)的頻繁程度。斷言可以跟隨設計和測試平臺一起仿真,也可以被形式驗證工具所證實??梢允褂肧V的程序性代碼編寫等效性檢查,但使用SVA(SV斷言)來表達會更容易。斷言最常用于查找錯誤,例如兩個信號間的相位關系,是否應該互斥或者請求與許可信號之間的時序等。
一旦檢測到問題,仿真就可以立即停止。
斷言可以用于查找感興趣的信號的值或者狀態(tài)。 可以使用cover property來測量這些關心的信號的值或者狀態(tài)是否發(fā)生。在仿真結束時,仿真工具可以自動生成斷言覆蓋率數(shù)據(jù)。斷言覆蓋率數(shù)據(jù)以及其它覆蓋率數(shù)據(jù)都會被集成在同一個覆蓋率數(shù)據(jù)庫中,verifier可以對其展開分析。
漏洞率以及漏洞曲線:
在一個項目實施期間,應該保持追蹤每周有多少個漏洞被發(fā)現(xiàn)。一開始,當創(chuàng)建測試程序時,通過觀察可能就會發(fā)現(xiàn)很多漏洞。當設計逐漸穩(wěn)定時,需要利用自動化的檢查方式來協(xié)助發(fā)現(xiàn)可能的漏洞。在設計臨近流片時,漏洞率會下降,甚至有望為零。即便如此,驗證工作仍然不能結束。每次漏洞率下降時,就應該尋找各種不同的辦法去測試可能的邊界情況(corner case)。
漏洞率可能每周都有變化,這跟很多因素都有關。不過漏洞率如果出現(xiàn)意外的變化,可能預示著潛在的問題。
1.2 覆蓋策略及覆蓋組
-
覆蓋策略:只測量需要的內(nèi)容,例如初始化階段不需要測試
-
只測試需要的內(nèi)容:驗證工程師需要懂得,在使能覆蓋率收集時,這一特性會降低很大的仿真性能。由于收集功能覆蓋率數(shù)據(jù)的開銷很大,所以應該只測量你會用來分析并且改進測試的那部分數(shù)據(jù)。同時也需要設定合理的覆蓋率采樣的事件,一方面提升采樣效率,一方面也可以降低收集覆蓋率的開銷。
-
驗證的完備性:完備的覆蓋率測量結果和漏洞增長曲線,可以幫助確認設計是否被完整地驗證過。如果功能覆蓋率高但代碼覆蓋率低,這說明驗證計劃不完整,測試沒有執(zhí)行設計的所有代碼。如果代碼覆蓋率高但功能覆蓋率低,這說明即使測試平臺很好地執(zhí)行了設計的所有代碼,但是測試還是沒有把設計定位到所有感興趣的狀態(tài)上。
你的目標是同時驅動高的代碼覆蓋率和功能覆蓋率。
-
覆蓋率比較:
-
-
覆蓋組covergroup
覆蓋組與類相似,一次定義就可以多次實例化且全都在同一時間采集。一個覆蓋組包含覆蓋點,選項,形式參數(shù)和可觸發(fā)(trigger),一個或多個數(shù)據(jù)點。
covergroup
可以定義在類中,也可以定義在interface或者module中,一個類里可以包含多個covergroup
,covergroup
可以采樣任何可見的變量,例如程序變量、接口信號或者設計端口。
當你擁有多個獨立的covergroup
時,每個covergroup
可以根據(jù)需要自行使能或者禁止。每個covergroup
可以定義單獨的觸發(fā)采樣事件,允許從多個源頭收集數(shù)據(jù)。covergroup必須被例化才可以用來收集數(shù)據(jù)。
-
入門案例:一個簡單對象的功能覆蓋率,測試程序使用CovPort覆蓋組對port字段的數(shù)值進行采樣,八種可能的數(shù)值,32次隨機。
interface busifc;logic clk;logic [31:0] data;logic [2:0] port; endinterfaceclass Transaction;rand bit [31:0] data; rand bit [2:0] port; // 八種端口數(shù)據(jù) endclass program automatic test(busifc.TB ifc);covergroup CovPortcoverpoint ifc.port; //測試覆蓋率:檢測8個port是否都出現(xiàn)過endgroup initial begin Transaction tr; CovPort ck; ck = new(); // 實例化組tr = new(); repeat (32) begin // 運行幾個周期assert(tr.randomize); ifc.port <= tr.port; // 發(fā)送到接口上ifc.data <= tr.data; ck.sample(); // 收集覆蓋率@ifc.clk; // 等待一個周期end end endprogram
8中可能,32次隨機,該例的VCS的覆蓋率報告(一部分)如下:
Coverage:87.50.......... bin #hit at least ::::::::::::::::::::::::::::::::::: auto[1] 7 1 auto[2] 7 1 auto[3] 1 1 auto[4] 5 1 auto[5] 4 1 auto[6] 2 1 auto[7] 6 1
-
例:在類里使用功能覆蓋率
class Transaction;rand bit [31:0] data; rand bit [2:0] port; endclass class Transactor;Transaction tr; mailbox mbx_in;virtual busifc ifc;covergroup CovPort;coverpoint tr.port;endgroup // 由于覆蓋組實例化在new里面,因此在program不需要實例化function new(mailbox mbx_in, virtual busifc ifc); CovPort = new(); this.mbx_in = mbx_in; this.ifc = ifc;endfunction task main; beginmbx_in.get(tr); ifc.port <= tr.port;ifc.data <= tr.data; CovPort.sample();end endtask endclassinterface busifc;logic clk;logic [31:0] data;logic [2:0] port; endinterfaceprogram automatic test(busifc ifc);Transaction tr;Transactor tr_c;mailbox mbx_in;initial begintr = new();mbx_in = new();tr_c = new(mbx_in,ifc);repeat (32) begin assert(tr.randomize); mbx_in.put(tr);tr_c.main();@(posedge ifc.clk);endend endprogrammodule top;busifc ifc();initial beginifc.clk=0;forever #10 ifc.clk=~ifc.clk;endtest test_u(ifc); endmodule
觸發(fā): covergroup由采樣的數(shù)據(jù)和數(shù)據(jù)被采樣的事件構成。當這兩個條件都準備好以后,測試平臺便會觸發(fā)covergroup。這個過程可以通過直接使用sample()
函數(shù)完成,也可以在covergroup中采樣阻塞表達式或者使用wait或@
實現(xiàn)在信號或事件上的阻塞。如果想在代碼中顯式地觸發(fā)covergroup采樣,或者不存在采樣時刻的信號或事件,又或者一個covergroup被例化為多個實例需要單獨觸發(fā),那么可以使用sample()方法。如果你想借助已有的事件或者信號觸發(fā)covergroup,可以在covergroup聲明中使用阻塞語句。
-
使用事件觸發(fā):
event trans_ready; covergroup CovPort @(trans_ready);coverpoint ifc.cb.port; endgroup
與直接調用
sample()
相比,使用事件觸發(fā)的好處在于你能夠借助已有的事件,來決定何時開始收集數(shù)據(jù)。
1.3 覆蓋率數(shù)據(jù)采樣
當在覆蓋點上指定一個變量或者表達式時,SV便會創(chuàng)建很多的倉bin來記錄每個數(shù)值被捕捉到的次數(shù)。這些bin是衡量覆蓋率的基本單位。為了計算出一個點上的覆蓋率,首先要了解域的概念,域是所有可能值的的個數(shù)。覆蓋率就是采樣值的數(shù)目除以域中bin的數(shù)目。
covergroup中可以定義多個coverpoint,coverpoint中可以自定義多個cover bin或者SV幫助自動定義多個cover bin,每次covergroup采樣,SV都會在一個或者多個cover bin中留下標記,用來記錄采樣時變量的數(shù)值和匹配的cover bin。
例如:一個3bit變量的域為0:7
,正常情況下會除以8個bin,如果在仿真的過程中只有7個值被采樣到,那么報告就會給出這個coverpoint點的覆蓋率是7/8也即87.5%。所有這些coverpoint點組合在一起就是covergroup組的覆蓋率,所有covergroup組組合在一起就是整個的仿真覆蓋率。而這也僅僅是單個仿真的情況,在實際中需要追蹤覆蓋率隨時間的變化情況,分析趨勢。
1.3.1 bin的創(chuàng)建與使用
SV會默認為某個coverpoint創(chuàng)建bin,用戶也可以自己定義bin的采樣域。如果采樣變量的域范圍過大而又沒有指定bin,那么系統(tǒng)會默認分配64個bin,將值域范圍平均分配給這64個bin。用戶可以通過covergroup的選項auto_bin_max來指定自動創(chuàng)建bin的最大數(shù)目。
實際操作中,自動創(chuàng)建bin的方法不實用,建議用戶自行定義bin(整體的去定義,或定義單獨的點),或者減小auto_bin_max的數(shù)值。
covergroup covport;// 所有coverpoint auto_bin數(shù)量=8option.auto_bin_max = 8; // 特定coverpoint auto_bin數(shù)量=2coverpoint tr.port {option.auto_bin_max = 2;}
endgroup
延用本章的入門案例,port位寬為3,值域是0個可能的值,因此第一個倉保存的是值域范圍的前半段0-3,第二個倉保存的是后半段4-7,VCS給出的覆蓋率報告部分如下:
bin #hit at least
:::::::::::::::::::::::::::::::::::
auto[0-3] 15 1
auto[4-7] 17 1
除此之外,還可以單獨命名覆蓋點的倉,例如下面對一個4bit的變量kind進行采樣,有16種可能,對其進行單獨的覆蓋采樣:
第一個倉:命名為zero,對kind=0的情況進行計數(shù)
第二個倉:命名為lo,對1~3,5這四個值進行計數(shù)
第三個倉:命名為hi,將8~15保存到單獨的倉里,分別為:hi_8,hi_9,hi_a,hi-b … hi_f
第四個倉:命名為misc,對前面沒有出現(xiàn)過的值進行采樣,也即4,6,7
covergroup CovKind;coverpoint tr.kind {bins zero = {0}; // 1個倉代表kind**0bins lo = {[1:3], 5}; // 1個倉代表1:3和5bins hi[] = {[8:$]}; // 8個獨立的倉代表8:15bins misc = default; // 1個倉代表剩余的所有值} // 沒有分號
endgroup
注意coverpoint定義使用{}
而不是begin…end,大括號的結尾沒有帶分號;
,VCS的部分報告如下
Bin #hits at least
:::::::::::::::::::::::::::::::::::
hi_8 0 1
hi_9 5 1
hi_a 3 1
hi_b 4 1
hi_c 2 1
hi_d 2 1
hi_e 9 1
hi_f 4 1
lo 16 1
misc 15 1
zero 1 1
1.3.2 條件覆蓋率
可以使用關鍵詞iff給coverpoint添加條件。這種做法常用于在復位期間關閉覆蓋以忽略不合理的條件觸發(fā)。
例:僅收集reset=0
(高電平有效)時port的值。
covergroup CoverPort;coverpoint port iff(!bus_if.reset);
endgroup
同樣的,也可以使用start和stop函數(shù)來控制 covergroup各個獨立實例。
initial begincovport ck = new();// 復位期間停止收集覆蓋率#1ns;ck.stop();bus_if.reset = 1;#100ns bus_if.reset = 0;// 復位結束ck.start();...
end
1.3.3 翻轉覆蓋率
coverpoint也可以用來記錄變量從A值到B值的跳轉情況。還可以確定任何長度的翻轉次數(shù)。
例:查詢port有沒有從0變?yōu)?,2,3。
covergroup CoverPort;coverpoint port {bins t1 = {(0 => 1), (0 => 2), (0 => 3)};}
endgroup
1.3.4 wildcard覆蓋率
可以使用關鍵字wildcard來創(chuàng)建多個狀態(tài)或者翻轉。在表達式中,任何X,Z或者?都會被當成0或1的通配符。
例如:采樣偶數(shù)與奇數(shù),兩個倉分別代表奇數(shù)偶數(shù)。
bit [2:0] port;
covergroup CoverPort;coverpoint port {wildcard bins even = {3'b??0};wildcard bins odd = {3'b??1};}
endgroup
1.3.5 忽略bin與非法bin
-
忽略bin:排除那些不用來計算覆蓋率的數(shù)值
在某些coverpoint可能始終無法得到全部的域值。對于那些不計算功能的域值可以使用
ignore_bins
來排除,最終它們并不會計入coverpoint的覆蓋率。例1:使用
ignore_bins
的覆蓋點bit [2:0] low_ports_0_5; // 只使用數(shù)值0-5 covergroup CoverPort;coverpoint low_ports_0_5 {ignore_bins hi = {[6,7]}; // 忽略數(shù)值6-7} endgroup
由于忽略了數(shù)值6-7,因此總倉數(shù)是6
例2:使用
ignore_bins
和auto_bin_max
的覆蓋點bit [2:0] low_ports_0_5; // 只使用數(shù)值0-5 covergroup CoverPort;coverpoint low_ports_0_5 {options.auto_bin_max=4; // 0:1 2:3 4:5 6:7ignore_bins hi = {[6,7]}; // 忽略數(shù)值6-7} endgroup
創(chuàng)建了四個倉,但由于最后一個倉被ignore_bins所忽略,所以只有三個倉被創(chuàng)建,因此覆蓋率只有四種可能值,分別為0%,33%,66%和100%。
-
非法bin:有些采樣值不僅應該被忽略,如果出現(xiàn)了還應該報錯。
這種情況可以在測試平臺中監(jiān)測,也可以使用illegal_bins對特定的bin進行標示。
bit [2:0] low_ports_0_5; // 只是用數(shù)值0-5 covergroup CoverPort;coverpoint low_ports_0_5 {illegal_bins hi = {[6,7]}; // 如果出現(xiàn)6-7便報錯} endgroup
1.4 交叉覆蓋率
coverpoint是記錄單個變量或者表達式的觀測值。如果像記錄在某一時刻,多個變量之間值的組合情況,需要使用交叉(cross) 覆蓋率。cross語句只允許帶coverpoint或者簡單的變量名。
class Transaction;rand bit [3:0] kind;rand bit [2:0] port;
endclassTransaction tr;
covergroup CovPort;kind: coverpoint tr.kind;port: coverpoint tr.port;cross kind, port;
endgroup
關心kind與port的組合情況的覆蓋率。
1.4.1 排除部分cross bin
通過使用ignore_bins、binsof和intersect分別指定coverpoint和值域, 這樣可以清除很多不關心的cross bin
covergroup Covport;port: coverpoint tr.port{bins port[] = {[0:$]};}kind: coverpoint tr.kind {bins zero = {0};bins lo = {[1:3]};bins hi[] = {[8:$]};bins misc = default;}cross kind, port {ignore_bins hi = binsof(port) intersect {7};ignore_bins md = binsof(port) intersect {0}&&binsof(kind) intersect {[9:11]};ignore_bins lo = binsof(kind.lo);}
endgroup
1.4.2 精細化交叉覆蓋率
隨著cross覆蓋率越來越精細,需要花費不少的時間來指定哪些bin應該被使用或者被忽略。更適合的方式是不使用自動分配的cross bin,自己聲明感興趣的cross bin。假如有兩個隨機變量a和b,只關心下面三種狀態(tài),{a**0,b**0}、 {a**1,b**0}和{b**1}
。
class Transaction;rand bit a, b;
endclass
covergroup CrossBinNames;a: coverpoint tr.a{ bins a0 = {0};bins a1 = {1};// 不計算覆蓋率type_option.weight=0;}b: coverpoint tr.b{ bins b0 = {0};bins b1 = {1};// 不計算覆蓋率type_option.weight=0;}ab: cross a, b{ bins a0b0 = binsof(a.a0) && binsof(b.b0);bins a1b0 = binsof(a.a1) && binsof(b.b0);bins b1 = binsof(b.b1); }
endgroup
上述的代碼等效于:
class Transaction;rand bit a, b;
endclass
covergroup CrossBinsofIntersect;a: coverpoint tr.a{ // 不計算覆蓋率type_option.weight=0; }b: coverpoint tr.b{// 不計算覆蓋率type_option.weight=0; }ab: cross a,b{ bins a0b0 = binsof(a) intersect {0} && binsof(b) intersect {0};bins a1b0 = binsof(a) intersect {1} && binsof(b) intersect {0};bins b1 = binsof(b) intersect {1}; }
endgroup
1.4.3 單個實例的覆蓋率
如果對一個covergroup例化多次,那么默認情況下SV會將所有實例的覆蓋率合并到一起。如果需要單獨列出每個covergroup實例的覆蓋率,則需要設置覆蓋選項。
covergroup CoverLength;coverpoint tr.length;// 設置單個實例覆蓋率option.per_instance = 1;
endgroup
1.4.4 注釋
如果有多個covergroup實例,可以通過參數(shù)來對每一個實例傳入單獨的注釋。這些注釋最終會顯示在覆蓋率數(shù)據(jù)的總結報告中。
covergroup CoverPort(int lo,hi, string comment);option.comment = comment;option.per_instance = 1;coverpoint port{bins range = {[lo:hi]};}
endgroup
...
CoverPort cp_lo = new(0,3,"Low port numbers");
CoverPort cp_hi = new(4,7,"High port numbers");
1.4.5 覆蓋率次數(shù)限定與目標
-
覆蓋率次數(shù)限定:
默認情況下,數(shù)值采樣了1次就可以計入有效的bin??梢酝ㄟ^修改
at_least
來修改每個bin的數(shù)值最少的采樣次數(shù),如果低于at_least數(shù)值,則不會被計入bin中。option.at_least可以在covergroup中聲明來影響所有的coverpoint,也可以在coverpoint中聲明來只影響該coverpoint下所有的bin。
一般不會更改。
-
覆蓋率目標
一個covergroup或者一個coverpoint的目標是100%覆蓋率。
不過你也可以將其設置為低于100%的目標。這個選項只會影響覆蓋率報告。
covergroup CoverPort;coverpoint port;option.goal = 90; endgroup
添加上之后,如果達到了90%,報告就會顯示100%,一般也不會更改
1.4.6 covergroup方法總結
sample()
:采樣。
get_coverage()/get_inst_coverage()
:獲取覆蓋率,返回0-100的real數(shù)值。
set_inst_name(string)
:設置covergroup的名稱。
start()/stop()
:使能或者關閉覆蓋率的收集。
- 覆蓋率分析
- 使用
$get_coverage()
可以得到總體的覆蓋率。 - 也可以使用
covergroup_inst.get_inst_coverage()
來獲取單個covergroup
實例的覆蓋 。 - 這些函數(shù)最實際的用處是在一個測試當中監(jiān)測覆蓋率的變化。
- 如果覆蓋率水平在一段時間之后沒有提高,那么這個測試就應該停止。
- 重啟新的隨機種子或者測試可能有望提高覆蓋率。
- 如果測試可以基于功能覆蓋率采取一些深入的行動,例如重新限定隨機的約束,那是一件非常好的事情,但這種測試很難編寫。
- 使用
現(xiàn)在很少去用命令行分析了,都是采用圖形化界面的方式去分析
1.4.7 案例
添加bins,并收集coverage信息,查看 bins的收集情況
TIPS: makefile elab的時候要添加覆蓋率選項: -cm tgl+branch run中也要添加: -cm tgl+branch -cov_dir top_cov
查看報告: dve -full64 -cov -dir top_cov/top.simv.vdb
生成報告:urg -dir top_cov/top.simv.vbd -format both -report report
-dir:vbd文件
-format:生成的格式:txt或html,both是兩者都要生成
-report:報告文件目錄
class Transaction;rand bit [4:0] data; rand bit [2:0] port;
endclass class Transactor;Transaction tr; mailbox mbx_in;virtual busifc ifc;covergroup CovPort;port: coverpoint tr.port {bins port[] = {[0:$]};}data: coverpoint tr.data{bins zero = {0}; bins lo = {[1:3]};bins hi[] = {[8:$]};bins misc = default;}cross port,data;endgroup // 由于覆蓋組實例化在new里面,因此在program不需要實例化function new(mailbox mbx_in, virtual busifc ifc); CovPort = new(); this.mbx_in = mbx_in; this.ifc = ifc;endfunction task main; beginmbx_in.get(tr); ifc.port <= tr.port;ifc.data <= tr.data; CovPort.sample();end endtask
endclassinterface busifc;logic clk;logic [31:0] data;logic [2:0] port;
endinterfaceprogram automatic test(busifc ifc);Transaction tr;Transactor tr_c;mailbox mbx_in;initial begintr = new();mbx_in = new();tr_c = new(mbx_in,ifc);repeat (32) begin assert(tr.randomize); mbx_in.put(tr);tr_c.main();@ifc.clk;endend
endprogrammodule top;busifc ifc();initial beginifc.clk=0;forever #10 ifc.clk=~ifc.clk;endtest test_u(ifc);
endmodule