config_db机制

config_db机制用于在UVM验证平台间传递参数。uvm_config_db#()是一个参数化的类,其参数就是要寄信的类型。uvm_config_db#( )::set(, , ,)和uvm_config_db#( )::get(, , ,)成对出现,这两个函数都是静态函数要使用::方式调用。

部分情况get可省略,field automation机制与uvm_component机制的结合,收信的component使用uvm_component_utils宏注册,build_phase阶段调用super.build_phase,要传递给的变量使用uvm_field注册。常见的枚举类型、virtual interface、bit类 型、队列等都可以成为config_db设置的数据类型。

uvm_config_db#( )::set(, , ,)有4个参数,其中第一个和第二个参数联合起来组成目标路径,与此路径符合的目标才能收信。第一个参数必须是一个uvm_component实例的指针,第二个参数是相对此实例的路径。第三个参数表示一个记号,用以说明这个值是传给目标中的哪个成员的,第四个参 数是要设置的值即实际传递的对象。set的前两个参数组成了收信的对象,和要传递的参数

get函数的第一个参数和第二个参数联合起来组成路径。第一个参数也必须是一个uvm_component实例的指针,第二个参数是相对此实例的路径。一般的,如果第一个参数被设置为this,那么第二个参数可以是一个空的字符串。第三个参数就是set函数 中的第三个参数,set和get的这两个参数必须严格匹配,第四个参数则是要设置的变量。get的第三个和第四个参数建议保持一致,但可以不一致。第四个参数是将get到的值赋值给哪个变量,即第四个参数是实际存在的,第三个随意起,只要set和get保持一致,作为值的载体而传递。

config_db::set哪些?virtual_intf,cfg类(env_cfg、agt_cfg、scb_cfg、refm_cfg...seq_cfg)、reg_model、default_seq。

在tb_top中run_test(my_driver),传递virtual_intf到driver。在driver中get virtual_intf。my_if是定义的intf,input_if是my_if声明的对象。在driver中不能直接使用intf,只能使用virtual intf。

class my_driver extends uvm_driver;


virtual my_if vif;

44 initial begin
45 uvm_config_db#(virtual my_if)::set(null, "uvm_test_top", "vif", input_if);
46 end

13 virtual function void build_phase(uvm_phase phase);
14 super.build_phase(phase);
15 `uvm_info("my_driver", "build_phase is called", UVM_LOW);
59
16 if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
17 `uvm_fatal("my_driver", "virtual interface must be set for vif!!!")
18 endfunction

uvm树形结构。在top_tb中设置virtual interface时,由于top_tb不是一个类,无法使用this指针,所以设置set的第一个参数为null,第二个参数使用绝对路径uvm_test_top.xxx。

在env中设置seq_cfg:uvm_config_db(seq_cfg)::set(this,$sformatf(“mo_env.mo_agent.*”),“mo_seq_cfg”,mo_seq_cfg)。其中第二个参数很奇怪,用了$sformatf和通配符*,其原因是要向seq传递seq_cfg,seq不属于component类,因此到了agent下无法传递agent.seq,后边使用了个通配符。

在UVM中使用get_full_name()可以得到一个component的完整路径,同样的,此函数也可以在一个sequence中被调用,在一个sequence的body中调用此函数,并打印出返回值,其结果大体如下: uvm_test_top.env.i_agt.sqr.case0_sequence。这个路径是由两个部分组成:此sequence的sequencer的路径,及实例化此sequence时传递的名字。因此,可以使用如下的方式 为一个sequence传递参数:

43 function void my_case0::build_phase(uvm_phase phase);
…
46 uvm_config_db#(int)::set(this, "env.i_agt.sqr.*", "count", 9);
…
52 endfunction

 set函数的第二个路径参数里面出现了通配符,这是因为sequence在实例化时名字一般是不固定的,而且有时是未知的(比如 使用default_sequence启动的sequence的名字就是未知的),所以使用通配符。

在sequence中以如下的方式调用config_db::get函数:

3 class case0_sequence extends uvm_sequence #(my_transaction);
…
11 virtual task pre_body();
12 if(uvm_config_db#(int)::get(null, get_full_name(), "count", count))
13 `uvm_info("seq0", $sformatf("get count value %0d via config_db", count), UVM_MEDIUM)
14 else
15 `uvm_error("seq0", "can't get count value!")
16 endtask
…
30 endclass

在get函数原型中,第一个参数必须是一个component,而sequence不是一个component, 所以这里不能使用this指针,只能使用null或者uvm_root::get()。前文已经提过,当使用null时,UVM会自动将其替换为 uvm_root::get(),再加上第二个参数get_full_name(),就可以完整地得到此sequence的路径,从而得到参数。

设置agent是active或passive。

class my_env extends uvm_env;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(uvm_active_passive_enum)::set(this, "i_agt", "is_active", UVM_ACTIVE);
uvm_config_db#(uvm_active_passive_enum)::set(this, "o_agt", "is_active", UVM_PASSIVE);
i_agt = my_agent::type_id::create("i_agt", this);
o_agt = my_agent::type_id::create("o_agt", this);
endfunction
endclass

 设置default_seq。config_db的参数类型规定为uvm_object_wrapper,第二个参数要到哪个seqr的哪个phase,第三个参数则是default_seq,第四个参数实际传递的对象。

virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
   uvm_config_db#(uvm_object_wrapper)::set(this,"agt.sqr.main_phase","default_seq",
     my_sequence::type_id::get());
endfunction

 type_id::get做了什么事情呢?

定义了宏uvm_object_registry,带两个参数T、S。

给这个宏起个别名,叫type_id

定义静态函数get_type返回type_id::get

`define uvm_object_registry(T,S) \
   typedef uvm_object_registry#(T,S) type_id; \
   static function type_id get_type(); \
     return type_id::get(); \
   endfunction \
   virtual function uvm_object_wrapper get_object_type(); \
     return type_id::get(); \
   endfunction 

在tb_top中,其层次化结构是tb_top.duv.module...,使用run_test创建的实例化对象uvm_test_top及下属的各component不属于上边的层次结构,在用verdi打开代码时也看不到验证代码的各component层次代码,只能看到intf,因为intf属于tb_top。所以使用config_db将intf从tb传递到某个component实际是两个跨层次结构的传输。除了virtual_intf,将seq_cfg传递给seq,seq_cfg和seq也不属于component,通过使用通配符和get_full_name 解决了路径层次问题。

非直线设置set,有一定风险,未知的component build_phase顺序。非直线获取get,可以有效减少对同一个参数的多次set到不同component,减小出错的可能,易于维护。

config_db机制类似一个桥梁,区别普通的层次路径,能够跨越障碍使命必达。

本文章参考《UVM实战》、《芯片验证漫游指南》等资料整理而成,仅作学习心得交流,如果涉及侵权烦请请告知,我将第一时间处理。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值