第5章 UVM验证平台的运行
5.1 phase机制
phase机制_wonder_coole的博客-CSDN博客
function phase,不耗费仿真时间,通过函数来实现;
task phase,它们耗费仿真时间,通过任务来实现。
对于function phase来说,在同一时间只有一个phase在执行;
但是task phase中,run_phase和其下属12个小的phase(12个之间顺序执行)并行运行。后者称为动态运行(run-time)的phase。如下代码所示:
run_phase 运行机制
fork begin run_phase(); end begin pre_reset_phase(); reset_phase(); post_reset_phase(); pre_configure_phase(); configure_phase(); post_configure_phase(); pre_main_phase(); main_phase(); post_main_phase(); pre_shutdown_phase(); shutdown_phase(); post_shutdown_phase(); end join
稍微解释一下上述代码含义,fork-join 表示两个 begin-end 是同时开始运行的,当 run_phase() 和 pre_reset_phase() 同时存在时,run_phase() 和 pre_reset_phase() 在同一个时刻点开始运行,在 run_phase() 和 pre_reset_phase() 两个 phase 均运行结束以后,主 phase 才会继续执行 extract_phase()。耗时的 phase 的运行是在 uvm_tree 中从下往上运行。
这里出现一个phase概念,与phase对应的还有domain,
前面已经说过了phase可以理解为一个动物的各个生命阶段,
domain可以理解为哪些动物是同步行动的一个范围,
这两个都是从object派生出来的类。然而phase又大体分为2种,具体见下图,一种是消耗仿真时间的task类,一种是不消耗时间的
function类,task类可以类比为什么婴儿期,青春期,更年期这类持续一段时间的东西。
function类可以类比为出生,死亡这种定义一个瞬间的东西。
当然function phase又分为自上而下执行与自下而上执行2种,只有build,final 2个是自上而下执行,其他的都是自下而上执行。所有的task phase也是自下而上启动,而后并发执行。可以看到图中run_phase与其他的task phase不同颜色表示,这是因为run_phase其实为了之前ovm的写法,代表了整个的耗时仿真过程,而uvm把这个过程进行了细分,分成12段。这里可以自由选择是使用整个的run还是分别使用12个分段的过程。
上面大体介绍了各种phase,现在再说m_run_phases,当我们不定义特殊的domain关系,则系统所有的部件使用统一的domain,也就是整个系统是统一行动的,对于相对简单的系统,这样就足够了。m_run_phases调用顶层的execute_phase 然后调用tranverse遍历顶层下面所有的test,env,agent,monitor,driver等节点,依据运行时段是否task或者function型,分别执行exec_task和exec_func。然后等待所有的components执行完当下的phase,也就是等待所有的objection都已经被解除,则继续执行下一个phase,如此循环,将整个结构下所有节点的所有时段执行完成,结束仿真。
以上整个过程都是uvm内部设定好的,不需要使用者进行改动,只需要在各个phase中添加具体的行为,使得各个component安需求运行即可。
动态运行(run-time)的phase
但是有了这些小的phase之后,分别在scoreboard、reference model及其他部分(如driver、monitor等)的reset_phase写好相关代码,之后如果想做一次复位操作,那么只要通过phase的跳转,就会自动跳转回reset_phase。
phase的执行顺序
(1)有直系关系的component
空间上的自上而下:先agent后driver
UVM的设计哲学就是在build_phase中做实例化的工作,driver和monitor都是agent的成员变量,所以它们的实例化都要在agent的build_phase中执行。
空间上的自下而上:先driver后agent
事实上,除了build_phase之外,所有不耗费仿真时间的phase(即function phase)都是自下而上执行的。如对于connect_phase即先执行driver和monitor的connect_phase,再执行agent的connect_phase。
(2)于同一层次的、具有兄弟关系的component
现执行顺序是按照字典序的。依据new时指定的名字。假如monitor在new时指定的名字为aaa,而driver的名字为bbb,那么将会先执行monitor的build_phase。无论是自上而下(build_phase)还是自下而上(connect_phase)的phase,其执行顺序都与实例化的顺序
无关,而是严格按照实例化时指定名字的字典序。
UVM树的遍历
build_phase的执行顺序_wonder_coole的博客-CSDN博客
UVM中采用的是深度优先的原则:对于在UVM树中具有叔侄关系的节点的创建顺序,并不能保证谁先谁后。
如果i_agt的build_phase执行完毕后,它接下来执行的是其孩子的build_phase,如果孩子还有孩子,那么再继续执行下去,一直到整棵以i_agt为树根的UVM子树的build_phase执行完毕,之后再执行i_agt的兄弟的build_phase。
super.phase的内容
于build_phase来说,uvm_component对其做的最重要的事情就是3.5.3节所示的自动获取通过config_db::set设置的参数。
除build_phase外,在写其他phase时,完全可以不必加上super.xxxx_phase语句
build阶段出现UVM_ERROR停止仿真
uvm_fatal是UVM内部自定义的。在end_of_elaboration_phase及其前的phase中,如果出现了一个或多个UVM_ERROR,那么UVM就认为出现了致命错误,会调用uvm_fatal结束仿真。给出的uvm_fatal是UVM内部自定义的。在end_of_elaboration_phase及其前的phase中,如果出现了一个或多个UVM_ERROR,那么UVM就认为出现了致命错误,会调用uvm_fatal结束仿真。
phase的跳转
实现main_phase到reset_phase的跳转。假如在验证平台中监测到reset_n信号为低电平,则马上从main_phase跳转到reset_phase。reset_phase主要做一些清理工作,并等待复位完成。
跳转中最难的地方在于跳转前后的清理和准备工作。如上面的运行结果中的警告信息就是因为没有及时对objection进行清理。
对于scoreboard来说,这个问题可能尤其严重。在跳转前,scoreboard的expect_queue中的数据应该清空,同时要容忍跳转后DUT可能输出一些异常数据。
jump函数的参数必须是一个uvm_phase类型的变量。
9大phase:建立、链接、运行、检查、报告等
run_phase包括12小phase( 1、 上电 2、复位(reset)3、寄存器配置(config)4、发送主要测试内容(main)5、等待DUT完成测试(shutdowm))
那么哪些phase可以作为jump的参数呢?在代码清单5-14中,uvm_pre_reset_phase::get()后的所有phase都可以。红框内不可以