UVM:UVM的树形结构

        UVM采用树形的组织结构来管理验证平台的各个部分。sequencer、driver、monitor、agent、model、 scoreboard、env等都是树的一个结点。为什么要用树的形式来组织呢?因为作为一个验证平台,它必须能够掌握自己治下的所 有“人口”,只有这样做了,才利于管理大家统一步伐做事情,而不会漏掉谁。树形结构是实现这种管理的一种比较简单的方式。

(1)uvm_component中的parent参数

        UVM通过uvm_component来实现树形结构。所有的UVM树的结点本质上都是一个uvm_component。每个uvm_component都有 一个特点:它们在new的时候,需要指定一个类型为uvm_component、名字是parent的变量

function new(string name, uvm_component parent);

        一般在使用时,parent通常都是this。假设A和B均派生自uvm_component,在A中实例化一个B:

class B extends uvm_component;…
endclassclass A extends uvm_component;B b_inst;virtual function void build_phase(uvm_phase phase);b_inst = new("b_inst", this);endfunction
endclass

        在b_inst实例化的时候,把this指针传递给了它,代表A是b_inst的parent。为什么要指定这么一个parent呢?一种常见的观点 是,b_inst是A的成员变量,自然而然的,A就是b_inst的parent了,无需再在调用new函数的时候指定,即b_inst在实例化时可以这 样写:

b_inst = new("b_inst");

        这种写法看似可行,其实忽略了一点,b_inst是A的成员变量,那么在SystemVerilog仿真器一级,这种关系是确定的、可知 的。假定有下面的类:

class C extends uvm_component;A a_inst;function void test();…a_inst.b_inst =…;a_inst.d_inst =…;…endfunction
endclass

        可以在C类的test函数中使用a_inst.b_inst来得到B的值或者给B赋值,但是不能用a_inst.d_inst来给D赋值。因为D根本就不存在 于A里面。SystemVerilog仿真器会检测这种成员变量的从属关系,但是关键问题是它即使检测到了后也不会告诉A:你有一个成员 变量b_inst,没有一个成员变量d_inst。A是属于用户写出来的代码,仿真器只负责检查这些代码的合理性,它不会主动发消息给代 码,所以A根本就没有办法知道自己有这么一个孩子。
        换个角度来说,如果在test中想得到A中所有孩子的指针,应该怎么办?读者可能会说,因为A是自己写出的,它就只有一个 孩子,并且孩子的名字叫b_inst,所以可以直接使用a_inst.b_inst就可以了。问题是,假设要把整棵UVM树遍历一下,即要找到每个结点及结点的孩子的指针,那如何写呢?似乎根本就没有办法实现。
        解决这个问题的方法是,当b_inst实例化的时候,指定一个parent的变量,同时在每一个component的内部维护一个数组 m_children,当b_inst实例化时,就把b_inst的指针加入到A的m_children数组中。只有这样才能让A知道b_inst是自己的孩子,同时也 才能让b_inst知道A是自己的父母。当b_inst有了自己的孩子时,即在b_inst的m_children中加入孩子的指针。

(2)UVM树的根

        UVM是以树的形式组织在一起的,作为一棵树来说,其树根在哪里?其树叶又是哪些呢?从第2章的例子来看,似乎树根应 该就是uvm_test。在测试用例里实例化env,在env里实例化scoreboard、reference model、agent、在agent里面实例化sequencer、 driver和monitor。scoreboard、reference model、sequencer、driver和monitor都是树的叶子,树到此为止,没有更多的叶子了。
        关于叶子的判断是正确的,但是关于树根的推断是错误的。UVM中真正的树根是一个称为uvm_top的东西,完整的UVM树如下 图所示。

        uvm_top是一个全局变量,它是uvm_root的一个实例(而且也是唯一的一个实例 ,它的实现方式非常巧妙),而uvm_root 派生自uvm_component,所以uvm_top本质上是一个uvm_component,它是树的根uvm_test_top的parent是uvm_top,而uvm_top的 parent则是null。UVM为什么不以uvm_test派生出来的测试用例(即uvm_test_top)作为树根,而是搞了这么一个奇怪的东西作为树 根呢?
        在之前的例子中,所有的component在实例化时将this指针传递给parent参数,如my_env在base_test中的实例化:

env = my_env::type_id::create("env", this);

但是,假如不按照上面的写法,向parent参数传递一个null会如何呢?

