[UVM源代码研究] 浅谈UVM PHASE机制的运行

[UVM源代码研究] 浅谈UVM PHASE机制的运行

PHASE机制作为UVM最为强大的功能之一,本人的理解可能只有冰山一角,今天也只敢抱着边学习边写便理解的态度来研究研究其内部实现,所以这里只敢用“浅谈”一词,可能还存在很多理解不到位或者“标为超纲”的内容。

开始分析之前我们先看一些PHASE相关的基本概念(全局类型)phase可以分为以下几种类型
在这里插入图片描述

  • UVM_PHASE_IMP:下图中所有phase都属于Phase实现类,这些phase只拥有单一对象,且都会实现exec_func或exec_task的方法用来调用用户定义在环境组件(uvm_component)中的各种xxxx_phase函数或者任务。它的含义就是说它所代表的就是具体干什么活,UVM_PHASE_NODE就是会指向某一个具体的UVM_PHASE_IMP。
    在这里插入图片描述

  • UVM_PHASE_DOMAIN:Phase域的概念比较抽象,它用来表示整个由节点(node)构成的有向无环图(graph)。如果有一组环境组件属于某个Phase域,那么这些组件中定义的各个phase函数/任务的执行就会遵循其所属Phase域的图。它的含义是从我开始,到后面的某个节点为止,这期间经过的所有节点都是我的管辖范围。

  • UVM_PHASE_SCHEDULE:Schedule对象包含了一组节点,以及这些节点的连接关系,所以它也可以看成是Phase域的子集。Schedule对象通过这些节点和连接关系来表征Phase的执行顺序。它的含义和UVM_PHASE_DOMAIN相同,唯一的区别就是它不具有独立行动的权利,它的外面至少需要套一层UVM_PHASE_DOMAIN;形象点说,UVM_PHASE_DOMAIN可以代表整个图形结构或者代表某个子图结构,但是,UVM_PHASE_SCHEDULE则只能代表某个子图结构,它必须属于某个DOMAIN,也就是它必须被某个DOMAIN wrap起来!例如我们源代码中run_time phase相关的12个节点就被调用add_uvm_phases()添加到了m_uvm_schedule中,然后m_uvm_schedule又被添加到了m_uvm_domain中,m_uvm_domain又被添加到了m_common_domain中。

  • UVM_PHASE_NODE:Node节点对象跟实现类比较容易混淆。节点是用来构成有向无环图的基本元素。节点对象包含一个重要的成员变量m_imp,该成员变量引用某一个实现类对象(IMP object)。也就是说,如果你有多个Phase域,那么在每个Phase域中都可以存在指向同一个实现类对象的节点。它的含义是图形结构中的某一个节点,它是一个句柄,它自己不干具体的活(比如main phase具体要干什么)。

  • UVM_PHASE_TERMINAL:这是一个比较特殊的类别,专门用来表示图中最末尾的节点,它没有什么其他大的作用。在代码实现上,在构造有向无环图的过程中,可以通过识别该节点来插入前序需要执行的节点。它是用来标定UVM_PHASE_DOMAIN和UVM_PHASE_SCHEDULE的势力范围的!就是说我后面的节点就不是你们的管辖范围了,只有一个domain或者schedule才有这个东西。

UVM_PHASE_NODE和UVM_PHASE_IMP的关系如果不好理解的话,你可以对照TLM中的port、export、和imp来理解,这样就容易些了;像port、export只负责传话或者发号施令,而imp才比较苦逼,是真正干活的。

将上面的这些概念跟Phase机制串起来:UVM中Phase机制的执行遵循一张图。这里的“图”,就是图论中的有向无环图,有节点有连接有方向。每一个Phase域拥有一张图(图中的节点需要add进去),图的每一个节点引用一个实现类对象,节点之间的有向连接表示这些实现类对象被处理的顺序。这里的“处理”指的是完成一轮Phase状态的跳转,在不同Phase状态下调用该节点m_imp引用的实现类对象中对应的函数。参与仿真的环境组件都会属于某一个Phase域,默认的Phase域为common_domain,其中的节点会在调用get_common_domain的时候自动添加。

Domian节点图的构造 通过uvm_phase::add方法来构造用于指导phase执行的有向无环图。
在这里插入图片描述

这里有必要对singleton(单例)做一下解释,这是设计模式的常用方法,我们在UVM种经常使用,例如uvm_root、uvm_factory,单例模式的使用特点就是定义的类都会提供一个get方法来获取类的实例,并且是唯一实例,如下图所示。
在这里插入图片描述
在这里插入图片描述

uvm_root的单例模式
在这里插入图片描述
在这里插入图片描述

uvm_factory的单例模式
使用单例模式的类一般不需要实例化,它只是提供了一些需要全局使用的方法、字段等等。这样我们就清楚了uvm_phase继承出来的UVM_PHASE_IMP类型的这些phase(uvm_build_phase等等)都是单例模式的应用。
在这里插入图片描述

接着我们从之前研究run_test()时uvm_phase里的m_run_phases()这个静态方法作为phase机制运行的入口开始说起。

该静态方法在uvm_phase里的定义如下
在这里插入图片描述

m_run_phases()主要干这么两件事情:

  1. 创建UVM默认的所有phases,即我们熟知的build phase、connect phase、run phase、main phase等等,并将其组织成我们前面会提到的有向无环图结构;实现这一步主要是靠调用uvm_domain中的get_common_domain

  2. 开始运行1中创建组织好的phases,当然如果有用户自定义的phase,也会在规定的点运行起来;实现这一步主要是靠调用对应的phase的execute_phase方法和一个无限循环的监控进程

uvm_domain的定义如下图所示
在这里插入图片描述

