【UVM实战】第五章:UVM验证平台的运行(1)phase机制(上)

15 篇文章 ¥19.90 ¥99.00

5.1、phase机制

5.1.1、task phase与function phase

UVM中的phase, 按照其是否消耗仿真时间( $time打印出的时间) 的特性, 可以分成两大类, 一类是function phase, 如build_phase、 connect_phase等, 这些phase都不耗费仿真时间, 通过函数来实现另外一类是task phase, 如run_phase等, 它们耗费仿真时间, 通过任务来实现。 给DUT施加激励、 监测DUT的输出都是在这些phase中完成的。 在图5-1中, 灰色背景所示的是task phase, 其他为function phase。

图5-1 UVM中的phase
图5-1 UVM中的phase

上述所有的phase都会按照图中的顺序自上而下自动执行:

代码清单 5-1

文件: src/ch5/section5.1/5.1.1/my_case0.sv

class my_case0 extends base_test;
   string tID = get_type_name();

   `uvm_component_utils(my_case0)
   function new(string name = "my_case0", uvm_component parent = null);
      super.new(name,parent);
   endfunction 
   virtual function void build_phase(uvm_phase phase); 
      super.build_phase(phase);
      `uvm_info(tID, "build_phase is executed", UVM_LOW)
   endfunction 

   virtual function void connect_phase(uvm_phase phase); 
      super.connect_phase(phase);
      `uvm_info(tID, "connect_phase is executed", UVM_LOW)
   endfunction 

   virtual function void end_of_elaboration_phase(uvm_phase phase); 
      super.end_of_elaboration_phase(phase);
      `uvm_info(tID, "end_of_elaboration_phase is executed", UVM_LOW)
   endfunction 

   virtual function void start_of_simulation_phase(uvm_phase phase); 
      super.start_of_simulation_phase(phase);
      `uvm_info(tID, "start_of_simulation_phase is executed", UVM_LOW)
   endfunction 
  
   virtual task run_phase(uvm_phase phase);
      `uvm_info(tID, "run_phase is executed", UVM_LOW)
   endtask

   virtual task pre_reset_phase(uvm_phase phase);
      `uvm_info(tID, "pre_reset_phase is executed", UVM_LOW)
   endtask

   virtual task reset_phase(uvm_phase phase);
      `uvm_info(tID, "reset_phase is executed", UVM_LOW)
   endtask

   virtual task post_reset_phase(uvm_phase phase);
      `uvm_info(tID, "post_reset_phase is executed", UVM_LOW)
   endtask

   virtual task pre_configure_phase(uvm_phase phase);
      `uvm_info(tID, "pre_configure_phase is executed", UVM_LOW)
   endtask

   virtual task configure_phase(uvm_phase phase);
      `uvm_info(tID, "configure_phase is executed", UVM_LOW)
   endtask

   virtual task post_configure_phase(uvm_phase phase);
      `uvm_info(tID, "post_configure_phase is executed", UVM_LOW)
   endtask

   virtual task pre_main_phase(uvm_phase phase);
      `uvm_info(tID, "pre_main_phase is executed", UVM_LOW)
   endtask

   virtual task main_phase(uvm_phase phase);
      `uvm_info(tID, "main_phase is executed", UVM_LOW)
   endtask

   virtual task post_main_phase(uvm_phase phase);
      `uvm_info(tID, "post_main_phase is executed", UVM_LOW)
   endtask

   virtual task pre_shutdown_phase(uvm_phase phase);
      `uvm_info(tID, "pre_shutdown_phase is executed", UVM_LOW)
   endtask

   virtual task shutdown_phase(uvm_phase phase);
      `uvm_info(tID, "shutdown_phase is executed", UVM_LOW)
   endtask

   virtual task post_shutdown_phase(uvm_phase phase);
      `uvm_info(tID, "post_shutdown_phase is executed", UVM_LOW)
   endtask

   virtual function void extract_phase(uvm_phase phase); 
      super.extract_phase(phase);
      `uvm_info(tID, "extract_phase is executed", UVM_LOW)
   endfunction 

   virtual function void check_phase(uvm_phase phase); 
      super.check_phase(phase);
      `uvm_info(tID, "check_phase is executed", UVM_LOW)
   endfunction 

   virtual function void report_phase(uvm_phase phase); 
      super.report_phase(phase);
      `uvm_info(tID, "report_phase is executed", UVM_LOW)
   endfunction 

   virtual function void final_phase(uvm_phase phase); 
      super.final_phase(phase);
      `uvm_info(tID, "final_phase is executed", UVM_LOW)
   endfunction 


