UVM:uvm_component与uvm_object

  (1)uvm_component与uvm_object的关系

      uvm_object是UVM中最基本的类,几乎所有的类都继承自uvm_object,包括uvm_component。uvm_component派 生自uvm_object这个事实会让很多人惊讶,而这个事实说明了uvm_component拥有uvm_object的特性,同时又有自己的一些特质。 但是uvm_component的一些特性,uvm_object则不一定具有。
        uvm_component有两大特性是uvm_object所没有的,一是通过在new的时候指定parent参数来形成一种树形的组织结构,二是 有phase的自动执行特点。图3-1列出了UVM中常用类的继承关系。
        从图中可以看出,从uvm_object派生出了两个分支,所有的UVM树的结点都是由uvm_component组成的,只有基于 uvm_component派生的类才可能成为UVM树的结点;最左边分支的类或者直接派生自uvm_object的类,是不可能以结点的形式出 现在UVM树上的

 

(2)常用的派生自uvm_object的类

        uvm_object是最基本的类,那么其能力恰恰也是最差的,当然了,其扩展性也是最好的。
        除了派生自 uvm_component类之外的类,几乎所有的类都派生自uvm_object。换个说法,除了driver、monitor、agent、model、scoreboard、 env、test之外的几乎所有的类,本质上都是uvm_object,如sequence、sequence_item、transaction、config等。
        举一个更加通俗点的例子,uvm_object是一个分子,用这个分子可以搭建成 许许多多的东西,如既可以搭建成动物,还可以搭建成植物,更加可以搭建成没有任何意识的岩石、空气等。uvm_component就 是由其搭建成的一种高级生命,而sequence_item则是由其搭建成的血液,它流通在各个高级生命(uvm_component)之间, sequence则是众多sequence_item的组合,config则是由其搭建成的用于规范高级生命(uvm_component)行为方式的准则。
        在验证平台中经常遇到的派生自uvm_object的类有:
        uvm_sequence_item:定义的所有的transaction要从uvm_sequence_item派生。transaction就是封装了一定信息的一个类。driver从sequencer中得到transaction,并且把其转换成端口上的信号。虽然UVM中有一个uvm_transaction 类,但是在UVM中,不能从uvm_transaction派生一个transaction,而要从uvm_sequence_item派生。事实上,uvm_sequence_item是从uvm_transaction派生而来的,因此,uvm_sequence_item相比uvm_transaction添加了很多实用的成员变量和函数/任务,从 uvm_sequence_item直接派生,就可以使用这些新增加的成员变量和函数/任务
        uvm_sequence:所有的sequence要从uvm_sequence派生一个sequence就是sequence_item的组合。sequence直接与sequencer打 交道,当driver向sequencer索要数据时,sequencer会检查是否有sequence要发送数据。当发现有sequence_item待发送时,会把此 sequence_item交给driver。
        config:所有的config一般直接从uvm_object派生。config的主要功能就是规范验证平台的行为方式。如规定driver在读取总线时 地址信号要持续几个时钟,片选信号从什么时候开始有效等。这里要注意config与config_db的区别。使用 config_db进行参数配置,这里的config其实指的是把所有的参数放在一个object中。然后通过config_db的方式设置 给所有需要这些参数的component。
        除了上面几种类是派生自uvm_object外,还有下面几种:
        uvm_reg_item:它派生自uvm_sequence_item,用于register model中
        uvm_reg_map、uvm_mem、uvm_reg_field、uvm_reg、uvm_reg_file、uvm_reg_block等与寄存器相关的众多的类都是派生自 uvm_object,它们都是用于register model
        uvm_phase:它派生自uvm_object,其主要作用为控制uvm_component的行为方式,使得uvm_component平滑地在各个不同的 phase之间依次运转

(3)常用的派生自uvm_component的类

        与uvm_object相比,派生自uvm_component的类比较少。
        uvm_driver:所有的driver都要派生自uvm_driverdriver的功能主要就是向sequencer索要sequence_item(transaction)并且将 sequence_item里的信息驱动到DUT的端口上,这相当于完成了从transaction级别到DUT能够接受的端口级别信息的转换。与 uvm_component相比,uvm_driver多了如下几个成员变量:

