自定義phase實現(xiàn)方法之: UVM經典推薦
掃描二維碼
隨時隨地手機看文章
問題引入
UVM中,phase機制是一個基本而又非常核心的特性之一,uvm phase將驗證環(huán)境的運行劃分為不同的階段,如build, configue, reset, main等。每個phase階段可對應著環(huán)境或者DUT的初始化或者處理過程。
phase的執(zhí)行機制遵循UVM的"樹"結構,從top-down角度看,有自上而下和自下而上的phase區(qū)別。也有function phase 和 task phase之分,區(qū)別在于是否消耗仿真時間。uvm中定義的phase如下所示:

UVM已有的phase機制已經可以解決大家絕大部分的場景需求。
近期項目驗證架構調整,遇到這樣的需求。簡化來說,SoC驗證環(huán)境中會集成數十個子系統(tǒng)的驗證UVC(有uvm_test, uvm_env,agent), 其中env A 和env B的初始化build有約束,需要保證env B的build phase內容在env A之前完成。
解決方案:
根據這個需求,其實有這樣幾個解決辦法。
將env A和env B build_phase中有約束的部分上移,將需要協(xié)調同步的內容放到uvm_test中的build_phase中實現(xiàn)。這樣就需要Block level和SoC level在集成時進行區(qū)別處理。
將uvm_env的實例名按字典排序。在uvm_phase或者樹的遍歷中,按照字典序進行,因此可以將env B和env A的實例名按字典序命名。
如果是類似隨機的過程的代碼,可以嘗試將env B的該部分代碼放到new函數中。new函數會在build_phase前執(zhí)行。
給env B建立一個自定義phase, 該phase在build_phase之前執(zhí)行,完成同步。
因此就對自定義phase的實現(xiàn)進行了小小的嘗試和solution的package設計,有幾種方路線可選:
UVM推薦的經典實現(xiàn) 基于UVM預先埋入的回調函數實現(xiàn) 基于interface class的插件式方法 基于AOP(Aspect Oriented Programming)實現(xiàn)
先介紹第一種的經典做法。
自定義phase實現(xiàn)之: UVM經典推薦
自定義phase的實現(xiàn),也能找到一些開源的代碼,主要步驟:
根據所需,選擇function phase還是task phase。并實現(xiàn)對應的exec_function或者exec_task。
獲取uvm_domain句柄。function phase對應uvm_domain::get_common_domain()。task phase使用uvm_domain::get_uvm_domain()。
獲取domain中需要插入phase的位置
調用uvm_domain的add函數,將自定義的phase插入到指定位置。
擴展包含新的phase的uvm組件
下面以建立一個pre_build_phase為例,相關代碼如下。
user_pre_build_test
先新建一個包含pre_build_phase的base component, 根據需求繼承uvm_test或者uvm_env。然后用戶的component均此component擴展。
class?user_pre_build_test?extends?uvm_test;
? ??`uvm_component_utils(pre_build_test)
? ??
? ??functionnew?(string?name="pre_build_test",uvm_component parent=null);
? ? ? ??super.new(name,parent);
? ??endfunction
? ??virtualfunctionvoid?pre_build_phase(uvm_phase phase);
? ??endfunction
endclass
class?user_test?extends?user_pre_build_test;
? ??`uvm_component_utils(user_test)
? ??functionnew?(string?name="pre_build_test",uvm_component parent=null);
? ? ? ??super.new(name,parent);
? ??endfunction
? ??virtualfunctionvoid?build_phase(uvm_phase phase);
? ? ? ??super.build_phase(phase);
? ? ? ??`uvm_info(get_type_name, "Here is build_phase", UVM_NONE)
? ??endfunction
? ??virtualfunctionvoid?pre_build_phase(uvm_phase phase);
? ? ? ??`uvm_info(get_type_name, "Here is pre_build_phase", UVM_NONE)
? ??endfunction
endclass
user_pre_build_phase
實現(xiàn)pre_build_phase的class, 可以參考uvm_build_phase的實現(xiàn)。如果是task類選的phase,需要繼承uvm_task_phase, 實現(xiàn)exec_task, 可以參考uvm_main_phase的實現(xiàn)。
class?user_pre_build_phase?extends?uvm_topdown_phase;
? ??localstatic?user_pre_build_phase m_inst;
? ??staticconststring?type_name =?"user_pre_build_phase";
? ??protectedfunctionnew(string?name="user_pre_build_phase");
? ??endfunction
? ??staticfunction?user_pre_build_phase get();
? ? ? ??if(m_inst ==?null) m_inst =?new();
? ? ? ??return?m_inst;
? ??endfunction
? ??virtualfunctionstring?get_type_name();
? ? ? ??return?type_name;
? ??endfunction
? ??virtualfunctionvoid?exec_func(uvm_component comp, uvm_phase phase);
? ? ? ? user_pre_build_test t;
? ? ? ??if($cast(t,comp) )?begin
? ? ? ? ? ? t.pre_build_phase(phase);
? ? ? ??end
? ??endfunction
endclass
uvm_domain.add(...)
最后在TB的initial里將user_pre_build_phase插入到build_phase之前即可。
module?tb;
? ??import?uvm_pkg::*;
? ??initialbegin
? ? ? ? uvm_domain sim_common_domain;
? ? ? ? uvm_phase ?target_phase;
? ? ? ? sim_common_domain = uvm_domain::get_common_domain();
? ? ? ? target_phase = sim_common_domain.find(uvm_build_phase::get() );
? ? ? ? sim_common_domain.add(
? ? ? ? ? ??.phase(user_pre_build_phase::get() ),
? ? ? ? ? ??.with_phase(null?),
? ? ? ? ? ??.after_phase(null?),
? ? ? ? ? ??.before_phase(target_phase )
? ? ? ? );
? ??end
? ??initialbegin
? ? ? ? run_test();
? ??end
endmodule
根據上面的代碼可以逐步實現(xiàn)所需要的phase實現(xiàn),可以看到期望的輸出,也是比較基礎和經典的代碼。后幾種方法可以進一步提升自定義phase的易用性和集成性。因為最近找不到可用的VCS平臺了,其他的方法后續(xù)再更新。





