UVM工厂机制

UVM 工厂(Factory)机制的核心是注册→创建→覆盖 ,用集中管控与动态绑定实现 "接口声明、实现可替换",是 UVM 实现高复用、易扩展验证环境的基石。下面从原理、核心组件、使用方法、典型场景与源码本质逐层详解。


一、核心设计思想

工厂本质是单例模式 + 依赖反转(IoC)

  • 解耦创建与使用 :不硬编码new(),而是通过工厂请求对象,创建逻辑由工厂统一管理
  • 运行时动态替换 :无需修改原有代码,用派生类替换基类实例,实现 "同一环境、不同行为"。
  • 全局唯一管控 :整个验证环境只有一个uvm_factory实例,集中管理所有注册类型与覆盖规则。

传统 new () 与工厂 create () 对比

复制代码
// 硬编码:写死类型,无法替换
my_driver drv = new("drv", this);

// 工厂方式:声明接口,实现由工厂决定
my_driver drv = my_driver::type_id::create("drv", this);

二、三大核心组件

1. 全局工厂单例:uvm_factory
  • 全局唯一实例,通过uvm_factory::get()获取。
  • 维护两张表:类型注册表 (记录所有注册类)、覆盖映射表(记录类型 / 实例替换规则)。
2. 类型注册宏

UVM 通过宏自动注册类到工厂,分两类:

用途 适用类
uvm_component_utils(T) 注册组件(有层次、生命周期) uvm_component派生类(driver/monitor/env)
uvm_object_utils(T) 注册对象(无层次、数据 / 配置) uvm_object派生类(transaction/config)

注册示例

复制代码
class my_driver extends uvm_driver#(my_transaction);
  `uvm_component_utils(my_driver) // 注册到工厂
  // ...
endclass

宏展开后会:

  • 定义type_iduvm_object_registry单例)。
  • 实现get_type()/create()等方法,供工厂查找与创建实例。
3. 类型代理:uvm_object_registry#(T)
  • 每个注册类对应一个type_id,是工厂与类之间的代理接口
  • 核心方法:create()(触发工厂创建)、set_type_override()(设置类型覆盖)。

三、工厂工作全流程(注册→覆盖→创建)

1. 注册(Registration)
  • 编译期:uvm_*_utils宏将类信息(类型名、创建函数)存入uvm_factory的类型表。
  • 关键:只有注册过的类,工厂才能创建或替换
2. 覆盖(Override):动态替换规则

覆盖分两种,均在创建前 设置(通常在build_phase)。

(1)类型覆盖(Type Override):全局替换所有实例
复制代码
// 所有base_driver实例 → 替换为enhanced_driver
base_driver::type_id::set_type_override(enhanced_driver::get_type());
// 或全局工厂调用
uvm_factory::get().set_type_override_by_type(
  base_driver::get_type(), 
  enhanced_driver::get_type()
);
(2)实例覆盖(Instance Override):仅替换特定路径实例
复制代码
// 仅替换env.agent.drv这一个实例
uvm_factory::get().set_inst_override_by_type(
  base_driver::get_type(),
  debug_driver::get_type(),
  "env.agent.drv" // 实例路径(通配符*支持模糊匹配)
);
3. 创建(Creation):工厂按规则实例化

调用type_id::create()时,工厂执行:

  1. 查覆盖表:是否有当前类型 / 实例的替换规则。
  2. 选实际类型:有覆盖则用替换类 ,无则用原类
  3. 实例化:调用替换类 / 原类的new(),返回句柄。

创建示例

复制代码
// 工厂创建:若有base_driver→enhanced_driver覆盖,实际返回enhanced_driver实例
my_driver drv = my_driver::type_id::create("drv", this);

四、关键使用规则与注意事项

  1. 继承要求 :替换类必须是基类的派生类(满足多态)。
  2. 宏一致性 :基类与派生类都必须用uvm_*_utils注册。
  3. 覆盖时机 :覆盖必须在创建前 设置(build_phase早于connect_phase)。
  4. 路径匹配 :实例覆盖路径需与get_full_name()完全一致,支持*通配符。
  5. 覆盖优先级实例覆盖 > 类型覆盖(局部规则优先于全局)。

五、典型应用场景

1. 功能扩展:用增强驱动替换基础驱动
  • 基类base_driver(基础功能)。
  • 派生类perf_driver(增加性能统计)、debug_driver(增加日志)。
  • 测试中通过覆盖切换,同一环境跑不同功能
2. 环境复用:同一 ENV 适配不同 DUT
  • 基类base_transaction(通用激励)。
  • 派生类dut1_transaction/dut2_transaction(适配不同 DUT 时序)。
  • 工厂覆盖动态切换激励类型,ENV 无需修改
3. 调试与错误注入:替换正常组件为故障组件
  • error_inject_driver替换正常driver无需修改原有代码即可注入错误,验证 DUT 容错性。

六、源码本质(简化理解)

1. uvm_factory核心逻辑
复制代码
class uvm_factory;
  static uvm_factory inst; // 单例
  uvm_type_info type_table[string]; // 类型注册表
  uvm_override_info type_override_table[uvm_type_info]; // 类型覆盖表
  uvm_override_info inst_override_table[string]; // 实例覆盖表

  virtual function uvm_object create_object(uvm_type_info type, string name, string inst_path);
    // 1. 查实例覆盖
    if (inst_override_table.exists(inst_path)) 
      type = inst_override_table[inst_path].new_type;
    // 2. 查类型覆盖
    else if (type_override_table.exists(type)) 
      type = type_override_table[type].new_type;
    // 3. 创建实例
    return type.create(name);
  endfunction
endclass
2. uvm_object_registry代理
复制代码
class uvm_object_registry#(T) extends uvm_type_info;
  static uvm_object_registry#(T) inst; // 单例type_id
  virtual function uvm_object create(string name);
    return new T(name); // 实际创建
  endfunction
endclass

七、总结

UVM 工厂机制是 **"接口抽象 + 动态绑定"** 的典范:

  • 注册:让工厂 "认识" 类,纳入统一管理。
  • 覆盖:运行时动态调整类型映射,实现无代码修改的功能切换。
  • 创建:工厂按规则实例化,解耦创建与使用,提升环境复用性。

掌握工厂机制,是写出高复用、易维护、可扩展UVM 验证环境的核心。

相关推荐
啄缘之间17 天前
8.【学习】工业级详细接口约束&覆盖率
开发语言·笔记·学习·uvm·sv
Ether IC Verifier17 天前
SystemVerilog 数据类型详解
php·systemverilog·uvm·ic验证
liuluyang5301 个月前
UVM 工厂机制 完整可编译运行 Demo
uvm·uvm工厂机制
liuluyang5301 个月前
UVM工厂机制(二)
uvm·工厂机制
liuluyang5302 个月前
SystemVerilog常用关键词与函数
uvm·systermverilog
liuluyang5302 个月前
SV主要关键词详解
fpga开发·uvm·sv
liuluyang5302 个月前
clk_mux_seq sv改进
fpga开发·uvm
谷公子的藏经阁2 个月前
DVCon 2025 论文精华导读及下载链接
ai·论文·systemverilog·uvm·dvcon
蓝天下的守望者5 个月前
SystemVerilog中 `timescale的使用问题
systemverilog·uvm·vcs