[UVM源代码研究] 浅谈UVM factory机制的实现原理
我们对UVM的factory机制有基本了解的同学都知道,要想实现factory,必须满足的条件该类必须使用uvm_object/component_utils系列进行注册,我们先来看看这个用来注册的宏都做了什么(以下都以
uvm_object_utils_begin/end为例),相关的宏和方法递归展开截图如下
根据上面宏展开后的结果,我们可以将我们自定义的uvm_object进行展开,例如我们定义了如下的class
我们将8-10行的宏按照我们之前的分析进行展开,得到实际的等效代码如下图所示
这里我们并没有将宏uvm_field_*进行展开,关于
uvm_field_*系列宏的展开分析我们在[UVM源代码研究] 谈谈uvm中的浅拷贝(shallow copy)与深拷贝(deep copy) 有过深入的解读,这里就不展开了。
于是我们可以粗略的认为uvm_object_utils_begin/end
宏刨去中间uvm_field_*
就相当于增加了如下内容:
-
声明了一个type_id类型
-
定义了静态函数get_type,返回值为type_id类型
-
定义了函数get_object_type,返回值为实际指向type_id类型的uvm_object_wrapper类型
-
定义了create函数,返回值为实际指向apb_transfer类型的uvm_object类型
-
定义了静态字符串常量type_name
-
定义了函数get_type_name返回type_name
于是当我们执行如下代码时
我们实际是调用的声明在apb_transfer中的type_id类中的静态create()方法,所以说只有通过`uvm_object_*注册过的类,才能使用type_id::create创建就是这么来的。
我们再看看参数化的类uvm_object_registery中的create方法的定义
这里245行通过uvm_factory中的静态函数get()获取了uvm_factory的唯一实例,这就是我们在前面的文章中反复提及的单例模式的使用,例如uvm_root的唯一实例是uvm_top,uvm_factory的唯一实例是factory,这里在uvm源代码中都已经做成了全局变量,如下图所示
248行执行uvm_factory中定义的create_object_by_type()如下图所示
这里的find_override_by_type()就是查看某个具体hierarchy下requested_type类型是否有override过,这个过程可以简单理解为遍历一个类uvm_factory_override队列m_type_overrides[$],而我们在调用factory.set_type_override_by_type()的时候实际操作的也是这个队列。只有当某个类在调用create之前被override过,该类队列才会有值,并且队列override遵循的一定的覆盖规则,所以遍历的时候也会有相应的替换规则,这样通过调用find_override_by_type()就获取了我们实际创建需要用到的type类型。
然后上面的1192行调用create_object()就会调用实际requested_type类型中的new函数进行最终的对象创建行为。
经过如上这么一个过程,我们便实现了最基本的factory机制里的override功能,上文中我们偷懒省去m_type_overrides这个队列相关内容的讨论,感兴趣的同学可以自行研究哈。
至于uvm_component的factory机制实现与上面类似,这里就不展开描述了。