UVM——phase objection
0. 介绍
UVM中,component的task phase是消耗仿真时间的,各个components需要在不同层次的task phase中同步信息。UVM中通过objection mechanism来控制phase的执行,通过raise or drop objection来决定phase中事件的开始和停止。
1. objection控制phase的执行
1.1 phase中收集到objection
当程序根据real-time phase的执行顺序,进入到某一个real-time phase中时,它会收集此phase提出的所有的objection(每个component都可以raise objection),当这个phase中所有的objection都被撤销(drop)之后,那么这个phase就执行结束。
比如说进入到main_phase后,driver中 raise objection,monitor的main phase没有raise objection,那么driver和monitor的main phase都会执行。monitor的的main phase的执行受driver的影响,当driver中drop objection之后,monitor的main phase也停止执行。
1 |
|
1.2 phase没有收集到objection
如果进入某个real-time phase后没有收集到objection,也就是说所有的component的这个real-time phase没有没raise objection,那么不会执行phase。
1.3 run_phase的执行
run_phase和real-time phase是并行执行关系,如果在12个real-time phase有任何一个phase提起了objection,那么run_phase都会执行;当然也可以在run_phase中提起objection。
外国人的代码中一般是在run_phase中进行操作,而且run_phase和main_phase的作用差不多,推荐run_phase。
2. 在sequence中提起objection
在验证平台中通常是在sequence 中来控制phase的执行,并且一般是在root sequence(没有parent sequence的sequence),比如嵌套sequence、virtual sequence。
2.1 设置phase的default sequence
在uvm_sequence中有一个starting_phase成员,它是uvm_phase类型。如果我们通过设置run phase的default sequence来启动一个sequence,那么会默认将run phase的phase传递给这个sequence的starting_phase.
1 |
|
sequencer在启动sequence时候会默认做如下操作:
1 |
|
这样我们就可以在sequence中控制objection
1 |
|
2.2 直接将task phase的phase传递给sequence
如果我们是用start函数来启动sequence,可以通过直接将phase传递给sequence的starting_phase。
1 |
|
在实际应用中不写seq.starting_phase=phase这一句也可以,但是在UVM UG中,写了。
3. 在哪控制objection
可以有两种方法。
3.1 在sequence中控制
之前讲的就是在sequence中控制,将phase传递给sequence的starting_phase
3.2 在scoreboard中控制
我们控制run phase任务运行的目的是想要正确的发送和接受激励序列。
发送的激励序列一方面传递给了参考模型,一方面传递给了DUT,参考模型产生预测数据,DUT产生真实的输出响应,所以,如果我们将DUT的所有合理的输出都在scoreboard完成了,那么我们的run phase其实就可以结束了。基于这个思想我们可以在scoreboard中控制objection。
如果我们有pkg_num个激励,那么我们可以在scoreboard中收集pkg_num个真实DUT输出就可以raise_objection。这个pkg_num可以通过config_db的get得到。
1 |
|
上面用的是fork join_any,fork里面有两个进程,第一个是个while循环会一直执行,所以当第二个进程for循环执行完之后,就会跳出fork,执行phase.drop_objection(this);结束任务。
4. set_drain_time
phase.phase_done.set_drain_time(this,200);
任何功能模块DUT都有处理延迟,我们发送transaction给DUT的输入到DUT产生输出,这中间会有延迟,如果我们在sequence中发送完最后一个transaction之后,立马drop_objection,那么可能最后发送的几个transaction还没有在DUT中产生输出,也就不会被scoreboard收集到。
为了让task phase在drop_objection后不立马结束,延迟一段时间,等待所有的transaction都在DUT产生输出,我们可以设置set_drain_time。
1 |
|
1 |
|
延迟1000ns之后调用drop_objection,立马进入post_main_phase.
如果我们使用了set_drain_time:
1 |
|
输出:
1 |
|
延迟了200ns才进入post_main_phase。
这里的phase_done是uvm_phase的一个成员,它是uvm_objection类型,我们在调用phase.raise_objection(this)的时候,其实调用的是phase_done.raise_objection(this)。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!