IC验证学霸笔记4——UVM-- 核心基类

1 核心基类

UVM_object

UVM世界中的类最初都是由一个uvm_void根类继承过来的,但实际上该类没有实际的成员变量和方法。uvm_void只是一个虚类(virtual class),里边的内容等待继承于它的子类去开垦,在继承与uvm_void的子类中,有两类,一类为uvm_object,另外一类为uvm_port_base。在类库地图中,除了事务接口类继承于uvm_port_base,其他的所有类都是从uvm_object类中一步步继承过来的。

从uvm_object提供的方法和相关的宏操作来看,它的核心方法主要提供与数据操作相关的主要事务:
copy、 clone、 compare、 print、pack/unpack

域的自动化

UVM通过域的自动化,使得用户在注册UVM类的同时也可以声明今后会参与到对象拷贝、克隆、打印等操作的成员变量
域的自动化解放了verifier的双手,这使得在使用uvm_object提供的一些预定义方法时,非常便捷,而无需再实现自定义方法。在了解了域的自动化常用的宏之后,用户需要考虑哪些成员变量 、在注册UVM类( uvm_{component, object}_utils)的时候,也一并将它们归置到对应的域列表中,以便为稍后的域方法提供可以自动实现的基础。



从这个域的自动化宏的例子来看,在注册box的同时,也声明了将来会参与到 uvm_object数据操作的成员变量;

凡是声明了的成员变量,都将在数据操作时自动参与进来

如果有一些数据没有通过域的自动化来声明的话,它们也将不会自动参与到数据的拷贝、打印等操作,除非用户自己去定义这些数据操作方法。

按照域的类型,将在域自动化自动化是声明的宏进行分类,如下:


