15. UVM Monitor [uvm_monitor]
摘要:uvm_monitor是UVM验证平台的关键观察组件,负责被动监测DUT接口信号并将其转换为事务级数据。核心功能包括:1)通过虚拟接口采集信号;2)使用uvm_analysis_port广播事务;3)可选执行协议检查和覆盖率采集。典型实现包含四个步骤:类定义、关键部件声明、构建阶段和运行阶段监控循环。Monitor与Agent的工作模式无关,始终运行,并通过分析端口实现松耦合架构。最佳实践强
理解 uvm_monitor 是掌握UVM“观察-反馈”回路的关键。如果说 driver 是工厂里将图纸变成零件的 “机械臂”,那么 monitor 就是安装在流水线上的“高清摄像头”和“传感器”。
它不参与驱动,只负责被动地、默默地观察 DUT接口上的信号,并将看到的一切翻译成高级的“事务”(Transaction),然后广播给所有关心的人(如记分板、覆盖率收集器)。
📡 Monitor的核心角色:被动的“观察者与翻译官”
下图清晰展示了 uvm_monitor 在验证平台中的数据流角色及其内部工作流程:
核心职责:实现 “信号级”回到“事务级”的逆向翻译。它需要知道,在特定的时钟沿,当 valid 和 ready 信号同时为高时,addr 和 data 线上的值就构成了一个有效的传输事务。
🛠️ 创建一个标准Monitor:四步法
以下是一个可直接套用的APB总线监视器模板,代码中的注释详细解释了每个步骤:
// 1. 定义监视器类,通常不需要参数化(除非特殊需要)
class apb_monitor extends uvm_monitor; // 注意继承自 uvm_monitor
`uvm_component_utils(apb_monitor)
// 2. 声明关键部件
// 2.1 虚拟接口:观察信号的“探头”
virtual apb_interface vif;
// 2.2 分析端口:广播数据的“电视台”。这是Monitor最独特的标志!
uvm_analysis_port #(apb_transaction) ap;
// 2.3 配置开关(可选,但很专业)
bit checks_enable = 1; // 是否进行基础协议检查
bit coverage_enable = 1; // 是否采样覆盖率
function new(string name = "apb_monitor", uvm_component parent = null);
super.new(name, parent);
endfunction
// 3. Build Phase:构建部件并获取虚拟接口
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// 3.1 实例化分析端口(必须!)
ap = new(“ap”, this);
// 3.2 从config_db获取虚拟接口(和driver获取的是同一个)
if (!uvm_config_db #(virtual apb_interface)::get(this, “”, “vif”, vif)) begin
`uvm_fatal(“MON_CFG”, “无法获取虚拟接口!监视器将失明。”)
end
endfunction
// 4. Run Phase (一个task):核心监控循环
virtual task run_phase(uvm_phase phase);
apb_transaction trans; // 用于暂存捕捉到的事务
super.run_phase(phase);
// 初始化:可以等待复位释放等
wait (vif.preset_n == 1);
forever begin
trans = apb_transaction::type_id::create(“trans”); // 创建新事务对象
// 4.1 捕捉一个完整的事务(这是协议相关的核心逻辑)
capture_transfer(trans);
// 4.2 (可选)进行基础协议检查
if (checks_enable) begin
perform_protocol_checks(trans);
end
// 4.3 (可选)采样覆盖率
if (coverage_enable) begin
trans.cg.sample(); // 假设事务类内定义了覆盖率组cg
end
// 4.4 最重要的一步:通过分析端口广播事务
`uvm_info(get_type_name(), $sformatf(“监听到事务:%s”, trans.convert2string()), UVM_HIGH)
ap.write(trans); // 所有连接了这个端口的组件都会立即收到trans的拷贝
end
endtask
// 5. 协议相关的捕捉任务(需要你根据协议具体实现)
virtual task capture_transfer(output apb_transaction t);
// 示例:等待APB传输开始(PSEL变高)
@(posedge vif.pclk iff vif.psel === 1‘b1);
t.paddr = vif.paddr;
t.pwrite = vif.pwrite;
if (vif.pwrite) begin
t.pwdata = vif.pwdata;
end
// 等待ENABLE信号,完成传输
@(posedge vif.pclk iff vif.penable === 1‘b1);
if (!t.pwrite) begin
t.prdata = vif.prdata; // 捕捉读数据
end
@(negedge vif.penable); // 等待传输结束
endtask
virtual function void perform_protocol_checks(apb_transaction t);
// 例如:检查地址是否对齐等基础协议违规
if (t.paddr[1:0] != 2‘b00) begin
`uvm_warning(“PROT_ERR”, $sformatf(“地址未对齐:0x%0h”, t.paddr))
end
endfunction
endclass
🔌 Monitor的灵魂:uvm_analysis_port
这是Monitor区别于Driver最显著的特征,也是UVM实现松耦合、高内聚架构的核心。
- 作用:它是一个广播端口。Monitor不关心谁在听,它只负责在事务发生时“喊一嗓子”(
ap.write(trans))。 - 连接:在**上一级容器(如
agent或env)的connect_phase**中,将Monitor的ap连接到其他组件的analysis_export或analysis_imp。// 在 my_agent 或 my_env 的 connect_phase 中 virtual function void connect_phase(uvm_phase phase); // 将monitor的端口连接到scoreboard的出口 m_monitor.ap.connect(m_scoreboard.ap_export); // 可以同时连接到覆盖率收集器 m_monitor.ap.connect(m_coverage.analysis_export); endfunction - 优势:Scoreboard、Coverage Collector等订阅者完全独立于Monitor。你可以轻松增加或移除订阅者,而无需修改Monitor的代码。
⚙️ 工作模式与Agent的关系
无论其父agent是 UVM_ACTIVE 还是 UVM_PASSIVE, monitor 永远都会被创建和运行。
- 在
ACTIVE模式中,Agent包含driver+sequencer+monitor,Monitor用于观察自己驱动的结果(回环检查)。 - 在
PASSIVE模式中,Agent仅包含monitor,用于观察其他主体驱动的接口,进行协议合规性检查或系统级数据流追踪。
💎 最佳实践与高级技巧
- 保持被动与轻量:Monitor绝不驱动任何信号。其内部的协议检查也应是被动断言,只报告违规,不干预运行。
- 分离关注点:将高级功能检查(如数据一致性)留给
scoreboard,Monitor只做最基础的、与协议时序强相关的检查。 - 处理复杂协议:对于多通道、流水线协议(如AXI),可以在
run_phase中**fork多个并行的线程**,分别监视不同通道,最后再汇聚成一个完整事务广播出去。 - 使用配置开关:像示例中那样,为
checks_enable和coverage_enable提供开关,可以通过uvm_config_db在测试层动态关闭,便于调试和提升仿真性能。 - 事务对象创建:务必在循环内为每个新事务创建新的对象(
type_id::create),避免覆盖前一个事务的数据。
总结:uvm_monitor 是验证平台的眼睛和耳朵。一个设计良好的Monitor,通过analysis_port将原始的物理世界与智能的分析世界解耦,是构建自动化、可复用验证环境的基石。
你的下一步:请为你之前的my_transaction和虚拟接口,创建一个my_monitor。暂时忽略复杂的协议捕捉,只需在run_phase中每隔几个时钟周期,就创建一个新事务,并给它的字段赋予任意值,然后通过ap.write()广播出去。最后,在你的my_agent中实例化它,并将其ap端口连接到你的my_scoreboard。当你看到Scoreboard能接收到Monitor发出的事务时,你就打通了UVM的另一条核心数据流 DUT信号 -> Monitor -> Scoreboard。
更多推荐



所有评论(0)