endclass

运行上述代码, 可以看到各phase被依次执行。 重要打印结果如下:

...
UVM_INFO @ 0: reporter [RNTST] Running test my_case0...
UVM_INFO my_case0.sv(13) @ 0: uvm_test_top [my_case0] build_phase is executed
UVM_INFO my_case0.sv(18) @ 0: uvm_test_top [my_case0] connect_phase is executed
UVM_INFO my_case0.sv(23) @ 0: uvm_test_top [my_case0] end_of_elaboration_phase is executed
UVM_INFO my_case0.sv(28) @ 0: uvm_test_top [my_case0] start_of_simulation_phase is executed
UVM_INFO my_case0.sv(32) @ 0: uvm_test_top [my_case0] run_phase is executed
UVM_INFO my_case0.sv(36) @ 0: uvm_test_top [my_case0] pre_reset_phase is executed
UVM_INFO my_case0.sv(40) @ 0: uvm_test_top [my_case0] reset_phase is executed
UVM_INFO my_case0.sv(44) @ 0: uvm_test_top [my_case0] post_reset_phase is executed
UVM_INFO my_case0.sv(48) @ 0: uvm_test_top [my_case0] pre_configure_phase is executed
UVM_INFO my_case0.sv(52) @ 0: uvm_test_top [my_case0] configure_phase is executed
UVM_INFO my_case0.sv(56) @ 0: uvm_test_top [my_case0] post_configure_phase is executed
UVM_INFO my_case0.sv(60) @ 0: uvm_test_top [my_case0] pre_main_phase is executed
UVM_INFO my_case0.sv(64) @ 0: uvm_test_top [my_case0] main_phase is executed
UVM_INFO my_case0.sv(68) @ 0: uvm_test_top [my_case0] post_main_phase is executed
UVM_INFO my_case0.sv(72) @ 0: uvm_test_top [my_case0] pre_shutdown_phase is executed
UVM_INFO my_case0.sv(76) @ 0: uvm_test_top [my_case0] shutdown_phase is executed
UVM_INFO my_case0.sv(80) @ 0: uvm_test_top [my_case0] post_shutdown_phase is executed
UVM_INFO my_case0.sv(85) @ 0: uvm_test_top [my_case0] extract_phase is executed
UVM_INFO my_case0.sv(90) @ 0: uvm_test_top [my_case0] check_phase is executed
TEST CASE PASSED
UVM_INFO my_case0.sv(95) @ 0: uvm_test_top [my_case0] report_phase is executed
UVM_INFO my_case0.sv(100) @ 0: uvm_test_top [my_case0] final_phase is executed
...

在这些phase中, 令人疑惑的是task phase。 对于function phase来说, 在同一时间只有一个phase在执行; 但是task phase中, run_phase和pre_reset_phase等12个小的phase并行运行。 后者称为动态运行( runtime) 的phase。 对于task phase, 从全局的观点来看其顺序大致如下:

代码清单 5-2

fork
	begin
		run_phase();
	end
	begin
		pre_reset_phase();
		reset_phase();
		post_reset_phase()
		pre_configure_phas
		configure_phase();
		post_configure_pha
		pre_main_phase();
		main_phase();
		post_main_phase();
		pre_shutdown_phase();
		shutdown_phase();
		post_shutdown_phase();
	end
join

UVM提供了如此多的phase, 在一般的应用中, 无论是function phase还是task phase都不会将它们全部用上。 使用频率最高的是build_phase、 connect_phase和main_phase。 这么多phase除了方便验证人员将不同的代码写在不同的phase外, 还有利于其他验证方法学向UVM迁移。 一般的验证方法学都会把仿真分成不同的阶段, 但是这些阶段的划分通常没有UVM分得这么多、 这么细致。 所以一般来说, 当其他验证方法学向UVM迁移的时候, 总能找到一个phase来对应原来方法学中的仿真阶段, 这为迁移提供了便利。

5.1.2、动态运行phase

动态运行( run-time) phase是UVM1.0引入的新的phase, 其他phase则在UVM1.0之前( 即UVM1.0EA版和OVM中) 就已经存在了。

UVM为什么引入这12个小的phase呢?

答:分成小的phase是为了实现更加精细化的控制reset、 configure、 main、 shutdown四个phase是核心, 这四个phase通常模拟DUT的正常工作方式

  • 在reset_phase对DUT进行复位、 初始化等操作;
  • 在configure_phase则进行DUT的配置;
  • DUT的运行主要在main_phase完成;
  • shutdown_phase则是做一些与DUT断电相关的操作。

