uvm_root详解

UVM uvm_root 详解

一、什么是 uvm_root

uvm_root 是 UVM (Universal Verification Methodology) 中的顶级类 ,它是所有 UVM 组件的隐式父类。在整个 UVM 验证环境中,有且仅有一个 uvm_root 实例。

关键要点

  • uvm_root 继承自 uvm_component,因此它本身就是一个 UVM 组件
  • 它是 UVM 树形结构(component hierarchy)的根节点
  • 它由 UVM 内部自动创建,无需用户手动实例化
  • 通过 uvm_root::get() 全局静态方法获取其单例引用

二、如何获取 uvm_root 实例

获取方式非常简单:

systemverilog 复制代码
uvm_root root;
root = uvm_root::get();

get() 是一个静态方法(singleton 模式),无论在代码的哪个位置调用,返回的都是同一个 uvm_root 实例。

在环境中的典型用法

systemverilog 复制代码
class test_base extends uvm_test;
    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        // 获取 top-level 的根
        uvm_root root = uvm_root::get();
        // 通过根节点可以遍历或查找整个组件树
    endfunction
endclass

三、uvm_root 扮演的核心角色

角色 说明
组件树的根 所有通过 create()type_id::create() 创建的组件,其父链最终都指向 uvm_root
全局拓扑管理器 维护完整的组件层次结构,提供全局查找、遍历功能
Phase 控制器 负责 UVM Phase 的执行调度,控制 run_phase 等所有 phase 的启动与结束
报告服务器 提供全局的报告处理机制,控制日志的严重级别、action 等
全局资源入口 通过 uvm_root 可以访问 UVM 的全局资源配置(resource database)
隐式 top 组件 未指定父组件时,父组件默认为 uvm_root

四、UVM 树形结构是如何建立的

创建阶段的层级

当用户创建组件实例时:

systemverilog 复制代码
// parent 为 uvm_root 或者某个已经挂载到 uvm_root 下的组件
my_driver drv = my_driver::type_id::create("drv", this);
  • 每个 uvm_component 都有一个 m_parent 指针
  • uvm_rootm_parentnull
  • 每个组件通过 m_children (关联数组) 维护其子组件列表
  • uvm_root 向下遍历,就得到了完整的组件树

树形结构示意图

复制代码
uvm_root (隐式创建,不可见)
├── uvm_test_top (用户定义的 test,顶层的可见组件)
│   ├── env
│   │   ├── agent
│   │   │   ├── driver
│   │   │   ├── monitor
│   │   │   └── sequencer
│   │   └── scoreboard
│   └── ...
└── (其他所有未指定 parent 的组件)

自动命名为 uvm_test_top

用户 test 类在 run_test() 中被实例化时,UVM 会自动将其命名为 uvm_test_top,作为 uvm_root 的直接子节点。


五、与结构相关的关键函数

以下函数均定义在 uvm_component 中(uvm_root 继承自它),用于操作和查询组件树的层次结构:

5.1 获取当前组件信息

