news 2026/10/17 2:41:59

UVM 中 raise_objection 与 drop_objection 的作用与重要性详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UVM 中 raise_objection 与 drop_objection 的作用与重要性详解

phase.raise.objection (phase); seq=new(); seq.start(e.sgr);
phase.drop_objection(phase) ;

其中raise和drop是什么作用?是否重要?

在 UVM 的run_phase(或其它消耗时间的 task phase)中,raise_objection和drop_objection是极其重要、不可或缺的机制。它们直接决定了仿真会不会“提前结束”,以及各个组件之间的运行时间能否对齐。


一、它们的作用是什么?

UVM 的 phase 机制(尤其是run_phase及其子 phase)靠objection(反对/异议)机制来判断“这个 phase 该不该结束”。

  • raise_objection(提起异议):告诉 UVM 调度器:“我现在正在干活(比如启动 sequence、驱动激励),这个 phase 还不能结束,请等我。”
  • drop_objection(撤销异议):告诉 UVM 调度器:“我干完活了,这个 phase 可以结束了(如果别人也没有异议的话)。”

UVM 只有在所有组件都 drop 了 objection(即没有任何 objection 被 raise)之后,才会结束当前 phase,进入下一个 phase。


二、结合你的代码逐行解析

phase.raise_objection(phase); seq = new(); seq.start(e.sgr); phase.drop_objection(phase);

1.phase.raise_objection(phase);

  • phase是当前运行的 phase 对象(比如run_phase)。
  • raise_objection是uvm_phase类的方法。
  • 传入的参数phase(注意:标准写法通常是this,即当前组件)表示是谁提出了这个 objection。
    • 标准写法是phase.raise_objection(this);。
    • 这里传了phase本身,语法上不报错,但追踪 objection 来源时会有些奇怪。建议改成this。
  • 执行这行后,UVM 的 objection 计数器加 1,当前 phase 不会结束。

2.seq = new();

  • 创建一个 sequence 对象。
  • 注意:这里用了new()而不是type_id::create(),意味着这个 sequence 不走 factory,不会被 override。如果想让 sequence 支持工厂覆盖,应该用seq = my_seq::type_id::create("seq");。
  • 这一步本身不消耗仿真时间,只是分配内存。

3.seq.start(e.sgr);

  • start是uvm_sequence的方法。
  • e.sgr是 sequencer 的句柄(假设e是某个环境组件,sgr是它里面的 sequencer)。
  • seq.start(e.sgr)会把 sequence 挂到 sequencer 上,然后开始执行 sequence 的body()任务。
  • 这是一个消耗仿真时间的操作:sequence 会通过start_item/finish_item把 item 发给 driver,driver 驱动 DUT,可能需要等几十、几百甚至几千个时钟周期。
  • 所以必须在它前面raise_objection,否则仿真会在时间 0 就结束,sequence 根本跑不完。

4.phase.drop_objection(phase);

  • sequence 跑完后,撤销之前的 objection。
  • 此时 objection 计数器减 1。
  • 如果这是最后一个 objection,UVM 就会结束当前 phase,进入下一个 phase。
  • 同样,标准写法是phase.drop_objection(this);。

三、为什么说它们“极其重要”?

1. 没有 raise/drop,仿真会瞬间结束

UVM 的run_phase默认行为是:

如果没有任何 objection 被 raise,run_phase会在时间 0 立即结束。

也就是说,如果你写:

task run_phase(uvm_phase phase); seq = new(); seq.start(e.sgr); endtask

仿真会在时间 0 直接跳过run_phase,你的 sequence 根本来不及跑,DUT 也收不到任何激励。你会看到仿真“什么都没干就结束了”。

2. 它们控制 phase 的结束时机

UVM 的 phase 执行流程:

进入 run_phase ↓ 所有组件并行执行 run_phase 任务 ↓ 等待所有 objection 被 drop ↓ run_phase 结束,进入下一个 phase
  • raise_objection相当于“拉住刹车”;
  • drop_objection相当于“松开刹车”;
  • 只有所有“刹车”都松开,phase 才会结束。

