ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

phase机制-UVM

2022-01-08 18:34:11  阅读:789  来源: 互联网

标签:run apb UVM phase 机制 super 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
  • 这里先执行run_phase再执行reset_phase,不会因为声明函数的先后而影响他们的执行顺序,而是按照run_phase与run-time并行执行的顺序进行的。这里的run_phase虽然消耗了一个时间单位#1,但是由于它没有raise_objection,所以与run-time的raise同时启动,别的组件中的run_phase(例如driver)都已经raise了,那么这里case_0的run_phase就可以先进行打印,这里仿真器任务仿真器。但是如果是别的组件的raise都删掉了,只有run_phase的raise那么就run-time就不会成立这个执行顺序;
    后面的monitor的打印的问题
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

在这里插入图片描述

  • 这里的main_phase没有raise和drop的,别的任何的main_phase都没有raise和drop。但是仍然会执行monitor里面的run_phase打印,并且#1后不会打印。也就是说我们在main_phase中是会检测是否有raise/drop_objection就不会执行任何消耗时间单位的语句,但是不消耗时间的就会执行
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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有