1.[UVM源代码研究] UVM的field_automation实现的print()函数如何灵活控制打印数组元素的数量
2.[UVM源代码研究] 如何定制一款个性化的打印格式
3.[UVM源代码研究] 谈谈uvm中的浅拷贝(shallow copy)与深拷贝(deep copy)
4.[UVM源代码研究] 当我们调用uvm_config_db里的函数时uvm内部都是怎么工作的
5.[UVM源代码研究] 聊聊寄存器模型的后门访问
6.UVM学习笔记(三)
[UVM源代码研究] UVM的field_automation实现的print()函数如何灵活控制打印数组元素的数量
实际工作中,我们常遇到需打印包含多个数组或队列元素的transaction时,仅默认显示开始5个和最后5个元素。若需查看更多元素值或完整内容,可考虑两种方法:一是重写transaction的do_print()函数,自定义打印内容与格式;二是奇异猫源码探索现有UVM源代码,修改相关设定以实现打印更多元素。
首先,分析can_txrx_transfer的注册方式,发现其默认仅显示特定数量的元素。通过查看源代码,发现实现打印机制的关键在于UVM_FIELD_QDA_INT宏与UVM_FIELD_UTILS_BEGIN宏的结合,它们共同调用_m_uvm_field_automation函数,该函数根据指定的what_参数(如UVM_PRINT)调用相应的打印函数。
在调用print()函数时,最终调用_m_uvm_field_automation,进一步调用uvm_print_array_int3宏。该宏通过uvm_print_qda_int4宏实现打印逻辑,对静态或动态数组、队列元素的打印格式进行统一处理。在uvm_print_qda_int4宏中,定义了uvm_printer与uvm_printer_knobs变量,用于接收打印参数与配置信息。
uvm_default_printer作为全局变量,其配置决定了打印格式。在打印数组时,通过设置uvm_printer_knobs中的begin_elements与end_elements变量,可以灵活控制打印元素的数量。具体配置方法可将uvm_default_printer配置在test_base的build_phase中,实现对打印数量的精确控制。
通过上述分析,我们了解了UVM源代码实现打印机制的iapp源码 注册登录原理,并掌握灵活配置数组/队列元素打印数量的方法。这种方法不仅提供了更为灵活的打印控制,还能根据实际需求调整打印内容与格式,增强代码的可读性和实用性。
[UVM源代码研究] 如何定制一款个性化的打印格式
文章总结:定制UVM的打印格式并非直接使用默认设置,而是涉及到UVM类库的深入理解。首先,`uvm_info`等宏的执行过程实际上是通过`uvm_report_enabled`函数,这个函数实际调用的是uvm_root的单例模式下的uvm_report_object的uvm_report_enabled方法,因为uvm_root支持这种模式。宏中的verbosity值会与预设阈值进行比较,同时还会检查action设置,以决定是否执行打印。打印格式的定制关键在于`compose_message`函数,它由uvm_report_server类定义,可以通过继承并重写此函数来自定义输出格式,比如使用`__FILE__`和`__LINE__`这些编译时指令。
实现个性化打印的步骤包括:创建一个自定义的report_server子类,重写`compose_message`函数,然后在测试环境中设置这个自定义的server。这样,无论执行`uvm_info`等宏,都会按照我们定制的格式显示,适用于所有四种severity(uvm_info/uvm_error/uvm_warning/uvm_fatal)。
通过上述方法,你就能为UVM的打印格式定制出符合自己需求的样式,让输出信息更加直观和易于理解。
[UVM源代码研究] 谈谈uvm中的浅拷贝(shallow copy)与深拷贝(deep copy)
在探讨UVM(Universal Verification Methodology)中的浅拷贝(shallow copy)与深拷贝(deep copy)之前,我们先对相关概念进行简要介绍,以便于理解以下讨论。浅拷贝和深拷贝是人脸识别ASP源码对象编程领域中基本概念,不仅限于系统Verilog(SV)和UVM(Universal Verification Methodology)。
浅拷贝:这一概念涉及的是拷贝对象的指针,即浅拷贝只复制指向对象内存空间的指针,使得目标对象与源对象共享同一内存空间。浅拷贝的局限性在于当内存空间被销毁时,所有指向该空间的指针必须重新定义,否则会导致野指针错误。
深拷贝:与此相反,深拷贝确保源对象和拷贝对象完全独立,两者之间互不影响,包括内存空间内容也被复制一份。例如,基本类型如Int、Double,以及结构体(struct)、枚举(Enum)会自动执行深拷贝,而类类型的对象则需区分浅拷贝与深拷贝。
在UVM中,`uvm_object`类提供了`copy`与`clone`函数来实现对象的拷贝。
`copy`函数为非虚拟、无返回值的函数,不能被重写,但`do_copy`函数为虚拟函数,可以通过重写`do_copy`函数实现对`copy`函数的间接重写。调用`copy`函数前,目标对象需先创建,以实现源对象内部对象的深拷贝赋值,而不会对目标对象本身分配空间。
`clone`函数为虚拟函数,返回`uvm_object`类型,可以被重写。discuz微社区源码由于返回值类型限制,`clone`只能通过`$cast`来实现目标对象类型的转换,而不能直接赋值。`clone`函数返回一个指向源对象类型的`uvm_object`句柄,因此目标对象类型必须与源对象一致(通过`$cast`检查),以确保成功执行`clone`操作,且目标对象不需要事先分配空间,因为`clone`会自动分配新空间。
`copy`函数的实现中,除了`do_copy`之外的第行的`__m_uvm_field_automation(rhs, UVM_COPY, "")`完成了在`field_automation`中的配置实现。如果未重写`do_copy`函数,则所有拷贝行为依赖于`__m_uvm_field_automation`函数。
`uvm_object_defines.svh`文件在第行实现了将`copy`传入参数转换为局部变量`local_data__`,该变量类型为通过`uvm_object_untils_begin`传入的参数类型。`local_data__`在后续的`uvm_field_automation`宏中根据传入的标志位进行相应操作,以`uvm_field_object`为例。
在`uvm_field_object`中,关于`UVM_COPY`的具体操作表明,调用`copy`的源对象不能为空。如果`FLAG&UVM_NOCOPY`位为1,则直接结束代码执行。如果`FLAG&UVM_REFERENCE`位为1,或者`local_data__.ARG == null`,则将目标对象的`ARG`对象句柄指向源对象的`ARG`句柄。这种做法对于未分配空间的对象赋值,以避免错误。`UVM_REFERENCE`的应用场景主要针对`uvm_component`类型的对象注册,确保在进行`copy`和`clone`时执行浅拷贝,避免深拷贝导致的问题。
`uvm_component`类型在`copy`时默认执行深拷贝,而`UVM_REFERENCE`标志位则实现浅拷贝。盖楼小游戏源码例如,在`apb_env`中,`bus_monitor`和`bus_collector`被例化为`master`中的`monitor`和`collector`,同时`cfg`对象也传递给`master`。通过`field_automation`的修改,可以观察到`uvm_top`在打印树型结构时,`apb_monitor`和`cfg`对象的打印信息。
总结而言,UVM中的默认拷贝/克隆操作为深拷贝,`UVM_REFERENCE`标志位用于实现浅拷贝。理解这些概念对于在UVM中进行对象拷贝时避免错误至关重要。
[UVM源代码研究] 当我们调用uvm_config_db里的函数时uvm内部都是怎么工作的
了解uvm_config_db的内部工作原理,我们首先应明确其包含的四个静态方法。接下来,本文将逐一解析这四个方法,揭开uvm_config_db的神秘面纱。
当我们调用uvm_config_db的set函数时,其实际作用是什么?答案在于uvm_config_db继承自uvm_resource_db。进一步探究,uvm_resource_base是一个虚拟类,继承自uvm_object,并且uvm_resource_db通过typedef定义了一个参数化的uvm_resource类型rsrc_t。因此,无论uvm_config_db使用哪个具体方法,其返回值或中间数据都是rsrc_t类型,本质上都是uvm_resource。
回到问题的核心,当我们调用set函数时,所设置的变量存储在哪里?答案在于uvm_config_db内部的m_rsc数组。这是一个由string作为键,uvm_resource#(T)作为值的静态键值对数组,以uvm_component为索引。这意味着,m_rsc数组实际上是一个以uvm_component为键,联合数组为值的结构,其中联合数组内部包含了key(string类型)和value(uvm_resource#(T)类型)。
接下来,我们分析set函数的内部执行逻辑。在函数的前半部分,会进行变量声明并获取全局变量,如uvm_top、phase、目标路径inst_name等。然后,检查发送路径cntxt是否发起过set操作,若未执行,则创建键值对,并将其赋值给uvm_pool。这一步实质上为m_rsc数组中的键值对添加了key。随后,生成联合数组的value,即uvm_pool。这个过程确保了set到的位置和内容根据uvm_component的层级和执行顺序进行优先级替换。
总结而言,通过uvm_config_db的set函数,我们能够将变量设置到m_rsc数组中。这个数组是静态的,意味着通过uvm_config_db类的任何实例都可以访问。设置过程已经包含了优先级判断,因此,数据被安全地存储和更新。
接下来,我们将讨论get函数。其工作原理相对简单,主要是在m_rsc数组中查找并返回对应的值。此外,exists和wait_modified函数负责处理m_rsc数组中键值对的存在性和状态判断,用于进一步的逻辑操作。
为了更直观地理解uvm_config_db的set和get过程,我们参考了cluelogic中的图示。通过这些图示,我们能够清晰地看到在env和agent层次上执行set和get操作的过程。
最后,参考UVM Tutorial for Candy Lovers - . Configuration Database,读者可以进一步深入了解uvm_config_db的具体应用和最佳实践,以增强对配置数据库的理解和使用能力。
[UVM源代码研究] 聊聊寄存器模型的后门访问
本文将深入探讨UVM源代码中寄存器模型的后门访问实现,尽管实际工作中这种访问方式相对有限,但在特定场景下其重要性不可忽视。后门访问有助于简化验证流程,特别是在检查阶段需要获取DUT寄存器值时。
在UVM源代码中,后门访问的实现主要围绕write任务展开,核心方法是do_write(),它包括获取uvm_reg_backdoor句柄、等待访问权限和更新期望值等步骤。uvm_reg_backdoor类是用户自定义后门访问的入口,允许通过派生类实现定制化的访问方式。
获取uvm_reg_backdoor句柄的过程会遍历寄存器模型的层次,如果没有自定义backdoor,就会从顶层寄存器模型开始查找。在默认情况下,寄存器模型使用sv语法的DPI方式访问,但可以通过自定义类实现其他形式的访问。
源代码中的get_full_hdl_path函数负责获取寄存器的完整HDL路径,这涉及到uvm_hdl_path_concat和uvm_hdl_path_slice等结构,它们用于描述寄存器的物理信息。通过配置或add_hdl_path操作,可以在寄存器模型中存储和管理多个HDL路径,对应不同的寄存器实例。
后门读写操作会调用uvm_hdl_read()函数,它是一个通过DPI-C实现的外部函数,根据编译选项的不同,可以选择使用C语言访问HDL路径。写操作成功后,会更新寄存器的镜像值并写入实际寄存器。
总结来说,实现寄存器模型后门访问的关键步骤包括设置寄存器的HDL路径,配置单个寄存器的物理信息,并确保与HDL中的实际结构对应。需要注意的是,如果寄存器在HDL中被拆分为多个字段,需正确配置这些字段的访问路径以避免警告。
UVM学习笔记(三)
前言
笔记内容对应张强所著的《UVM实战》。该书对UVM使用进行了比较详尽的介绍,并在前言中提供了书籍对应源码的下载网址,是一本带有实操性的书籍,对新手比较友好,推荐阅读。
第2章一个简单的UVM验证平台2.4 UVM的终极大作: sequence
2.4.1 在验证平台中加入sequencer
sequence机制作用:用于产生激励。其分为两部分,一是sequence,二是sequencer。
在定义driver时指明此driver要驱动的transaction的类型,这样定义的好处是可以直接使用uvm_driver中的某些预先定义好的成员变量,如uvm_driver中有成员变量req,它的类型就是传递给uvm_driver的参数。由此带来的变化如下:(不需要定义中间变量tr了)
2.4.2 sequence机制
三者关系:
每一个sequence都有一个body任务,当一个sequence启动之后,会自动执行body中的代码。body中uvm_do这个宏的作用如下:
如果不使用uvm_do宏,也可以直接使用start_item与finish_item的方式产生transaction。
sequencer负责协调sequence和driver的请求
get_next_item和try_next_item的比较
2.4.3 default_sequence的使用
引入default_sequence的原因:
如何使用default_sequence:
使用default_sequence时如何提起和撤销objection?
2.5 建造测试用例2.5.1 加入base_test
对my_env进一步封装,添加一些公司个性化内容,举例如下:
2.5.2 UVM中测试用例的启动
通过传递参数变量值启动的原因:
如何使用:
参考资料
UVM实战(卷一) 张强 编著 机械工业出版社
uvm实战卷 1 与卷 2 内容差别是什么呢?
UVM实战卷1与卷2的内容在基础理论、内容深度和案例分析等方面有所区别。具体分析如下:
基础理论
卷1:全面介绍了UVM的基本概念、组件和机制,通过实例引导读者理解UVM的工作原理。
卷2:侧重于高级应用和研究性质的主题,比如源代码分析和特定领域的验证技术。
内容深度
卷1:注重实用性,通过大量实例详细讲解了如何在实际项目中使用UVM构建验证环境。
卷2:更深入地探讨了UVM的内部机制和优化方法,适合有一定经验的验证工程师。
案例分析
卷1:包含大量经过验证的例子和源代码,方便读者动手实践和理解。
卷2:可能更侧重于复杂设计和高级验证技巧的案例分析。
适用人群
卷1:主要面向UVM初学者和中级工程师,帮助他们快速上手UVM。
卷2:更适合有经验的验证工程师,帮助他们深入研究和掌握UVM。
学习路径
卷1:提供了从基本概念到实际应用的完整学习路径。
卷2:可能在卷1的基础上进一步拓展,提供更专业的学习内容。
新特性
卷1:涵盖了UVM的基础特性和用法。
卷2:可能聚焦于UVM的新版本特性和更新,如.2-标准的新内容。
迁移策略
卷1:介绍了从OVM到UVM的迁移策略,帮助工程师适应新的验证方法。
卷2:可能讨论从旧版本UVM到新版本迁移的最佳实践。
针对上述分析,可以考虑以下几点建议:
阅读《UVM实战(卷1)》以建立扎实的基础。
关注书中示例代码,并尝试自己实现和测试。
在学习过程中,积极参与社区讨论,提问或解答他人问题。
随着能力提升,逐步过渡到《UVM实战(卷2)》的高级话题。
保持对最新UVM版本更新的关注,了解行业最佳实践。
综上所述,卷1更侧重于基础学习和实践操作,为读者提供了全面的入门教程;而卷2可能会更加专注于深入研究和高阶应用,为有经验的工程师提供进阶指导。对于希望深入学习UVM的工程师来说,这两本书都是宝贵的资源。