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的调试。