这些用于域的自动化的宏声明应在 uvm_object 或 uvm_ component 注册时发生, 即在`uvm_object_utils_begin 和uvm_object_ utils_end 之间,或者在'uvm_ component_ utils_ begin 和 uvm_ component_ utils _ end 之间声明要自动化的域。在声明自动化的域时,除了要注意运用正确的宏来匹配域的成员类型 (ARG), 还应声明这些域在将来参与的数据操作 (FLAG), 这一声明由下表枚举类型来表示。
建议初学者只需要默认采取UVM_ALL_ON或者 UVM_DEFAULT, 即将所有的数据操仵方法都打开。

拷贝(copy)

•    在UVM的数据操作中, 需要对copy和clone加以区分。 前者默认已经创建好了对象,只需要对数据进行拷贝;后者则会自动创建对象并对source object进行数据拷贝, 再返回target object句柄。
•    无论是copy或者clone, 都需要对数据进行复制。
•     在进行copy时, 默认进行的是深拷贝(deep copy) , 即会执行copy()和do_copy()。
代码案例:

输出结果:
新添加了一个类ball, 并且在box中例化了一个ball的对象。 在拷贝过称中, box的其它成员都正常拷贝了, 但对于box::b的拷贝则通过了ball的深拷贝方式进行。 
•    即先执行自动拷贝copy(), 来拷贝允许拷贝的域, 由于ball::color不允许拷贝, 所以只拷贝了ball::diameter。
•    接下来,再执行do_copy()函数,这个函数是需要用户定义的回调函数(callback function) , 即在copy()执行完后会执行do_copy()。
•    如果用户没有定义该函数, 那么则不会执行额外的数据操作。
•    从ball::do_copy()函数可以看到, 如果被拷贝对象的diameter小于20, 那么则将自身的diameter设置为20。 囚此, 最后对象b2.b的 成员与b1.b的成员数值不同。

比较(compare)

function bit compare (uvm_object rhs, uvm_comparer comparer =null);

•    默认情况下, 如果不对比较的情况作出额外配置, 用户可以在调用compare()方法时, 省略第二项参数, 即采用默认的比较配置。
•    比较方法经常会在两个数据类中进行。 例如从generator产生的 一个transaction (数据类), 和在设计输出上捕捉的transaction(数据类), 如果它们为同一种类型, 除了可以自定义数据比较之外, 也可以直接使用uvm_object::compare()函数来实现数据比较和消息打印。
在上面的两个对象比较中,会将每一个自动化的域进行比较,所以在执行compare()函数时,内置的比较方***将比较错误输出。•    从结果来看,比较发生了错误,返回0值。那么,b1.color和b2.color虽然不相同,却没有比较错误的信息。
•    原因在于, 默认的比较器, 即uvm_package::uvm_default_comparer最大输出的错误比较信息是1, 也就是说当比较错误发生时, 不会再进行后续的比较。
•    实际上, 在uvm_object使用到的方法compare()、print()和pack(), 如果没有指定数据操作配置对象作为参数时,会使用在uvm_pkg 中例化的全局数据操作配置成员。

全局对象

在uvm_pkg中例化了不少全局对象,在本节中我们会使用到的全局配置对象包括有uvm_default_comparer, uvm_default_printer和uvm_default_packer。
如果用户不想使用默认的比较配置,而是想自己对比较 进行设定,可以考虑创建一个uvm_comparer对象,或者修改全局的uvm_comparer对象。
下表为uvm_pkg全局对象:

打印(print) 

•    打印方认是核心基类提供的另外才中便于“开发和调试的功能“;
•    通过field automation, 使得声明之后的各个成员域会在调用 uvm_object::print()函数时自动打印出来。
•   相比于在仿真中设置断点、逐从调试,打印是另外一种调试方法,它的好处在于可以让仿真继续进行,会在最终回顾执行过程中, 从全局理解执行的轨迹和逻辑。

 •    只要在field automation中声明过的域,在稍后的print()函数执行时,都将打印出它们的类型、大小和数值。如果用户不对打印的格式做出修改, 那么在打印时,UVM会按照uvm_default_pri nter规定的格式来打印。
•    uvm_pkg所包含的用于打印的全局对象, 它们分别是:

  uvm_default_tree_printer: 可以将对象按照树状结构打印”;

  uvm_default_line_printer : 可以将对象数据打印到一行上;

  uvm_default_table_printer : 可以将对象按照表格的方式打印;

  uvm_default_printer : UVM坏境默认的打印设置,该句柄默认指向了 uvm_default_table_printer

•    通过给全局打印机uvm_default_printe赋予不同的打印机句柄, 就可以在调用行何uvm_object的print()方法时, 得到不同的打印格式。
•    如果用户需要自定义一些打印属性, 可以自己创建一个打印机, 进而通过修改其属件uvm_printer:: knobs中的成员, 来定制打印格式。

打包和解包(pack/unpack)

function int pack (ref bit bitstream[ ], input uvm_packer packer=null);
function int unpack (ref bit bitstream[ ], input uvm_packer packer=null); 

•    pack足为了将自动化声明后的域(标量)打包为比特流(bit stream)。即将各个散乱的数据,整理到bit数据串中,类似于 struct packed的整理方式,但又能充分利用数据空间,也更容易与硬件之间进行数据传递和比对。

•    unpack与pack相反,即将串行数据解包变为原有的各自域。该操作适用于从硬件一侧接收串行数据,进行校验后,还原为软件一侧对象中各自对应的成员变量。

•    pack与unpack在通常的UVM环境中使用较少,但是当与外界环境,例如System(发生大规模数据传递,该方法是首选,因为可以通过简单数据流实现精确的数据传输,另外,在UVM与FPGA emulator之间进行数据交换时,该方法也由于简便得到了青眯。


输出结果:
 •    b1将声明过的域通过pack()进行打包,打包好的数据存入到一个比特数组packed_bits,这个数组存放着所有经过field automation 的域值。
•    接下来b2又从packed_bits中解包, 将数据存入到自己的各个域中。
•    这种操作即完成了大型标量数据的整形串发, 主要面向SV与硬件和其它语言接口直接的精确通信。
•    在pack()和unpack()的参数中,有一个是可以缺省的参数即 uvm_packer, 如果用户不做特别指定,那么打包和解包的uvm_packer将会使用uvm_pkg中例化的全局对象uvm_default_packer。
•    此外, 用户如果需要自行打包, 例如规定将b1.volume打包成多少长度的比特数组, 来匹配硬件信号的位宽, 则需要自己定义do_pack( )回调函数。

以下案例涵盖本小结的重点内容:
注:优秀验证学员随堂笔记,已经征求到学生的同意,会持续给牛友们分享!
大家看完记得 一键三连!多多支持
#做项目##深度学习##芯片IC验证工程师##芯片设计工程师##你为什么选择硬件行业#
全部评论
收藏啦,自身还有好多不足之处,期待更新
点赞 回复 分享
发布于 2022-09-25 16:05 陕西

相关推荐

爱吃肉的伊登在写日记:好棒,27届简历能做成这个样子,但是第一个项目感觉cover住难度还是不小的,特别是二面的时候肯定要对分布式系统设计这一块儿有高出正常面试者的水平才行
点赞 评论 收藏
分享
04-25 18:13
五邑大学 Java
后来123321:大二两段实习太厉害了,我现在大二连面试都没有
点赞 评论 收藏
分享
评论
5
10
分享

创作者周榜

更多
牛客网
牛客企业服务