3. 多组件并行时的同步作用

一个测试平台里可能有多个组件同时 raise objection:

  • test里启动 sequence;
  • scoreboard里等待比对完成;
  • monitor里等待采集完最后一笔数据。

只要任何一个组件还持有 objection,run_phase就不会结束。这保证了所有组件都能把自己该干的事干完。


四、标准写法示例

class my_test extends uvm_test; `uvm_component_utils(my_test) my_sequence seq; my_env e; function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); e = my_env::type_id::create("e", this); endfunction task run_phase(uvm_phase phase); // 1. 提起 objection,阻止 phase 结束 phase.raise_objection(this); // 2. 创建并启动 sequence seq = my_sequence::type_id::create("seq"); seq.start(e.sgr); // 3. 撤销 objection,允许 phase 结束 phase.drop_objection(this); endtask endclass

注意顺序:

  • raise_objection必须在消耗时间的操作(如seq.start)之前;
  • drop_objection必须在消耗时间的操作之后;
  • 如果中间有fork...join或异常,要确保drop_objection一定被执行(可以用try...finally或仔细控制流程)。

五、常见误区与注意事项

误区说明
在build_phase里用 objectionbuild_phase是 function phase,不消耗时间,objection 无效,也不该用
raise了忘记drop仿真会一直卡住,直到超时(phase_done超时)
drop了没raiseUVM 会报 warning/error,objection 计数器不能为负
用new()创建 sequence不推荐,应该用type_id::create(),否则无法被 factory override
传参传phase而不是this语法允许,但标准写法是传this,便于调试和追踪 objection 来源

六、一句话总结

raise_objection是“等等我还没干完”,drop_objection是“我干完了,可以走了”。
它们决定了run_phase什么时候结束,是 UVM 仿真时间推进的核心控制机制。没有它们,run_phase会在时间 0 直接结束,sequence 根本跑不起来。所以它们非常重要,而且是每个 UVM 验证工程师必须掌握的基础。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 2:41:42

35岁程序员必看:AI时代如何拥抱变革,掌握高薪复合型岗位的秘诀?

AI技术正在重塑职场结构,初级执行岗位大幅缩减,而复合型资深岗位需求激增。企业更青睐具备多年行业经验和AI技能的人才,能驾驭AI、解决复杂业务问题的人将成为市场宠儿。对于35岁以上的程序员,关键在于拥抱AI,提升自身…

作者头像 李华
网站建设 2026/10/17 2:40:31

锂电串联主动均衡原理与MP2642GR-Z+PIC18F47K40实战设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 2:40:29

Qt Quick与QML从零上手:声明式界面开发实战路线

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 2:40:19

养一套图数据库集群有多重?HydraDB 把 WAL、索引、选主全搬进对象存储,RustFS 正好当这个桶

管过图数据库的人心里都有一张运维清单:副本怎么放、共识组怎么扩、snapshot 定不定期备份、扩缩容要不要搬数据。HydraDB 给出的答案是直接把这张清单划掉:S3 兼容对象存储是唯一持久层,图记录、WAL、manifest、遍历索引、连写入者租约和心跳…

作者头像 李华
网站建设 2026/10/17 2:40:19

芯参谋(56):IPM 智能功率模块 · 系统设计指南

重要前提 IPM 把 6 个 MOSFET/IGBT 高低压驱动 过流/过温/欠压保护 集成一体,极大降低三相驱动的设计门槛,但 母线耐压、自举供电、散热与保护配合 仍是必须正确处理的工程要点。 核心结论速览 IPM 三相逆变桥(6 开关) 内置…

作者头像 李华
网站建设 2026/10/17 2:39:56

AC791 杰理芯片开发入门:简介、开发流程与编译烧录+AI辅助

1. AC791 芯片简介 AC791 是杰理科技(Jieli Technology)推出的一款高性能音视频 SoC 芯片,主要面向蓝牙音频、智能穿戴、车载电子和物联网终端等应用场景。芯片内部集成了蓝牙、音频编解码、电源管理和丰富的接口资源,适合用于开…

作者头像 李华