函数 返回值 说明
get_name() string 返回当前组件的名称
get_full_name() string 返回从 uvm_root 开始的完整路径名称,如 uvm_test_top.env.agent.driver
get_parent() uvm_component 返回当前组件的父组件(uvm_root 返回 null
get_depth() int 返回当前组件在树中的深度(uvm_root 深度为 0)

5.2 遍历子组件

函数 返回值 说明
get_num_children() int 返回直接子组件的数量
get_child(string name) uvm_component 通过名称获取一个直接子组件
get_children(ref uvm_component children[$]) void 将所有直接子组件放入队列
get_first_child() string 返回第一个子组件的名称(用于迭代)
get_next_child(ref string name) int 返回下一个子组件(与上面配合实现迭代遍历)
has_child(string name) bit 检查是否存在名为 name 的直接子组件

5.3 全局查找组件

函数 返回值 说明
find(string name) uvm_component 在全局范围内搜索任意组件
find_all(string name, ref uvm_component comps[$]) int 查找全局范围内所有匹配的组件(支持通配符 *)

这些函数通常在 uvm_root 句柄上调用,实现从根开始的全局搜索:

systemverilog 复制代码
uvm_root root = uvm_root::get();
uvm_component comp;

// 通过完整路径查找
comp = root.find("uvm_test_top.env.agent.driver");

// 使用通配符查找所有 monitor
uvm_component monitors[$];
root.find_all("*monitor*", monitors);

5.4 类型化查找

函数 说明
find_all(uvm_component comps[$], T obj) SystemVerilog 参数化版本,查找所有指定类型的组件
get_objectors() 返回所有注册此类型的组件队列

5.5 创建与销毁

函数 说明
create(string name, uvm_component parent, ...) 创建一个子组件并自动挂载到组件树中
type_id::create(string name, uvm_component parent) 推荐的 factory 创建方式,自动挂载
build_phase(uvm_phase phase) UVM phase 回调,在 build_phase 中创建子组件

5.6 树形结构的核心机制:build_phase 递归

uvm_rootbuild_phase 中会递归调用 所有子组件的 build_phase

复制代码
uvm_root.build_phase()
  └─ uvm_test_top.build_phase()
       └─ env.build_phase()
            ├─ agent.build_phase()
            │    ├─ driver.build_phase()
            │    ├─ monitor.build_phase()
            │    └─ sequencer.build_phase()
            └─ scoreboard.build_phase()

这就是为什么用户只需要在 envbuild_phase 中创建组件,它们就会被自动整合到树中。


六、uvm_root 的 Phase 控制

uvm_root 负责整个仿真的 phase 调度,关键函数:

函数 说明
run_test() 全局入口,创建 test、启动 phase 调度
stop_phase(string phase_name) 停止指定的 phase
phase_done() 组件通知 phase 结束(用于 objection 机制)
phase_ready_to_end() Phase 结束前的回调,由 objection 机制使用

run_test() 的执行流程

复制代码
1. run_test("my_test")
2. └─ 创建 uvm_root 实例(如果不存在)
3. └─ 设置报告服务器
4. └─ 创建 my_test 实例,命名为 uvm_test_top
5. └─ 依次执行所有 phase:
       build_phase → connect_phase → end_of_elaboration_phase
       → start_of_simulation_phase → run_phase (及12个run-time sub-phases)
       → extract_phase → check_phase → report_phase → final_phase

七、常见使用场景与示例

场景 1:在任意位置获取组件树根

systemverilog 复制代码
uvm_root root = uvm_root::get();
`uvm_info("ROOT", $sformatf("Top level test: %s", root.get_full_name()), UVM_LOW)

场景 2:遍历整个组件树(调试用)

systemverilog 复制代码
function void print_hierarchy(uvm_component comp = null, int depth = 0);
    uvm_root root = uvm_root::get();
    if (comp == null) comp = root;

    for (int i = 0; i < depth; i++) $write("  ");
    $display("- %s", comp.get_name());

    uvm_component children[$];
    comp.get_children(children);
    foreach(children[i])
        print_hierarchy(children[i], depth + 1);
endfunction

场景 3:全局查找特定组件

systemverilog 复制代码
uvm_root root = uvm_root::get();
uvm_component comps[$];
root.find_all("*scoreboard*", comps);

场景 4:通过 uvm_top 句柄(已被标注为 deprecated)

早期 UVM 版本使用全局变量 uvm_top 作为 uvm_root 的句柄,当前推荐使用 uvm_root::get()

systemverilog 复制代码
// 旧方式 (deprecated)
// uvm_component comp = uvm_top.find("...");

// 推荐方式
uvm_component comp = uvm_root::get().find("...");

八、总结

概念 要点
单例模式 整个 UVM 环境有且仅有一个 uvm_root 实例
自动创建 在第一次调用 run_test()uvm_root::get() 时由 UVM 内核自动创建
树根 所有 UVM 组件的最终父级
全局访问 通过 uvm_root::get() 在任何位置获取
Phase 调度 负责启动、控制、停止所有 UVM Phase
全局查找 find() / find_all() 提供基于名称的组件搜索
uvm_test_top 用户 test 的默认顶层实例名称

理解 uvm_root 是掌握 UVM 组件层级管理和仿真控制流程的第一步,几乎所有 UVM 环境的建立和运行机制都与它直接相关。

相关推荐
happyDogg_7 小时前
UVM 中 virtual 关键字的使用详解
virtual·uvm·interface·数字验证
啄缘之间2 个月前
8.【学习】工业级详细接口约束&覆盖率
开发语言·笔记·学习·uvm·sv
Ether IC Verifier2 个月前
SystemVerilog 数据类型详解
php·systemverilog·uvm·ic验证
liuluyang5302 个月前
UVM 工厂机制 完整可编译运行 Demo
uvm·uvm工厂机制
liuluyang5302 个月前
UVM工厂机制
uvm·工厂机制
liuluyang5302 个月前
UVM工厂机制(二)
uvm·工厂机制
liuluyang5302 个月前
SystemVerilog常用关键词与函数
uvm·systermverilog
liuluyang5302 个月前
SV主要关键词详解
fpga开发·uvm·sv
liuluyang5303 个月前
clk_mux_seq sv改进
fpga开发·uvm