其他分享
首页 > 其他分享> > phase机制-UVM

phase机制-UVM

作者:互联网

文章目录

一、phase机制

UVM中的phase机制是将仿真阶段层次化,各个phase按照先后顺序执行,并且同一层次的phase中的层次化组件之间按照顺序执行

1.1 为什么要使用phase机制?

在这里插入图片描述
从上图中可以看出UVM提供了很多phase,但是在一般情况下是不会把所有的phase都使用上的,使用频率最高的是build_phase、connect_phase和main_phase。这里能够很方便验证工程师将不同的代码写在不同的phase上,还有利与其他验证学向UVM迁移。

  1. build phase——实现验证平台的创建、连接、配置;
  2. run phase——产生激励并运行仿真,需要消耗仿真事件;
  3. clean up phase——测试用例结果收集与报告;

1.2 phase是如何运行的?

在1.1节中笼统说了phase是自上而下执行的,但是这里需要注意的是针对不同阶段的phase,这个自上而下的概念会不一样。在build phase中的自上而下执行是指它在实例化时进行的方式,例如针对driver和monitor,它都是agent的成员变量,所以它必须现实现agent的实例化才能实现它们的实例化。如果在agent实例化之前,driver想要实例化,那么会报错。
除了build phase之外,所有不耗费仿真时间的phase都是自下而上的执行,例如connect_phase需要先执行driver和monitor的connect_phase才能够执行agent的connect_phase。
无论自上而下还是自下而上,都只适应UVM树中有直系关系的component,对于同一层次、有兄弟关系的component,例如driver和monitor它在执行顺序是按照字典执行的。
针对非父子关系的component,UVM采用的是深度优先的执行顺序,如果active_agent如果比passive_agent先执行,那么driver、monitor、sequencer全部执行完后,passive_agent才会执行
针对UVM树来说,build_phase阶段自顶向下执行,创建空间,搭建UVM数;
其余阶段自下而上执行,耗时阶段自下而上执行。

class case_0 extends base_test;
  `uvm_component_utils(case_0);
  function new(string name = "case_0",uvm_component parent = null);
      super.new(name,parent);
  endfunction
  virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      uvm_config_db#(uvm_object_wrapper)::set(this,"v_sqr.main_phase","default_sequence",vseq_0::type_id::get());
      `uvm_info(get_full_name(),"build_phase",UVM_MEDIUM);
  endfunction
  virtual function void connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      `uvm_info(get_full_name(),"connect_phase",UVM_MEDIUM);
  endfunction
  virtual task reset_phase(uvm_phase phase);
     super.rest_phase(phase);
     phase.raise_objection(this);
     #1;
     `uvm_info(get_full_name(),"rest_phase",UVM_MEDIUM)
     phase.drop_objection(this);
  endtask
  virtual task main_phase(uvm_phase phase);
     //phase.raise_objection(this);
     #1;
     `uvm_info(get_full_name(),"main_phase",UVM_MEDIUM)
     //phase.drop_objection(this);
  endtask
  virtual task shutdown_phase(uvm_phase phase);
     //phase.raise_objection(this);
     #1;
     `uvm_info(get_full_name(),"shutdown_phase",UVM_MEDIUM)
     //phase.drop_objection(this);
  endtask
  virtual task run_phase(uvm_phase phase);
     #1;
     `uvm_info(get_full_name(),"run_phase",UVM_MEDIUM)
  endtask
   virtual function void report_phase(uvm_phase phase);
      super.report_phase(phase);
      `uvm_info(get_full_name(),"report_phase",UVM_MEDIUM)
  endfunction