uvm_seq_item_pull_port #(REQ, RSP) seq_item_port;
uvm_seq_item_pull_port #(REQ, RSP) seq_item_prod_if; // alias
uvm_analysis_port #(RSP) rsp_port;
REQ req;
RSP rsp;

        在函数/任务上,uvm_driver并没有做过多的扩展。
        uvm_monitor:所有的monitor都要派生自uvm_monitormonitor做的事情与driver相反,driver向DUT的pin上发送数据,而 monitor则是从DUT的pin上接收数据,并且把接收到的数据转换成transaction级别的sequence_item,再把转换后的数据发送给 scoreboard,供其比较。与uvm_component相比,uvm_monitor几乎没有做任何扩充。uvm_monitor的定义如下:

源代码virtual class uvm_monitor extends uvm_component;…function new (string name, uvm_component parent);super.new(name, parent);endfunctionconst static string type_name = "uvm_monitor";virtual function string get_type_name ();return type_name;endfunctionendclass

        虽然从理论上来说所有的monitor要从uvm_monitor派生。但是实际上如果从uvm_component派生,也没有任何问题。
        uvm_sequencer:所有的sequencer都要派生自uvm_sequencer。sequencer的功能就是组织管理sequence,当driver要求数据时, 它就把sequence生成的sequence_item转发给driver。与uvm_component相比,uvm_sequencer做了相当多的扩展。
        uvm_scoreboard:一般的scoreboard都要派生自uvm_scoreboard。scoreboard的功能就是比较reference model和monitor分别发送 来的数据,根据比较结果判断DUT是否正确工作。与uvm_monitor类似,uvm_scoreboard也几乎没有在uvm_component的基础上做扩展。

virtual class uvm_scoreboard extends uvm_component;…function new (string name, uvm_component parent);super.new(name, parent);endfunctionconst static string type_name = "uvm_scoreboard";virtual function string get_type_name ();return type_name;endfunctionendclass

        所以,当定义自己的scoreboard时,可以直接从uvm_component派生。
        reference model:UVM中并没有针对reference model定义一个类。所以通常来说,reference model都是直接派生自 uvm_component。reference model的作用就是模仿DUT,完成与DUT相同的功能。DUT是用Verilog写成的时序电路,而reference model则可以直接使用SystemVerilog高级语言的特性,同时还可以通过DPI等接口调用其他语言来完成与DUT相同的功能
        uvm_agent:所有的agent要派生自uvm_agent。与前面几个比起来,uvm_agent的作用并不是那么明显。它只是把driver和 monitor封装在一起,根据参数值来决定是只实例化monitor还是要同时实例化driver和monitor。agent的使用主要是从可重用性的角 度来考虑的。如果在做验证平台时不考虑可重用性,那么agent其实是可有可无的。与uvm_component相比,uvm_agent的最大改动 在于引入了一个变量is_active

 virtual class uvm_agent extends uvm_component;uvm_active_passive_enum is_active = UVM_ACTIVE;…function void build_phase(uvm_phase phase);int active;super.build_phase(phase);if(get_config_int("is_active", active)) is_active = uvm_active_passive_enum' (active);endfunction

        get_config_int是uvm_config_db#(int)::get的另一种写法,这种写法最初出现在OVM中。由于is_active是一个枚举变量,其两个取值为固定值0或者1。所以在上面的代码中可以以int类型 传递给uvm_agent,并针对传递过来的数据做强制类型转换。
        uvm_env:所有的env(environment的缩写)要派生自uvm_env。env将验证平台上用到的固定不变的component都封装在一 起。这样,当要运行不同的测试用例时,只要在测试用例中实例化此env即可。uvm_env也并没有在uvm_component的基础上做过多扩展:

 virtual class uvm_env extends uvm_component;…function new (string name="env", uvm_component parent=null);super.new(name,parent);endfunctionconst static string type_name = "uvm_env";virtual function string get_type_name ();return type_name;endfunctionendclass

        uvm_test:所有的测试用例要派生自uvm_test或其派生类,不同的测试用例之间差异很大,所以从uvm_test派生出来的类各不 相同。任何一个派生出的测试用例中,都要实例化env,只有这样,当测试用例在运行的时候,才能把数据正常地发给DUT,并 正常地接收DUT的数据。uvm_test也几乎没有做任何扩展:

 virtual class uvm_test extends uvm_component;…function new (string name, uvm_component parent);super.new(name,parent);endfunctionconst static string type_name = "uvm_test";virtual function string get_type_name ();return type_name;endfunctionendclass

