在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 86032|回复: 161

[原创] UVM phase的用法研究------个人总结

[复制链接]
发表于 2013-3-19 17:08:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
明天开始,我把近期研究UVM phase的一些个人的想法和实践过程通过发帖的方式写出来,主要是通过一个复杂一点的自己想的例子来慢慢讲解和展现,结合自己看代码的理解。
      之所以UVM phase,是因为在UVM官方资料里面对UVM phase这块讲的东西比较少。

      俗话说,好记忆不如烂笔头,发个帖子,一来是给自己写点东西,很多东西知道和能写出来讲清楚是两码事;二来是抛砖引玉,希望各位同行慢陆续把你们自己对UVM的研究使用心得也表达出来,共同进步;我始终相信只有研究-》实战-》交流讨论-》再研究才是学好一门东西的路径。
在写的过程中,我会按照点来讲,可能顺序性不强,请大家谅解。
发表于 2013-3-20 00:04:39 | 显示全部楼层
phase只要记住:
1. build_phase是自上而下执行,其他至下而上执行
2. main_phase中,raise_objection
发表于 2013-3-20 12:21:59 | 显示全部楼层
顶,楼主好样的!
 楼主| 发表于 2013-3-20 14:43:09 | 显示全部楼层
以后这个总结中的任何观点都是个人观点,对与不对希望大家结合自己的经历和理解进行反驳、讨论。
另外需要说明一点的就是,我相信很多朋友都在坛子里下载过一份《UVM1.1应用指南和源代码分析》的资料,我很佩服这位前辈,我也从中收益匪浅,但是可惜在讲解phase的时候对一些初学者来说有些东西跳跃性有点大,更主要的是没有用一个稍微全面而复杂的例子来进行进一步的总结,让读者知道在实际项目中如何构建一个user-defined的phase组织架构图。我在这里也是志在狗尾续貂吧,废话少说,开始吧。

一、什么是phase?
      phase翻译成中文就是相、阶段的意思。在UVM中,官方的说法是:phase是使tb中各种各样的component按照各自的需求可以阶段性执行的一种自动化的机制。简单的说就是使验证组件能够按需自动化执行的一种机制。
二、OVM有phase的概念吗?
      有。那为什么OVM中没有看到在各个function 或者  task的形参表里看到(ovm_phase phase)呢?因为OVM已经为用户提供了现成的、固定的几个phase,它们是 new phase(对一个合格的tb来说,new phase是被 ovm root component在执行run_test()的时候通过factory机制调用的,也就是通过静态函数create调用的)、build phase、connect phase、end_of_elaboration phase、 start_of_simulation phase、run phase、extract phase、check phase、report phase。
     OVM 没有提供API给用户进行一些操作,比如增加一个phase、让不同的component的同一个phase异步的运行等等.......
三、UVM为什么在OVM的基础上扩展、增强这个功能?
     因为不够用所以才需要扩展,因为不完美用才需要增强。
     不完美体现在哪里?我提一点,其余的大家可以挖掘。
     一个正常的DUT,从上电到正常工作到关闭是一个相对比较通用的流程,所以把这些比较通用的流程放在一个run phase里面可以但不完美,那我把run phase按照这些通用流程拆分成几个子的阶段不是更好么?比如拆分成reset phase、configure phase、main phase、shutdown phase。
     不够用体现在哪里?我同样提一点,其余的大家继续挖掘、跟帖。
     一个大的chip里面有很多功能性比较独立的模块,这些功能性独立意味着一个模块A在run的时刻另一个模块B可以不run,也可以run,B运行不运行和A运行不运行关联度不大甚至没有关联,比如A是只负责处理发通路的而B只负责收通路;但是另一方面,功能性独立并不意味着什么都独立,举例来说,A模块和B模块功能性很独立,比如A是一个clock generation模块,B是一个processor模块,那在A没有正常work的前提下B是不能正常工作的。
      由此我们至少可以提出两点需求:
      (1)能不能让B的reset phase发生在A的reset phase之后,这样等待clock都稳定了再对B做reset操作或者release reset操作?
      (2)能不能让A的main phase和B的main phase异步的运行?
      上面两点至少需要用到UVM中的的如下机制:新建一个domain、给不同的component设置不同的domain、不同的domain之间phase的同步和异步。
      再如,功能更复杂的tb可能需要新建一个user-defined的phase,让它在某一需要个时刻点运行,可以是function性质的或者task性质的。

今天先开个头,明天准备聊聊UVM phase的组织结构。
发表于 2013-3-20 22:59:58 | 显示全部楼层
感谢大牛的细心总结和分享。

