0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

UVM环境debug的正确开启方式

冬至子 来源:CSDN 作者:谷公子 2023-07-03 18:14 次阅读

在使用UVM搭建环境时,遇到问题时,调试方式有千千万万,但很有必要了解下UVM库提供了哪些内建的调试手段,可以少走弯路,大大提升效率,而不是疯狂加各种打印消息。

UVM库给各个主要机制都提供了易于使用的内置调试方法,来辅助定位使用UVM环境遇到的问题。

一、调试config_db机制问题

UVM库内实现了一个资源库,它用于存储配置信息,TB里各个组件可以根据情况使用config_db往里面存或者取各种类型数据。config_db存(set())和取(get())的关键在于字符串匹配,为此UVM库提供了一些功能来帮助调试这些字符串匹配。

1. 使用+UVM_CONFIG_DB_TRACE和+UVM_RESOURCE_DB_TRACE命令行参数

UVM库在Command Line上提供了+UVM_CONFIG_DB_TRACE和+UVM_RESOURCE_DB_TRACE命令行参数,当运行仿真命令时,如果带上上述的参数,那么在log中会打印出对资源库的存和取的信息。+UVM_CONFIG_DB_TRACE用于uvm_config_db进行的存取,+UVM_RESOURCE_DB_TRACE用于uvm_resource_db进行的存取。比如我们在Questasim工具的vsim命令后加上+UVM_CONFIG_DB_TRACE,然后有以下的uvm_config_db的set()和get()调用:

