uvm phase(component)

1,516 阅读2分钟

uvm component phase

a.phase基本概念

在这里插入图片描述

  • 按照其是否消耗仿真时间($time打印出的时间)的特性,可以分成两大类:一类是function phase,这些phase是通过函数实现;另外一类是task phase,这些phase是通过任务实现的
  • run_phase启动时间是0ns
  • 除了build_phase自顶而下(top-down)之外,所有不耗费仿真时间的phase(即function phase)都是自下而上(bottom-up)执行的
  • 类似run_phase、main_phase等task_phase也都是按照自下而上的顺序执行
  • task phase是耗费时间的,所以它并不是等到“下面”的phase(如driver的run_phase)执行完才执行“上面”的phase(如agent的run_phase),而是将这些run_phase通过fork…join_none的形式全部启动。所以更准确的说法是task 的phase 自下而上的启动,同时在运行。

图1中,灰色背景所示的是task phase,其他白色背景为function phase。在时间上,所有的phase都会按照图1中的顺序自上而下自动执行。
最右侧的12个phase是run-time phase (动态运行phase)
在这里插入图片描述

  • 对于同一component来说,其12个run-time的phase(动态运行phase)是顺序执行的,但是它们也仅仅是顺序执行,并不是说前面一个phase执行完就立即执行后一个phase。
  • phase的调试可以用 +UVM_PHASE_TRACE来打印phase相关信息

a1. phase同步

以A component和B component中的main_phase和post_main_phase为例,如图2所示。
在这里插入图片描述

从图中可以看到对于A来说,main_phase在100时刻结束,其post_main_phase在200时刻执行。在100~200时刻,A处于等待B的状态,除了等待不做任何事情。B的post_main_phase在400时刻结束,之后处于等待A的状态。无论从A还是从B的角度看,都存在一段 等待时间。但是从整个验证平台的角度来看,各个task phase之间是没有任何空白的。整个验证平台必须所有的main_phase执行完毕,接下来执行post_main_phase;所有的post_main_phase执行完毕,接下来执行下一个phase,如pre_shutdown_phase。
在这里插入图片描述

  • 这种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)。phase同步主要可以总结为图3的三种方式。

在这里插入图片描述
参考UVM中的PHASE类别及PHASE同步

b. run_phase 和 main_phase区别

  • 从uvm1.1后,uvm的run_phase会与12个task phase并行执行,12个task phase包括pre_reset_phase, reset_phase,…main_phase等等,一般的大部分人并不太用除了main_phase之外的别的task phase,因此一般使用可以认为main_phase跟run_phase几乎相同的作用;
  • run_phase跟12个task phase所属的domain并不一样,run_phase属于common_domain, 其余的12个task phase属于uvm_domain
  • run_phase和main phase都是task phase,且是并行运行的,后者称为动态运行(run-time)的phase。如果想执行一些耗费时间的代码,那么要在此phase下任意一个component中至少提起一次objection,这个结论只适用于12个run-time的phase。
  • 对于run_phase则不适用,由于run_phase与动态运行的phase是并行运行的,如果12个动态运行的phase有objection被提起,那么run_phase根本不需要raise_objection就可以自动执行。
  • 不要混合使用run_phase与main_phase
  • phase.raise_objection(this) 这里的this是调用这个的component
virtual function void raise_objection (
uvm_object obj,
string description = "",
int count = 1
)

uvm中应该推荐使用reset,main等run_time phase,还是使用run_phase?
UVM基础之------uvm phases机制

c.一个sequence可以指定在main_phase中跑,也可以在其他phase中跑;

来源《uvm实战》7.7.1
case0_cfg_vseq在configure_phase中跑,如果都指定在main_phase中则,后边一个会覆盖前一个;

`ifndef MY_CASE0__SV
`define MY_CASE0__SV
class case0_sequence extends uvm_sequence #(my_transaction);
   my_transaction m_trans;
   function  new(string name= "case0_sequence");
      super.new(name);
   endfunction 
   virtual task body();
      repeat (10) begin
         `uvm_do(m_trans)
      end
   endtask
   `uvm_object_utils(case0_sequence)
endclass