(4)与uvm_object相关的宏

        在UVM中与uvm_object相关的factory宏有如下几个:
        uvm_object_utils:它用于把一个直接或间接派生自uvm_object的类注册到factory中。         uvm_object_param_utils:它用于把一个直接或间接派生自uvm_object的参数化的类注册到factory中。所谓参数化的类,是指类 似于如下的类:

class A#(int WIDTH=32) extends uvm_object;

        参数化的类在代码可重用性中经常用到。如果允许,尽可能使用参数化的类,它可以提高代码的可移植性。 uvm_object_utils_begin:当需要使用field_automation机制时,需要使用此宏。如 果使用了此宏,而又没有把任何字段使用uvm_field系列宏实现,那么会出现什么情况呢?

`uvm_object_utils_begin(my_object)
`uvm_object_utils_end

        答案是不会出现任何问题,这样的写法完全正确,可以尽情使用。         uvm_object_param_utils_begin:与uvm_object_utils_begin宏一样,只是它适用于参数化的且其中某些成员变量要使用 field_automation机制实现的类
        uvm_object_utils_end:它总是与uvm_object_*_begin成对出现,作为factory注册的结束标志

(5)与uvm_component相关的宏

        在UVM中与uvm_component相关的factory宏有如下几个:
        uvm_component_utils:它用于把一个直接或间接派生自uvm_component的类注册到factory中
        uvm_component_param_utils:它用于把一个直接或间接派生自uvm_component的参数化的类注册到factory中
        uvm_component_utils_begin:这个宏与uvm_object_utils_begin相似,它用于同时需要使用factory机制和field_automation机制注册 的类。在类似于my_transaction这种类中使用field_automation机制可以让人理解,可是在component中使用field_automation机制有必 要吗?uvm_component派生自uvm_object,所以对于object拥有的如compare、print函数都可以直接使用。但是filed_automation机制 对于uvm_component来说最大的意义不在于此,而在于可以自动地使用config_db来得到某些变量的值。
        uvm_component_param_utils_begin:与uvm_component_utils_begin宏一样,只是它适用于参数化的,且其中某些成员变量要使 用field_automation机制实现的类。         uvm_component_utils_end:它总是与uvm_component_*_begin成对出现,作为factory注册的结束标志

(6)uvm_component的限制

        uvm_component是从uvm_object派生来的。从理论上来说,uvm_component应该具有uvm_object的所有的行为特征。但是,由 于uvm_component是作为UVM树的结点存在的,这一特性使得它失去了uvm_object的某些特征。
        在uvm_object中有clone函数,它用于分配一块内存空间,并把另一个实例复制到这块新的内存空间中。clone函数的使用方式 如下:

class A extends uvm_object;…
endclassclass my_env extends uvm_env;virtual function void build_phase(uvm_phase phase);A a1;A a2;a1 = new("a1");a1.data = 8'h9;$cast(a2, a1.clone());endfunction
endclass

        上述的clone函数无法用于uvm_component中,因为一旦使用后,新clone出来的类,其parent参数无法指定

        copy函数也是uvm_object的一个函数,在使用copy前,目标实例必须已经使用new函数分配好了内存空间,而使用clone函数 时,目标实例可以只是一个空指针。换言之,clone=new+copy。
        虽然uvm_component无法使用clone函数,但是可以使用copy函数。因为在调用copy之前,目标实例已经完成了实例化,其 parent参数已经指定了
        uvm_component的另外一个限制是,位于同一个父结点下的不同的component,在实例化时不能使用相同的名字。如下的方式 中都使用名字“a1”是会出错的:

class A extends uvm_component;…
endclassclass my_env extends uvm_env;virtual function void build_phase(uvm_phase phase);A a1;A a2;a1 = new("a1", this);a2 = new("a1", this);endfunction
endclass




 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/255262.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CentOS上的HTTPS:如何设置安全的HTTPS连接

