最近组长让我多学习,别天天写代码,于是,这两天摸鱼读了一下UVM源码。
首先先下结论,UVM的factory是不能重载parameterized class的。也就是说,
set_type_override_by_type(ahb_lite_monitor#(.VIF_TYPE(virtual ahb_lite_if))::get_type(), asramc_ahb_monitor_le#(.VIF(virtual ahb_lite_if))::get_type());
这种玩法实际上是没有效果的。
我个人对factory的理解是,factory机制本质上是一个映射表和一系列对映射表的函数组成。这个映射表主要就是uvm object和string的映射。比如说我有一个叫做ahb_monitor的函数,那么注册了之后实际上映射表里面就是一个叫做ahb_monitor的object和一个值为“ahb_monitor”的string。factory里面基于string创建uvm_object也是基于这个查找表。也就是,先通过string找到对应的object,然后创建它。
这一点,可以从uvm factory机制的源代码的注释里面可以看出:
// Simple (non-parameterized) components must use the uvm_components_utils*
// versions, which do the following:
//
// o Implements get_type_name, which returns TYPE as a string.
//
// o Implements create, which allocates a component of type TYPE using a two
// argument constructor. TYPE's constructor must have a name and a parent
// argument.
//
// o Registers the TYPE with the factory, using the string TYPE as the factory
// lookup string for the type.
//
// o Implements the static get_type() method which returns a factory
// proxy object for the type.
并且从源代码中可以看出,这个object对应的string就是类的名字本身:
`m_uvm_component_registry_internal(T,T)
`define m_uvm_component_registry_internal(T,S)
typedef uvm_component_registry #(T,`"S`") 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
Factory中还有一个重载机制,正是基于这种string的映射。也就是一个string映射到另一个string。假设我们有两个class,分别为A和B,A extends B。那么当我们使用`uvm_component_utils 宏后,本质上就是把A,B和字符串“A”“B”的映射加入factory。然后当我们这样做:
set_type_override_by_type(A,B)
Factory里面会加入一组字符串和字符串的映射,也就是“A”和“B”的映射。
在这种情况下,当我们这么创建B的时候:
B_inst = B::type_id::create("B_inst", this);
本质上,factory会先查找对应uvm_object B对应的string,也就是“B”。然后查到“B”对应有一个映射“A”,然后找到“A”对应的object,然后cast,成功!于是就用A替代了B。
However,有一类特殊的uvm_object。也就是带参数的object。这类object中,两个同样的object可以有无数种不一样的写法,比如说:
1st way:
ahb_lite_monitor#(virtual ahb_lite_if)
2nd way(assume that all parameters of ahb_lite_if used below are default)
ahb_lite_monitor#(virtual ahb_lite_if #( .AHB_DATA_WIDTH(32), .AHB_ADDR_WIDTH(32), .AHB_MASTER_WIDTH(1)))
3nd way(lets do something interesting):
typedef virtual ahb_lite_if #( .AHB_DATA_WIDTH(32), .AHB_ADDR_WIDTH(32), .AHB_MASTER_WIDTH(1)) AHB_VIF;
ahb_lite_monitor#(AHB_VIF)
在这种情况下,没办法保证两个一样的object会是对应一样的string,于是整个机制没办法运行。UVM的做法就是:不支持了。这一点,在UVM源码中明确提到了:
// Parameterized classes must use the uvm_object_param_utils* versions. They
// differ from `uvm_object_utils only in that they do not supply a type name
// when registering the object with the factory. As such, name-based lookup with
// the factory for parameterized classes is not possible.
//
// The macros with _begin suffixes are the same as the non-suffixed versions
// except that they also start a block in which `uvm_field_* macros can be
// placed. The block must be terminated by `uvm_component_utils_end.
实际上,从仿真中,可以看出,带参数的object注册的时候也是带string映射的,只不过映射的字符串全部是 “<unknown>”。
于是,之前的那个set_type_override_by_type,其实也能运行,我尝试着运行后print了一下factory的信息:
运行环境:Cadence Xcelium。
参考:http://www.studio-muzzi.com/project/docs/UVMdocs_smu/uvm-1.1d/uvm__object__defines_8svh_source.html