uvm_config_db在UVM验证环境中的应用

如何在有效的使用uvm_config_db来搭建uvm验证环境对于许多验证团队来说仍然是一个挑战。一些验证团队完全避免使用它,这样就不能够有效利用它带来的好处;另一些验证团队却过多的使用它,这让验证环境变得不稳定。

本文讨论如何简单有效平衡的在验证环境中使用uvm_config_db,让它验证环境贡献最多的力量,却又不会成为验证环境搭建的累赘。

接下来=通过三部分来进行阐述:

  1. uvm_config_db的使用方法

  2. uvm_config_db的作用对象

  3. uvm_config_db的具体应用

第一部分:uvm_config_db的使用方法

uvm_config_db作用是把验证环境的一些资源配置为类似全局变量一样,使得它对于整个验证环境来说是可见的。最常见的是在验证环境顶层通过它对一些组件进行配置,组件可以在建立的阶段读取这些配置实现组件不同工作模式的切换,下面是使用uvm_config_db的语法:

uvm_config_db#(T)::set(uvm_component cntxt, string inst_name, string field_name,      T value);

uvm_config_db#(T)::get(uvm_component cntxt, string inst_name, string field_name, ref T value);

例子:

uvm_config_db#(virtual my_if)::set(null, "uvm_test_top", "vif", input_if)

uvm_config_db#(virtual my_if)::get(this,                     "", "vif",        vif)

在以上两个函数set和get是使用它时要调用的函数,set表示把要处理的资源放进全局可见的数据库,get表示从全局可见的数据库输出需要的资源,使用set和get函数时有五个参数需要制定,第一个是uvm_config_db类的参数#(T),T表示要set或get的资源的类型,它可以是虚拟接口,sequencer等等,第二个cntxt和第三个参数inst_name一起定义了uvm_config_db中set或get函数的作用范围。第四个参数决定了是对作用范围中的哪个对象或变量进行操作,第五个参数value会存储当前操作对象的句柄或者操作变量的值。需要注意的是,当制定第二个参数是一个uvm组件时,uvm会用它的全局名字取替换它,而全局名字会通过uvm的get_full_name来获取。

第二部分:uvm_config_db的作用对象

在uvm验证环境中并不是所有的资源我们都会用uvm_config_db去配置,这样会让我们的验证环境变得不可维护,下面是一些典型的在验证环境中使用uvm_config_db去配置的资源:

  • 虚拟接口,虚拟接口提供了一个访问真实虚接口的入口,我们会把虚拟接口的句柄放到全局的数据库中,uvm中的这些组件会通过get函数拿到虚拟接口的句柄对接口数据进行操作。

  • 配置数据,负责配置环境的类中包含许多可以控制验证环境的变量,它会改变这些变量,并且通过set函数把它放到我们全局的数据库中,其他的组件通过get函数来取到这些变量的值,再根据这些值去改变工作模式

  • sequencers,在uvm中sequencers负责把我们写的sequence进行排队送到driver上去,所以sequence需要有对sequencer的访问入口,我们同样通过uvm_config_db的方式来把sequencer的句柄传给sequence

 第三部分:uvm_config_db的具体应用

上图是我们的一个设计实例,下面介绍针对上图的实例我们应该如何使用uvm_config_db,首先我们把上图中可以配置的资源用一张更清晰的表列出来,如下:

在上面的表中,一共有四列,分别列出了五个接口的描述,类型,传送的数据类型以及它们自己唯一性的名字,下面把它对应到uvm_config_db的调用函数set和get中。

对于第二列type类型,我们会把它放入uvm_config_db的第一个参数#(T)的位置,表示处理的数据类型是axi_if,如下:

uvm_config_db#(virtual vif axi_if)::get(...

uvm_config_db#(virtual vif axi_if)::set(..

而对于第三列,transaction是在配置sequencer时需要制定的传送类型,然后再把sequencer放到全局数据库中去,如下:

typedef uvm_sequencer#(axi_transaction) axi_sequencer_t;

uvm_config_db#(axi_sequencer_t)::set(...

uvm_config_db#(axi_sequencer_t)::get(...

对于identifier这一列会被放在前面语法解析部分中的inst_name部分,这一列的名字要求是唯一的,但是如果接口或者sequencer的类型不同,则允许重复,例如如果都是axi_if类型,那么要求名字必须具有唯一性,因为它们处于同一个数据库(axi_if数据库)中,而如果一个类型是ahb_if,另一个是axi_if,则不要求唯一性,因为它们处于不同数据库的区域中。

