上一节图片中说明了uvm平台中的各个组件以及其基本功能。这些组件相互连接构成了整个平台,那对于这些由类例化来的组件,我们是否需要完整的开发他们的全部功能呢?当然不用,因为uvm的基类库,已经将一个验证组件所需的基础功能写好,我们仅仅需要根据项目的实际需要添加具体功能即可,例如对于apb_driver,我们可以从uvm_driver派生得到,并且覆盖它的run_phase加入具体的驱动功能即可,不需要对其他部分进行改动。所以uvm的基类库为我们提供了很多方便,我们就来看一下这个基类库都提供了些什么。
这个图展示了uvm库中常用的大部分基类,我们构建自己的平台时所用的组件,都会派生自这些类。这个图展示了这些类的相互派生关系。这个是从其他网站的截图,最右边应该还有个uvm_agent派生自uvm_component。首先最原始的类是uvm_void,这个是个空壳什么,都没做,但是所有的uvm类全部由它派生得到。uvm_object直接从uvm_void派生而来,定义了类似create,copy clone, print, compare, pack,unpack这些功能。像是上节中讲到的config配置元素,就可以直接使用这个uvm_object基类。具体以上函数的用法与解释,可以直接看uvm基类库的代码,后边示例中也会有涉及。
之后uvm_object分为2个支线,一路通过uvm_report_object演化为uvm_component以及之后的各种组件,一路通过uvm_transaction演化为uvm_sequence_item和uvm_sequence。这两条线演化出的类有显著的不同。可以认为右边的类是各种动物,有生老病死的过程,并能进行各种动作,左边演化出的类是各种动物之间的语言文字,用来在不同的动物间相互传递信息。这样在整个验证平台中,就有各种猫猫狗狗相互呼来叫去,相互配合着完成各种动作。
uvm_transaction增加了诸如begin_tr end_traccept_tr等函数,使得普通的object具备基本的被传输的辅助功能。由于uvm_transaction并不会被直接用到,这些函数一般也不需要重入,所以这个类很少被用到。
从uvm_transaction派生得到uvm_sequence_item,这是一个uvm平台中非常常用的类,相当于各个部件之间传递的信息的最基本元素,可以类比为构成语言的单个单词。它定义了像set_sequencerget_sequencer以及一些report相关的函数。这几个函数在一般情况也不需要改变。在使用uvm_sequence_item时要做的最主要事情是定义这个基础信息元素的格式,比如一个读操作对应的数据,地址,读写使能信号的格式。
从uvm_sequence_item派生得到uvm_sequence_base,这个类定义了一个uvm_sequence所需的大部分的操作,uvm_sequence是多个连接在一起的uvm_sequence_item的集合,可以认为是多个部件之间传递的一个完整有意义的一段话。其中最主要的函数是start。当执行时,会以此执行以下操作。
//| sub_seq.pre_start() (task)
//| sub_seq.pre_body() (task) if call_pre_post==1
//| parent_seq.pre_do(0) (task) if parent_sequence!=null
//| parent_seq.mid_do(this) (func) if parent_sequence!=null
//| sub_seq.body (task) YOUR STIMULUS CODE
//| parent_seq.post_do(this) (func) ifparent_sequence!=null
//| sub_seq.post_body() (task) if call_pre_post==1
//| sub_seq.post_start() (task)
这些prepost可以认为是为方便修改发送行为设置的挂钩程序,而具体的信息发送行为,实在body任务中执行。在使用uvm_sequence的派生类时,最主要的任务是修改这个body任务。在实际的环境中,有时用uvm_do这个宏来执行某个sequence,虽然具体的执行跟start略微不同,但是主要也是触发body任务。
从uvm_sequence_base派生得到uvm_sequence,增加了几个request,response相关的函数,这里的request,response是连接driver,sequencer以传输sequence_item的一种机制,将在后边解释。另外需要指出的是uvm_sequence是一个参数化的类,这个参数就是构成uvm_sequence的uvm_sequence_item
uvm_object的另外一个分支得到uvm_report_object,这个主要增加了报告相关的函数,比如info,error,fatal以及verbosity的设置等,使得它的派生类对生成报告的控制更加方便灵活。
uvm_component是所有类中最关键,也是最复杂的一个类,它是的uvm_object这个普通的物件变成了一个有生命阶段的动物,并且可以与相互交换信息,执行操作。uvm_component最重要的函数任务就是他的不同phase,这对应着他们不同生命阶段要做的事情,再就是domain,这个可以认为是某个动物与哪些同步行动。另外还有config的设定,这可以认为是动物出生前的基因设定。以及typeoverride,这个可以认定是为动物置换器官或者更换行为方式等.
从uvm_component派生得到uvm_monitor uvm_driver等等这些具体的物种,是验证环境中执行具体操作的动物,他们在各自的位置上接受同伴的信息,执行具体的操作,共同完成任务。
uvm_monitor没有定义新的函数,使用时一般是在build_phase配置相关参数,run_phase或者main_phase设置数据收集转发的程序。
uvm_driver没有定义新的函数,使用时一般是在build_phase配置相关参数,run_phase或者main_phase设置数据发送的程序。uvm_driver也是一个参数化的类,参数为对应的uvm_sequence_item。
uvm_agent没有定义新的函数,使用时一般是在build_phase配置相关参数,connet_phase连接内部相关的driver和sequencer
uvm_env没有定义新的函数,使用时一般是在build_phase配置自身以及其下的uvm_agent uvm_driveruvm_monitor的相关参数
uvm_scoreboard没有定义新的函数,使用时一般是在build_phase配置相关参数,run_phase或者main_phase对不同端口数据进行比较检查,报告错误状态,另外在check_phase也可以对最终仿真结束后的状态进行检查,报告整个仿真的运行结果。
uvm_test没有定义新的函数,使用时一般是在build_phase配置相关参数,run_phase或者main_phase设置数据发送的程序,主要是选取特定的sequence进行发送。另外一般也在report_phase等运行后的时段打印一下仿真总结信息。
uvm_component派生得到uvm_sequencer_base,uvm_sequencer_param_base最后得到uvm_sequencer,这之间主要增加了有关 response, request,arbit的函数,其作用就是实现sequencer与driver进行相互协调,将sequence按需求发送出去。用户使用sequencer时基本不用做什么修改,只需要把对应的uvm_sequence_item类型指定一下即可
uvm_root由uvm_component派生得到,这个类跟其他的uvm_component有很大不同,它是一个singleton单实例,用户在使用uvm平台时,不用修改例化uvm_root,uvm平台会自动创建他的实例,并将它作为整个平台的最顶层。用户只需要在最顶层的module中执行run_test。这个uvm_root对应的uvm_top实例的run_test函数就会被执行,从而启动整个验证平台。
以上就是常用的一些类的相互关系以及他们提供的函数任务。用户构建的验证平台,可以借用这些组件已有的功能,构建自己的组件,并进行配置连接,以完成特定功能的平台。