在CentOS系统上设置安全的HTTPS连接是保护你的网站和用户数据的关键步骤。通过使用HTTPS,你可以加密与用户的通信,并确保数据在传输过程中的安全性。以下是设置安全的HTTPS连接的步骤概述: 获取SSL证书: 首先,你需要…

星闪的三层架构

在数字化转型的浪潮中,物联网技术正成为连接世界的纽带,将各种智能设备融为一个无缝的整体。而在这个大背景下,星闪崭露头角,将成为连接未来的关键枢纽。本文将介绍星闪系统的三层架构,包括基础应用层、基础服务层和星…

热烈祝贺许战海老师成为北京湖南商会特聘专家!

在北京的初冬时节,一股商业的暖流在世纪华天大酒店的湖南厅中涌动。2023年12月3日下午,这里迎来了一场盛大的聚会——北京湖南企业商会成立20周年的预热活动之一:“湘商大讲堂”。这不仅是一次庆祝,更是一次对未来的展望&#xff…

C语言二叉树的基本概念(一)

目录 二叉树 二叉树的分类(目前只谈两种) 满二叉树 完全二叉树 二叉树的性质(其余的可以自己总结) 选择练习 二叉树的存储结构 顺序存储方式 链式存储方式 二叉树 定义:二叉树是一种特殊的树状数据结构&…

系统调用过程

应用程序通过系统调用请求操作系统的服务。而系统中的各种共享资源都由操作系统内核统一掌管,因此凡是与共享资源有关的操作(如存储分配、/O操作、文件管理等),都必须通过系统调用的方式向操作系统内核提出服务请求,由…

qt 5.15.2 主窗体菜单工具栏树控件功能

qt 5.15.2 主窗体菜单工具栏树控件功能 显示主窗体效果&#xff1a; mainwindow.h文件内容&#xff1a; #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QFileDialog> #include <QString> #include <QMessageBox>#inc…

SFX的妙用——如何在不安装软件的情况下打开自定义格式文件?

前段时间看到群友讨论压缩包能不能运行&#xff0c;想起了n年前用自解压文件SFX实现的一个“需求”&#xff1a;在没有安装任何应用软件的Windows&#xff08;当时还要支持XP&#xff09;上能双击打开自定义格式的文件。当时第一反应是这“需求”太奇葩了&#xff0c;简直是不可…

【JavaScript】JS——Map数据类型

【JavaScript】JS——Map数据类型 什么是Map?特性Map与Object的比较 map的创建map的属性map相关方法map的遍历 什么是Map? 存储键值对的对象。 能够记住键的原始插入顺序任何值&#xff08;对象或原始值&#xff09;都可以作为键或值。 特性 Map中的一个键只能出现一次&am…

PAT乙级—1002 写出这个数(C语言)

读入一个正整数 n&#xff0c;计算其各位数字之和&#xff0c;用汉语拼音写出和的每一位数字。 输入样例&#xff1a; 1234567890987654321123456789 输出样例&#xff1a; yi san wu #include <stdio.h>int main() {char number[100] { \0 };int i 0, sum 0, n[8] {…

应用现代化加速企业数字化转型

目录 一、数字化转型的必要性 二、应用现代化的推动力 数字化时代&#xff0c;企业正面临着前所未有的挑战和机遇。为了保持竞争力&#xff0c;许多企业正在寻求数字化转型&#xff0c;以提升运营效率、优化客户体验、创新商业模式。本文将探讨如何通过应用现代化加速企业数字化…

c++11计时器chrono库

去实现一下开始说的高精度计时器&#xff1a; #ifndef _TimerClock_hpp_ #define _TimerClock_hpp_#include <iostream> #include <chrono>using namespace std; using namespace std::chrono;class TimerClock { public:TimerClock(){update();}~TimerClock(){}v…

MySQL和MongoDB简介以及它们之间的区别

本文主要介绍MySQL和MongoDB的简介以及它们之间的区别。 目录 MySQL简介MySQL的优缺点MySQL的应用场景MongoDB简介MongoDB的优缺点MongoDB的应用场景MySQL和MongoDB的区别 MySQL简介 MySQL是一种开源的关系型数据库管理系统&#xff0c;是世界上最流行的数据库之一。它支持多用…