UVM验证方法学_打印信息控制

仿真过程中可能会出现各种各样的问题,查看所打印的log是debug过程很重要的一个环节。环境中的信息有很多,对打印信息的合理控制有助于我们快速定位问题,过滤掉我们不想看到的冗余信息。除此之外,我们还可以根据打印的信息对整个环境进行反馈控制,让我们可以实时地掌控整个环境的状态,让仿真过程更加顺利,产生我们所期望的结果。


一、设置冗余度

uvm通过冗余度级别的设置提高了仿真日志的可读性,让我们可以专注于我们想看到的信息。

在打印信息之前,uvm会比较要显示信息的冗余度级别与默认的冗余度阈值,如果小于等于阈值,就会显示,否则不会显示。默认的冗余度阈值是UVM_MEDIUM,所有低于等于UVM_MEDIUM的信息都会被打印出来。

uvm的信息级别:

UVM_NONE   = 0,
UVM_LOW    = 100,
UVM_MEDIUM = 200,
UVM_HIGH   = 300,
UVM_FULL   = 400,
UVM_DEBUG  = 500

UVM_NONE的级别最低,UVM_DEBUG的级别最高。一般UVM_LOW,UVM_MEDIUM,UVM_HIGH会比较常用,基本会在这三个中进行选择。可以通过get_report_verbosity_level函数得到某个component的冗余度阈值,函数所返回的就是每个级别的阈值数。

uvm提供set_report_verbosity_level函数来设置某个特定component的默认冗余度阈值。设置完后,所有低于等于该阈值的信息都会被打印。

如果牵扯到层次引用,则需要在connect_phase及以后的phase才能调用这个函数。如果不牵扯到任何层次引用,如设置当前component的冗余度阈值,那么可以在connect_phase之前调用。

以异步FIFO为例,例如在wr_driver的main_phase中进行设置

    task wr_driver::main_phase(uvm_phase phase);
        int cnt;
        super.main_phase(phase);
        this.set_report_verbosity_level(UVM_HIGH);
        $display("wr_driver verbosity level is %0d.",this.get_report_verbosity_level());

        ...

打印结果

wr_driver verbosity level is 300.

set_report_verbosity_level只对某个特定的component起作用,uvm还提供了递归的设置函数set_report_verbosity_level_hier,可以用在agent或者env中,会把其下所有的component的冗余度阈值进行设置。

在env的build_phase进行设置:

   function void env::build_phase(uvm_phase phase);
       super.build_phase(phase);
       ...

       this.wr_agt.set_report_verbosity_level_hier(UVM_FULL);
   endfunction

观察wr_agent下每个组件的阈值级别,都已经更改。

wr_driver verbosity level is 400.
wr_sequencer verbosity level is 400.
wr_agent verbosity level is 400.
wr_monitor verbosity level is 400.

除了在代码中设置外,uvm也支持在仿真命令行中设置冗余度阈值,同样可以添加至Makefile中。

<sim command> +UVM_VERBOSITY=UVM_HIGH
<sim command> +UVM_VERBOSITY=HIGH

这两个命令行参数是等价的,即可以把冗余度级别的前缀“UVM_”省略。

这个命令行参数会把整个环境的冗余度阈值设置为UVM_HIGH,相当于是在base_test中调用set_report_verbosity_level_hier函数,把testcase及以下所有component的冗余度级别设置为UVM_HIGH。

通过设置不同env的冗余度级别,可以更好地控制整个验证环境输出信息的质量,避免产生过多不需要的信息。

二、重载打印的严重性设置

重载是uvm中很重要的特性之一,对于仿真过程,uvm默认有四种信息严重性:UVM_INFO、UVM_WARNING、UVM_ERROR、UVM_FATAL。

只有UVM_INFO需要加上第三个参数来指示阈值级别(一般为UVM_LOW或者UVM_MEDIUM),其他三种不需要第三个参数。

这四种严重性可以互相重载。

set_report_severity_override(UVM_WARNING, UVM_ERROR);
// UVM_WARNING重载为UVM_ERROR

重载严重性也可以只针对某个component内的某个特定的ID起作用,使用set_report_severity_id_override函数。

set_report_severity_id_override(UVM_WARNING, "rd_driver", UVM_ERROR);

与设置冗余度不同,uvm并不提供递归的严重性重载函数。严重性重载用的较少,一般的只会对某个component内使用,而不会递归的使用。

同样的,重载严重性也可以在仿真命令行中实现,或者加入Makefile。

<sim command> +uvm_set_severity=<comp>,<id>,<current severity>,<new severity>

三、UVM_ERROR达到一定数量结束仿真

uvm_fatal出现时,仿真会马上停止,表示环境中已经出现了致命错误,需要马上检查。uvm同样支持UVM_ERROR达到一定数量时结束仿真。如果出现了大量的UVM_ERROR,根据这些错误已经可以确定bug所在了,再继续仿真下去意义已经不大,此时就可以结束仿真,而不必等到所有的objection被撤销。