class case0_cfg_vseq extends uvm_sequence;
   `uvm_object_utils(case0_cfg_vseq)
   `uvm_declare_p_sequencer(my_vsqr)
   function  new(string name= "case0_cfg_vseq");
      super.new(name);
   endfunction 
   virtual task body();
      uvm_status_e   status;
      uvm_reg_data_t value;
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      p_sequencer.p_rm.invert.read(status, value, UVM_FRONTDOOR);
      `uvm_info("case0_cfg_vseq", $sformatf("invert's initial value is %0h", value), UVM_LOW)
      p_sequencer.p_rm.invert.write(status, 1, UVM_FRONTDOOR);
      p_sequencer.p_rm.invert.read(status, value, UVM_FRONTDOOR);
      `uvm_info("case0_cfg_vseq", $sformatf("after set, invert's value is %0h", value), UVM_LOW)
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask
endclass

class case0_vseq extends uvm_sequence;

   `uvm_object_utils(case0_vseq)
   `uvm_declare_p_sequencer(my_vsqr)
   
   function  new(string name= "case0_vseq");
      super.new(name);
   endfunction 
   virtual task body();
      case0_sequence dseq;
      uvm_status_e   status;
      uvm_reg_data_t value;
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      #10000;
      dseq = case0_sequence::type_id::create("dseq");
      dseq.start(p_sequencer.p_my_sqr);      
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask
endclass
class my_case0 extends base_test;
   function new(string name = "my_case0", uvm_component parent = null);
      super.new(name,parent);
   endfunction 
   extern virtual function void build_phase(uvm_phase phase); 
   `uvm_component_utils(my_case0)
endclass
function void my_case0::build_phase(uvm_phase phase);
   super.build_phase(phase);
   //case0_cfg_vseq在configure_phase中跑,
   //如果都指定在main_phase中则,后边一个会覆盖前一个;
   uvm_config_db#(uvm_object_wrapper)::set(this, 
                                           "v_sqr.configure_phase", 
                                           "default_sequence", 
                                           case0_cfg_vseq::type_id::get());
   uvm_config_db#(uvm_object_wrapper)::set(this, 
                                           "v_sqr.main_phase", 
                                           "default_sequence", 
                                           case0_vseq::type_id::get());
endfunction
`endif

case0_cfg_vseq跑在bus_driver的configure_phase
bus_driver中要定义run_phase, 因为run_phase包含config_phase;也可以在bus_driver使用configure_phase; 但是不能使用其他phase,会造成不匹配的情况

task bus_driver::run_phase(uvm_phase phase);
   vif.bus_cmd_valid <= 1'b0;
   vif.bus_op <= 1'b0;
   vif.bus_addr <= 15'b0;
   vif.bus_wr_data <= 15'b0;
   while(!vif.rst_n)
      @(posedge vif.clk);
   while(1) begin
      seq_item_port.get_next_item(req);
      drive_one_pkt(req);
      seq_item_port.item_done();
   end
endtask

my_driver使用main_phase 跑 case0_vseq

task my_driver::main_phase(uvm_phase phase);
   vif.valid <= 1'b0;
   vif.data <= 8'b0;
   while(!vif.rst_n)
      @(posedge vif.clk);
   while(1) begin
      seq_item_port.get_next_item(req);
      drive_one_pkt(req);
      seq_item_port.item_done();
   end
endtask

set_drain_time

  • UVM 在main_phase 检查到所有objection 被撤销后,会检查是否设置drain_time,如果有,则延迟drain_time。
  • UVM所有的objection 设置了 drain_time 属性;
  • 一个phase 对应一个drain_time,其他phase 要用,要给自己单独设置。不共享。
    在这里插入图片描述
    可以set_drain_time设置一个大的延迟,避免用下边方法
    在这里插入图片描述
    在这里插入图片描述

timeout

在这里插入图片描述

domain

  • run_phase 是common
  • 12个小phase是uvm
    在这里插入图片描述

55、uvm_component类中的phase_ready_to_end()方法有什么用途?

phase_ready_to_end(uvm_phase phase)是component类中的回调(callback)方法,当该phase的所有objections均被drop之后调用该方法。component类可以使用此回调方法来定义phase即将结束时需要执行的功能。
如果某个组件希望在objections被drop之后将phase结束延迟到某个条件,可以使用此回调方法来完成;
这个方法和set_drain_time区别???