通过细分实现对DUT更加精确的控制。 假设要在运行过程中对DUT进行一次复位( reset) 操作, 在没有这些细分的phase之前, 这种操作要在scoreboard、 reference model等加入一些额外的代码来保证验证平台不会出错。 但是有了这些小的phase之后, 分别在scoreboard、reference model及其他部分( 如driver、 monitor等) 的reset_phase写好相关代码, 之后如果想做一次复位操作, 那么只要通过phase的跳转, 就会自动跳转回reset_phase。

关于跳转的内容, 请参考5.1.7节。

5.1.3、phase的执行顺序

5.1.1节笼统地说明了phase是自上而下执行的, 而在3.5.4节时曾经提到过, build_phase是一种自上而下执行的。 但这两种“自
上而下”是有不同含义的。

5.1.1节中的自上而下是时间的概念, 不同的phase按照图5-1中所示的phase顺序自上而下执行。 而3.5.4节所说的自上而下是空间的概念, 即在图3-2中, 先执行的是my_case的build_phase, 其次是env的build_phase, 一层层往下执行。 这种自上而下的顺序其实是唯一的选择。

对于UVM树来说, 共有三种顺序可以选择, 一是自上而下, 二是自下而上, 三是随机序。 最后一种方式是不受人控制的, 在编程当中, 这种不受控制的代码越少越好。 因此可以选择的无非就是自上而下或者自下而上

假如UVM不使用自上而下的方式执行build_phase, 那会是什么情况呢? UVM的设计哲学就是在build_phase中做实例化的工作, driver和monitor都是agent的成员变量, 所以它们的实例化都要在agent的build_phase中执行。 如果在agent的build_phase之前执行driver的build_phase, 此时driver还根本没有实例化, 所以调用driver.build_phase只会引发错误。

UVM是在build_phase中做实例化工作, 这里的实例化指的是uvm_component及其派生类变量的实例化, 假如在其他phase实例化一个uvm_component, 那么系统会报错。 如果是uvm_object的实例化, 则可以在任何phase完成, 当然也包括build_phase了。

除了自上而下的执行方式外, UVM的phase还有一种执行方式是自下而上。 事实上, 除了build_phase之外, 所有不耗费仿真时间的phase( 即function phase) 都是自下而上执行的。 如对于connect_phase即先执行driver和monitor的connect_phase, 再执行agent的connect_phase。

无论是自上而下还是自下而上, 都只适应于UVM树中有直系关系的component。 对于同一层次的、 具有兄弟关系的component, 如driver与monitor, 它们的执行顺序如何呢? 一种猜测是按照实例化的顺序。 如代码清单5-3中, A_inst0到A_inst3的build_phase是顺序执行的, 这种猜测是错误的。 通过分析源代码, 读者可以发现执行顺序是按照字典序的。 这里的字典序的排序依据new时指定的名字。 假如monitor在new时指定的名字为aaa, 而driver的名字为bbb, 那么将会先执行monitor的build_phase。 反之若monitor为mon, driver为drv, 那么将会先执行driver的build_phase。 如下面的代码:

代码清单 5-3

文件: ch5/section5.1/5.1.3/brother/my_env.sv
class my_env extends uvm_env;

   A   A_inst0;
   A   A_inst1;
   A   A_inst2;
   A   A_inst3;
   
   
   function new(string name = "my_env", uvm_component parent);
      super.new(name, parent);
   endfunction

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);

      A_inst0 = A::type_id::create("dddd", this);
      A_inst1 = A::type_id::create("zzzz", this);
      A_inst2 = A::type_id::create("jjjj", this);
      A_inst3 = A::type_id::create("aaaa", this);

   endfunction

   `uvm_component_utils(my_env)
endclass

其中A的代码为:

代码清单 5-4

文件: ch5/section5.1/5.1.3/brother/A.sv
class A extends uvm_component;
   `uvm_component_utils(A)

   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction

   extern function void build_phase(uvm_phase phase);
   extern function void connect_phase(uvm_phase phase);
endclass

function void A::build_phase(uvm_phase phase);
   super.build_phase(phase);
   `uvm_info("A", "build_phase", UVM_LOW)
endfunction

function void A::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   `uvm_info("A", "connect_phase", UVM_LOW)
endfunction

输出的结果将会是:

