uvm-1.2 examples —— 2.4 package

2.4 package



前言

本文以uvm-1.2/examples/simple/basic_examples/pkg为例,主要的内容包括:1、两种方式注册工厂模式,手动注册和宏注册;2、打印调试config_db机制。


一、基本介绍

这个测试用例和上一节2.3的module类似,不过这个测试用例的侧重点,在于展示通过两种不同的方式,将一个组件注册到UVM工厂中去,另外还展示了如何开启了config_db的打印调试功能。

和上一个测试用例相比,系统的层次化结构一样,但换了一种打印风格。

mu: (myunit@335) {
  l1: (lower@344) {
    data: 'h30 
    str: "" 
  }
  l2: (lower@353) {
    data: 'h40 
    str: "" 
  }
  a: {
    [0]: 'h0 
    [1]: 'h1 
    [2]: 'h4 
    [3]: 'h9 
    [4]: 'h10 
  }
}

执行完仿真,得到的仿真结果如下。

mu: (myunit@335) {
  l1: (lower@344) {
    data: 'h37 
    str: hi 
  }
  l2: (lower@353) {
    data: 'h65 
    str: hi 
  }
  a: {
    [0]: 'h0 
    [1]: 'h1 
    [2]: 'h4 
    [3]: 'h9 
    [4]: 'h10 
  }

二、代码分析

这个测试用例只有一个文件test.sv

1、test.sv

test.sv的代码如下所示。

module test;
  import uvm_pkg::*;

  //--------------------------------------------------------------------
  // lower
  //--------------------------------------------------------------------
  class lower extends uvm_component;
    int data;
    string str;

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

    task run_phase(uvm_phase phase);
      phase.raise_objection(this);
      $display("%0t: %m: start run", $time);
      #10 $display("%0t: %s HI", $time, get_full_name());
      phase.drop_objection(this);
    endtask

    function string get_type_name();
      return "lower";
    endfunction

    function void build_phase(uvm_phase phase);
       void'(uvm_config_int::get(this, "", "data", data));
       void'(uvm_config_string::get(this, "", "str", str));
    endfunction 

    function void do_print(uvm_printer printer);
      printer.print_field("data", data, 32);
      printer.print_string("str", str);
    endfunction
  endclass

  //--------------------------------------------------------------------
  // myunit
  //--------------------------------------------------------------------
  class myunit extends uvm_component;
   lower l1;
   lower l2;
   int a[];

    function new (string name, uvm_component parent);
      super.new(name, parent);
      l1 = new ("l1", this);
      l2 = new ("l2", this);
      uvm_config_string::set(this, "l1", "str", "hi");
      uvm_config_int::set(this, "*", "da*", 'h100);
      l1.data = 'h30;
      l2.data = 'h40;
      a = new[5]; for(int i=0; i<5;++i) a[i] = i*i;
    endfunction

    task run_phase(uvm_phase phase);
      phase.raise_objection(this);
      #10 $display("%0t: %s HI", $time, get_full_name());
      phase.drop_objection(this);
    endtask

    function string get_type_name();
      return "myunit";
    endfunction

    function void do_print(uvm_printer printer);
      printer.print_array_header("a", a.size());
      for(int i=0; i<a.size(); ++i) 
        printer.print_field($sformatf("a[%0d]", i), a[i], 32, UVM_HEX, "[");
      printer.print_array_footer();
    endfunction
      
  endclass


  // Factory registration 

  //--------------------------------------------------------------------
  // lower_wrapper
  //--------------------------------------------------------------------
  class lower_wrapper extends uvm_object_wrapper;
  
    function uvm_component create_component(string name, uvm_component parent);
      lower u;
      u = new(name, parent);
      return u;
    endfunction
  
    function string get_type_name();
      return "lower";
    endfunction
  
    static function bit register_me(); uvm_coreservice_t cs_ = uvm_coreservice_t::get();

      uvm_factory factory = cs_.get_factory();
      lower_wrapper w; w = new;
      factory.register(w);
      return 1;
    endfunction

    static bit is_registered = register_me();
  endclass

  //--------------------------------------------------------------------
  // myunit_wrapper
  //--------------------------------------------------------------------
  class myunit_wrapper extends uvm_object_wrapper;

    function uvm_component create_component(string name, uvm_component parent);
      myunit u;
      u = new(name, parent);
      return u;
    endfunction

    function string get_type_name();
      return "myunit";
    endfunction

    static function bit register_me(); uvm_coreservice_t cs_ = uvm_coreservice_t::get();

      uvm_factory factory = cs_.get_factory();
      myunit_wrapper w; w = new;
      factory.register(w);
      return 1;
    endfunction

    static bit is_registered = register_me();
  endclass

  myunit mu = new("mu", null);

  //--------------------------------------------------------------------
  // mydata
  //--------------------------------------------------------------------
`ifdef USE_MACROS
  class mydata extends uvm_object;
    `uvm_object_utils(mydata)

  function new(string name="mydata");
     super.new(name);
  endfunction

  endclass
`else
  class mydata extends uvm_object;
    function uvm_object create(string name="");
      mydata d; d=new; d.set_name(name);
      return d;
    endfunction // uvm_object
    function string get_type_name();
      return "mydata";
    endfunction
  endclass

  //--------------------------------------------------------------------
  // mydata_wrapper
  //--------------------------------------------------------------------
  class mydata_wrapper extends uvm_object_wrapper;

    function uvm_object create_object(string name="");
      mydata u;
      u = new;
      if(name !="") u.set_name(name);
      return u;
    endfunction

    function string get_type_name();
      return "myobject";
    endfunction

    static function bit register_me(); uvm_coreservice_t cs_ = uvm_coreservice_t::get();

      uvm_factory factory = cs_.get_factory();
      mydata_wrapper w; w = new;
      factory.register(w);
      return 1;
    endfunction

    static bit is_registered = register_me();
  endclass
`endif 

  mydata bar = new;

  initial begin automatic uvm_coreservice_t cs_ = uvm_coreservice_t::get();

    uvm_factory factory;
    factory=cs_.get_factory();
    uvm_top.finish_on_completion = 0;
    uvm_config_int::set(null, "mu.*", "data", 101);
    uvm_config_string::set(null, "mu.*", "str", "hi");
    uvm_config_int::set(null, "mu.l1", "data", 55);
    //uvm_config_object::set(null, "mu.*", "obj", bar);
    //mu.print_config_settings("", null, 1);
    mu.print_config(1);
    uvm_default_printer = uvm_default_tree_printer;
    mu.print();
    factory.print(1);
    run_test();
    mu.print();
  end
  //initial
  //  #5 mu.l1.kill();
endmodule

第1行,例化test这个module,这个测试用例将所有的组件都放在了module里边。
第7到73行,定义从uvm_component继承过来的类lower和myunit,这个定义和上一节2.3的一样。
第81到102行和107到128行,通过一个wrapper类,手动的将lower类和myunit类,注册到UVM的工厂中。有几点需要注意的是:1、wrapper类必须继承自uvm_object_wrapper类;2、在create_component函数中,例化的是需要注册的类。
第135到181行,通过一个宏USE_MACROS来切换,是选择采用宏注册,还是手动注册的方式注册mydata类,通过对比可以看出,宏注册的方式只需要一条语句就完成了注册,而手动注册则需要另外构造一个wrapper的类去实现。
第185到201行,通过一个initial来实现仿真,其中195行的print_config(1)函数会遍历整个验证平台的所有结点,找出那些被设置过的信息并打印出来,打印的信息如下所示。这个函数在张强的《UVM实战》中的3.5.10节也有介绍。

UVM_INFO @ 0: mu [CFGPRT] visible resources:
UVM_INFO ../../../../src/base/uvm_resource.svh(1321) @ 0: reporter [UVM/RESOURCE/PRINT] <none>
UVM_INFO @ 0: mu.l1 [CFGPRT] visible resources:
 str [/^mu\..*$/] : (string) "hi"   
 str [/^mu\.l1$/] : (string) "hi"   
 data [/^mu\.l1$/] : (logic signed[4095:0]) 55   
 data [/^mu\..*$/] : (logic signed[4095:0]) 101   
 da* [/^mu\..*$/] : (logic signed[4095:0]) 256   
UVM_INFO @ 0: mu.l2 [CFGPRT] visible resources:
 str [/^mu\..*$/] : (string) "hi"   
 data [/^mu\..*$/] : (logic signed[4095:0]) 101   
 da* [/^mu\..*$/] : (logic signed[4095:0]) 256   

2、仿真结果

仿真log如下所示,通过log还可以看到一个现象,由于代码196行,改变了打印的方式,所以,mu打印的格式也发生的改变,变成了树状结构。

UVM_INFO @ 0: mu [CFGPRT] visible resources:
UVM_INFO ../../../../src/base/uvm_resource.svh(1321) @ 0: reporter [UVM/RESOURCE/PRINT] <none>
UVM_INFO @ 0: mu.l1 [CFGPRT] visible resources:
 str [/^mu\..*$/] : (string) "hi"   
 str [/^mu\.l1$/] : (string) "hi"   
 data [/^mu\.l1$/] : (logic signed[4095:0]) 55   
 data [/^mu\..*$/] : (logic signed[4095:0]) 101   
 da* [/^mu\..*$/] : (logic signed[4095:0]) 256   
UVM_INFO @ 0: mu.l2 [CFGPRT] visible resources:
 str [/^mu\..*$/] : (string) "hi"   
 data [/^mu\..*$/] : (logic signed[4095:0]) 101   
 da* [/^mu\..*$/] : (logic signed[4095:0]) 256   
mu: (myunit@335) {
  l1: (lower@344) {
    data: 'h30 
    str: "" 
  }
  l2: (lower@353) {
    data: 'h40 
    str: "" 
  }
  a: {
    [0]: 'h0 
    [1]: 'h1 
    [2]: 'h4 
    [3]: 'h9 
    [4]: 'h10 
  }
}
UVM_INFO ../../../../src/base/uvm_factory.svh(1645) @ 0: reporter [UVM/FACTORY/PRINT] 
#### Factory Configuration (*)

  No instance or type overrides are registered with this factory

All types registered with the factory: 50 total
  Type Name
  ---------
  lower
  mydata
  myunit
(*) Types with no associated type name will be printed as <unknown>

####


UVM_INFO @ 0: reporter [RNTST] Running test ...
0: test.\lower::run_phase : start run
0: test.\lower::run_phase : start run
10: mu.l1 HI
10: mu.l2 HI
10: mu HI
UVM_INFO ../../../../src/base/uvm_report_server.svh(847) @ 10: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

** Report counts by severity
UVM_INFO :    7
UVM_WARNING :    0
UVM_ERROR :    0
UVM_FATAL :    0
** Report counts by id
[CFGPRT]     3
[RNTST]     1
[UVM/FACTORY/PRINT]     1
[UVM/RELNOTES]     1
[UVM/RESOURCE/PRINT]     1

mu: (myunit@335) {
  l1: (lower@344) {
    data: 'h37 
    str: hi 
  }
  l2: (lower@353) {
    data: 'h65 
    str: hi 
  }
  a: {
    [0]: 'h0 
    [1]: 'h1 
    [2]: 'h4 
    [3]: 'h9 
    [4]: 'h10 
  }
}
           V C S   S i m u l a t i o n   R e p o r t 
Time: 10 ns

总结

通过这个测试用例,主要可以学习到两点,其一是通过手动的方式将组件注册到UVM的工厂中去,其二是可以调用print_config(1)函数实现config_db的调试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值