typedef uvm_sequencer#(axi_transaction) axi_sequencer_t;

uvm_config_db#(   virtual axi_if   )::set(cntxt, inst_name, "primary_master",...

uvm_config_db#(axi_sequencer_t)::set(cntxt, inst_name, "primary_master",...

uvm_config_db#(   virtual axi_if   )::get(cntxt, inst_name, "primary_master",...

uvm_config_db#(axi_sequencer_t)::get(cntxt, inst_name, "primary_master",...

上面为了能够更清楚的展示细节,所有的identifier都是用字符串,但在实际项目中为了以后的复用,我们会考虑定义一个package文件,把所有的identifier都用一个全局变量代替,这样方便以后维护,具体如下图:

// In a test level parameters package

// This code defines the unique string used to identify each interface in the resource database

// A parameter is used to eliminate runtime errors due to typing errors.

parameter string PRIMARY_MASTER = "primary_master";

parameter string SECONDARY_MASTER = "secondary_master";

parameter string CONFIG_MASTER = "config_master";

parameter string MEMORY_SLAVE = "memory_slave";

parameter string PERIPHERAL_SLAVE = "peripheral_salve";

配置interface到全局数据库

// In the module where the interfaces reside

uvm_config_db#(virtual axi_if)::set(null, "VIRTUAL_INTERFACES", PRIMARY_MASTERS, primary_axi_master_bus);

uvm_config_db#(virtual axi_if)::set(null, "VIRTUAL_INTERFACES", SECONDARY_MASTER, secondary_axi_master_bus);

uvm_config_db#(virtual apb_if)::set(null, "VIRTUAL_INTERFACES", CONFIG_MASTER, config_apb_master_bus);

uvm_config_db#(virtual axi_if)::set(null, "VIRTUAL_INTERFACES", MEMORY_SLAVE, axi_memory_slave_bus);

uvm_config_db#(virtual ahb_if)::set(null, "VIRTUAL_INTERFACES", PERIPHERAL_SALVE, peripheral_ahb_slave_bus);

配置sequencer为默认sequencer

//In the agents class declaration file

//Each protocol would have its own agent class: axi_agent, apb_agent, etc.

//For this example xxx represent axi,apb or ahb

class xxx_agent extends uvm_agent #(...

//This variable is a handle to thihs agents configuration class

xxx_configuration xxx_config;

 

function void build_phase(uvm_phase phase);

//Get this agents configuration

uvm_config_db#(xxx_configuration)::get(this, "", "AGENT_CONFIG", xxx_config);

...

//Place this agents sequencer in the uvm_config_db using the interface identifier

uvm_config_db#(uvm_sequencer #(xxx_transaction))::set(null, "SEQUENCERS", xxx_config.interface_name, xxx_sequencer);

配置发送数据波形可见

总结

本篇论文详细介绍了uvm_config_db在uvm验证环境中的应用(interface,config,sequencer),它的使用可以极大的方便我们对一些需要全局可见的变量或类的处理,让我们能够更容易的去管理验证环境中的一些组件,也在一定程度上方便了构建测试激励的验证人员,他们无须关注验证环境的细节便可以构建测试场景对设计行为进行验证

 

转载于:https://www.cnblogs.com/YINBin/p/6833533.html

