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

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.svhclass 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;     endfunctionendclassstatic function bit glb_func_before_initial(string x);    int cnt;    cnt++;    $display(glb_func_before_initial: ,x,@,$time);    return 1; endfunctionclass 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);    endtaskendclassprogram 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); endendprogram  
仿真结果如下:
cls_func_before_initial: static_wrapper: fst_flag@                   0cls_func_before_initial: static_wrapper: snd_flag@                   0glb_func_before_initial: thd_flag@                   0initial begin... @                   0uvm_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 severityuvm_info :    2uvm_warning :    0uvm_error :    0uvm_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变量初始化这一特性,可以尝试更多的应用。


一种时钟日历芯片DS12C887介绍过程
斑点猫信息技术给大门装了一把“回家的诱惑”
NVIDIA全栈AI方案为全球零售企业赋能
富捷电子开年喜获政府殊荣 树电子元器件行业发展典范
锂电池技术:笔记本电脑电池损耗的原因是什么
initial begin-end真的是仿真最早执行的吗?
如何提高 BTB 连接器的性能
智能座舱的关键技术,以及其正在面临的技术瓶颈
三星Galaxy S20 Fan Edition旗舰级智能手机的性能评测
电源测试大全(四):常规功能测试
中国电信顺应趋势积极探索智慧养老
经纬度时控开关接线图
Micro LED显示相比OLED与LCD的优势有哪些
国产IoT再添新军,国产IoT操作系统走向何方?
新型社交VR应用rumii为企业和教育带来最好的协作解决方案
科技小知识:一种独立微电网动态低频减载控制方法
一文看懂行业年度评选奖项申报流程
现在的智能机器人可以和人类沟通吗
TT Electronics推出两款能够拓展、提高其高性能CR和HR系列产品的新电阻器
新唐科技新一代增强型32位MCU,内建两组CAN总线