...
UVM_INFO @ 0: reporter [RNTST] Running test my_case0...
UVM_INFO A.sv(16) @ 0: uvm_test_top.env.aaaa [A] build_phase
UVM_INFO A.sv(16) @ 0: uvm_test_top.env.dddd [A] build_phase
UVM_INFO A.sv(16) @ 0: uvm_test_top.env.jjjj [A] build_phase
UVM_INFO A.sv(16) @ 0: uvm_test_top.env.zzzz [A] build_phase
UVM_INFO A.sv(21) @ 0: uvm_test_top.env.aaaa [A] connect_phase
UVM_INFO A.sv(21) @ 0: uvm_test_top.env.dddd [A] connect_phase
UVM_INFO A.sv(21) @ 0: uvm_test_top.env.jjjj [A] connect_phase
UVM_INFO A.sv(21) @ 0: uvm_test_top.env.zzzz [A] connect_phase
TEST CASE PASSED
...

这里可以清晰地看出无论是自上而下( build_phase) 还是自下而上( connect_phase) 的phase, 其执行顺序都与实例化的顺序无关, 而是严格按照实例化时指定名字的字典序。

只是这个顺序是在UVM1.1d源代码中找到的, UVM并未保证一直会是这个顺序。 如果代码的执行必须依赖于这种顺序, 例如要求必须先执行driver的build_phase, 再执行monitor的build_phase, 那么应该立即修改代码, 杜绝这种依赖性在代码中出现。

类似run_phase、 main_phase等task_phase也都是按照自下而上的顺序执行的。 但是与前面function phase自下而上执行不同的是, 这种task phase是耗费时间的, 所以它并不是等到“下面”的phase( 如driver的run_phase) 执行完才执行“上面”的phase( 如agent的run_phase) , 而是将这些run_phase通过fork…join_none的形式全部启动。 所以, 更准确的说法是自下而上的启动, 同时在运行。

对于同一component来说, 其12个run-time的phase是顺序执行的, 但是它们也仅仅是顺序执行, 并不是说前面一个phase执行完就立即执行后一个phase。 以main_phase和post_main_phase为例, 对于A component来说, 其main_phase在0时刻开始执行, 100时刻执行完毕:

代码清单 5-5

文件: src/ch5/section5.1/5.1.3/phase_wait/A.sv
class A extends uvm_component;
   `uvm_component_utils(A)

   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction

   extern function void build_phase(uvm_phase phase);
   extern virtual  task main_phase(uvm_phase phase);
   extern virtual  task post_main_phase(uvm_phase phase);
endclass

function void A::build_phase(uvm_phase phase);
   super.build_phase(phase);
endfunction

task A::main_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info("A", "main phase start", UVM_LOW)
   #100;
   `uvm_info("A", "main phase end", UVM_LOW)
   phase.drop_objection(this);
endtask

task A::post_main_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info("A", "post main phase start", UVM_LOW)
   #300;
   `uvm_info("A", "post main phase end", UVM_LOW)
   phase.drop_objection(this);
endtask

对于B component来说, 其main_phase在0时刻开始执行, 200时刻执行完毕:

代码清单 5-6

文件: src/ch5/section5.1/5.1.3/phase_wait/B.sv
class B extends uvm_component;
   `uvm_component_utils(B)

   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction
   extern virtual  task main_phase(uvm_phase phase);
   extern virtual  task post_main_phase(uvm_phase phase);
endclass

task B::main_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info("B", "main phase start", UVM_LOW)
   #200;
   `uvm_info("B", "main phase end", UVM_LOW)
   phase.drop_objection(this);
endtask

task B::post_main_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info("B", "post main phase start", UVM_LOW)
   #200;
   `uvm_info("B", "post main phase end", UVM_LOW)
   phase.drop_objection(this);
endtask

此时整个验证平台的main_phase才执行完毕, 接下来执行post_main_phase, 即A和B的post_main_phase都是在200时刻开始执行。 假设A的post_main_phase执行完毕需要300个时间单位, 而B只需要200个时间单位, 无论是A或者B, 其后续都没有其他耗时间的phase了, 整个验证平台会在500时刻关闭。 上述代码的执行结果如下:

