initial begin-end真的是仿真最早执行的吗?

电子说

1.2w人已加入

描述

SystemVerilog中,initial begin-end是仿真开始就会执行的代码块。比如UVM的test入口函数run_test,一般就是在initial begin-end中调用。还有一些tb会在initial begin-end中使用fork join_none,用于创建一些仿真中的后台进程,如时钟产生,后门驱动等。

那么initial begin-end真的是仿真最早执行的吗?

如果是消耗仿真时间的,那initial begin-end中的代码是仿真开始最早执行的。如果不消耗仿真时间,那还有一种代码会早于initial begin-end执行。

static property/function !!!

static类型变量,无论是全局变量,还是class内部参数,会在仿真开始前确定其初始值。如果该初始值是一个由static类型的function返回值决定,则该function的代码会在initial begin-end前执行完毕。

可以参考如下的测试:

 

import uvm_pkg::*;
`include "uvm_macros.svh"
class static_wrapper;
    static bit fst_flag = cls_func_before_initial("static_wrapper: fst_flag");
    static bit snd_dlag = cls_func_before_initial("static_wrapper: snd_flag");

    static function bit cls_func_before_initial(string x);
        int cnt;
        cnt++;
        $display("cls_func_before_initial: ",x,"@",$time);
        return 1; 
    endfunction
endclass

static function bit glb_func_before_initial(string x);
    int cnt;
    cnt++;
    $display("glb_func_before_initial: ",x,"@",$time);
    return 1; 
endfunction

class test extends uvm_test;
    `uvm_component_utils(test)
    function new(string name="test",uvm_component parent = null);
        super.new(name,parent);
    endfunction

    virtual task main_phase(uvm_phase phase);
        super.main_phase(phase);
        phase.raise_objection(this);
        uvm_top.print();
        phase.drop_objection(this);
    endtask
endclass
program tb_top;
    static bit thd_flag = glb_func_before_initial("thd_flag"); 
 initial begin
        $display("initial begin... @",$time);
        run_test("test");
        $display("initial end... @",$time);
 end
endprogram

 

仿真结果如下:

 

cls_func_before_initial: static_wrapper: fst_flag@                   0
cls_func_before_initial: static_wrapper: snd_flag@                   0
glb_func_before_initial: thd_flag@                   0
initial begin... @                   0
UVM_INFO @ 0: reporter [RNTST] Running test test...
-------------------------------------
Name            Type      Size  Value
-------------------------------------
       uvm_root  -     @172 
  uvm_test_top  test      -     @336 
-------------------------------------
UVM_INFO /apps/vcsmx/vcs/S-2021.09//etc/uvm-1.2/src/base/uvm_report_server.svh(904) @ 0: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

** Report counts by severity
UVM_INFO :    2
UVM_WARNING :    0
UVM_ERROR :    0
UVM_FATAL :    0
** Report counts by id
[RNTST]     1
[UVM/RELNOTES]     1
$finish called from file "/apps/vcsmx/vcs/S-2021.09//etc/uvm-1.2/src/base/uvm_root.svh", line 527.
$finish at simulation time                    0

 

可以看到cls_func_before_initial和glb_func_before_initial两个function都会在initial begin-end前执行。

上面的例子也可以看到,在run_test之后的代码块并不会执行,这是因为run_test执行结束后,UVM机制会直接调用$finish函数结束仿真。

其实在UVM中,已经利用了static变量的初始化这一特性。UVM的工厂模式中,使用uvm_component_utils/uvm_object_utils向工厂中注册组件时,就利用了这一特性。逐层展开uvm_component_utils宏时,可以看到如下的代码:

 

class uvm_component_registry #(type T=uvm_component, string Tname="") extends uvm_object_wrapper;
//....
  local static this_type me = get();
  static function this_type get();
    if (me == null) begin
     uvm_coreservice_t cs = uvm_coreservice_t::get();                                                     
     uvm_factory factory=cs.get_factory();
      me = new;
      factory.register(me);
    end
    return me;
  endfunction
//....

 

思路打开,利用static变量初始化这一特性,可以尝试更多的应用。






审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分