路科验证的个人空间 https://blog.eetop.cn/1561828 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

UVM结构篇之一:组件家族

已有 6266 次阅读| 2018-1-13 18:31 |个人分类:验证系统思想|系统分类:芯片设计

在我们之前《SV组件实现篇》中,那几位verifier们分别就着MCDF的几个模块实现了验证环境的组件。这些验证组件的按照功能的需要,分别称之为激励器(stimulator)、监测器(monitor)和检查器(checker)。这三个核心的组件与验证环境的三个关键特性对应,即激励、监测和检查。在过往的那么多的验证方法学中,都有与其对应的组件(component)。我们接下来要介绍的便是UVM的组件家族。


首先,回顾上一章的《类库地图》,可以看到从UVM的核心基类中继承一个核心的分支,即uvm_component类。



从uvm_component类继承而来的类均可以构成验证环境,这是因为它们都从uvm_component类继承了phase机制,都会经历各个phase阶段。本节中我们主要介绍构成环境的常见组件类:

  • uvm_driver

  • uvm_monitor

  • uvm_sequencer

  • uvm_agent

  • uvm_scoreboard

  • uvm_env

  • uvm_test


uvm_driver

该类会将从uvm_sequencer中获取的事务(transaction)经过转化,进而在硬件接口中对其进行时序激励。任何继承于uvm_driver的类需要注意的是,该类是参数化的类,因此在定义时需要声明参数的类型。首先看看uvm_driver类的定义:

class uvm_driver #(type REQ=uvm_sequence_item, type RSP=REQ) extends uvm_component;


用户在定义新的driver类时,应当声明该类获取的是事务类参数REQ类型,默认情况下,RSP参数类型同REQ类型保持一致。实际上,driver在uvm_component基础上没有扩展新的函数,而只是扩展了一些用来通信的端口:

uvm_seq_item_pull_port #(REQ, RSP) seq_item_port;

uvm_analysis_port #(RSP) rsp_port;

REQ req;

RSP rsp;


driver类与sequencer类之间的通信就是为了获取新的事务对象,这一操作是通过pull的方式实现的:

driver.seq_item_port.connect(sequencer.seq_item_export);

driver.rsp_port.connect(sequencer.rsp_export);


更多关于组件之间的通信方式,我们将会在下一章《UVM通信篇》中详细介绍。


uvm_monitor

从名字来看,这个类是为了监测接口数据的,而任何需要用户自定义数据监测行为的monitor都应当继承于该类。虽然,uvm_monitor与它的父类相比,并没有增添新的成员和方法,但将monitor类都继承于uvm_monitor有助于实现父类monitor的方法和特性。


uvm_sequencer

uvm_sequencer就如同一个管道,从这个管道中会产生连续的激励事务,并最终通过与driver的端口送至driver一侧。如果需要的话,uvm_sequencer也可以从uvm_driver那里获取随后的RSP对象来得知数据通信是否正常。


uvm_sequencer恐怕是这些组件中技能最超凡的一个成员了,单从它的继承层级就可见一斑。从uvm_sequencer类的定义来看,它也同uvm_driver一样是个参数类,需要在定义sequencer的时候声明REQ的类型。


在uvm_sequencer与uvm_component之间还多了两个中间类uvm_sequencer_base和uvm_sequencer_param_base。sequencer既管理着sequence,同时也将sequence中产生的transaction item传送到driver一侧,可以说是整个激励环节中的“路由器”。

而就sequence、sequencer与driver之间的缠绵悱恻的故事,路桑将会在后面的《UVM序列篇》中详细介绍。


uvm_agent

uvm_agent本身不具备什么神技,但它却是一个标准的验证环境“单位”。这样的一个单位中,通常应该包含一个driver、一个monitor以及一个sequencer。这三个小伙伴经常是聚在一起,组成一个小团伙agent。同时为了复用,有的时候uvm_agent中只需要包含一个monitor,而不需要driver和sequencer,这就需要通过一个变量来进行有条件的例化。

uvm_active_passive_enum is_active = UVM_ACTIVE;


is_active是agent的一个成员,缺省值是UVM_ACTIVE,这表示处在active模式的agent需要例化driver、monitor和sequencer;而如果is_active的值是UVM_PASSIVE,这表示agent是passive模式,只可以例化monitor。active模式的agent既有激励功能也有监测功能,passive模式的agent只具有监测功能。active模式对应着DUT的接口暴露给agent需要激励的场景,而passive模式对应着DUT的接口已经连接只需要监测的场景。


通过is_active变量,agent需要在build_phase()和connect_phase()等函数中通过选择语句来对driver和sequencer进行有条件的例化和连接。下面这段例码是个如何对agent内三个组件进行有条件例化的参考。




uvm_scoreboard