需要调用set_report_max_quit_count函数,可以在任意phase设置:

set_report_max_quit_count(3);

这样当出现了3个UVM_ERROR时,仿真就会自动退出。与set_max_quit_count相对应的是get_max_quit_count函数,可以用于查询当前的退出阈值,如果函数返回值为0则表示无论出现多少个UVM_ERROR都不会退出仿真。

当然,除了在代码中使用set_max_quit_count设置外,还可以在仿真命令行中设置退出阈值,同样也可以加入到Makefile当中。

<sim command> +UVM_MAX_QUIT_COUNT=5,NO

参数5表示退出阈值,第二个参数NO表示此值不可以被后面的设置语句重载,也可以是YES。

四、计数设置

(1)严重性计数

UVM_ERROR达到一定数量时可以自动退出仿真,但是在计数当中默认是不包含UVM_WARNING的。不过,我们可以通过设置set_report_severity_action函数来把UVM_WARNING加入计数目标。

set_report_max_quit_count(5);
this.wr_agt.set_report_severity_action(UVM_WARNING, UVM_DISPLAY|UVM_COUNT);

设置了显示并计数。set_report_severity_action也有相应的递归调用方式:

set_report_severity_action_hier(UVM_WARNING, UVM_DISPLAY| UVM_COUNT);

set_report_severity_action函数以及set_report_severity_action_hier函数的第一个参数除了可以是UVM_WARNING外,还可以是UVM_INFO和UVM_ERROR。不过在默认情况下,UVM_ERROR就已经加入了计数。如果不需要,我们也可以把其从统计计数目标中移除,例如:

set_report_severity_action(UVM_ERROR, UVM_DISPLAY);

这种或关系很类似field_automation机制,如果不需要此功能则相应地从或关系中移除。

(2)特定ID计数

除了针对严重性进行计数外,还可以对某个特定的ID进行计数,以监测特定的组件:

set_report_id_action("rd_drv", UVM_DISPLAY| UVM_COUNT);

该函数会把UVM_INFO,UVM_WARNING,UVM_ERROR,UVM_FATAL地所有信息都加入到计数中。

该函数同样有其递归调用方式:

fifo_env.rd_agt.set_report_id_action_hier("rd_drv", UVM_DISPLAY| UVM_COUNT);

(3)严重性和ID联合计数

除了分别对严重性和ID进行设置计数外,也可以把它们联合起来进行设置

set_report_severity_id_action(UVM_WARNING, "rd_driver", UVM_DISPLAY| UVM_COUNT);

此时指定了计数ID为rd_driver,同时严重性设置为UVM_WARNING,进行计数。

同样也有其递归调用函数:

set_report_severity_id_action_hier(UVM_WARNING, "rd_driver", UVM_DISPLAY| UVM_COUNT);

除此之外,uvm也支持在命令行中设置计数目标,设置方式为

<sim command> +uvm_set_action=<comp>,<id>,<severity>,<action>

// 具体例子如:
<sim command> +uvm_set_action="uvm_test_top.fifo_env.rd_agt.drv,rd_driver,UVM_WARNING,UVM_DISPLAY|UVM_COUNT"

若要针对所有的ID设置,可以使用_ALL_代替ID:

<sim command> +uvm_set_action="uvm_test_top.fifo_env.rd_agt.drv,_ALL_,UVM_WARNING,UVM_DISPLAY|UVM_COUNT"

五、仿真断点

调试程序时断点功能是非常有用的一个功能,在程序运行时预先在某语句处设置一断点,当程序执行到此处时停止仿真,进入交互模式,从而进行调试。断点功能需要从仿真器的角度进行设置,不过不同仿真器的设置方式不同。所以为了消除这些设置方式的不同,uvm支持内建的断点功能,当执行到断点时会自动停止仿真,进入交互模式。

