提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
工厂机制是UVM的真正魅力所在,也是软件的一种设计模式,接下来我将对工厂的意义和背后机制做一个简单的说明
一、工厂(factory)的意义
factory的存在就是为了更方便的**替换**验证环境中的实例或注册了的类型,从而避免了在原有代码上的改动,便于复用。
二、工厂(factory)的运行
1.注册
uvm_object和uvm_component是factory的模具,工厂机制是为了这两个类服务。要想使用工厂机制,必须先注册
·uvm_object_ubils、·uvm_component_ubils
2.注册的背后
注册由上述两个宏完成,以·uvm_object_utils为例,把宏进行展开。
代码如下(示例):
typedef uvm_object_registry#(trans,"trans") type_id;
static function type_id get_type();
return type_id::get();
endfunction
virtual function uvm_object_wrapper get_object_type();
return type_id::get();
endfunction
function uvm_object create (string name="");
trans tmp;
`ifdef UVM_OBJECT_DO_NOT_NEED_CONSTRUCTOR
tmp = new();
if (name!="")
tmp.set_name(name);
`else
if (name=="") tmp = new();
else tmp = new(name);
`endif
return tmp;
endfunction
const static string type_name = "trans";
virtual function string get_type_name ();
return type_name;
endfunction
function void __m_uvm_field_automation (uvm_object tmp_data__,
int what__,
string str__);
begin
trans local_data__; /* Used for copy and compare */
typedef trans ___local_type____;
string string_aa_key; /* Used for associative array lookups */
uvm_object __current_scopes[$];
if(what__ inside {UVM_SETINT,UVM_SETSTR,UVM_SETOBJ}) begin
if(__m_uvm_status_container.m_do_cycle_check(this)) begin
return;
end
else
__current_scopes=__m_uvm_status_container.m_uvm_cycle_scopes;
end
super.__m_uvm_field_automation(tmp_data__, what__, str__);
/* Type is verified by uvm_object::compare() */
if(tmp_data__ != null)
/* Allow objects in same hierarchy to be copied/compared */
if(!$cast(local_data__, tmp_data__)) return;
end
endfunction
上述代码显示,通过宏做了以下几步:
1、定义了type_id类型,类型为uvm_object_registry。
2、定义了get_type、get_object_type、create、get_type_name、 __m_uvm_field_automation四个静态方法(component没有最后一个和create)****
解释:
1、uvm_object_registry和uvm_component_registry为uvm_object_wrapper的子类,uvm_object_wrapper有三个函数(creat_object、creat_component、get_type_name),uvm_object_registry在此基础上新增了create,set_type_overvide, set_inst_override,get四个方法
2、如上图代码所示,通过定义get_type和get_object_type会调用type_id的get函数,get函数会调用uvm_factory::register对type_id(也就是代理类)进行注册。注册后,type_id的create就可以通过factory::create_object_by_type()来实现。
static function this_type get();
if (me == null) begin
uvm_coreservice_t cs = uvm_coreservice_t::get();
uvm_factory factory=cs.get_factory();
me = new;
factory.register(me);
end
return me;
endfunction
3.create的背后
注册好的object或component也就有了三种create方式,分别是利用uvm_object_wrapper的create_object,利用uvm_object_registry的create,利用工厂的create_object_by_type,但是背后实际都是由factory的create_object_by_type完成,工厂会根据代理类的type或者name来创建type句柄并返回
static function T create (string name="", uvm_component parent=null,
string contxt="");
uvm_object obj;
uvm_coreservice_t cs = uvm_coreservice_t::get();
uvm_factory factory=cs.get_factory();
if (contxt == "" && parent != null)
contxt = parent.get_full_name();
obj = factory.create_object_by_type(get(),contxt,name);
if (!$cast(create, obj)) begin
string msg;
msg = {"Factory did not return an object of type '",type_name,
"'. A component of type '",obj == null ? "null" : obj.get_type_name(),
"' was returned instead. Name=",name," Parent=",
parent==null?"null":parent.get_type_name()," contxt=",contxt};
uvm_report_fatal("FCTTYP", msg, UVM_NONE);
end
endfunction
在create之前工厂还会看里面的代理类是否被override,根据被覆盖的type创建。
覆盖方法:
set_type_override_by_type (uvm_object_wrapper original_type,
uvm_object_wrapper override_type,bit replace=1);factory
set_type_override_by_name (string original_type_name,
string override_type_name, bit replace=1);factory
set_type_override (uvm_object_wrapper override_type, bit replace=1);registry
set_inst_override(uvm_object_wrapper override_type,string inst_path,
uvm_component parent=null);registry
实际registry的override背后也由factory执行
static function void set_inst_override(uvm_object_wrapper override_type,
string inst_path,
uvm_component parent=null);
string full_inst_path;
uvm_coreservice_t cs = uvm_coreservice_t::get();
uvm_factory factory=cs.get_factory();
if (parent != null) begin
if (inst_path == "")
inst_path = parent.get_full_name();
else
inst_path = {parent.get_full_name(),".",inst_path};
end
factory.set_inst_override_by_type(get(),override_type,inst_path);
endfunction
总结
以上就是我总结的factory机制,覆盖是factroy最有优势的地方。要想使用factory机制,必须要先注册。通过注册、创建、覆盖即可发挥出factory的全部优势。
create方法和override的方法有很多,但背后都有由actory实现,选择其中一种使用即可,我推荐采用registry的方法,因为相比于factory更加简单。
create: T::type_id::create();
set_type_override: T1::type_id::set_type_override(T2::get_type());