从名字来看,uvm_scoreboard担任着同SV中介绍的checker一样的功能,即进行数据比对和报告。uvm_scoreboard本身也并没有额外的成员变量和方法,但UVM建议用户将检查器类继承与uvm_scoreboard,这也便于日后的子类可以自动继承于可能被扩充到uvm_scoreboard中的成员。在实际环境中,uvm_scoreboard会接收来自于多个monitor中的监测数据,进行比对和报告。也正由于uvm_scoreboard通用的比较数据的特性,UVM自带的其它两个用来做数据比较的类则很少被使用到:

  • uvm_in_order_comparator #(type T)

  • uvm_algorithm_comparator #(type BEFORE, type AFTER, type TRANSFORMER)


uvm_in_order_comparator是一个参数类,并且它有两个端口

uvm_analysis_export #(T) before_export;

uvm_analysis_export #(T) after_export;


分别用来从DUT的输入端的monitor和输出端的monitor获取观测到的数据事务。该数据事务时将多个时钟周期内的数据整合为更高抽象级别的数据对象,而且要求是前后端监测到数据事务类型应该相同。为了进行数据比对,用户应该事先定义好需要的type T类,并且事先必要的函数compare()和convert2string()函数。这是因为uvm_in_order_comparator类会间接调用type T类的T::compare()函数进行数据比对,并且记录数据比较成功和失败的次数;同时在比较数据时如果发生不匹配,也会调用T::conver2string()将两个数据事务对象的内容进行报告。


uvm_algorithm_comparator也是一个参数类,只不过它的参数数目要更多。这是为了贴合更多实际的场景中,DUT的输入端监测数据格式不同于输出端数据格式,因此type BEFORE与type AFTER两个类不相同,同时用户也应该提供一个用来将type BEFORE转换为type AFTER类的转换类type TRANSFORMER。至于uvm_algorithm_comparator类的实现,它是内嵌了一个uvm_in_order_comparator作为数据比对的基础,在比较之前,用户需要实现BEFORE类和AFTER类的compare()、conver2string()函数,同时也应当实现TRANSFORMER类的transform()函数。这样便可以将接收到的BEFORE类,通过TRANSFORMER::transform()函数转化为AFTER类送给其内置的uvm_in_order_comparator对象,保证提供给uvm_in_order_comparator对象的输入端和输出端的数据类型一致,最终完成数据比对。


而在更多的项目实践中,上面这两种类很少被使用的一个主要原因是,“一千个验证者就有一千个比较器”。UVM在开发初始,期望通过一般化的原则提取比较的主要方式,提供给用户两个更具有可维护性的类,但这仍然难以阻止用户们打扮自己的scorebaord,而不怎么热衷于使用这两个有碍于他们发挥横溢才华的盒子。


uvm_env

从将来的环境层次结构而言,uvm_env中可能包含多个uvm_agent和其它的component。这些不同的组件共同构成一个完成的验证环境,而这个环境在将来的复用中可以作为子环境被进一步集成到更高的环境中来。譬如下面的图中就定义了一个高层的环境,它里面包含sub-env、agent、scoreboard等:

从这个结构层次的例子可以看出,uvm_env的角色就是一个结构化的容器,可以容纳其它的组件,同时它本身也可以作为子环境在更高层的集成中被例化嵌入。在实际使用当中,用户容易混淆uvm_env与uvm_agent之间的嵌套关系,而且容易在创建对象阶段出现错误,这里建议的嵌套关系是:

  • uvm_agent作为一个标准单元,在更上层的集成中,应该使用uvm_env来集成。

  • uvm_env在更高层的复用中,可以使用新的uvm_env来集成。


uvm_test

uvm_test类本身没有什么新的成员,但是它作为测试用例的“代言人”,不但决定着环境的结构和连接关系,也决定着测试使用哪一个序列。如果没有这个代言人,整个环境都无从建立,所以uvm_test是验证环境建立的唯一入口,只有通过它才能正常运转UVM的phase机制。下面是一个示例,可以看到,在一个顶层的test中可以例化多个组件,譬如uvm_env或者uvm_agent。而在仿真时,通过uvm_test可以实现验证环境的运转。但实际上,我们推荐在uvm_test中例化一个顶层的uvm_env,这便于提供一个唯一的环境,形成树状的拓扑结构,而这种环境结构也对应着一种树状的配置结构。

在下一节当中,我们再结合之前的设计MCDF,运用UVM的组件来搭建各个模块的验证环境和通过复用来完成MCDF的子系统集成环境。


谢谢你对路科验证的关注,也欢迎你分享和转发真正的技术价值,你的支持是我们保持前行的动力。



点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 253

    粉丝
  • 25

    好友
  • 33

    获赞
  • 45

    评论
  • 访问数
关闭

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

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

GMT+8, 2024-4-27 09:34 , Processed in 0.022146 second(s), 12 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部