...
UVM_INFO @ 0: reporter [RNTST] Running test my_case0...
UVM_INFO A.sv(21) @ 0: uvm_test_top.env.A_inst [A] main phase start
UVM_INFO B.sv(15) @ 0: uvm_test_top.env.B_inst [B] main phase start
UVM_INFO A.sv(23) @ 100000: uvm_test_top.env.A_inst [A] main phase end
UVM_INFO B.sv(17) @ 200000: uvm_test_top.env.B_inst [B] main phase end
UVM_INFO A.sv(29) @ 200000: uvm_test_top.env.A_inst [A] post main phase start
UVM_INFO B.sv(23) @ 200000: uvm_test_top.env.B_inst [B] post main phase start
UVM_INFO B.sv(25) @ 400000: uvm_test_top.env.B_inst [B] post main phase end
UVM_INFO A.sv(31) @ 500000: uvm_test_top.env.A_inst [A] post main phase end
TEST CASE PASSED
...

可以看到对于A来说, main_phase在100时刻结束, 其post_main_phase在200时刻开始执行。 在100~200时刻, A处于等待B的状态, 除了等待不做任何事情。 B的post_main_phase在400时刻结束, 之后就处于等待A的状态。

这个过程如图5-2所示。

图5-2 phase的同步
图5-2 phase的同步

无论从A还是B的角度来看, 都存在一段空白等待时间。 但是从整个验证平台的角度来看, 各个task phase之间是没有任何空白的

上述的这种同步不仅适用于不同component的动态运行( run-time) phase之间, 还适用于run_phase与run_phase之间。 这两种同步都是不同component之间的相同phase之间的同步。 除了这两种同步外, 还存在一种run_phase与post_shutdown_phase之间的同步。 这种同步的特殊之处在于, 它是同一个component的不同类型phase( 两类task phase, 即run_phase与run-time phase) 之间的同步, 即同一个component的run_phase与其post_shutdown_phase全部完成才会进入下一个phase( extract_phase) 。 例如, 假设整个验证平台中只在A中控制objection:

代码清单 5-7

文件: src/ch5/section5.1/5.1.3/phase_wait2/A.sv
task A::post_shutdown_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info("A", "post shutdown phase start", UVM_LOW)
   #300;
   `uvm_info("A", "post shutdown phase end", UVM_LOW)
   phase.drop_objection(this);
endtask

task A::run_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info("A", "run phase start", UVM_LOW)
   #200;
   `uvm_info("A", "run phase end", UVM_LOW)
   phase.drop_objection(this);
endtask

在上述代码中, post_shutdown_phase在300时刻完成, 而run_phase在200时刻完成。 验证平台进入extract_phase的时刻是300。部分重要打印信息如下:

...
UVM_INFO @ 0: reporter [RNTST] Running test my_case0...
UVM_INFO A.sv(29) @ 0: uvm_test_top.env.A_inst [A] run phase start
UVM_INFO A.sv(21) @ 0: uvm_test_top.env.A_inst [A] post shutdown phase start
UVM_INFO A.sv(31) @ 200000: uvm_test_top.env.A_inst [A] run phase end
UVM_INFO /home/verifier/workspace/uvm_book/uvm-1.1d/src/base/uvm_objection.svh(1267) @ 200000: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO A.sv(23) @ 300000: uvm_test_top.env.A_inst [A] post shutdown phase end
TEST CASE PASSED
...

从整个验证平台的角度来说,只有所有component的run_phase和post_shutdown_phase都完成才能进入extract_phase

无论是run-time phase之间的同步, 还是run_phase与post_shutdown_phase之间的同步, 或者是run_phase与run_phase之间的同步, 它们都与objection机制密切相关。 关于这一点, 请参考5.2.1节。

5.1.4、UVM树的遍历

图3-2 完整的UVM树
图3-2 完整的UVM树

在图3-2中, 除了兄弟关系的component, 还有一种叔侄关系的component, 如my_scoreboard与my_driver, 从树的层次结构上来说, scoreboard级别是高于driver的, 但是, 这两者build_phase的执行顺序其实也是不确定的。 这两者的执行顺序除了上节提到的字典序外, 还用到了图论中树的遍历方式: 广度优先或是深度优先

所谓广度优先指的是如果i_agt的build_phase执行完毕后, 接下来执行的是其兄弟component的build_phase, 当所有兄弟的build_phase执行完毕后, 再执行其孩子的build_phase

所谓深度优先指的是如果i_agt的build_phase执行完毕后, 它接下来执行的是其孩子的build_phase, 如果孩子还有孩子, 那么再继续执行下去, 一直到整棵以i_agt为树根的UVM子树的build_phase执行完毕, 之后再执行i_agt的兄弟的build_phase。

