[UVM源代码研究] 如何控制UVM环境所有phase都执行完后仿真不立即结束(uvm-1.2版)
引言
标题写的有点冗长,其实通过前面UVM源代码研究关于run_test任务的分析我们知道整个UVM环境是有run_test这么一个task启动phase机制的,并且所有的phase都执行完之后也是在run_test中调用 f i n i s h 来结束仿真的,但是有时候 U V M 环境 p h a s e 跑完之后我们还想在 t b 中做一些额外的,甚至是消耗时间的行为,然后再主动调用 finish来结束仿真的,但是有时候UVM环境phase跑完之后我们还想在tb中做一些额外的,甚至是消耗时间的行为,然后再主动调用 finish来结束仿真的,但是有时候UVM环境phase跑完之后我们还想在tb中做一些额外的,甚至是消耗时间的行为,然后再主动调用finish来结束仿真,需要怎么处理呢?换句话说,run_test中是否可以控制不去调用$finish这个系统函数呢?
源代码分析
要回答这个问题我们又得回到UVM源代码中的run_test任务,如下图所示
uvm_root源代码中run_test()方法代码片段
于是我们知道我们是可以将其中的变量finish_on_completion赋值为0来控制run_test不调用$finish,我们再看看finish_on_complete的定义
finish_on_completion变量的定义
这是定义在uvm_root中的一个bit类型的变量,并且default值为0,我们需要将uvm_root实例中的这个变量赋值为0,而uvm_root是一个class类型,而finish_on_completion又不是一个static类型,因而我们只能对uvm_root的instance进行操作来修改其中的变量值,并且我们调用uvm_root中的run_test任务的时候也是调用其对应实例中run_test任务,之所以我们能够在tb里面不通过任何uvm_root的实例去调用其中的run_test而是直接执行run_test是因为在UVM源代码中对run_test()这个函数做了一个封装,将uvm_root对应instance调用run_test方法封装为了一个全局可见的task,放在了uvm_globals.svh中,如下图所示
src/base/uvm_globals.svh中定义的全局方法run_test
于是我们在tb中直接调用run_test方法就实现了调用uvm_root实例中的run_test方法,并且uvm_root的实例使用的是单例模式,通过上图中39-42的操作便可以获取uvm_root的唯一实例,而我们在UVM源代码中也定义了一个可以直接引用的全局变量uvm_top来指向uvm_root的唯一实例,如下图所示
src/base/uvm_root.svh中定义的uvm_root实例uvm_top
于是乎我们便可以通过如下方法来控制run_test不结束仿真。
tb中添加控制run_test不主动调用$finish的代码
150行的代码可以替换为run_test();结果相同,是因为run_test()获取到的uvm_root的实例与uvm_top本质上指向的是同一个实例,因而run_test()中用到的finish_on_completion变量就是被149行修改为0了,仿真结果如下图所示
仿真结果
于是我们便实现了在uvm的final_phase执行完了之后仍然在tb中执行了额外的内容,类似的我们也可以在调用run_test前添加内容,但是在run_test调用之前添加的仿真代码不允许有延时,因为run_phase必须在0时刻启动,否则会报如下错误(uvm_root中添加了run_phase启动时间点检查机制)
run_test调用前添加延时仿真报错
仿真中我们使用的是uvm-1.1d的版本,而uvm-1.2版本中这个检查机制的截图代码如下图所示,两个版本这部分内容是一致的,只是代码的位置不一样,所以显示的行号不同。
uvm-1.2中uvm_root.svh中检查run_phase启动的时间点必须为0时刻
我们可以进一步修改仿真代码如图所示
run_test调用前后都添加仿真代码
仿真结果如下图所示
仿真结果1
仿真结果2
总结
UVM环境代码的执行本质上是通过uvm_root中的run_test展开调用所有uvm树形结构中的uvm_component的所有phase,从build_phase开始到final_phase结束,最终会在run_test中默认调用$finish来结束整个仿真,由此我们分析出来了可以在run_test调用前添加不消耗仿真时间(UVM源代码要求run_phase必须在0时刻开始)的代码,在run_test调用前修改uvm_root唯一实例中的finish_on_complete值来实现run_test调用后不立即结束仿真而是仍然可以添加额外的仿真代码,并且是可以消耗时间的。