UVM基礎(chǔ)總結(jié)——基于《UVM實(shí)戰(zhàn)》示例
掃描二維碼
隨時隨地手機(jī)看文章
一、前言
工作一直在做SoC驗(yàn)證,更關(guān)注模塊間的連接性和匹配性,所以相比于擅長隨機(jī)約束激勵的UVM來說,定向測試的概念更容易debug。當(dāng)然前提是IP已經(jīng)被充分驗(yàn)證。因此覺得接觸UVM的機(jī)會較少。到現(xiàn)在發(fā)現(xiàn)即使在SoC驗(yàn)證中依然有它的用武之地。比如驗(yàn)證可獨(dú)立于CPU工作的IP、快速對系統(tǒng)性能進(jìn)行評估、重用IP級別的驗(yàn)證環(huán)境,甚至是一些通用的VIP也有基于UVM編寫的?;谶@些考量,也逐漸開始接觸。《UVM實(shí)戰(zhàn)》是很多驗(yàn)證工程師的啟蒙,本文借用書中開頭的示例簡單梳理下UVM的基本知識。
二、UVM基礎(chǔ)概述
關(guān)于UVM的知識網(wǎng)絡(luò)上已經(jīng)鋪天蓋地了,下邊的內(nèi)容只是自己的一些認(rèn)識和隨記。UVM其實(shí)就是基于SV語言寫的用于驗(yàn)證的代碼庫和對應(yīng)的驗(yàn)證規(guī)范。下圖是UVM驗(yàn)證環(huán)境的整體結(jié)構(gòu)(圖來源見參考文獻(xiàn)1)。圖中注釋介紹了每個組成部分的作用?!禪VM實(shí)戰(zhàn)》書中給我留下最深刻的印象就是用子彈、彈夾和手槍分別類比transaction sequence和sequencer,這也是UVM環(huán)境靈活的重要原因之一。這是激勵的產(chǎn)生機(jī)制,至于響應(yīng)的采集和響應(yīng)任務(wù)會交給monitor和scoreboard。后者中的期望數(shù)據(jù)或者參考數(shù)據(jù)的來源比較靈活,函數(shù)、文件或是reference model的響應(yīng)均可。
以上是UVM的空間維度,這一概念也被抽象成如下的樹狀結(jié)構(gòu)。各個部分必然存在信息交互。sequence和sequencer之間傳遞的是transaction,實(shí)際上component之間也是transaction級別的通信,叫做TLM (transaction level model)最常見的就是monitor中uvm_analysis_port通過uvm_tlm_analysis_fifo連接到reference model或scoreboard中的uvm_blocking_get_port。這樣可以確保transaction能夠傳遞給目的組件。
另一方面UVM在時間維度上也做了規(guī)范。phase機(jī)制明確劃分了各個階段所要完成的任務(wù)。其中比較重要的是run phase這一消耗仿真時間的task phase以及ojbection的概念。只有每個phase中所有raise的objection都被drop后才會執(zhí)行下一個phase的任務(wù)。搭建空間與時間維度橋梁的也是Phase--build phase是在樹狀結(jié)構(gòu)中自上而下執(zhí)行,其他不消耗仿真時間的phase都是自下而上運(yùn)行。run phase則自上而下啟動同事運(yùn)行。所有phase的順序見圖3(圖來源見參考文獻(xiàn)2)
弄明白這三張圖,也就是組件、組件間通信和phase機(jī)制,基本上可以看懂別人寫的代碼了。
三、驗(yàn)證環(huán)境示例
各個UVM object和component:
-
sequence:
-
transaction:
-
sequencer:
-
driver:
-
monitor:
-
agent:
-
reference model:
-
scoreboard:
-
base test:
-
Interface:
-
testbench top:
需要注意是在定義class前,如果這個class會使用到其他class,最好在前面加type class。例如在class my_sequence extends uvm_sequence前一行加上type class my_transaction。否則如果my_sequence在my_transaction之前編譯,就會報錯。雖然可以通過在testbench top中先include my_transaction.sv解決,但是大大降低了代碼的重用性。
四、測試用例及仿真
1 `ifndef MY_CASE0__SV 2 `define MY_CASE0__SV 3 class case0_sequence extends uvm_sequence #(my_transaction); 4 my_transaction m_trans; 5 6 function new(string name= "case0_sequence"); 7 super.new(name); 8 endfunction 9 10 virtual task body();11 if(starting_phase != null) 12 starting_phase.raise_objection(this);13 repeat (10) begin14 `uvm_do(m_trans)15 end16 #100;17 if(starting_phase != null) 18 starting_phase.drop_objection(this);19 endtask20 21 `uvm_object_utils(case0_sequence)22 endclass23 24 25 class my_case0 extends base_test;26 27 function new(string name = "my_case0", uvm_component parent = null);28 super.new(name,parent);29 endfunction 30 extern virtual function void build_phase(uvm_phase phase); 31 `uvm_component_utils(my_case0)32 endclass33 34 35 function void my_case0::build_phase(uvm_phase phase);36 super.build_phase(phase);37 38 uvm_config_db#(uvm_object_wrapper)::set(this, 39 "env.i_agt.sqr.main_phase", 40 "default_sequence", 41 case0_sequence::type_id::get());42 endfunction43 44 `endif my_case0
所用的測試用例都擴(kuò)展自自定義的base_test,后者又來自uvm_test。base_test例化整個UVM environment,用例中主要要做的事情就是啟動sequence, 包括調(diào)用start任務(wù)手動啟動和自動啟動方式,具體見參考文獻(xiàn)3.這里是最常見的自動啟動方式:用uvm_config_db將要啟動的sequence設(shè)置為sequencer main_phase的default_sequence.
每個sequence中都有個叫body的task,當(dāng)sequence被啟動時會自動調(diào)用這個task。通過`uvm_do宏來產(chǎn)生transaction。更靈活的方式是先后使用`uvm_create()和`uvm_send()實(shí)現(xiàn)這一功能,并在兩者間控制transaction的各個field。只有當(dāng)消耗仿真時間的driver調(diào)用了item_done()后一次transaction的發(fā)送才算結(jié)束。
五、總結(jié)
我們不創(chuàng)造知識,我們只是知識的搬運(yùn)工。將知識靈活運(yùn)用,創(chuàng)造出合理高效可重用的VIP,驗(yàn)證環(huán)境乃至整個驗(yàn)證流程方法是IC驗(yàn)證的核心技能,這些技能都是為盡可能快速發(fā)現(xiàn)潛在問題這一核心任務(wù)做的準(zhǔn)備。





