UVM入门与进阶学习笔记4——UVM仿真的开始与结束


UVM的编译和运行顺序

下图是UVM的编译运行顺序,非常重要的知识点!
在这里插入图片描述

  1. 在加载硬件模型调用仿真器之前,要完成编译和建模阶段。
  2. 在开始仿真之前,分别执行硬件的always/initial语句,以及UVM的调用测试方法run_test和几个phase,分别是build、connect、end_of_elaboration和start_of_simulation
  3. 在开始仿真后,执行run phase或对应的12个分支phase
  4. 在仿真结束后,执行剩余的phase,分别是extract、check、report和final

UVM仿真开始

要在仿真开始时建立验证环境,可考虑选择下面几种方式:

  • 可通过全局函数run_test()uvm_pkg提供)选择性指定运行哪个uvm_test,这里的test类均继承于uvm_test。指定的test类将被例化并指定为顶层的组件run_test()函数可在合适的module/program中的initial进程块中调用
  • 若无任何参数传递给run_test(),那么用户可在仿真时通过传递参数+UVM_TESTNAME=<test_name>指定仿真时调用的uvm_test;即便run_test()函数在调用时已经有test名称传递,在仿真时+UVM_TESTNAME=<test_name>也可从顶层覆盖已指定的test。这种方式使仿真不用通过再次修改run_test()调用的test名称和重复编译,就可灵活选定test。
  • 无论上面哪种方式都必须在顶层调用全局函数run_test()
  • 全局函数run_test()的重要性,正是从uvm_root创建一个UVM世界

UVM世界的“诞生”

task run_test (string test_name="");
	uvm_root top;
	uvm_coreservice_t cs;
	cs = uvm_coreservice_t::get();
	top = cs.get_root();
	top.run_test(test_name);
endtask
uvm-1.2/base/uvm_globals.svh
  • UVM顶层类uvm_root继承于uvm_component,可以作为顶层结构类,也是UVM环境结构的一员提供一些像run_test()的方法充当UVM世界中的核心角色
  • 在uvm_pkg中有且只有一个顶层类uvm_root所例化的对象,即uvm_top

uvm_top充当的主要核心任务包括:

  • 作为隐形的UVM世界顶层,任何其它的组件都在它之下,通过创建组件时指定parent来构成层次。如果parent设定为null,那么它将作为uvm_top的子组件。
  • phase控制:控制所有组件的phase顺序。
  • 索引功能:通过层次名称来索引组件实例。
  • 报告配置:通过uvm_top来全局配置报告的繁简度(verbosity)。
  • 全局报告设备:由于uvm_top全局可以访问,因此UVM的报告配置在组件内部和组件外部(例如module和sequence)都可以访问。

通过uvm_top调用方法run_test(test_name),uvm_top做了如下的初始化:(重点)

  • 得到正确的test_name;
  • 初始化objection机制;
  • 创建uvm_test_top实例;
  • 调用phase控制方法,安排所有组件的phase方法执行顺序;
  • 等待所有phase执行结束,关闭phase控制进程;
  • 报告总结和结束仿真。

UVM仿真结束

UVM-1.1之后,结束仿真的机制只有利用objection挂起机制来控制仿真结束——uvm_objection类提供一种供所有component和sequence共享的计数器,若有组件挂起objection,还应记得落下objection;参与到objection机制的组件,可各自独立挂起objection防止run phase退出,只有这些组件都落下objection后,uvm_objection共享的counter才变为0,即可以退出run phase。

uvm_objection类用来反停止的控制方法包括:

  • raise_objection(uvm_object obj = null, string description = " " , int count = 1)挂起objection。
  • drop_objection(uvm_object obj = null, string description = " " , int count = 1)落下objection。
  • set_drain_time(uvm_object obj = null , time drain)设置退出时间。

对这些方法在实际应用中的建议:

  • 对于component(),用户可在run_phase()中使用。phase.raise_objection()/phase.drop_objection()控制run phase退出。
  • 用户最好为description字符串参数提供说明,这有利于后期的调试。
  • 使用默认count值
  • 对于uvm_top或uvm_test_top应尽可能少地使用set_drain_time()
class test1 extends uvm_test;
`uvm_component_utils(test1)
function new(string name, uvm_component parent);
    super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
    phase.raise_objection(this); //在run_phase中进行objection机制的使用
    `uvm_info("run_phase", "entered ..", UVM_LOW)
    #1us;
    `uvm_info("run_phase", "exited ..", UVM_LOW)
    phase.drop_objection(this);
endtask
endclass
initial begin
    run_test("test1");
end
endmodule
输出结果
UVM_INFO @ 0: reporter [RNTST] Running test test1...
UVM_INFO @ 0: uvm_test_top [run_phase] entered ..
UVM_INFO @ 1000000: uvm_test_top [run_phase] exited ..
UVM_INFO @ 1000000: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO @ 1000000: reporter [UVM/REPORT/CATCHER]
  • uvm_pkg::uvm_test_done实例会在test1的run_phase()执行完毕之后,才会退出run_phase,这得益于test1::run_phase()在仿真一开始就挂起objection
  • 执行完毕才落下objection。这时uvm_pkg::uvm_test_done认为run_phase已经可以退出,进而转向extract_phase。
  • 直到退出所有phase之后,UVM进入报告总结阶段。

如果没有第一时间挂起objection:

class test1 extends uvm_test;
`uvm_component_utils(test1)
function new(string name, uvm_component parent);
    super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
    #1ps;  //NOTICE
    phase.raise_objection(this);
    `uvm_info("run_phase", "entered ..", UVM_LOW)
    #1us;
    `uvm_info("run_phase", "exited ..", UVM_LOW)
    phase.drop_objection(this);
endtask
endclass
initial begin
    run_test("test1");
end
endmodule
输出结果
UVM_INFO @ 0: reporter [RNTST] Running test test1...
UVM_INFO @ 0: reporter [UVM/REPORT/CATCHER]
  • 看起来挂起objection()已经晚了,因为run phase立即退出了。这是因为在挂起objection之前还需运行1ps,而处于fork_join_none后的run_phase任务在0时刻被调用后,run_phase退出机制在0时刻发现没有挂起objection,因此终止所有run_phase()任务,继而转入extract phase。
  • 所以,如果要在component中挂起objection,建议在一进入run_phase()后就挂起,保证objection counter及时被增加
  • 另外需要用户习惯在sequence中挂起objection,由于sequence是uvm_object类,因此它只有body()方法而没有run_phase()方法。
  • 所以在sequence中使用objection机制,可以在body()中的首尾部分挂起和落下objection
  • 9
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值