class apb_monitor extends uvm_monitor;
  `uvm_component_utils(apb_monitor)
  virtual apb_interface vif;
  uvm_analysis_port#(apb_trans) apb_mon_port;
  function new(string name = "apb_monitor",uvm_component parent)l
      super.new(name,parent);
  endfunction
  virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      if(!uvm_config_db#(virtual apb_interface)::get(this,"","vif",vif))begin
          `uvm_fatal("NOVIF/VIP/MON","NO ")
      end
      apb_mon_port = new("apb_mon_port",this);
  endfunction
  virtual task main_phase(uvm_phase phase);
      super.main_phase(phase);
      `uvm_info(get_full_name(),$sformatf("psel = %x",vif.psel),UVM_MEDIUM
      `uvm_info(get_full_name(),$sformatf("penable = %x",vif.penable),UVM_MEDIUM)
      `uvm_info(get_full_name(),$sformatf("pwrite = %x",vif.pwrite),UVM_MEDIUM)
      `uvm_info(get_full_name(),$sformatf("paddr = %x",vif.paddr),UVM_MEDIUM)
      `uvm_info(get_full_name(),$sformatf("pwdata = %x",vif.pwdata),UVM_MEDIUM)
      `uvm_info(get_full_name(),$sformatf("prdata = %x",vif.prdata),UVM_MEDIUM)
      #1;
      `uvm_info(get_full_name(),$sformatf("pwdata2 = %x",vif.pwdata),UVM_MEDIUM)
  endtask
  virtual task run_phase(uvm_phase phase);
      super.run_phase(phase);
  endtask
endclass

在这里插入图片描述

virtual task main_phase(uvm_phase phase);
     phase.raise_objection(this);
     #1;
     `uvm_info(get_full_name(),"main_phase",UVM_MEDIUM)
     phase.drop_objection(this);
  endtask

在这里插入图片描述
如果在main_phase中加了raise/drop之后,那么延时#1的就可以打印出来,因为这里的main_phase有进行raise/drop。
但是如果将消耗时间由#1变为#2,那么就不会打印出来,这时因为在#1时钟单位后就drop了。

1.3 phase的调试

<sim command>+UVM_PHASE_TRACE//1、可以对phase机制进行调试
//2、设置防止测试用例挂起的超时时间
function void base_test::build_phase(uvm_phase phase);
    super.build_phase(phase);
    env = my_env::type_id::create("env",this);
    uvm_top.set_timeout(500ns,0);//第一个参数设置时间,第二个参数设定是否可以被其他的set_timeout语句覆盖
endfunction

//3、命令行设置超时
<sim command>+UVM_TIMEOUT=<timeout>,<overridable>

1.4 如何使用super.xxx_phase的执行

我们首先需要知道super.xxx_phase的作用是执行父类的内容

1.4.1 在component中使用super.xxx_phase的执行

class apb_driver extends uvm_driver#(apb_trans);
  ...
  virtual protected task run_phase(uvm_phase phase);
      //super.run_phase(phase);这里的可以删掉
      forever begin
        seq.item_port.get_next_item(req);
        send(req);
        seq.item_port.item_done();
      end
  endtask

上面的代码中如果将super.run_phase(phase)删掉不会影响的,这时因为apb_driver是派生自uvm_driver,uvm_driver的run_phase是没有东西的,有时候还有进行消耗时间。如果写另一个driver去继承这个apb_driver,那么如果在它的run_phase中也执行父类的forever循环,导致一直无法跳出。通常task中不添加super.xxx_phase

1.4.2 在object中使用super.xxx_phase的执行

class base_test extends uvm_test;
  `uvm_component_utils(base_test)
  apb_environment apb_env;
  virtual_sequencer v_sqr;
  ...
  virtual function void build_phase(uvm_phase phase);;
    super.build_phase(phase);
    apb_env = apb_environment::type_id::create("apb_env",this);
    v_sqr = virtual_sequencer::type_id::create("v_sqr",this);
    sb = scoreboard::type_id::create("sb",this);
  endfunction
  virtual function void connect_phase(uvm_phase phase);
      v_sqr.apb_sqr = apb_env.act_agt.sqr;
      ...

这里的base_test中的除了build_phase进行了例化,在connect_phase中也进行了操作,例如v_sqr.apb_sqr = apb_env.act_agt.sqr那么我们在base_test派生的类中就需要进行super.

class case_0 extends base_test;
  virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      ...
   endfunction
  virtual function void connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      ...  

标签:run,apb,UVM,phase,机制,super,uvm
来源: https://blog.csdn.net/weixin_42705678/article/details/122156236