皮皮网

【意大利离美国源码】【图文论坛源码】【攒攒平台源码】uvm 源码

2024-11-18 23:46:16 来源:微信外卖源码官网

1.[UVM源代码研究] 谈谈uvm中的浅拷贝(shallow copy)与深拷贝(deep copy)
2.[UVM源代码研究] 如何定制一款个性化的打印格式
3.uvm实战卷 1 与卷 2 内容差别是什么呢?
4.[UVM源代码研究] 聊聊寄存器模型的后门访问
5.UVM学习笔记(三)
6.[UVM源代码研究] UVM的field_automation实现的print()函数如何灵活控制打印数组元素的数量

uvm 源码

[UVM源代码研究] 谈谈uvm中的浅拷贝(shallow copy)与深拷贝(deep copy)

       在探讨UVM(Universal Verification Methodology)中的浅拷贝(shallow copy)与深拷贝(deep copy)之前,我们先对相关概念进行简要介绍,以便于理解以下讨论。浅拷贝和深拷贝是对象编程领域中基本概念,不仅限于系统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`类型,可以被重写。由于返回值类型限制,`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源代码,攒攒平台源码我们首先定位`uvm_info宏定义的位置:

       这段代码对uvm_info/uvm_warning/uvm_error/uvm_fatal等宏进行了描述,实际上是对uvm_report_*函数的封装。以`uvm_info为例,分析其执行过程,其中使用了全局函数uvm_report_enabled。

       这里又调用了uvm_root中定义的uvm_report_enabled函数。需要注意的是,在uvm_root中并未找到这个函数的定义。经过查找源代码,发现uvm_report_object中定义了uvm_report_enabled。

       为什么要通过uvm_root实例调用这个函数呢?这需要了解uvm类库的继承关系。通过分析,我们发现通过调用uvm_root中uvm_report_enabled的函数,是因为uvm_root支持单例模式,可以获取uvm_root的单例句柄执行uvm_report_object中定义的自动继承的函数,避免了创建额外的实例。

       接下来分析函数执行过程,原本简单的获取severity对应的verbosity阈值设置,却涉及了severity的override问题。我们可以通过调用函数或运行时传入参数来对severity进行override。

       所有severity的override都记录在uvm_pool键值对severity_id_verbosities中。

       severity和verbosity枚举类型定义如下:

       回到uvm_report_object中行的代码,可以认为调用`uvm宏传入的verbosity值如果大于设置的verbosity阈值,则uvm_report_enabled返回0。另外行还有一种函数返回0的情况。

       关于uvm_action和verbosity的设置类似,不再展开。执行`uvm_info系列宏时,不仅需要考虑severity对应的verbosity_level的设置是否大于阈值,还需要考虑对severity设置的行为是否为UVM_NO_ACTION来判断uvm_report_enabled的返回值。

       本质上,执行的是uvm_report_server中的compose_message函数,该函数规定了uvm_info系列宏的打印格式。

       这个函数的参数filename和line是我们调用uvm_report_info传入的`uvm_file和`uvm_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进行调用。接下来,我们通过一个例子来看看如何实现个性化打印的定制。

       首先,我们定制自己的report_server:

       然后,在base_test中实例化并set_server:

       现在,我们来看看最初那句打印的执行情况:

       通过以上步骤,我们便实现了个性化的打印定制,该定制对4种severity同时生效。

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的工程师来说,这两本书都是宝贵的资源。

[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源代码研究] 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源代码实现打印机制的原理,并掌握灵活配置数组/队列元素打印数量的方法。这种方法不仅提供了更为灵活的打印控制,还能根据实际需求调整打印内容与格式,增强代码的可读性和实用性。

