[UVM源代码研究] 如何定制一款个性化打印格式的printer

[UVM源代码研究] 如何定制一款个性化打印格式的printer

如果使用默认的打印格式,我们执行如下代码
在这里插入图片描述

实际打印结果格式如下
在这里插入图片描述

查看UVM源代码,我们首先看下`uvm_info这个宏定义在哪里
在这里插入图片描述
在这里插入图片描述

上面这段包含了对uvm_info/uvm_warning/uvm_error/uvm_fatal这一系列宏的描述,其本质是对uvm_report_*一系列函数的封装,我们还是以`uvm_info为例继续分析其执行过程,这里使用到了全局函数uvm_report_enbaled
在这里插入图片描述

这里又调用了uvm_root中定义的uvm_report_enabled函数,这里需要做个引申,因为我们查看uvm_root的时候发现其中并没有定义这个uvm_report_enabled函数,搜遍源代码我们发现uvm_report_object中有定义uvm_report_enabled
在这里插入图片描述

为什么要通过uvm_root的实例来调用呢?回答这个问题我们需要了解下uvm类库中的继承关系
在这里插入图片描述

于是我们不难发现为什么通过调用uvm_root里uvm_report_enabled的函数了,因为uvm_root支持单例模式,所以可以通过get来获取uvm_root的单例句柄来执行uvm_report_object里定义的自动继承的函数,而不会专门创建一个uvm_report_object或者uvm_component类实例来调用uvm_report_enabled函数。

接着分析上面函数的执行过程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本来很简单的一个获取severity(包含uvm_info/uvm_error/uvm_warning/uvm_fatal四种)对应的verbosity(对应枚举类型UVM_NONE/UVM_LOW…)阈值的设置,结果发现写了这么多复杂的代码,其实这边涉及到了一个severity的override的问题,我们是可以通过调用下面的函数或者通过运行时传入相应的参数来对某个severity进行相应的override的。
在这里插入图片描述

所有severity的override都记录下下面这个uvm_pool键值对severity_id_verbosities中
在这里插入图片描述

severity枚举类型定义如下
在这里插入图片描述

verbosity枚举类型定义如下
在这里插入图片描述

再次绕回到我们讲uvm_report_object里464行的代码,我们可以认为是我们调用的`uvm宏传入的verbosity值如果大于我们设置的verbosity阈值(代码里调用函数set_report_verbosity_level(verbosity_level)或者通过运行时命令行传入+UVM_VERBOSITY=verbosity_level),返回值uvm_report_enabled返回0。另外465行还有一种函数返回0的情况
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

这里关于uvm_action跟verbosity的设置类似,就不展开讲了,也就是说我们执行`uvm_info系列宏的时候,不仅要看severity对应的verbosity_level的设置是否大于阈值,还需要看我们对于该severity设置的行为是否为UVM_NO_ACTION来判断uvm_report_enabled的返回值。只有当verbosity_level设置大于阈值并且action没有设置为UVM_NO_ACTION,uvm_report_enabled才返回1,uvm_message_defines.svh的114行才会执行,于是一系列的核心函数调用如下所示

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

本质上执行的就是uvm_report_server中compose_message函数
在这里插入图片描述

这个函数就规定了我们打印uvm_info系列宏的打印格式,这个函数的参数filename和line就是我们在调用uvm_report_info传入的宏uvm_fileuvm_line
在这里插入图片描述

进一步解释,宏__FILE____LINE__ 都是systemverilog的编译指令,在编译阶段被替换掉:
__FILE__被替换为当前文件的文件名,以字符串的形式存在。__LINE__被替换为当前文件的行号,以十进制数字的形式存在。

于是我们如果需要定义我们自己的个性化的打印格式,就可以通过从uvm_report_server继承一个类重写compose_message函数即可。值得注意的是这里不能用set_type_override_by_type/name,因为uvm_report_server这个类并没有用uvm_object_utils注册,并且也没有实现get_type()函数,所以不能用传统的factory的override方法进行override,好在uvm_report_server已经预留好了子类server的覆盖函数set_server
在这里插入图片描述

这个静态函数可以直接使用类uvm_report_server进行调用,我们通过一个lab来看看具体如何实现个性化打印的定制。

首先,我们定制自己的report_server
在这里插入图片描述

然后base_test里例化并set_server
在这里插入图片描述

现在我们来看看我们最开始那句打印的执行情况
在这里插入图片描述

于是我们便实现了个性化的打印定制,该定制对4种severity同时生效。

  • 26
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值