2.5 config_db - automated
文章目录
前言
本文以uvm-1.2/examples/simple/configuration/automated为例,主要介绍在config_db机制中,如何省去get函数实现参数的传递。其次展示了,在一个参数被多个set函数配置时,哪个set函数优先级更高。
一、基本介绍
这个测试用例在top下面例化了两个组件A和B,其中A下面例化了两个C,B下面例化了一个C,具体的组件层次结构和参数如下所示。测试用例主要是在top中,通过set函数去配置组件下面的参数。
-------------------------------------------------
Name Type Size Value
-------------------------------------------------
topenv my_env - @364
inst1 A - @383
u1 C - @403
v integral 32 'h1e
s integral 32 'h10
myaa aa(string,string) 3 -
[bar] string 3 bye
[foo] string 3 boo
[foobar] string 6 boobah
u2 C - @411
v integral 32 'h5
s integral 32 'h10
myaa aa(string,string) 3 -
[bar] string 3 bye
[foo] string 2 hi
[foobar] string 5 howdy
debug integral 1 'h1
inst2 B - @391
u1 C - @431
v integral 32 'ha
s integral 32 'h0
myaa aa(string,string) 3 -
[bar] string 3 bye
[foo] string 2 hi
[foobar] string 5 howdy
debug integral 1 'h1
debug integral 1 'h1
二、代码分析
代码共5个文件,包括:top.sv,my_env_pkg.sv,classA.svh,classB.svh,classC.svh。下面分别介绍这5个文件的代码。
1、top.sv
module top;
import uvm_pkg::*;
import my_env_pkg::*;
my_env topenv;
initial begin
//set configuration prior to creating the environment
uvm_config_int::set(null, "topenv.*.u1", "v", 30);
uvm_config_int::set(null, "topenv.inst2.u1", "v", 10);
uvm_config_int::set(null, "*", "recording_detail", 0);
uvm_config_int::set(null, "*", "debug", 1);
uvm_config_string::set(null, "*", "myaa[foo]", "hi");
uvm_config_string::set(null, "*", "myaa[bar]", "bye");
uvm_config_string::set(null, "*", "myaa[foobar]", "howdy");
uvm_config_string::set(null, "topenv.inst1.u1", "myaa[foo]", "boo");
uvm_config_string::set(null, "topenv.inst1.u1", "myaa[foobar]", "boobah");
topenv = new("topenv", null);
run_test();
end
endmodule
这个文件主要实现顶层的例化,并通过config_db的set函数,往组件中传递参数。这里比较值得注意的是13到17行,实现关联数组的传递。
2、my_env_pkg.sv
package my_env_pkg;
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "classA.svh"
`include "classB.svh"
class my_env extends uvm_env;
bit debug = 0;
A inst1;
B inst2;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_int::set(this, "inst1.u2", "v", 5);
uvm_config_int::set(this, "inst2.u1", "v", 3);
uvm_config_int::set(this, "inst1.*", "s", 'h10);
$display("%s: In Build: debug = %0d", get_full_name(), debug);
inst1 = new("inst1", this);
inst2 = new("inst2", this);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
uvm_top.print_topology();
#10;
phase.drop_objection(this);
endtask
`uvm_component_utils_begin(my_env)
`uvm_field_int(debug, UVM_DEFAULT)
`uvm_component_utils_end
endclass
endpackage : my_env_pkg
这个文件主要是搭建仿真环境,环境中分别例化了A和B两个组件。
第17到27行,在build_phase中,通过config_db中的set函数,向A和B两个组件传递参数,这里的参数传递,和顶层的参数传递有重复,通过仿真结果可以看到,利用config_db中的set函数传递参数时,set函数所在的层级越高,越靠近uvm tree的根目录,优先级越高。
第29到34行,在run_phase中,利用uvm的objection机制,先打印整个UVM的树状结构,再保证仿真时间执行10ns。
第36到38行,利用uvm的field机制,将debug参数注册到uvm中,这个注册是省略config_db中get函数的关键。
要想省略get函数,必须满足以下几个条件:1、组件需要注册到UVM的工厂机制中,参考36行;2、参数需要通过field机制注册,参考37行;3、在set函数中,第三个参数必须要与变量中的名字一致。
满足上述的三个条件后,在build_phase中调用super.build_phase时,就会自动的执行get函数。
3、classA.svh
`ifndef CLASSA_SVH
`define CLASSA_SVH
`include "classC.svh"
class A extends uvm_component;
bit debug = 0;
C u1;
C u2;
`uvm_component_utils_begin(A)
`uvm_field_int(debug, UVM_DEFAULT)
`uvm_component_utils_end
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_int::set(this, "*", "v", 0);
$display("%s: In Build: debug = %0d", get_full_name(), debug);
u1 = new("u1", this);
u2 = new("u2", this);
endfunction
endclass
`endif
这个文件A中例化了两个C。第11到13行,将debug参数通过field机制进行注册;第18到26行,调用set函数设置C中的参数v,这个set函数优先级最低,同样的会被顶层的set函数覆盖;
4、classB.svh
`ifndef CLASSB_SVH
`define CLASSB_SVH
`include "classC.svh"
class B extends uvm_component;
bit debug = 0;
C u1;
`uvm_component_utils_begin(B)
`uvm_field_int(debug, UVM_DEFAULT)
`uvm_component_utils_end
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_int::set(this, "u1", "v", 0);
$display("%s: In Build: debug = %0d", get_full_name(), debug);
u1 = new("u1", this);
endfunction
endclass
`endif
这个文件B中例化了一个C。其他的代码基本与A一致。
5、classC.svh
`ifndef CLASSC_SVH
`define CLASSC_SVH
class C extends uvm_component;
int v=0;
int s=0;
string myaa[string];
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
$display("%s: In Build: v = %0d s = %0d", get_full_name(), v, s);
endfunction
`uvm_component_utils_begin(C)
`uvm_field_int(v, UVM_DEFAULT)
`uvm_field_int(s, UVM_DEFAULT)
`uvm_field_aa_string_string(myaa, UVM_DEFAULT)
`uvm_component_utils_end
endclass
`endif
这个文件C中,定义了两个整型变量v和s,还定义了一个字符串关联数组myaa。
重点是:在18到22行,准备好了省略get函数的三个条件,在14行调用super.build_phase(phase)自动执行get函数。
总结
通过这个测试用例可以学习到,1、如何省略config_db中的get函数;2、当有多个set函数向同一个参数传递数据时,如何判断哪个set函数优先级更高。
1、如何省略config_db中的get函数
必须满足三个条件:1)组件需要注册到UVM的工厂机制中;2)参数需要通过field机制注册;3)在set函数中,第三个参数必须要与变量中的名字一致。满足上述的三个条件后,在build_phase中调用super.build_phase时,就会自动的执行get函数。
2、如何判断哪个set函数优先级更高
越靠近UVM根节点的组件拥有的set函数优先级更高。set函数执行的过程是,先执行低优先级的set函数,再执行高优先级的set函数。在这个例子中,top.sv中的set函数优先级最高。