<think>好的,我现在需要处理用户关于UVM框架中uvm_config_db的使用方法和最佳实践的问题。首先,我得回顾一下用户提供的引用内容,确保回答准确。 用户引用了几个关于uvm_config_dbuvm_resource_db区别的资料,其中提到uvm_config_db主要用于组件间配置传递,而uvm_resource_db更全局。同时,用户提供的示例中有在sequence中使用config_db::get的代码,这可能是用户关心的一个点。另外,用户的问题明确询问使用方法和最佳实践,所以需要结构化的回答,可能包括基本概念、示例、使用场景、注意事项等。 首先,我需要解释uvm_config_db的基本机制,如set和get方法。根据引用4,config_db机制用于组件间高效通信和参数传递,这对验证平台的灵活性很重要。接着,需要给出典型的使用示例,比如在test层设置参数,在env或component中获取,可能引用用户提供的case0_sequence的例子(引用3),说明如何在sequence中使用get方法。 然后,关于最佳实践,引用5提到优先使用uvm_config_db而非resource_db,因为后者缺乏层次支持。这点需要强调,避免用户误用。此外,注意事项部分应包括路径匹配规则(引用1提到正则匹配,涉及uvm_glob_to_re和uvm_re_match函数),类型一致性,作用域管理,以及调试技巧,比如检查返回值和使用uvm_info/error。 还要考虑用户可能的后续问题,比如性能分析、优化方法、应用场景,所以在相关问题部分可以建议这些方向。同时,确保回答符合中文,使用正确的LaTeX格式,比如变量用$...$,独立公式用$$...$$,但在这个问题中可能数学公式较少,但如果有变量如路径字符串可能需要用代码块或斜体。 最后,验证回答是否覆盖了用户的需求,是否有遗漏的关键点,比如优先级(引用2提到resource_db优先级更高,但config_db更推荐),数据类型处理,以及错误处理的实际代码示例。确保所有引用都被正确标注,比如在讨论set/get方法时引用4,路径匹配引用1,sequence示例引用3,最佳实践引用5和2。 现在需要组织这些信息,确保结构清晰,分点说明,并给出代码示例,帮助用户理解。同时,检查LaTeX格式是否正确,没有使用错误,例如变量用$...$,代码块用三个反引号包裹。此外,相关问题部分需要生成与uvm_config_db相关的深入问题,引导用户进一步学习。</think>### UVM框架中uvm_config_db使用方法与最佳实践 #### 一、uvm_config_db基本机制 `uvm_config_db` 是UVM中用于跨组件传递配置参数的核心机制,通过**层次化路径匹配**和**类型安全**实现数据共享[^4]。其核心操作包含: - `uvm_config_db#(T)::set()`:在某一上下文中设置配置值 - `uvm_config_db#(T)::get()`:在目标组件中获取配置值 #### 二、典型使用示例 1. **Test层设置参数** ```systemverilog // 在Test类中设置超时参数 class base_test extends uvm_test; virtual function void build_phase(uvm_phase phase); uvm_config_db#(int)::set(this, "env.agent*", "timeout", 100); endfunction endclass ``` 2. **Sequence获取参数** ```systemverilog // 在Sequence中获取参数(引用示例扩展) class case0_sequence extends uvm_sequence#(my_transaction); int count; virtual task pre_body(); if (!uvm_config_db#(int)::get(null, get_full_name(), "count", count)) `uvm_fatal("CFG_ERR", "Failed to get count parameter") // 更严格的错误处理 `uvm_info("SEQ", $sformatf("Count=%0d", count), UVM_MEDIUM) endtask endclass // [^3] ``` 3. **组件间传递接口** ```systemverilog // 传递虚拟接口示例 interface bus_if; logic [31:0] data; endinterface class env extends uvm_env; bus_if vif; virtual function void build_phase(uvm_phase phase); if (!uvm_config_db#(virtual bus_if)::get(this, "", "BUS_IF", vif)) `uvm_error("CFG_ERR", "Bus interface not found") endfunction endclass ``` #### 三、最佳实践建议 1. **路径匹配规则** - 使用`*`匹配任意层次(如`env.agent*.driver`) - 使用`?`匹配单个节点(如`agent?.monitor`) - 实际匹配通过`uvm_glob_to_re()`转换为正则表达式[^1] 2. **类型一致性** ```systemverilog // 错误示例:类型不匹配 uvm_config_db#(int)::set(null, "*", "data_size", 32'hff); // 正确应使用bit[31:0] ``` 3. **作用域管理** - 优先使用相对路径:`set(this, "sub_component", ...)` 而非全局路径 - 层次化设置优先级:低层次组件的设置会覆盖父级设置 4. **调试技巧** - 检查返回值:`if (!get(...))` 配合`uvm_error` - 启用UVM调试信息:`+UVM_CONFIG_DB_TRACE` #### 四、与uvm_resource_db对比 | 特性 | uvm_config_db | uvm_resource_db | |---------------------|-----------------------|-----------------------| | 作用范围 | 层次化作用域 | 全局作用域 | | 类型检查 | 强类型检查 | 允许类型转换 | | 推荐使用场景 | 组件间参数传递 | 全局资源管理 | | 优先级 | 低 | 高 | (根据[^2][^5]整理) #### 五、常见问题解决方案 1. **参数未找到错误** - 检查路径字符串是否包含`uvm_component::get_full_name()`的完整路径 - 使用`+UVM_CONFIG_DB_TRACE`编译选项查看配置流 2. **性能优化** - 避免在`build_phase`之外频繁调用`set/get` - 对高频访问参数使用缓存机制 3. **动态配置** ```systemverilog // 运行时动态更新配置 task run_phase(uvm_phase phase); #100ns; uvm_config_db#(int)::set(null, "env.agent", "packet_size", 256); endtask ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值