除了细分各个DUT模块的工作状态以外,个人还想到了一个实现phase转换的理由。那就是在很多config中的random items在一次simulation往往只是会被randomize一次,效率很低,function coverage的提高要消耗大量的regression testcase。个人感觉如果通过phase jump从extract phase或者report phase再跳转到reset phase/config phase,可以大大提高 verification efficiency。
 楼主| 发表于 2013-3-21 13:34:22 | 显示全部楼层
本帖最后由 asic_wang 于 2013-3-21 13:45 编辑

四、UVM phase的组织架构
    (1)在大学学习数据结构的时候,我们知道有几种基本的数据结构,其它的结构都可以分解成这几种的组合;它们分别是线性数据结构(比如链表)、树形结构(比如二叉树)、图形结构(有向图和无向图);
      UVM的phase的组织结构也不例外,都可以分解成上述三种。总体上来说,是按照有向图结构进行组织的。
    (2)既然是有向图形结构,那么这个数据结构中自然有若干节点和连接这些节点的有向边。另外,一个图也可以分解为若干个子图。
      在默认情况下,这些节点就像铁路的一个个站点,每个节点都有自己的属性;这里所说的属性就是指的是UVM库中定义的如下几种:
      UVM_PHASE_DOMAIN:它的含义是从我开始,到后面的某个节点为止,这期间经过的所有节点都是我的管辖范围。
      UVM_PHASE_SCHEDULE:它的含义和UVM_PHASE_DOMAIN相同,唯一的区别就是它不具有独立行动的权利,它的外面至少需要套一层UVM_PHASE_DOMAIN;形象点说,UVM_PHASE_DOMAIN可以代表整个图形结构或者代表某个子图结构,但是,UVM_PHASE_SCHEDULE则只能代表某个子图结构,它必须属于某个DOMAIN,也就是它必须被某个DOMAIN  wrapper起来!
      UVM_PHASE_NODE:它的含义是图形结构中的某一个节点,它是一个句柄,它自己不干具体的活(比如main phase具体要干什么)。
      UVM_PHASE_IMP:它的含义就是说它所代表的就是具体干什么活,上述的UVM_PHASE_NODE就是会指向某一个UVM_PHASE_IMP。
      UVM_PHASE_TERMINAL:它是用来标定UVM_PHASE_DOMAIN和UVM_PHASE_SCHEDULE的势力范围的!就是说我后面的节点就不是你们的管辖范围了,只有一个domain或者schedule才有这个东西。

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

      有向图中的边在UVM phase里则代表了运行的顺序,就是说这个节点过了,下个节点是哪些,我想这个应该比较好理解。
    (3)默认UVM phase的具体的图形结构
                                       common (UVM_PHASE_DOMAIN) id=204
                                                                     |
                                       build (UVM_PHASE_NODE) id=222
                                                                     |
                                       connect (UVM_PHASE_NODE) id=234
                                                                     |
                                       end_of_elaboration (UVM_PHASE_NODE) id=246
                                                                     |
                                       start_of_simulation (UVM_PHASE_NODE) id=258
                                             /                                 \
    run (UVM_PHASE_NODE) id=270         uvm (UVM_PHASE_DOMAIN) id=319
                                             |                                  |
                                             |         uvm_sched (UVM_PHASE_SCHEDULE) id=331
                                             |                                  |
                                             |                   pre_reset (UVM_PHASE_NODE) id=349
                                             |                                  |
                                             |                   reset (UVM_PHASE_NODE) id=361
                                             |                                  |   
                                             |             post_reset (UVM_PHASE_NODE) id=373
                                             |                                  |
                                             |        pre_configure (UVM_PHASE_NODE) id=385
                                             |                                  |
                                             |            configure (UVM_PHASE_NODE) id=397
                                             |                                  |
                                             |       post_configure (UVM _PHASE_NODE) id=409
                                             |                                  |
                                             |           pre_main (UVM_PHASE_NODE) id=421
                                             |                                  |
                                             |           main (UVM_PHASE_NODE) id=433
                                             |                                  |
                                             |        post_main (UVM_PHASE_NODE) id=445
                                             |                                  |
                                             |         pre_shutdown (UVM_PHASE_NODE) id=457
                                             |                                  |
                                             |         shutdown (UVM_PHASE_NODE) id=469
                                             |                                  |
                                             |       post_shutdown (UVM_PHASE_NODE) id=481
                                             |                                  |
                                             |    uvm_sched_end (UVM_PHASE_TERMINAL) id=337
                                             |                                  |
                                             |          uvm_end (UVM_PHASE_TERMINAL) id=325
                                              \                                  /
                                   extract (UVM_PHASE_NODE) id=277
                                                                |
                                   check (UVM_PHASE_NODE) id=289
                                                                |
                                   report (UVM_PHASE_NODE) id=301
                                                                |
                                    final (UVM_PHASE_NODE) id=313
                                                                |
                        common_end (UVM_PHASE_TERMINAL) id=210                              

      这个图的每个节点是通过调用m_print_successors()函数得到的,当然中间的“|”这些符号是我自己编辑的,这个函数在UVM class reference的pdf资料里没有提到,应该是UVM开发人员自己调试用的,但是如果你自己阅读代码就知道有这个函数,因为它不是local的,所以我们可以随时调用它。
      每个节点的名字,属性和id号都一清二楚,细心的朋友可能已经注意到了这些id号不是随机的,而是有顺序的,是的,它是按照这些节点的建立的先后顺序分配的,id越大表示越晚建立,实际上这个id号就是通过调用get_inst_id()得来的,这个函数是uvm_object的一个基本函数,我就不多讲这个了。
      从这个图中,我们可以得到如下几个重要的信息:
    (1)这张大的图形结构中有两个domain,一个叫做common,一个叫做uvm,这个概念很重要,以后的分析中会反复用到;
    (2)UVM中新加的12个phase(不包括final phase),从pre reset到post shutdown都被一个叫做uvm_sched的 SCHEDULE包起来了,作为一个子图隶属于uvm domain;
    (3)OVM和UVM中的run phase属于common domain;
    (4)start_of_simulation phase节点有两个后继节点:run phase node和uvm domain;