env = my_env::type_id::create("env", null);

        如果一个component在实例化时,其parent被设置为null,那么这个component的parent将会被系统设置为系统中唯一的uvm_root的实例uvm_top,如下图所示。

        uvm_root的存在可以保证整个验证平台中只有一棵树,所有结点都是uvm_top的子结点。
        在验证平台中,有时候需要得到uvm_top,由于uvm_top是一个全局变量,可以直接使用uvm_top。除此之外,还可以使用如 下的方式得到它的指针:

uvm_root top;
top=uvm_root::get();

(3)层次结构相关函数

        UVM提供了一系列的接口函数用于访问UVM树中的结点。这其中最主要的是以下几个

(3.1)get_parent函数

        get_parent函数,用于得到当前实例的parent,其函数原型为:

extern virtual function uvm_component get_parent ();

(3.2)get_child函数

        与get_parent相对的就是get_child函数:

extern function uvm_component get_child (string name);

        与get_parent不同的是,get_child需要一个string类型的参数name,表示此child实例在实例化时指定的名字。因为一个component 只有一个parent,所以get_parent不需要指定参数;而可能有多个child,所以必须指定name参数

(3.3)get_children函数

        为了得到所有的child,可以使用get_children函数

extern function void get_children(ref uvm_component children[$]);

        它的使用方式为:

uvm_component array[$];
my_comp.get_children(array);
foreach(array[i])
do_something(array[i]);

(3.4)get_first_child和get_next_child

        除了一次性得到所有的child外,还可以使用get_first_child和get_next_child的组合依次得到所有的child:

string name;
uvm_component child;
if (comp.get_first_child(name))
do beginchild = comp.get_child(name);child.print();
end while (comp.get_next_child(name));

        这两个函数的使用依赖于一个string类型的name。在这两个函数的原型中,name是作为ref类型传递的:

extern function int get_first_child (ref string name);
extern function int get_next_child (ref string name);

        name只是用于get_first_child和get_next_child之间及不同次调用get_next_child时互相之间传递信息。无需为name赋任何初始 值,也没有必要在使用这两个函数过程中对其做任何赋值操作

(3.5)get_num_children函数

        get_num_children函数用于返回当前component所拥有的child的数量

extern function int get_num_children ();


 

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

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

相关文章

安防监控系统镜头选型分析,低噪声,低振动,多通道

安防镜头步进驱动选用型号 GC6107 C6109 GC6209 GC6119 GC6129 GC6139 GC6208 GC6150 GC6151 GC6152 GC6125 GC6236采用5V的镜头驱动 。其中GC6107 C6109 GC6209 GC6119 GC6129 GC6139 GC6208关键特性两通道,256细分,低噪,内部和外部时钟…

解决CentOS下PHP system命令unoconv转PDF提示“Unable to connect or start own listener“

centos系统下,用php的system命令unoconv把word转pdf时提示Unable to connect or start own listene的解决办法 unoconv -o /foo/bar/public_html/upload/ -f pdf /foo/bar/public_html/upload/test.docx 2>&1 上面这个命令在shell 终端能执行成功&#xff0c…

solidity案例详解(六)服务评价合约

有服务提供商和用户两类实体,其中服务提供商部署合约,默认诚信为true,用户负责使用智能合约接受服务及评价,服务提供商的评价信息存储在一个映射中,可以根据服务提 供商的地址来查找评价信息。用户评价信息&#xff0c…

HarmonyOS4.0从零开始的开发教程03初识ArkTS开发语言(中)

HarmonyOS(二)初识ArkTS开发语言(中)之TypeScript入门 浅析ArkTS的起源和演进 1 引言 Mozilla创造了JS,Microsoft创建了TS,Huawei进一步推出了ArkTS。 从最初的基础的逻辑交互能力,到具备类…

13年测试老鸟总结,性能测试常遇问题+解决方案+分析...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、内存溢出 1&a…

Cmkae外部依赖管理

文章目录 一、cmake依赖管理介绍二、源码依管理1. FetchContent与find_package进行集成 2. CPM3. git submodule附加: address_sanitizer 和 undefined sanitizer 一、cmake依赖管理介绍 CMake 是跨平台的构建系统,支持 C/C、Objective-C、Fortran 等多种…

Python第三次练习

Python 一、如何判断一个字符串是否是另一个字符串的子串二、如何验证一个字符串中的每一个字符均在另一个字符串中出现三、如何判定一个字符串中既有数字又有字母四、做一个注册登录系统 一、如何判断一个字符串是否是另一个字符串的子串 实现代码: string1 inp…

