factory机制的一大特点就是根据类的名字来创建类的实例。
factory 机制中根据类名来创建类的实例所用到的技术:一是参数化的类,二是静态变量和静态函数。这两者是factory机制实现的根本所在。
UVM 中有两大关键类,uvm_object 和 uvm_component。一个 uvm_object 在定义时一般要调用 uvm_object_utils 宏,而一个 uvm_component 在定义时要调用uvm_component_utils宏。factory所有的操作都通过这两个宏来完成。
factory 机制的核心就是一个联合数组,m_type_names。这个联合数组的索引是string 类型的,其存储的内容是uvm_object_wrapper类型的
通过展开uvm_object_utils宏,我们发现这里面有一个m_uvm_object_registry_internal
407 `define m_uvm_object_registry_internal(T,S) \
408 typedef uvm_object_registry#(T,`"S`") type_id; \ //每个object都有一个属于自己的代理类,这个type_id就是对应object的代理
409 static function type_id get_type(); \ //uvm_object_registry针对每个object都是一个单态类,也就是一个object,有只有一个代理
410 return type_id::get(); \ //拿到这个代理的
411 endfunction \
412 virtual function uvm_object_wrapper get_object_type(); \
413 return type_id::get(); \
414 endfunction
这个宏里面定义一个static的function get_type,我们知道,所有static的function和property在elaborate结束之前存在,所以这里面很巧妙地利用了类的静态成员变量。简单看一下这个type_id::get()执行什么东西:
182 class uvm_object_registry #(type T=uvm_object, string Tname="<unknown>")
183 extends uvm_object_wrapper;
184 typedef uvm_object_registry #(T,Tname) this_type;
…
212 local static this_type me = get();//me在定义的时候就通过get初始化了,。get首先检查 me 是否为 null,如果不为 null,说明 me 已经是非空了,因此直接返回me 的值。如果为 null的话,则创建一个 me的实例,然后通过factory的register 函数注册到factory中。
…
219 static function this_type get();
220 if (me == null) begin
221 uvm_factory f = uvm_factory::get();
222 me = new;
223 f.register(me);
224 end
225 return me;
226 endfunction
…
296 endclass
我们先不管这里面register的具体实现,在这个点做一个总结,之后我们具体分析一下这些类里面的具体实现。
首先,我们定义了一个类(component类或者object类),然后再这个类里面调用uvm_*_utils的宏,在这个宏里面typedef uvm_object_registry#(T,`"S`") type_id;定义了type_id这个变量,每个参数化的类都是不同的类,因此,每一个component类都有与之对应的一个uvm_object_registry类。而这个uvm_object_registry里面有个me的静态成员变量,这个静态成员变量在elaborate结束的时候就被创建出来。在创建这个me的时候调用get()的function,在这个function里面调用factory的register,将对应类的uvm_object_registry类注册到factory里面。
Factory Component and Object Wrappers:
这一部分定义了factory使用的代理组件和代理object类。To avoid the overhead of creating an instance of every component and object that get registered, the factory holds lightweight wrappers, or proxies. When a request for a new object is made, the factory calls upon the proxy to create the object it represents.
采用了singleton模式,每种uvm_object对应一个注册器,该注册器被自动注册到singleton模式的工厂,被注册到工厂后工厂可以识别这种注册器产生的uvm_object对象。
1. uvm_component_registry #(T,Tname) The uvm_component_registry serves as a lightweight proxy for a component of type T and type name Tname, a string.
2. uvm_object_registry #(T,Tname) The uvm_object_registry serves as a lightweight proxy for an uvm_object of type T and type name Tname, a string.
uvm_component_registry #(T,Tname):
Note: Without it, registration would require an instance of the component itself.
主要的方法:
1. virtual function uvm_component create_component ( string name, uvm_component parent )
1. 根据提供的name和parent创建一个T的组件。
2. 这个函数重写了uvm_object_wrapper的方法。
3. 这个方法不会被直接调用,在create中间接调用。
2. virtual function string get_type_name():
3. static function this_type get() //拿到本type的一个单态实例,
Type-based factory 操作依赖于对于每个寄存的type,只有一个代理例化
4. static function T create( string name, uvm_component parent, string contxt = "" )
1. Returns an instance of the component type, T, represented by this proxy, subject to any factory overrides based on the context provided by the parent’s full name. The contxt argument, if supplied, supercedes the parent’s context. The new instance will have the given leaf name and parent.
static function T create(string name, uvm_component parent, string contxt="");
uvm_object obj;
uvm_factory f = uvm_factory::get(); //拿到整个环境中factory
if (contxt == "" && parent != null) //判断contxt
contxt = parent.get_full_name();
obj = f.create_component_by_type(get(),contxt,name,parent); //调用factory中的create_component_by_type(get(),contxt,name,parent);创建T的例化
if (!$cast(create, obj)) begin
string msg;
msg = {"Factory did not return a component 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
5. static function void set_type_override ( uvm_object_wrapper override_type, bit replace =1);//在factory的m_type_overrides[$]数组中通过一个factory_override类记录把一个wrapper用另外一个wrapper替代
1. factory.set_type_override_by_type(get(),override_type,replace);
6. static function void set_inst_override( uvm_object_wrapper override_type, string inst_path, uvm_component parent = null )//在factory的m_inst_override_queues[uvm_object_wrapper]数组中通过一个uvm_factory_queue_class 的成员factory_override记录把一个wrapper用另外一个wrapper替代
1. 配置factory去创建一个被override_type里面type代表的组件,当有创建对象的请求发生。
2. If parent is not specified, inst_path is interpreted as an absolute instance path, which enables instance overrides to be set from outside component classes. If parent is specified, inst_path is interpreted as being relative to the parent’s hierarchical instance path, i.e. {parent.get_full_name(),”.”,inst_path} is the instance path that is registered with the override. The inst_path may contain wildcards for matching against multiple contexts.
3. factory.set_inst_override_by_type(get(),override_type,inst_path);
uvm_object_registry #(T,Tname):的作用和实现跟uvm_component_registry #(T,Tname)类似
USAGE:
1. The wrapper classes are used to register lightweight proxies of objects and components.
2. class mycomp extends uvm_component; //每个组建类都有一个代理类,名字叫做 type_id,这个type_id对每个组建类都是唯一的,使用这个type_id.create创建一个组件的例化。
typedef uvm_component_registry #(mycomp,"mycomp") type_id;
endclass
UVM Factory:
首先factory是一个单态类,整个仿真环境中只有一个factory。
1. uvm_factory As the name implies, uvm_factory is used to manufacture (create) UVM objects and components.
2. uvm_object_wrapper The uvm_object_wrapper provides an abstract interface for creating object and component proxies.
在factory中注册的是的实际的objects和component的创建的轻量级代理:
1. The uvm_object_registry #(T,Tname) and uvm_component_registry #(T,Tname) class are used to proxy uvm_objects and uvm_components.
2. factory提供 name-based和 type-based 接口
type-based The type-based interface is far less prone to errors in usage. When errors do occur, they are caught at compile-time.
name-based The name-based interface is dominated by string arguments that can be misspelled and provided in the wrong order. Errors in name-based requests might only be caught at the time of the call, if at all. Further, the name-based interface is not portable across simulators when used with parameterized classes.
Register:
function void register ( uvm_object_wrapper obj )
1. 在Factory中Registers那些提供代理的object。proxy object是它所表示的对象的一个轻量级代理,When the factory needs to create an object of a given type, it calls the proxy’s create_object or create_component method to do so.
2. When doing name-based operations, the factory calls the proxy’s get_type_name method to match against the requested_type_name argument in subsequent calls to create_component_by_name and create_object_by_name. If the proxy object’s get_type_name method returns the empty string, name-based lookup is effectively disabled.
3. 这是factory最主要实现的function,完成一个wrapper在factory中的注册,该注册函数将wrapper的名字和inst分别记录在m_types[uvm_object_wrapper]和m_type_names[string]中,注册wrapper的同时,如果在m_inst_override_name_queues中记录了该名字的wrapper则声称一个override记录该override并写入 m_inst_override_queues中,同时在m_inst_override_name_queues中删除对应的override的记录;此外,还要检查_wildcard_inst_overrides查找其中记录的override和注册的wrapper的名字的匹配情况,如果匹配则将对应的override录入m_inst_override_queues队列。
function void uvm_factory::register (uvm_object_wrapper obj);
if (obj == null) begin
uvm_report_fatal ("NULLWR", "Attempting to register a null object with the factory", UVM_NONE);
end
if (obj.get_type_name() != "" && obj.get_type_name() != "<unknown>") begin //检查object的get_type_name是否为空
if (m_type_names.exists(obj.get_type_name())) //如果在m_type_names中存在这个名字,则报告一个warning
uvm_report_warning("TPRGED", {"Type name '",obj.get_type_name(),
"' already registered with factory. No string-based lookup ",
"support for multiple types with the same type name."}, UVM_NONE);
else //不存在则在m_type_names中用这个名字作为key指向这个对象的句柄
m_type_names[obj.get_type_name()] = obj; //指向某个实例的指针放入 m_type_names中,在放入之前先检查一下m_type_names中是否已经有了这条记录,索引是string类型,其存储的内容是 uvm_object_wrapper 类型的
end
if (m_types.exists(obj)) begin //如果在m_types中存在obj的句柄
if (obj.get_type_name() != "" && obj.get_type_name() != "<unknown>")
uvm_report_warning("TPRGED", {"Object type '",obj.get_type_name(),
"' already registered with factory. "}, UVM_NONE);
end
else begin
m_types[obj] = 1; //在m_types以这个对象句柄为key,并置为1,表示这个obj已经在factory里面注册过
// If a named override happens before the type is registered, need to copy
// the override queue.
// Note:Registration occurs via static initialization, which occurs ahead of
// procedural (e.g. initial) blocks. There should not be any preexisting overrides.//后面的代码主要用于override
if(m_inst_override_name_queues.exists(obj.get_type_name())) begin
m_inst_override_queues[obj] = new;
m_inst_override_queues[obj].queue = m_inst_override_name_queues[obj.get_type_name()].queue;
m_inst_override_name_queues.delete(obj.get_type_name());
end
if(m_wildcard_inst_overrides.size()) begin
if(! m_inst_override_queues.exists(obj))
m_inst_override_queues[obj] = new;
foreach (m_wildcard_inst_overrides[i]) begin
if(uvm_is_match( m_wildcard_inst_overrides[i].orig_type_name, obj.get_type_name()))
m_inst_override_queues[obj].queue.push_back(m_wildcard_inst_overrides[i]);
end
end
end
endfunction
总结一下如上所谓的注册,其实质就是把 uvm_object_registry#(T1,"S1")的 me放入 m_type_names 中,并把"S1"作为索引;把 me 作为 m_types 的索引,其内容为1。
主要的属性:
static local uvm_factory m_inst; //factory是要一个单态类
protected bit m_types[uvm_object_wrapper]; //按类型记录注册的wrapper
protected bit m_lookup_strs[string];
protected uvm_object_wrapper m_type_names[string]; //按类型的名字记录注册的wrapper
- UVM基础之-------uvm factory机制override<博>
override功能是UVM中一个比较重要的功能,这个功能也是在factory里面实现的,我们会在env或者具体的case中使用override功能. class case_x extends bas ...
- UVM基础之---------uvm factory机制base
从名字上面就知道,uvm_factory用来制造uvm_objects和component.在一个仿真过程中,只有一个factory的例化存在. 用户定义的object和component types ...
- UVM基础之------uvm phases机制
代码的书写顺序会影响代码的实现,在不同的时间做不同的事情,这是UVM phase的设计哲学,UVM phase提供了一个通用的TB phase 解决方案.支持显示的隐式的同步方案,运行时刻的线程控制和 ...
- UVM基础之---------uvm report 机制分析
uvm 中的信息报告机制相对来说比较简单,功能上来说主要分为两部分: 第一通过ID对component的信息报告冗余级别进行控制,针对每个冗余级别进行不同的行为控制.这部分工作主要由uvm_repor ...
- UVM基础之-------uvm report机制的使用
后面的例子我会继续补充: 1. 因为uvm默认定义的message格式比较长,非常不利于debug过程中的分析使用,一般情况下,开始使用uvm,都要利用uvm_report_server重新定义mes ...
- UVM/OVM中的factory【zz】
原文地址:http://bbs.eetop.cn/viewthread.php?tid=452518&extra=&authorid=828160&page=1 在新的项目中再 ...
- UVM的factory机制
在UVM中使用工厂模式基本上分为三个步骤: 1. 注册 当定义一个类的时候,它的类型必须要注册,UVM已经提供了专用的宏. `uvm_component_utils(class_type_name) ...
- UVM中factory机制的使用
UVM中的factory机制一般用在sequence的重载,尤其是virtual sequence.当Test_case变化时,通过virtual sequence的重载,可以很容易构建新的测试. 因 ...
- UVM中的factory机制实现
首先在Systemverilog中便有对于重载的最基本的支持. 1)定义task/function时,使用virtual关键字.那之后在test_case中调用时,便使用句柄指向的对象的类型而不是句柄 ...
随机推荐
- Django学习系列之路由系统
一.基于App的路由 作用: 根据App对路由规则进行分类,在全局urls.py包含某个项目的urls.py 示例 定义全局urls.py(全局路由系统) #导入include from django ...
- Redis官网下载步骤(含windows版)
①.百度redis ,进入官网 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- android/java经常使用的工具类源代码
anroid.java经常使用的工具类源代码,当中包含文件操作.MD5算法.文件操作.字符串操作.调试信息log.base64等等. 下载地址:http://download.csdn.net/det ...
- Android帧动画实现,防OOM,比原生动画集节约超过十倍的资源
2015年项目接到一个需求,实现一个向导动画,这个动画一共六十张图片,当时使用的是全志A33的开发(512的内存),通过使用Android的动画集实现,效果特别卡顿,然后想到这样的方式来实现,效果非常 ...
- ubuntu14.04 的ibus不能卸载(安装fcitx输入法框架时可能有这个需求)。出现无system setting有用程序
每年的ubuntu新版本号公布,都会吸引一大批热血青年. 关注越多也让ubuntu越来越好了. 使用ubuntu的人都会在安装系统之后马上安装顺手的输入法,也可能不会.看人. 安装输入法,对于中文输入 ...
- S5P4418裸机开发系列教程--源代码下载
S5P4418裸机系列教程之stdio S5P4418裸机系列教程之shell命令行 S5P4418裸机系列教程之串口回显 S5P4418裸机系列教程之复位測试 S5P4418裸机系列教程之led跑马 ...
- hdu, KMP algorithm, linear string search algorithm, a nice reference provided
reference: Rabin-Karp and Knuth-Morris-Pratt Algorithms By TheLlama– TopCoder Member https://www.top ...
- 安卓图片载入之使用universalimageloader载入圆形圆角图片
前言 话说这universalimageloader载入图片对搞过2年安卓程序都是用烂了再熟悉只是了.就是安卓新手也是百度就会有一大堆东西出来,今天为什么这里还要讲使用universalimagelo ...
- SICP习题练习
练习1.6 new-if的三个参数会先被执行,这样就会无限循环下去 练习1.7 (define (sqrt-iter last-guess guess x) (if (good-enough? las ...
- 【POI2007】【Bzoj 1103】大都市meg
http://www.lydsy.com/JudgeOnline/problem.php?id=1103 在线查询某点到根节点的点权和,参考DFS序&欧拉序列,用树状数组维护即可O(nlogn ...