6、IC验证面试88问——UVM启动、接口传递、UVM优势

Q10:UVM从哪里启动?

(1)在导入 uvm_pkg 文件时,会自动创建 uvm_root 所例化的对象 uvm_top,UVM 顶层的类会提供 run_test()方法充当 UVM 世界的核心角色,通过uvm_top 调用 run_test()方法。
(2)在环境中输入 run_test 来启动 UVM 验证平台,run_test 语句会创建一个 my_case0 的实例,得到正确的 test_name。
(3) 依次执行 uvm_test 容器中的各个 component 组件中的 phase 机制,按照顺序:

  1. build-phase(自顶向下构建 UVM 树)
  2. connet_phase(自底向上连接各个组件)
  3. end_of_elaboration_phase
  4. start_of_simulation_phase
  5. run_phase() objection 机制仿真挂起,通过 start 启动 sequence(每个 sequence 都有一个 body 任务。当一个 sequence 启动后,会自动执行sequence 的 body 任务。)。等到 sequence 发送完毕则关闭 objection,结束run_phase()。
    (UVM_objection 提供 component 和 sequence 共享的计数器,当所有参与到 objection 机制中的组件都 drop objection 时,计数器 counter才会清零,才满足 run_phase()退出的条件)
  6. 执行后面的 phase。

Q11:接口怎么传递到验证环境中?

  • 通过uvm_cofig_db机制配置,可以将virtual interface传递到环境中。

  • 虽然SV可以通过层次化的interface的索引完成传递,但是这种传递方式不利于软件环境的封装和复用。通过使用uvm_config_db配置机制来传递接口,可以将接口的传递与获取彻底分离开。

  • 接口传递从硬件世界到UVM环境可以通过uvm_config_db来实现,在实现过程中应当注意:

    • 接口传递应发生在run_test()之前。这保证了在进入build_phase之前,virtual interface已经被传递到uvm_config_db中。
    • 用户应当把interface与virtual interface区分开来,在传递过程中的类型应当为virtual interface,即实际接口的句柄。

Q12:UVM的优势。

UVM 其实是 SV 的一个封装,将我们在搭建测试平台过程中的一些重复性和重要的工作进行封装,从而使我们能够快速的搭建一个需要的测试平台,并且可重用性还高。但是 UVM 又不仅仅是封装。

11 uvm_config_db机制

常见使用方式:

  • 传递virtual interface到环境中;
  • 配置单一变量值,例如int、string、enum等;
  • 传递配置对象(config_object)到环境。

11.1 vif的传递

interface   intf1;       //接口定义
    logic   enable = 0;
endinterface

class  comp1  extends  uvm_component;      //组件配置接口
    `uvm_component_utils(comp1)
  	 virtual   intf1  vif;          //接口声明
    ...
    function void build_phase(uvm_phase phase);
       if(!uvm_config_db #(virtual intf1)::get(this,"","vif",vif)) begin     //**3. 获取配置接口vif = intf**
          `uvm_error("GETVIF","no virtual interface is assigned")
       end
       `uvm_info("SETVAL",$sformatf("vif.enable is %b before set",vif.enable),UVM_LOW)
       vif.enable = 1;
       `uvm_info("SETVAL",$sformatf("vif.enable is %b after set",vif.enable),UVM_LOW)       
    endfunction
endclass

class  test1  extends  uvm_test;       //测试用例层,可在此进行接口配置,也可在顶层配置
    `uvm_component_utils(test1)
    comp1    c1;
    ...
endclass

intf1    intf();                 //**1. 接口配置前,例化借口**
initial  begin
    uvm_config_db #(virtual intf1)::set(uvm_root::get(),"uvm_test_top.c1","vif",intf)     //**2. 启动接口配置**
    run_test("test1");      //在run_test()之前完成接口配置
end

11.2 配置单一变量值,例如int、string、enum等;

各个 test 中,可以在 build_phase 阶段对底层组件的各个变量加以配置,进而在环境例化之前完成配置,使得环境可以按照预期运行。

class  comp1  extends  uvm_component;      //组件
    `uvm_component_utils(comp1)
    int   val1 = 1;
    string   str1 = "null";
    ...
    function void build_phase(uvm_phase phase);   //在build_phase阶段进行配置
       `uvm_info("SETVAL",$sformatf("val1 is %d before get",val1),UVM_LOW)       
       `uvm_info("SETVAL",$sformatf("str1 is %d before get",str1),UVM_LOW)  
       uvm_config_db #(int)::get(this,"","val1",val1);        //使用get()方法获取配置
       uvm_config_db #(string)::get(this,"","str1",str1); 
       `uvm_info("SETVAL",$sformatf("val1 is %d after get",val1),UVM_LOW)       
       `uvm_info("SETVAL",$sformatf("str1 is %d after get",str1),UVM_LOW)  
    endfunction
endclass

class  test1  extends  uvm_test;       //测试用例层, 启动配置
    `uvm_component_utils(test1)
    comp1    c1;
    ...
    function void build_phase(uvm_phase phase);
       uvm_config_db #(int)::set(this,"c1","val1",100);        //使用set()方法获取配置
       uvm_config_db #(string)::set(this,"c1","str1","comp1"); 
       c1 = comp1::type_id::create("c1");   
    endfunction
endclass

11.3 config object对象传递;

  • 在test配置中,需要配置的参数不只是数量多,可能还分属于不同的组件。对这么多层次的变量做出类似上边的单一变量传递,需要更多的代码,容易出错且不易复用。
  • 如果整合各个组件中的变量,将其放置在一个uvm_object中,再对中心化的配置对象进行传递,将有利于整体环境的修改维护,提升代码的复用性。
class  config1  extends  uvm_object;         //**1. 创建一个配置类,将需要配置的变量放于其中**
   `uvm_object_utils(config1)
   int   val1 = 1;
   int   str1 = "null";
   ...
endclass

class  comp1  extends  uvm_component;      //组件
    `uvm_component_utils(comp1)
    config1      cfg ;                 //声明配置类句柄
    ...
    function void build_phase(uvm_phase phase);
       uvm_object    tmp;         //声明类句柄
       uvm_config_db #(uvm_object)::get(this,"","cfg",tmp);     //**3. 获取变量配置**
       void`($cast(cfg,tmp));         //类型转韩,将传到tmp中的值赋给cfg
       `uvm_info("SETVAL",$sformatf("cfg.val1 is %d after get",cfg.val1),UVM_LOW)       
       `uvm_info("SETVAL",$sformatf("cfg.str1 is %d after get",cfg.str1),UVM_LOW)  
    endfunction
endclass

class  test1  extends  uvm_test;       //测试用例层, 启动配置
    `uvm_component_utils(test1)
    comp1    c1, c2;
    config1  cfg1, cfg2;
    ...
    function void build_phase(uvm_phase phase);
       cfg1 = config1::type_id::create("cfg1");
       cfg2 = config1::type_id::create("cfg2");
       c1 = comp1::type_id::create("c1");      
       c2 = comp1::type_id::create("c2");       //创建对象
       cfg1.val1 = 30;
       cfg1.str1 = "c1";
       cfg2.val1 = 50;
       cfg2.str1 = "c2";
       uvm_config_db #(uvm_object)::set(this,"c1","cfg",cfg1);     //**2. 启动变量配置**       
       uvm_config_db #(uvm_object)::set(this,"c2","cfg",cfg2);     //启动变量配置 
    endfunction 
endclass
  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值