我们通常会在top写下类似下面的代码
module top();
import uvm_pkg::*;
......
initial begin
run_test();
end
......
endmoudle
我们写的这个run_test()就是整个UVM验证平台最顶层的入口。这里的run_test()不是任何一个类的成员,而是一个global task,位于uvm_globals.svh中。如下:
![](https://i-blog.csdnimg.cn/blog_migrate/83767c9dc1c81e15dd44f8d19a2e62c9.png)
在这个global的run_test task中,通过cs.get_root创建了uvm_root单例,然后调用了uvm_root的的run_test task。在uvm_root的run_test task中,根据plus args UVM_TESTNAME创建了uvm_test_top对象,如下:
![](https://i-blog.csdnimg.cn/blog_migrate/fff69a8e200648c81e15862f08642f23.png)
然后,还是在uvm_root的run_test task中,调用了uvm_phase的一个static task m_run_phases, 开始了uvm phases的启动,如下:
![](https://i-blog.csdnimg.cn/blog_migrate/bf4ebb804e166fc0a337c36dc14132e1.png)
uvm_phase的静态成员m_run_phases的实现如下:
![](https://i-blog.csdnimg.cn/blog_migrate/3949953dc7e1a25f1238586c0dc91fcc.png)
上面的m_phase_hopper是一个uvm_phase类型的mailbox,在m_run_phases中,先是将common domain的第一个phase(即build_phase) put进mailbox中,然后进入forever,在forever中不断地去get phase,get成功就去执行phase的execute_phase task。
在uvm_phase的execute_phase中,会遍历uvm components tree上的所有component. 这里是通过调用uvm_phase的traverse()函数实现的。如下,在execute_phase中调用traverse:
![](https://i-blog.csdnimg.cn/blog_migrate/a29a9fefbfaddbbca09d2acac097320a.png)
遍历完成之后,当然要进入下一个phase,于是在退出execute_phase之前,将下一个phase给put进mailbox中。如下:
![](https://i-blog.csdnimg.cn/blog_migrate/d510d13ad452e5d2c1ef9cd555b86724.png)
这里还涉及到一些phase跳转的处理,暂时不作具体的研究讨论。
uvm_phase分为function phase和task phase, 而function phase又可以分为uvm_topdown_phase和uvm_bottomup_phase。uvm_bottomup_phase和uvm_task_phase都是从下往上遍历,而uvm_topdown_phase是从上往下遍历。function phase中只有build_phase和final_phase是topdown phase,其它的都是bottomup_phase。uvm_task_phase,uvm_bottomup_phase和uvm_topdown_phase都是继承于uvm_phase的子类,而traverse又是uvm_phase的虚函数,所以这3个子类理所当然地实现了自己的traverse()。
这里我们就挑uvm_topdown_phase的traverse实现出来看看吧,如下:
![](https://i-blog.csdnimg.cn/blog_migrate/e0713b25ec1158d60e8e6b1a70b5fae3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d07a87b1dfffe7d36eef122b31130320.png)
这里通过函数迭代的方式实现了遍历,不断地去get_child并用child去迭代。这个地方调用了execute函数,execute函数的实现如下:
![](https://i-blog.csdnimg.cn/blog_migrate/85aa2cbada15cba4b428cad0faaa711c.png)
这里的execute函数又调用了exec_func(),exec_func也是虚函数,各个子类有不同的实现,比如uvm_build_phase的实现:
![](https://i-blog.csdnimg.cn/blog_migrate/d42a1ef5d2d0688e7d9e2a8d98285698.png)
终于,uvm_build_phase实现的地方调用了component的build_phase函数。
总结一下整个过程的调用栈:run_test -> uvm_root::run_test -> uvm_phase::m_run_phases -> uvm_phase::execute_phase -> uvm_topdown_phase::traverse -> uvm_topdown_phase::execute -> uvm_build_phase::exec_func -> uvm_component::build_phase