// In the TB env:
uvm_config_db #(int)::set(this, "*", "var", 666);
// In the TB driver:
int get_value;
if ( !uvm_config_db #(int)::get(this, "*", "var", get_value) ) begin
    `uvm_fatal(get_type_name(), "var is missing in config_db")
end else begin
    `uvm_info(get_type_name(), $sformatf("get var from env"), UVM_LOW)
end

那么在log中 可以找到以下打印信息:

UVM_INFO  …/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0.000ns: reporter 
// db类型                   匹配字符串               数据类型          路径                   数据值
[CFGDB/SET] Configuration 'uvm_test_top.env.*.var' (type int) set by uvm_test_top.env = (int) 666
UVM_INFO  …/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0.000ns: reporter [CFGDB/GET] Configuration 
'uvm_test_top.env.d_agent.drv_h.*.var' (type int) read by uvm_test_top.env.d_agent.drv_h = (int) 666

从log信息可以看出,UVM会把对资源库的set()和get()的数据类型,数据值、存取路径、存取类型和匹配字符都打印出来,这样就很方便我们去定位uvm_config_db的匹配问题了。

2. 调用UVM component内置函数

在uvm_component内部提供了print_config()内建函数,使用它可以打印出当前uvm_component范围可见的所有config_db操作内容。如果参数recurse为1,会把所有子components的可见的config_db操作内容也递归调用打印出来。如果audit为1,会把调用config_db进行操作的时间、次数和操作者路径也打印出来。print_config()的函数定义如下:

function void uvm_component::print_config(bit recurse = 0, audit = 0);

假如我们在之前例子的TB driver里调用:

print_config(.recurse(0), .audit(1));

那么将会有以下log输出:

#  var [/^uvm_test_top\\.env\\..*$/] : (int) 666   
# UVM_INFO .../uvm-1.2/src/base/uvm_resource.svh(564) @ 0.000ns: reporter [UVM/RESOURCE/ACCESSOR] 
uvm_test_top.env reads: 0 @ 0.000ns  writes: 1 @ 0.000ns
# uvm_test_top.env.d_agent.drv_h reads: 1 @ 0.000ns  writes: 0 @ 0.000ns

它会把TB driver上config_db操作的字符串匹配、数据类型和数据值都打印出来,另外,由于我们指定audit为1,因此也会把config_db操作的时间、次数和操作者路径打印出来了。这个一个很强大的debug功能。

建议可以在end_of_elaboration_phase里去调用这个函数,因为这时候config_db操作基本都已经完成了。

3. dump整个资源库

如果遇到奇怪的访问资源库问题无法解决,另一种暴力debug方式就是将整个资源库都打印出来。UVM提供了uvm_config_db #()::dump()函数,可以将当前资源库的信息都打印出来,其中可以指定任何类型,主要是因为dump()是个static的函数,提供任何类型最终访问的dump()函数是同一个,打印出的资源库信息也是一样的。

比如我们仍在TB driver里调用:

uvm_config_db #(bit)::dump();

在log里增加的信息将有:

# UVM_INFO .../uvm-1.2/src/base/uvm_resource.svh(1347) @ 0.000ns: reporter
 [UVM/RESOURCE/DUMP] 
# === resource pool ===
...
#  var [/^uvm_test_top\\.env\\..*$/] : (int) 666  
...
# UVM_INFO .../uvm-1.2/src/base/uvm_resource.svh(1354) @ 0.000ns: reporter

 [UVM/RESOURCE/DUMP] === end of resource pool ===

也是建议可以在end_of_elaboration_phase里去调用这个函数,因为这时候config_db操作基本都已经完成了。

结合上述的三个方法,可以说100%的config_db相关的问题都可以搞定了。

二、调试objection机制问题

Objection用于控制消耗时间的uvm_phase在何时结束,TB中raise和drop的objection次数要一样,但如果在多个地方进行raise或drop的话,遇到objection没有启动或无法结束时,就比较难调试了。因此,UVM库提供了用于跟踪objection raise和drop的命令行参数+UVM_OBJECTION_TRACE。

比如我们在Questasim工具的vsim命令后加上+UVM_OBJECTION_TRACE。那么log里将增加以下类似信息。

# UVM_INFO @ 0.000ns: run [OBJTN_TRC] Object uvm_test_top raised 1 objection(s) 
(START basetest): count=1  total=1
# UVM_INFO @ 0.000ns: run [OBJTN_TRC] Object uvm_top added 1 objection(s) to its 
total (raised from source object uvm_test_top, START basetest): count=0  total=1
...
# UVM_INFO @ 14190.000ns: run [OBJTN_TRC] Object uvm_test_top dropped 1 objection(s) 
(END basetest): count=0  total=0
# UVM_INFO @ 14190.000ns: run [OBJTN_TRC] Object uvm_test_top all_dropped 1 objection(s) 
(END basetest): count=0  total=0
# UVM_INFO @ 14190.000ns: run [OBJTN_TRC] Object uvm_top subtracted 1 objection(s) 
from its total (dropped from source object uvm_test_top, END basetest): count=0  total=0
# UVM_INFO @ 14190.000ns: run [OBJTN_TRC] Object uvm_top subtracted 1 objection(s) 
from its total (all_dropped from source object uvm_test_top, END basetest): count=0  total=0

三、调试phase机制问题

为了帮助用户查看各个uvm_phase在何时开始和结束,UVM库提供了+UVM_PHASE_TRACE命令行参数。

比如我们在Questasim工具的vsim命令后加上+UVM_PHASE_TRACE。那么log里将增加以下类似信息。

# UVM_INFO .../uvm-1.2/src/base/uvm_phase.svh(1620) @ 0.000ns: reporter [PH/TRC/DONE] 
Phase 'common.connect' (id=37) Completed phase
# UVM_INFO .../uvm-1.2/src/base/uvm_phase.svh(1655) @ 0.000ns: reporter [PH/TRC/SCHEDULED]
 Phase 'common.end_of_elaboration' (id=40) Scheduled from phase common.connect
# UVM_INFO .../uvm-1.2/src/base/uvm_phase.svh(1345) @ 0.000ns: reporter [PH/TRC/STRT] 
Phase 'common.end_of_elaboration' (id=40) Starting phase
# UVM_INFO .../uvm-1.2/src/base/uvm_phase.svh(1620) @ 0.000ns: reporter [PH/TRC/DONE] 
Phase 'common.end_of_elaboration' (id=40) Completed phase

四、调试factory机制问题

UVM库的factory机制用于创建对象,它是1个singleton对象,我们可以通过调用uvm_factory::get()获得它的句柄。当我们对factory机制创建的对象有疑问时,可以使用factory机制提供的函数去调试有谁注册了factory,factory override机制覆盖了谁,最终factory为给定类型返回什么对象。Factory机制提供了3个函数去辅助debug。

1. print()

这个函数会根据参数all_types的不同,打印出当前factory中注册的类型、实例覆盖和类型覆盖。它的定义为:

function void print (int all_types=1);
比如我们仍在TB driver中使用以下代码:

uvm_factory f = uvm_factory::get();
f.print();

那么输出log将增加以下类似信息:

#### Factory Configuration (*)
# 
#   No instance overrides are registered with this factory
#
#   Requested Type  Override Type
#   --------------  -------------
#   seq_base    seq1
#
# All types registered with the factory: 288 total
#   Type Name
#   ---------
    
#   ...
 
# (*) Types with no associated type name will be printed as < unknown >

从log中可以很清楚的看出,factory注册了多少类型,类型之间的override关系,instance之间的override关系,基本上factory的问题看这个信息都可以搞定了。

2. debug_create_by_type()和debug_create_by_name()

这两个函数对factory的搜索算法类似于create_ by_type()和create _by_type(),但它们不创建新对象。相反,它们提供了关于将返回的对象类型的详细信息,和列出了override相关信息。具体传递参数用法,大家可以查询UVM手册。

总结上面的三个方法,不管有没有factory问题,推荐统一都在TB base testcase的end_of_elaboration_phase里调用factory的print()函数,方便大家查询。

五、调试TLM 问题

UVM中的组件是通过TLM ports/exports/imps连接在一起的。UVM提供了两个函数都可以在port/export/imp上使用,可以帮助用户理解哪些对象连接在一起的。这两个函数是get_connected_to()和get_provided_to(),这两个函数返回的是uvm_port_component_base类型的关联数组。TLM ports通常是fanout类型的,所以它通常会使用get_connected_to(),TLM exports/imps通常是fanin类型的,所以它一般会使用get_provided_to()。

在IEEE 1800.2中,增加了debug_connected_to() 和debug_provided_to(),它们的功能与上述两个函数其实一样,只不过它们返回的是可视化文本消息,方便用户查看。个人比较推荐使用这两个函数。

这四个函数的定义如下:

function void get_connected_to (ref uvm_port_list list);
function void get_provided_to (ref uvm_port_list list);
function void debug_connected_to (int level=0, int max_level=-1);
function void debug_provided_to  (int level=0, int max_level=-1);

这些函数需要在end_of_elaboration_phase里或之后调用,由于这时候TLM的port连接才完成了。

六、调试callback问题

Callback允许标准对象的外部对象上调用函数和任务,来扩展额外的功能。如果在UVM TB中使用callback功能,可以调用uvm_typed_callbacks#(type T=uvm_object)里的display()函数打印出当前注册的所有callback。display()函数定义如下:

static function void display( T obj = null )

这个函数也是需要在end_of_elaboration_phase里调用,而且它是静态类型的,可以使用uvm_callbacks(xxx)::display()方式使用。

UVM也给callback的调试增加了+define+UVM_CB_TRACE_ON编译选项,当编译带上UVM_CB_TRACE_ON宏时,在log会也会打印出callback的跟踪信息。

七、其它调试方式**

1.打印UVM层次结构

在UVM环境搭建后之后,我们可以通过print_topology()函数将UVM层次结构打印出来。

比如我们在TB里以下任一种方法代码:

// 方法1:
uvm_top.print_topology();   // 需要UVM hierarchy建立之后调用
// 方法2:
uvm_top.enable_print_topology = 1;  // 在end_of_elaboration phase之前调用

在log中会出现以” [UVMTOP] UVM testbench topology:”开头的打印信息,里面详细列出了当前UVM结构。

2. uvm_info打印控制

在UVM中,可以指定verbosity来有选择性的打印出uvm_info里的消息。UVM提供了全局式和分布式的控制方法。

全局式:这种控制方法是使用+UVM_VERBOSITY命令行参数来完成的。

分布式:这种控制方法是使用每个组件自带的verbosity设置方法完成的,通过使用+uvm_set_verbosity命令行参数。当然也可以直接在组件里使用set_report_verbosity_level()等方法设置的。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • UVM
    UVM
    +关注

    关注

    0

    文章

    181

    浏览量

    19146
  • TLM
    TLM
    +关注

    关注

    1

    文章

    32

    浏览量

    24741
收藏 人收藏

    评论

    相关推荐

    IC验证之UVM常用宏汇总分析(四)

    OVM中过时的用法,使用纯净的UVM环境:`define UVM_NO_DEPRECATED除了上述通用的宏外,针对不同的仿真工具需要定义不同的宏:QUESTA、VCS、INCA分别对应Mentor
    发表于 12-02 15:24

    什么是uvmuvm的特点有哪些呢

    大家好,我是一哥,上章内容我们介绍什么是uvmuvm的特点以及uvm为用户提供了哪些资源?本章内容我们来看一看一个典型的uvm验证平台应该是什么样子的,来看一个典型的
    发表于 02-14 06:46

    UVM sequence分层有哪几种方式

    验证环境需要对数据进行分层。例如,将32比特的寄存器读写封装成数据读写和状态读写等实际业务操作等或者对底层sequence进行一些随机控制等。实现这种分层可以有两种方式:1、Sequence
    发表于 04-11 16:37

    如何构建UVM寄存器模型并将寄存器模型集成到验证环境

    ),通常也叫寄存器模型,顾名思义就是对寄存器这个部件的建模。本文要介绍的内容,包括对UVM寄存器模型的概述,如何构建寄存器模型,以及如何将寄存器模型集成到验证环境中。篇幅原因,将在下一篇文章再给出寄存器
    发表于 09-23 14:29

    谈谈UVM中的uvm_info打印

    ,  UVM_FULL = 400,  UVM_DEBUG = 500  } uvm_verbosity;  2. uvm_report_enabled(xxx)函数上有个
    发表于 03-17 16:41

    一种基于UVM的混合信号验证环境

    一种基于UVM的混合信号验证环境_耿睿
    发表于 01-07 21:39 1次下载

    利用Systemverilog+UVM搭建soc验证环境

    利用Systemverilog+UVM搭建soc验证环境
    发表于 08-08 14:35 5次下载

    如何优雅地结束UVM Test

    分享一下在UVM验证环境中,结束仿真的几种方式,不同结束仿真的方式适合不同的应用场景。
    的头像 发表于 12-17 11:23 2546次阅读
    如何优雅地结束<b class='flag-5'>UVM</b> Test

    Easier UVM Code Generator Part 4:生成层次化的验证环境

    本文使用Easier UVM Code Generator生成包含多个agent和interface的uvm验证环境
    的头像 发表于 06-06 09:13 1113次阅读

    UVM里的6个常见参数介绍分析

    UVM预先定义了六个详细程度; UVM_NONE到UVM_DEBUG。这些级别只不过是整数枚举值
    的头像 发表于 06-06 12:33 4200次阅读
    <b class='flag-5'>UVM</b>里的6个常见参数介绍分析

    基于UVM验证环境开发测试流程

    验证环境用户需要创建许多测试用例来验证一个DUT的功能是否正确,验证环境开发者应该通过以下方式提高测试用例的开发效率
    的头像 发表于 06-09 11:11 950次阅读
    基于<b class='flag-5'>UVM</b>验证<b class='flag-5'>环境</b>开发测试流程

    如何用Verdi查看UVM环境中的变量?

    我们常用的debug UVM的方法是通过打印log实现。有没有办法像 debug RTL代码一样将 UVM 中变量拉到波形上看呢?答案是有的,下面让我们看看是怎么做到的。
    的头像 发表于 06-25 16:01 1672次阅读
    如何用Verdi查看<b class='flag-5'>UVM</b><b class='flag-5'>环境</b>中的变量?

    有没有办法像debug RTL代码一样将UVM中变量拉到波形上看呢?

    我们常用的debug UVM的方法是通过打印log实现。有没有办法像 debug RTL代码一样将 UVM 中变量拉到波形上看呢?答案是有的,下面让我们看看是怎么做到的。
    的头像 发表于 06-29 15:14 1473次阅读
    有没有办法像<b class='flag-5'>debug</b> RTL代码一样将<b class='flag-5'>UVM</b>中变量拉到波形上看呢?

    UVM设计中的sequence启动方式有哪几种呢?

    本篇介绍UVM中的sequence,这是UVM中最基础的部分。对于前面介绍的uvm_callback, uvm_visitor等,很少被使用到或者也只有搭建平台的人会使用。
    的头像 发表于 08-17 10:07 4060次阅读
    <b class='flag-5'>UVM</b>设计中的sequence启动<b class='flag-5'>方式</b>有哪几种呢?

    为什么需要debug时钟频率 Debug时钟频率原理详解

    在芯片设计中,为了便于定位故障,有时候需要确认部分时钟频率是否正确,需要部分debug手段。常见的方式是:将时钟信号引到芯片管脚,通过仪器测量。这类方式必须要测量仪器,并且需要熟练使用
    的头像 发表于 09-20 14:17 820次阅读
    为什么需要<b class='flag-5'>debug</b>时钟频率 <b class='flag-5'>Debug</b>时钟频率原理详解