首先我们注意到uvm_domain是从uvm_phase继承而来的。这里对uvm_domain的理解可以认为是用来隔离不同的uvm_component在run-time phase的phase域(很多文章用的是时钟域,个人觉得这里用phase域更为准确,即统一domain的run-time phase是同步的),而run_phase和各个function phase在不同的uvm_component始终是保持同步的。如下图所示两个不同的domain中的driver的run-time phase是可以不同步的。
在这里插入图片描述

而我们看到uvm_domain里充斥了大量的static变量和方法,目的是为了存放全局性的domain信息,这样全局都可以通过uvm_domain类来直接获取这些static信息。

下面看看get_common_domain里都在做些什么
在这里插入图片描述

关于common_domain,指的是除run-time phases之外的phase域,根据我们上面的分析,这部分phase在所有的domain里都是同步执行的。

uvm_domain中的get_common_domain主要是干这么三件事情:

  1. 创建我上述phase有向图结构的第一部分,即
    build->connect->end_of_elaboration->start_of_simulation->run->extract->check->report->final。
    很自然的实现这个功能需要用到两个函数:创建它们用new函数,组织它们让它们有如此先后顺序用add函数

  2. 创建我上述phase有向图结构的第二部分,即
    pre_reset->reset->post_reset->pre_configure->configure->post_configure->pre_main->main->post_main->pre_shutdown->shutdown->post_shutdown。
    很自然的实现这个功能需也要用到两个函数:创建它们用new函数,组织它们让它们有如此先后顺序用add函数

  3. 正如phase有向图结构所示,(2)搞出来的东西是作为一个子图呈现在(1)所搞出来的结构中的;那么怎嘛让(2)搞出来的东西就成了(1)所搞出来的东西的一部分了呢?而且还要和run phase并行的运行呢?还是要靠这个add函数!只不过需要用到add函数形参表中一个叫做with_phase的东西,显而易见,这个定义在uvm phase class中的add函数真是无比的重要,正式它让我们可以根据需要把一个个phase节点组织成一个任意的被UVM 规则所允许的图形结构

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

以上的add函数可以理解为把相应的phase节点添加到common_domain中,随后再对uvm_domain中的一些static变量做了赋值方便全局引用,用到了find等方法以及其他一些变量如下图所示
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

以上内容完成了对common_domain的创建,接着继续回到m_run_phases()里看后续执行内容。

这里的m_phase_hopper是一个mailbox,定义如下
在这里插入图片描述

1848行将common_domain添加到该mailbox中随后1856行执行commain_domain里添加的各个phase节点。,这里用的是fork…joine,如果有自定的domain此时也可以同步进行。

关于这个excute_phase就是phase机制运行的核心代码,phase的execute_phase函数主要干哪些事情呢?

简单点说就是按照phase的有向图结构一个一个节点的走下去,直到结束;它会调用每个节点所拥有的traverse函数!正是通过这个函数,我们在各个phase中所写的自己的代码才得意被调用、执行!traverse函数主要干的事情就是根据每个节点的属性来调用我们自己重载的各个phase方法。主要是两个函数一个是exec_func(uvm_component comp, uvm_phase phase),

一个是exec_task(uvm_component comp, uvm_phase phase)。

很自然的我们想到,执行build phase这种function性质的就会调用exec_func,执行如main phase这种task性质的就会调用exec_task,没错,的确如此!这两个方法的形参列表里的comp对应该方法所被调用的uvm_component实参,phase对应phase运行阶段的UVM_PHASE_IMP(如uvm_build_phase对应的单例等)。

这里需要介绍下phase各个状态的跳转顺序,涉及到uvm_state的枚举类型
在这里插入图片描述
在这里插入图片描述

各个phase_state的跳转描述如下图所示
在这里插入图片描述

上面简单介绍了phase机制的运行过程,下面再介绍下phase的分类。

uvm_phase衍生的phase分成了三大类:uvm_topdown_phase、uvm_bottomup_phase和uvm_task_phase。

uvm_topdown_phase作为所有需要自顶向下执行的phase的父类,例如uvm_build_phase,uvm_final_phase。
在这里插入图片描述
在这里插入图片描述

uvm_bottomup_phase作为所有需要自下而上执行的phase的父类,包括所有除uvm_build_phase和uvm_final_phase之外的所有的function phase,如uvm_connect_phase等。
在这里插入图片描述
在这里插入图片描述

uvm_task_phase顾名思义是task相关的phase的父类,包括uvm_run_phase以及12个分解的runtime_phase
在这里插入图片描述
在这里插入图片描述

仔细看下源代码可以发现,以上几个父类的核心函数在于traverse方法,它递归调用UVM树形结构上每个组件的traverse方法。

uvm_topdown_phase跟uvm_bottomup_phase的区别在于traverse childen放在execute前执行还是后执行,先traverse的话那就是先执行children里的execute再执行自己的execute,对应的就是bottomup,反之则是topdown,如下图所示

在这里插入图片描述
在这里插入图片描述

这就是我们在学习function phase时所谓phase执行顺序的同一层次按照字母顺序、不同层次深度优先执行的具体实现原理,具体的一个例子见下图
在这里插入图片描述

这里还发现UVM源代码里其实是有问题的,就是uvm_task_phase的execute这么个function调用了exec_task这样一个task,虽然说execute里用了fork…join_none来保证不消耗时间,但是我记得systemverilog语法有规定function是不能调用task的,这里提出一个小小的疑问。
在这里插入图片描述
在这里插入图片描述

以上就是关于uvm_phase源代码的一些个人理解与解读,有些函数、类的解读只是蜻蜓点水不仅详细,有些执行过程也没有具体深究,花了两天左右的时间研究还只是分析了冰山一角,后面有深入理解后继续补充,讲的有问题的也欢迎评论区留言指正。

  • 25
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值