3. UVM组件家族:核心构件与事务级建模
UVM组件家族是搭建验证环境的基础骨架。每个组件在事务级建模(TLM)中承担特定职责,并通过标准化的接口进行通信。本章将系统梳理 uvm_component、uvm_object、uvm_agent、uvm_driver、uvm_monitor、uvm_sequencer 和 uvm_scoreboard 的核心特性、继承关系与典型用法。
3.1 两大基类:uvm_object 与 uvm_component
UVM中所有数据对象和组件都派生自两个核心基类:uvm_object 和 uvm_component。理解它们的区别是掌握UVM组件层次结构的第一步。
| 特性 | uvm_object | uvm_component |
|---|---|---|
| 层次结构 | 无层次,独立对象 | 有层次,属于组件树 |
| 生命周期 | 通过 new() 创建,手动管理 |
通过 create() 创建,由phase自动管理 |
| phase机制 | 不支持 | 支持完整的phase执行 |
| 典型用途 | 事务、配置、序列项 | driver、monitor、agent、env |
| 构建方式 | new("name") |
new("name", parent) |
实践要点: 所有需要参与phase自动调度、拥有父组件或子组件的类,必须从
uvm_component 派生。纯数据对象(如事务描述)则从 uvm_object 派生,以获得工厂注册、复制、比较等内置功能。
3.2 核心驱动组件:uvm_driver 与 uvm_sequencer
uvm_driver 和 uvm_sequencer 是验证环境中激励生成与发送的核心搭档。它们通过TLM端口实现事务级通信。
- uvm_sequencer:负责管理序列(sequence)的执行顺序,向driver发送事务请求。
- uvm_driver:从sequencer获取事务,并将其转换为接口上的信号级时序。
典型连接方式如下:
class my_driver extends uvm_driver #(my_transaction);
`uvm_component_utils(my_driver)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
// 将事务驱动到接口
drive_transaction(req);
seq_item_port.item_done();
end
endtask
endclass
关键接口:
seq_item_port 是driver内建的TLM端口,用于从sequencer拉取事务。务必在每次驱动完成后调用 item_done(),以通知sequencer释放该事务。
3.3 监测与检查组件:uvm_monitor 与 uvm_scoreboard
uvm_monitor 负责被动监测DUT接口,收集事务级数据;uvm_scoreboard 负责比对预期结果与实际行为,完成验证的最终检查。
| 组件 | 职责 | TLM端口方向 |
|---|---|---|
| uvm_monitor | 监测接口信号,打包成事务对象 | 输出(analysis_port) |
| uvm_scoreboard | 接收事务,执行比对或检查 | 输入(analysis_export) |
monitor通过 analysis_port 将采集到的事务广播给所有订阅者(如scoreboard)。scoreboard通过 analysis_export 接收事务,并在内部维护参考模型或比对队列。
3.4 容器组件:uvm_agent
uvm_agent 是一个容器组件,用于封装特定协议接口所需的driver、monitor和sequencer。它提供两种工作模式:
- 主动模式(is_active = UVM_ACTIVE):包含driver、monitor和sequencer,可主动驱动激励。
- 被动模式(is_active = UVM_PASSIVE):仅包含monitor,只监测不驱动。
agent的典型结构如下:
class my_agent extends uvm_agent;
`uvm_component_utils(my_agent)
my_driver driver;
my_sequencer sequencer;
my_monitor monitor;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
monitor = my_monitor::type_id::create("monitor", this);
if (get_is_active() == UVM_ACTIVE) begin
driver = my_driver::type_id::create("driver", this);
sequencer = my_sequencer::type_id::create("sequencer", this);
end
endfunction
virtual function void connect_phase(uvm_phase phase);
if (get_is_active() == UVM_ACTIVE) begin
driver.seq_item_port.connect(sequencer.seq_item_export);
end
endfunction
endclass
3.5 组件家族关系总览
下图展示了UVM组件家族的核心成员及其在验证环境中的层次关系:
3.6 组件间TLM通信路径
下图展示了验证环境中各组件之间的事务级通信路径:
3.7 组件选择速查表
在实际搭建验证环境时,可根据以下速查表快速确定每个组件的使用场景:
| 组件 | 基类 | 是否参与phase | 典型数量 | 主要TLM端口 |
|---|---|---|---|---|
| uvm_driver | uvm_component | 是 | 每个接口1个 | seq_item_port(输入) |
| uvm_monitor | uvm_component | 是 | 每个接口1个 | analysis_port(输出) |
| uvm_sequencer | uvm_component | 是 | 每个接口1个 | seq_item_export(输出) |
| uvm_scoreboard | uvm_component | 是 | 通常1个 | analysis_export(输入) |
| uvm_agent | uvm_component | 是 | 每个协议接口1个 | 无直接TLM端口 |
| 事务对象 | uvm_object | 否 | 动态创建 | 无 |
常见误区: 不要将
uvm_object 直接作为组件添加到组件树中。所有需要 build_phase、connect_phase 等phase回调的类,必须从 uvm_component 派生。事务对象应通过工厂创建,而非直接 new()。
3.8 本章小结
UVM组件家族为验证环境提供了清晰的层次化架构:
- uvm_object 和 uvm_component 构成两大基类体系,分别服务于数据对象和硬件组件。
- uvm_driver、uvm_sequencer、uvm_monitor 和 uvm_scoreboard 是验证环境的核心功能组件。
- uvm_agent 作为容器组件,封装了特定协议接口的完整驱动与监测能力。
- 组件之间通过TLM端口实现事务级通信,保证了验证环境的可重用性和可扩展性。