例如在异步FIFO中,在rd_driver的main_phase中进行设置:

            if(cnt == 30)begin
                    `uvm_warning(this.name,"severity action test.")
            end

循环到第30个包的时候上报一个UVM_WARNING。在testcase当中设置断点:

   function void tc_sanity::connect_phase(uvm_phase phase);
        super.connect_phase(phase);

        ...
        this.fifo_env.rd_agt.drv.set_report_severity_action(UVM_WARNING, UVM_DISPLAY| UVM_STOP);
    endfunction

使用set_report_severity_action函数,当出现UVM_WARNING时即停止仿真,进入交互模式。

-------------------------------------------------------------------------------------------------
UVM_WARNING ../ver/rd_agent/rd_driver.sv(73) @ 13906.00ns: uvm_test_top.fifo_env.rd_agt.drv [drv] severity action test.
ucli% 

仿真即停止。再次输入run命令会继续仿真。

之前统计计数用到的所有函数,将其中的UVM_COUNT替换为UVM_STOP,就可以实现相应的断点功能。同样的,也可以在命令行中设置断点。

六、导出信息

默认情况下,uvm会将UVM_INFO等信息显示在终端上。各个仿真器提供将显示在终端的信息同时输出到一个日志文件中的功能。这个log文件混杂了所有的UVM_INFO、UVM_WARNING、UVM_ERROR及UVM_FATAL,信息会非常多。此时uvm提供将特定信息输出到特定日志文件的功能。

首先需要创建相应的log文件,并设置可以写入

info_log    = $fopen("info.log", "w");
warning_log = $fopen("warning.log", "w");
error_log   = $fopen("error.log", "w");
fatal_log   = $fopen("fatal.log", "w");

控制信息写入

set_report_severity_file(UVM_INFO,    info_log);
set_report_severity_file(UVM_WARNING, warning_log);
set_report_severity_file(UVM_ERROR,   error_log);
set_report_severity_file(UVM_FATAL,   fatal_log);

set_report_severity_action(UVM_INFO,    UVM_DISPLAY| UVM_LOG);
set_report_severity_action(UVM_WARNING, UVM_DISPLAY| UVM_LOG);
set_report_severity_action(UVM_ERROR,   UVM_DISPLAY| UVM_COUNT | UVM_LOG);
set_report_severity_action(UVM_FATAL,   UVM_DISPLAY| UVM_EXIT | UVM_LOG);

这样就可以把不同级别的信息输入到相应的log文件中。同样也可以进行递归调用。

set_report_severity_file_hier(UVM_INFO,    info_log);
set_report_severity_file_hier(UVM_WARNING, warning_log);
set_report_severity_file_hier(UVM_ERROR,   error_log);
set_report_severity_file_hier(UVM_FATAL,   fatal_log);

set_report_severity_action_hier(UVM_INFO,    UVM_DISPLAY| UVM_LOG);
set_report_severity_action_hier(UVM_WARNING, UVM_DISPLAY| UVM_LOG);
set_report_severity_action_hier(UVM_ERROR,   UVM_DISPLAY| UVM_COUNT |UVM_LOG);
set_report_severity_action_hier(UVM_FATAL,   UVM_DISPLAY| UVM_EXIT | UVM_LOG);

还可以根据不同的ID来设置不同的日志文件:

set_report_id_file("rd_driver", rd_driver_log);

set_report_id_file函数同样也有递归调用的方式:

set_report_id_file_hier("rd_driver", rd_driver_log);

这样就可以将结点下所有的输出信息中ID为rd_driver的输出到rd_driver.log中。

当然,还可以组合严重性和ID:

set_report_severity_id_file(UVM_WARNING, "rd_driver",rd_driver_log)

set_report_severity_id_file函数也有其递归调用的方式:

set_report_severity_id_file_hier(UVM_WARNING, "rd_driver",rd_driver_log)

七、打印信息行为控制

uvm共定义了如下几种行为:

typedef enum
{
UVM_NO_ACTION = 'b000000,
UVM_DISPLAY = 'b000001,
UVM_LOG = 'b000010,
UVM_COUNT = 'b000100,
UVM_EXIT = 'b001000,
UVM_CALL_HOOK = 'b010000,
UVM_STOP = 'b100000
} uvm_action_type;

之前也提到过,这些行为的使用与field automation机制类似,也把UVM_DISPLAY等定义为一个整数。不同的行为有不同的位偏移,所以不同的行为可以使用“或”的方式组合在一起。

UVM_DISPLAY| UVM_COUNT | UVM_LOG

UVM_NO_ACTION  :不做任何操作;

UVM_DISPLAY        :输出到标准输出上;

UVM_LOG               :输出到日志文件中,前提是设置好了日志文件;

UVM_COUNT          :作为计数目标;

UVM_EXIT               :直接退出仿真;

UVM_CALL_HOOK :调用一个回调函数;

UVM_STOP             :停止仿真,进入命令行交互模式;

在默认的情况下,UVM设置了如下的行为:

set_severity_action(UVM_INFO, UVM_DISPLAY);
set_severity_action(UVM_WARNING, UVM_DISPLAY);
set_severity_action(UVM_ERROR, UVM_DISPLAY | UVM_COUNT);
set_severity_action(UVM_FATAL, UVM_DISPLAY | UVM_EXIT);

UVM_INFO到UVM_FATAL都会输出到标准输出中;UVM_ERROR会作为仿真退出计数器的计数目标;当出现UVM_FATAL时会自动退出仿真。

通过设置不同的行为,可以实现更加强大的功能,更好地控制环境中产生的各种信息。


总结

打印信息的控制有众多的函数可以选择,不论是对于严重级别的控制、对某节点或者某个ID的单独操作还是进行递归操作,都可以很轻松的完成。这些函数可以帮助我们更加有效地处理仿真过程中产生的各种信息,便于我们利用这些信息去调试环境或者debug。除此之外,我们还可以根据打印的信息对整个环境进行反馈控制,让我们可以实时地掌控整个环境的状态,让仿真过程更加顺利,产生我们所期望的结果。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clock_926

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值