明天准备讨论一下当我们在top运行run_test()函数是,UVM phase发生了什么。
 楼主| 发表于 2013-3-22 15:21:55 | 显示全部楼层
五、UVM的phase是如何自动运行起来的
      从build phase到最后的final phase,自动运行会经过以下几个主要步骤:
     1、在tb_top.sv中的某个地方调用 run_test(),这个函数在uvm_root.sv中,是整个tb 树形组织结构的根节点,这个函数主要是干三件事情:
        (1)通过factory模式create你自己希望运行的testcase instance,不管你的testcase叫神马名字,最后uvm都会给它重命名为
                “uvm_test_top”
        (2)调用uvm phase的一个函数,叫做m_run_phases(),等下再讲这个函数主要干的事情
        (3)等待(2)结束,kill所有和(2)有关的进程,如果允许则调用$finish结束仿真,退出仿真器

     2、m_run_phases()主要干这么两件事情:
        (1)创建UVM默认的所有phases,即我们熟知的build phase、connect phase、run phase、main phase等等,并将其组织成我上
                面所讲的那个有向图结构;实现这一步主要是靠调用uvm_domain class中的get_common_domain()
        (2)开始运行(1)创建组织好的phases,当然如果有用户自定义的phase,也会在规定的点运行起来;实现这一步主要是靠调用对应
                的phase的execute_phase()函数和一个无限循环的监控进程
     3、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 规则所允许的图形结构,所以既然它这么重要,我们下一贴就准备专门来谈谈它!
     4、phase的execute_phase()函数主要干哪些事情呢?
          简单点说就是按照phase的有向图结构一个一个节点的走下去,知道结束;当然这个走的过程是复杂的、曲折的,呵呵,此函数也是比较
     复杂、曲折的;但是有一点,也是最主要最重要的一点,那就是它会调用每个节点所拥有的traverse()函数!正式通过这个函数,我们在
     各个phase中所写的自己的代码才得意被调用、执行!
          既然这个函数也是如此的重要,那我将用另一个帖子来专门讨论它一下。
     5、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(),没错,的确如此!
          注意到了这两个函数的形参表了么?我想大家都猜出它们是干什么用的吧。比如component A的build phase在执行,那么形参comp
     就是A,形参phase就是build。
     
     这一贴就讨论到这里,很多细节我没有讲,我觉得抓住主线了,那么枝节的东西不难理解,而且UVM class的源代码随处可下,要想弄个清楚明白,读源代码是必不可少的。如果设计到这一贴中的某些细节需要了解,可以联系我,我们私下讨论。
 楼主| 发表于 2013-3-22 15:23:13 | 显示全部楼层
不知道怎么回事,每次在编辑的时候对的都挺整齐的,发表之后就成了这个鸟样,请大家多包涵。。。。
发表于 2013-3-25 09:51:36 | 显示全部楼层
楼主的帖使人受益良多,望坚持下去!
 楼主| 发表于 2013-3-25 17:33:13 | 显示全部楼层
接下来两周有个chip要tapeout了,有几个ECO,会比较忙,我尽量抽空些,抱歉。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-4-26 00:37 , Processed in 0.031173 second(s), 6 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表