factory机制
factory机制
本质
- factory机制是UVM框架中的一个重要组件,用于创建和管理组件实例
- 它通过注册组件类型和根据类型创建实例,实现了组件的动态创建和管理
- factory机制的核心是
uvm_factory类,它负责注册组件类型、创建组件实例和管理组件实例 - 注册发生在编译时和初始化阶段,通过调用
uvm_component_utils宏来注册组件类型
目的:
- 实现组件的动态创建和管理
- 确保组件在树形结构中的正确位置和命名
1. Factory机制的核心概念
- factory机制的核心是
uvm_factory类,它负责注册类型、管理类型重载和创建实例 uvm_factory是一个抽象类,UVM使用uvm_default_factory作为默认实现- 类型注册和实例创建通过代理模式实现,使用轻量级的
uvm_object_wrapper子类作为类型代理
2. uvm_factory的主要功能
uvm_factory类提供以下核心功能:
- 类型注册:通过
register方法注册类型代理 - 类型重载:通过
set_type_override_by_type/name和set_inst_override_by_type/name方法设置类型重载 - 实例创建:通过
create_component_by_type/name和create_object_by_type/name方法创建实例 - 类型查找:通过
find_wrapper_by_name等方法查找已注册的类型
3. 类型注册机制
-
类型注册是将组件或对象类型的代理(
uvm_object_wrapper子类)注册到factory中 -
注册过程在
uvm_default_factory中通过以下成员变量实现:m_types[uvm_object_wrapper]:存储已注册的类型代理m_type_names[string]:存储类型名称到类型代理的映射
-
注册流程:
- 组件/对象类通过宏注册生成类型代理(
uvm_component_registry或uvm_object_registry) - 类型代理通过
initialize方法调用factory.register(this)完成注册 - factory将类型代理添加到内部数据结构中
- 组件/对象类通过宏注册生成类型代理(
4. 实例创建机制
- 实例创建是根据类型代理或类型名称创建组件或对象实例
- 创建过程:
- 检查是否存在实例重载
- 如果没有实例重载,检查是否存在类型重载
- 根据重载规则确定最终的类型代理
- 调用类型代理的
create_component或create_object方法创建实例
5. 宏注册的实现
- 宏注册是使用UVM提供的工具宏,简化类型注册过程
- 对于组件类,使用
uvm_component_utils(T)宏;对于对象类,使用uvm_object_utils(T)宏 - 宏展开后会生成以下代码:
- 类型代理的typedef(
type_id) get_type()静态方法get_object_type()虚方法create_component/create_object方法(根据类型)- 类型名称声明和
get_type_name()方法
- 类型代理的typedef(
宏注册的实现细节
以uvm_component_utils(T)宏为例,其展开逻辑如下:
// uvm_component_utils宏的实现
`define uvm_component_utils(T) \
`m_uvm_component_registry_internal(T,T) \
`uvm_type_name_decl(`"T") \
// 其中m_uvm_component_registry_internal宏展开为:
`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 \
function uvm_component create_component(string name, uvm_component parent); \
uvm_component tmp; \
tmp = type_id::create(name, parent); \
return tmp; \
endfunction
// uvm_type_name_decl宏展开为:
`define uvm_type_name_decl(N) \
const static string type_name = N; \
virtual function string get_type_name(); \
return type_name; \
endfunction
当在组件类中使用uvm_component_utils(my_component)时,宏会展开为:
class my_component extends uvm_component;
// 宏展开后的代码
typedef uvm_component_registry#(my_component, "my_component") 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_component create_component(string name, uvm_component parent);
uvm_component tmp;
tmp = type_id::create(name, parent);
return tmp;
endfunction
const static string type_name = "my_component";
virtual function string get_type_name();
return type_name;
endfunction
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass
6. 注册与创建的完整流程
-
编译时:
- 组件/对象类使用宏注册,生成类型代理相关代码
- 类型代理的静态初始化触发延迟注册
-
初始化时:
- UVM核心初始化,处理延迟注册队列
- 类型代理调用
initialize方法,完成向factory的注册
-
运行时:
- 通过
type_id::create()或factory方法创建实例 - factory根据重载规则确定最终类型
- 类型代理创建并返回实例
- 通过
7. 利用factory的重载的特点与方法
-
factory机制支持组件和对象类型的重载,允许在运行时替换默认类型为其他类型,实现灵活的测试配置
-
重载分为两种类型:
- 类型重载:对所有该类型的实例进行替换
- 实例重载:仅对特定路径的实例进行替换
-
重载过程是在创建实例之前通过factory的方法设置,当调用
create方法时,factory会根据重载规则创建相应的类型实例 -
内置重载方法:
- 类型重载方法:
set_type_override_by_type(original_type, override_type, replace)set_type_override_by_name(original_type_name, override_type_name, replace)
- 实例重载方法:
set_inst_override_by_type(relative_inst_path, original_type, override_type)set_inst_override_by_name(relative_inst_path, original_type_name, override_type_name)
- 类型重载方法:
-
命令行重载:
- 可以在命令行中使用
-uvm_set_type_override和-uvm_set_inst_override选项来设置类型和实例重载
- 可以在命令行中使用
-
覆盖优先级
- 类型重载:根据注册顺序,后注册的类型会覆盖先注册的类型
- 实例重载:根据路径顺序,后设置的实例重载会覆盖先设置的实例重载
- 命令行重载:在命令行中使用
-uvm_set_type_override和-uvm_set_inst_override选项来设置类型和实例重载,命令行设置的重载会覆盖程序中设置的重载
-
override机制必须满足的三个条件:
- 原始类(被覆盖的类)和覆盖类(新的派生类)都必须使用uvm_component_utils或uvm_object_utils宏在工厂中注册
- 原始类必须通过工厂的type_id::create()方法创建
- 覆盖操作(调用set_type_override或set_inst_override)必须在目标对象被创建之前进行
UVM的树形结构实现
UVM的树形结构本质是通过uvm_component的构造函数实现的,具体机制如下:
uvm_component具有如下变量和方法:
-
变量
- m_parent:指向父组件的指针
- m_children:关联数组,存储子组件的指针
- m_children_by_handle:关联数组,根据组件句柄存储子组件的指针
-
方法
- new:构造函数,用于创建组件实例
- m_add_child:将子组件添加到当前组件的子组件列表中
1. 构造函数的核心逻辑
uvm_component的构造函数是树形结构形成的关键,其核心代码如下:
function uvm_component::new (string name, uvm_component parent);
uvm_root top;
uvm_coreservice_t cs;
super.new(name);
// 获取核心服务和根节点
cs = uvm_coreservice_t::get();
top = cs.get_root(); // 获取uvm_root实例
// 当parent为null时,自动设置为uvm_root
if (parent == null) begin
parent = top;
end
// 检查子组件名称唯一性
if (parent.has_child(name) && this != parent.get_child(name)) begin
// 处理名称冲突错误
end
// 设置父组件并添加到父组件的子列表中
m_parent = parent;
set_name(name);
if (!m_parent.m_add_child(this)) begin
m_parent = null;
end
// 继承父组件的域
m_domain = parent.m_domain;
// 其他初始化...
endfunction
2. 树形结构的形成过程
-
根节点初始化:
-
uvm_root是一个特殊的uvm_component,作为整个组件树的根节点 -
通过
uvm_coreservice_t::get().get_root()获取唯一的根节点实例 -
核心代码:
static local uvm_root m_inst; // 静态局部变量,存储**单例实例** function uvm_root uvm_root::new(); super.new("**top**", null); // 防止创建多个根实例 if (m_inst != null) begin `uvm_fatal_context("UVM/ROOT/MULTI", "Attempting to construct multiple roots", m_inst) return; end m_inst = this; // 将当前实例赋值给静态变量 // 其他初始化... endfunction
-
-
父组件设置:
- 当创建组件时不指定父组件(设为
null),系统会自动将其父组件设置为uvm_root - 这样确保了所有组件最终都归属于同一个根节点下
- 通常,uvm_test的parent是null,其他组件的parent都是uvm_test
- 当创建组件时不指定父组件(设为
-
子组件添加:
- 通过
m_parent.m_add_child(this)将当前组件添加到父组件的子组件列表中
- 通过
3. 树形结构的特点
- 唯一性:每个组件在其父组件下都有唯一的名称
- 层次化:通过点号分隔的层次化名称表示组件在树中的位置
- 完整性:所有组件都属于同一个组件树,根节点是
uvm_root - 可遍历性:通过
get_first_child、get_next_child等方法可以遍历组件树

浙公网安备 33010602011771号