如何跑通《UVM实战》书上的例子?

       在求职过程中,面试官常会询问关于UVM实战的学习情况,特别是是否实践过书中的例子。我最近抽空按照《UVM实战》书中的指导进行了实践,现在已经能够成功运行书中的例子。以下是关键步骤和注意事项:

       首先,确保你的虚拟机上安装了VCS和Verdi工具,可以从华章网站获取《UVM实战》的源代码。在虚拟机设置中,将共享文件夹指向代码目录,以便于访问。将example_and_uvm_source_code文件夹复制到你的工作目录下。

       在代码中,有两个部分需要修改。一是setup_vcs脚本,用于设置VCS和Verdi的路径。你需要根据你的实际工具路径进行调整,可能需要修改export语句格式。二是run脚本,需要添加必要的命令,如"–full",这对于位Linux系统至关重要,否则可能会遇到VCS_HOME路径错误。

       为了便于debug和波形dump,我增加了dump波形相关的代码,并在top_tb文件夹中添加了输出仿真信息到test.log的命令。这样,你就可以跟踪仿真过程,查找关键信息。

       经过这些步骤,你应该就能成功运行《UVM实战》中的例子了。如果你觉得这些信息有帮助,请别忘了点赞支持!我是不二鱼,祝你在学习和求职路上顺利。

Untangle分析

       Untangle是一款广受欢迎的开源防火墙,主要用于商业应用。对比其他开源防火墙,如PFSense、Untrangle、ClearOS等,Untangle以其丰富的功能和易于使用的图形界面脱颖而出。本文将对Untangle进行深入分析,以供讨论和对比。

       Untangle作为下一代防火墙(NGFW)的典型代表,提供了一系列比通用防火墙(UTM)更全面的功能。尽管某些高级特性需要付费购买,但其基本功能对用户免费开放。Untangle基于Debian系统,采用shell界面,没有命令行界面(CLI)。由于二次开发资料较少,主要提供了用户指南和使用文档,内容相对有限,分为两大部分:一部分是必需的dpkg包,用于系统配置和功能软件的安装;另一部分是src文件,包含各种应用程序,以Java编写。

       Untangle NG Firewall 综合管理内容过滤、Web缓存、远程访问和策略实施,通过直观的图形界面实现。其应用协同工作,执行复杂的规则,提高性能和吞吐量。在第七层(应用级别)上监控网络活动,使管理员能够实施符合组织需求的策略,如过滤不适当内容、优先处理关键业务站点或应用。

       Untangle的核心功能是其应用程序(apps),分为过滤器(filters)和服务(services)两大类。以反垃圾邮件应用为例,它作为一个守护进程运行,Web端开启时自动启动进程和配置。可通过命令查看运行状态,禁用某些功能,如获取运行日志。

       Untangle的其他服务进程包括但不限于反垃圾邮件、内容过滤、Web缓存等应用,其功能强大,涵盖网络安全的多个方面。为了确保功能完整性和更新,所有应用程序在线安装,某些服务可能需要与云服务交互。

       系统架构上,Untangle由内核(UVM)和应用两大部分组成。NGFW运行在UVM之上,处理本地流量,并负责路由、NTA等其他网络处理。应用同样运行在UVM上,处理流量判断和后续处理。UVM作为平台无关层,提供数据服务给Java应用程序,并通过JNI调用C实现网络数据包处理,主要使用libnetcap库。通过Linux内核协议栈控制数据包,支持通过源码深入分析。

       为了实现高可用性,Untangle支持主备模式,基于虚拟路由器冗余协议(VRRP)。所有Untangle NGFW服务器需保持运行状态,并配置静态IP地址和VRRP虚拟地址。

       在源码方面,Untangle的源码托管在GitHub上,包括核心功能和各种应用程序。NGFW功能主要由Java实现,而网络流处理则通过C语言实现。对于希望定制或深入理解系统实现的用户来说,这可能需要一定的时间和资源,且缺乏详细的开发文档。不过,Untangle提供了一个专有的SD-WAN产品,虽然不开放源代码,但与Untangle系统结合使用时,可以提供额外的功能和性能优化。