外包干了2个多月,技术明显有退步了。。。。。

先说一下自己的情况,本科生,19年通过校招进入武汉某软件公司,干了接近4年的功能测试,今年国庆,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

JVM:强软弱虚四种引用

下面依次解释五种引用 一、强引用 把一个对象赋值给一个引用变量,就相当于把这个对象的强引用放到变量中。 只要对象可达, GC一定不会回收这个对象(A1) 二、软引用 当一个对象(A2)没有强引用时&#xff…

Rust UI开发(五):iced中如何进行页面布局(pick_list的使用)?(串口调试助手)

注:此文适合于对rust有一些了解的朋友 iced是一个跨平台的GUI库,用于为rust语言程序构建UI界面。 这是一个系列博文,本文是第五篇,前四篇链接: 1、Rust UI开发(一):使用iced构建UI时…

网络安全(一)--网络环境构成,系统的安全

2. 网络攻防环境 目标 了解攻防环境构成了解入侵检测系统(平台)的部署位置 2.1. 环境构成 2.1.1. 环境框图 一个基本的网络攻防实验环境包括:靶机、攻击机、入侵检测分析系统、网络连接四部分组成。 一个基础的网络攻防实验环境需要如下…

【SpringCloud】通过Redis手动更新Ribbon缓存来解决Eureka微服务架构中服务下线感知的问题

文章目录 前言1.第一次尝试1.1服务被调用方更新1.2压测第一次尝试1.3 问题分析1.4 同步的不是最新列表 2.第二次尝试2.1调用方过滤下线服务2.2压测第二次尝试2.3优化 写到最后 前言 在上文的基础上,通过压测的结果可以看出,使用DiscoveryManager下线服务…

EasyExcel如何读取全部Sheet页数据方法

一、需求描述 Excel表格里面大约有20个sheet页,每个sheet页65535条数据,需要读取全部数据,并导入至数据库。 找了好多种方式,EasyExcel比较符合,下面看代码。 二、实现方式 采用EasyExcel框架的doReadAll()方法 1、…

Linux驱动开发学习笔记2《LED驱动开发试验》

目录 一、Linux下LED灯驱动原理 1.地址映射 二、硬件原理图分析 三、实验程序编写 1.LED 灯驱动程序编写 2.编写测试APP 四、运行测试 1.编译驱动程序和测试APP (1)编译驱动程序 (2)编译测试APP 2.运行测试 一、Linux下…

redis应用-分布式锁

目录 什么是分布式锁 分布式锁的基本实现 引入过期时间 引入校验id 引入lua 引入看门狗 引入redlock算法 什么是分布式锁 在一个分布式系统中,也会涉及到多个节点访问同一个公共资源的情况,此时就需要通过锁来做互斥控制,避免出现类似于"线程安全"的问题. 而…

Selenium无头模式容易遇到的坑

在无头模式下,我们看不到浏览器的操作,但是selenium无头模式的浏览器向服务器发送的请求头和正常模式下还是有点区别的,这就导致了一些网站会检测到我们是用selenium来访问的,从而导致一些问题 下面就是我在使用selenium无头模式时…

134. 加油站(贪心算法)

根据题解 这道题使用贪心算法,找到当前可解决问题的状态即可 「贪心算法」的问题需要满足的条件: 最优子结构:规模较大的问题的解由规模较小的子问题的解组成,规模较大的问题的解只由其中一个规模较小的子问题的解决定&#xff…

SpringSecurity(五)

深入理解HttpSecurity的设计 一、HttpSecurity的应用 在前章节的介绍中我们讲解了基于配置文件的使用方式,也就是如下的使用。 也就是在配置文件中通过 security:http 等标签来定义了认证需要的相关信息,但是在SpringBoot项目中,我们慢慢脱离…

SpringBoot读取properties文字乱码问题及相关问题

问题:在idea的编辑器中properties文件一般用UTF-8编码,SpringBoot2读取解码方式默认不是UTF-8,当值出现中文时SpringBoot读取时出现了乱码。 解决方式1:在SpringBoot框架层面解决,在配置类注解上添加encoding属性值为…

Linux---逻辑卷管理

本章主要介绍逻辑卷的管理。 了解什么是逻辑卷创建和删除逻辑卷扩展逻辑卷缩小逻辑卷逻辑卷快照的使用 前面介绍了分区的使用,如果某个分区空间不够,想增加空间是非常困难的。所以,建议尽可能使用逻辑卷而非普通的分区,因为逻辑卷…