IC验证学霸笔记4——UVM-类库地图、工厂机制及覆盖方法

1 类库地图

UVM 验证方法学作为所有方法学的融合之体,其初衷是将验证过程中可以重用和标准化的部分规定在其类库当中,以一种标准化的方式减轻验证人员构建环境的负担。

验证环境的共同需求:

1. 组件的创建和访问;

2.环境的结构构建,各组件之间的连接和运行;

3.不同阶段的顺序安排;

4.激励的生成、传递和控制;

5.测试的报告机制。

1.核心基类:提供最底层的支持,包括一些基本的方法,如复制,创建,比较和打印。
2.工厂(factory)类:提供注册环境组件,创建环境组件和覆盖组件类型的方法。
3.事务(transaction)和序列(sequence)类:用来规定在TLM(transaction level model)传输管道中的数据类型和数据生成方式。
4.结构创建(structure creation)类
5.环境组件(environment component)类:构成验证结构的主要部分,组件之间的嵌套关系通过层层例化和连接形成结构层次关系。
6.通信管道(channel)类:实现数据储存。
7.信息报告(message report):将UVM 报告信息一致化,便于整体的控制和过滤。
8.寄存器模型(register model):完成对寄存器存储的建模,访问和验证。
9.线程同步(thread synchronization)类:同步是传递更多的信息。
10.事务接口(transaction interface)类:实现组件之间的通信。

2 工厂机制

UVM工厂的存在就是为了更方便地覆盖验证环境中的实例或者注册了的类型,同时工厂的注册机制也带来了配置的灵活性。

UVM 的验证环境可以分为两部分,一部分构成了环境的层次,这部分代码通过uvm_component类实现;另一部分构成了环境的属性(配置)和数据传输,这部分代码通过uvm_object类实现。uvm_ component类继承于uvm_object类。

注册、创建实例: 
注册 component/object 范式:
uvm_{component,object}_utils(comp/obj_type);

创建component范式
comp_type::type_id::create(string name, uvm_component parent);

创建object范式:
object_type::type_id::create(string name);

一般运用工厂的步骤:

1. 将类注册到工厂;

2. 在例化前设置覆盖对象和类型;(可选)

3.对象创建。

创建对象时,需要结合工厂的注册和覆盖机制来决定应该使用component还是object来创建对象。

uvm_component::new(name,parent)保留两个参数,一种类似与钩子的做法,一层层由底层勾住上一层,将整个UVM 结构串起来。

uvm_object::new(name)没有parent参数,因此也不会显示在UVM 层次中,只能作为transaction和configuration用来做抽象数据传输的数据结构体和传递的配置结构体。

除了使用component/object来创建实例,factory也提供了创建范例:

creat_component/object_by_name( )

creat_component/object_by_type( )

uvm_component/object 提供了配合工厂注册,创建和覆盖的相关方法:

create()

create_component( )

get ( )

get_type_name()

set_inst_override()

set_type_override( )

3 覆盖方法

覆盖机制将其原来某些类型替换为一个新的类型

在覆盖之后,原本用来创建原属类型的请求,将由工厂来创建新的替换类型。

无需修改原始代码,继而保证的原始代码的封装性;
新的替换类型必须与被替换类型相兼容,否则稍后的句柄赋值将失败,所以使用继承。
要想实现覆盖特性, 原有类型和新类型均需要注册。

覆盖发生时, 可以使用类型覆盖或者实例覆盖:
•    类型覆盖指,UVM层次结构下的所有原有类型都被覆盖类型所替换;
•    实例覆盖指, 在某些位置中的原有类型会被覆盖类型所替换。



uvm_object_wrapper override_type
并不是一个实际的句柄,是注册过后的某一个类在工厂中注册时的句柄,可通过new_type::get_type()找到;

bit replace=1  

1表示如果已经有覆盖存在, 那么新的覆盖会替代旧的覆盖。0表示 如果已经有覆盖存在, 那么该覆盖将不会生效。

rig_type::tpe_id::set_type_override(new_type::get_type());


•    string inst_path指向的是组件结构的路径字符串
•    uvm_component parent=null
如果缺省, 表示使用inst_path 内容为绝对路径
如果有值传递, 则使用 {parent.get_full_name(),'.', inst_path}来作为目标路径。

orig_type:: type_id::set_inst_override(new_type::get_type(), "orig_inst_path")

覆盖实例:



输出结果:
comp2覆盖了comp1类型解析:
comp1:: type_id::set_type_override(comp2::get_type());
•    接着若对c1和c2对象进行了创建,可以从输出结果看到,c1的所属类型仍然是 comp1, c2的所属类型则变为了comp2。这说明了factory的覆盖机制只会影响通过factory注册并且创建的对象。
•    所以通过type_id::create( )和factory的类型覆盖可以实现对象所属类型在例化时的灵活替换。
•    在例化c2之前,首先应该用comp2来替换comp1的类型。只有先完成了类型替换,才可以在后面的例化时由factory选择正确的类型。
•    在后面发生了类型替换以后,如果原有的代码不做更新,那么c2句柄的类型仍然为comp1, 但却指向了comp2类型的对象。这就要求,comp2应该是comp1的子类,只有这样,句柄指向才是安全合法的。
•    c2在调用hello()方法时,由于首先是comp1类型,那么会查看comp1::hello(),又由于该方法在定义时被指定为虚函数,这就通过了多态性的方法调用,转而调用了comp2::hello()函数。因此,显示的结果也是"comp2:: c2 said hello!"

覆盖发生在创建之前,层次越高配置覆盖优先级越高。

首先需要知道, 有不止一个类提供与覆盖有关的函数, 然而名称与参数列表可能各不相同:
•    uvm _ component::set_{type, inst}_override{_by_type}
•    uvm _ component:,_registry: :set_{type, inst}_override
•    uvm_object_registry: :set_{type, inst}_override
•    uvm_factory:: set._{ type , inst}_override

整个UVM世界的构建, 离不开factory的三个核心要素: 注册、 创建和覆盖

最后,笔者根据实验内容新加一部分代码,覆盖该文的所有重点:





注:优秀验证学员随堂笔记,已经征求到学生的同意,会持续给牛友们分享!
大家看完记得 一键三连!多多支持


#做项目##深度学习##芯片设计工程师##芯片IC验证工程师##你为什么选择硬件行业#
全部评论

相关推荐

程序员花海:实习和校招简历正确格式应该是教育背景+实习+项目经历+个人评价 其中项目经历注意要体现业务 实习经历里面的业务更是要自圆其说 简历模板尽可能保持干净整洁 不要太花哨的
点赞 评论 收藏
分享
评论
3
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务