UVM中采用的是深度优先的原则, 对于图3-2中的scoreboard及driver的build_phase的执行顺序, i_agt实例化时名字为“i_agt”,而scb为“scb”, 那么i_agt的build_phase先执行, 在执行完毕后, 接下来执行driver、 monitor及sequencer的build_phase。 当全部执行完毕后再执行scoreboard的build_phase:

# UVM_INFO my_agent.sv(29) @ 0: uvm_test_top.env.i_agt [agent] build_phase
# UVM_INFO my_driver.sv(16) @ 0: uvm_test_top.env.i_agt.drv [driver] build_phase
# UVM_INFO my_agent.sv(29) @ 0: uvm_test_top.env.o_agt [agent] build_phase
# UVM_INFO my_scoreboard.sv(23) @ 0: uvm_test_top.env.scb [scb] build_phase

反之, 如果i_agt实例化时是bbb, 而scb为aaa, 则会先执行scb的build_phase, 再执行i_agt的build_phase, 接下来是driver、monitor及sequencer的build_phase。

如果读者的代码中要求scoreboard的build_phase先于driver的build_phase执行, 或者要求两者的顺序反过来, 那么应该立即修改这种代码, 去除这种对顺序的要求。

5.1.5、super.phase的内容(不必理会,这个技巧性的东西不学也罢)

在前文的代码中, 有时候出现super.xxxx_phase语句, 有些时候又不会出现。 如在main_phase中, 有时出现super.main_phase,有时又不会; 在build_phase中, 则一般会出现super.build_phase。 那么uvm_component在其各个phase中都默认做了哪些事情呢? 哪些phase应该加上super.xxxx_phase, 哪些又可以不加呢?

对于build_phase来说, uvm_component对其做的最重要的事情就是3.5.3节所示的自动获取通过config_db::set设置的参数。如果要关掉这个功能, 可以在自己的build_phase中不调用super.build_phase。(感觉这种技巧不学也罢,不利于维护阅读代码!)

除了build_phase外, UVM在其他phase中几乎没有做任何相关的事情:

代码清单 5-8

来源: UVM源代码
function void uvm_component::connect_phase(uvm_phase phase);
	connect();
	return;
endfunction
function void uvm_component::start_of_simulation_phase(uvm_phase phase);
	start_of_simulation();
	return;
endfunction
function void uvm_component::end_of_elaboration_phase(uvm_phase phase);
	end_of_elaboration();
	return;
endfunction
task uvm_component::run_phase(uvm_phase phase);
	run();
	return;
endtask
function void uvm_component::extract_phase(uvm_phase phase);
	extract();
	return;
endfunction
function void uvm_component::check_phase(uvm_phase phase);
	check();
	return;
endfunction
function void uvm_component::report_phase(uvm_phase phase);
	report();
	return;
endfunction

//8个phase
function void uvm_component::connect(); return; endfunction
function void uvm_component::start_of_simulation(); return; endfunction
function void uvm_component::end_of_elaboration(); return; endfunction
task uvm_component::run(); return; endtask
function void uvm_component::extract(); return; endfunction
function void uvm_component::check(); return; endfunction
function void uvm_component::report(); return; endfunction
function void uvm_component::final_phase(uvm_phase phase); return; endfunction

//12个run-time phase
task uvm_component::pre_reset_phase(uvm_phase phase); return; endtask
task uvm_component::reset_phase(uvm_phase phase); return; endtask
task uvm_component::post_reset_phase(uvm_phase phase); return; endtask
task uvm_component::pre_configure_phase(uvm_phase phase); return; endtask
task uvm_component::configure_phase(uvm_phase phase); return; endtask
task uvm_component::post_configure_phase(uvm_phase phase); return; endtask
task uvm_component::pre_main_phase(uvm_phase phase); return; endtask
task uvm_component::main_phase(uvm_phase phase); return; endtask
task uvm_component::post_main_phase(uvm_phase phase); return; endtask
task uvm_component::pre_shutdown_phase(uvm_phase phase); return; endtask
task uvm_component::shutdown_phase(uvm_phase phase); return; endtask
task uvm_component::post_shutdown_phase(uvm_phase phase); return; endtask

由如上代码可以看出, 除build_phase外, 在写其他phase时, 完全可以不必加上super.xxxx_phase语句, 如第2章中所有的super.main_phase都可以去掉。 当然, 这个结论只适用于直接扩展自uvm_component的类。 如果是扩展自用户自定义的类, 如base_test类, 且在其某个phase, 如connect_phase中定义了一些重要内容, 那么在具体测试用例的connect_phase中就不应该省略super.connect_phase。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值