【UVM】Factory Pattern In UVM

使用工厂模式可以动态的生成对象,能够封装具体类型的实例化操作,通过让子类型决定要创建的对象达到将对象创建的过程封装的目的.工厂机制不仅是OO的精华,也是UVM的基石,通过Factory机制实现了通过字符串创建实例,面对UVM测试平台中众多的组件,使用该机制可以方便实现组件的注册和创建,极大地简化了测试平台的搭建,可以说,Factory贯穿每一个UVM测试平台的始终,因此其重要性可见一斑。为此本文将以具体示例叙述工厂机制的基本原理。

UVM中,一般使用工厂机制主要实现以下几个操作:

1.注册;

2.实例化;

3.重载(通过类型或者名称进行重载);

为了简化UVM复杂的工厂机制的原理,本文以汽车的制造销售为例,简要阐述Factory工作的基本原理,示例结构与UVM源代码中Factory类似,但是功能不如UVM源代码完全,只为大家方便理解构建环境时一些奇怪的写法的原因。

【示例概述】工厂负责生产不同品牌汽车的部件,4S点可以根据工厂提供的部件组装汽车然后贴牌销售。基本结构如下图所示:

 


我们更好的分析整个汽车的实现过程,我们依据上图定义了如下几个类以实现上图描述的各个角色,各类的大致功能如下:

car_base为原型车,一般包括所有汽车的共性,例如轮子、方向盘等;

car_brand是基于原型车派生的各种类型的汽车,例如燃油汽车、电动汽车等;

下图为燃油汽车派生出的不同品牌的汽车,例如法拉利、劳斯莱斯、宾利等,当同品牌的汽车更新换代时,可以使用新一代的汽车代替(override)旧一代的汽车,例如雅阁9覆盖雅阁8

car_licence为制造销售汽车的许可证,其中包含了销售店铺必须具有的基本条件和要求等;

car_4s_proxy为取得销售汽车资质的销售不同品牌的店铺,本例中一个店铺仅制造销售一个品牌的汽车;

而制造销售店铺(car_4s_proxy)一般并不存放大量的具体汽车(car_brand),一般情况下客户都是到店里看车模或者宣传册,然后由店里向汽车部件生产制造商提出某品牌汽车部件需求,汽车生产制造工厂(car_factory)然后制造相关汽车相关汽车的部件。根据汽车销售和制造的流程,我们结合下述代码对工厂机制工作流程进行简要分析。

上图的类属框图如下图所示:

当客户想购买一辆Ferrari时,需要到取得销售Ferrari4s店进行购买,这个4s店通过该车定义时"`car_brand_utils(Ferrari)"与销售Ferrari4s店关联起来(成立一个销售Ferrari4s店),同时将该店注册到(factory.register)可以为该店生产汽车部件的生产工厂名录中(该工厂只为该名录中的4s店生产汽车部件),这样后续如果要生产Ferrari汽车部件,工厂就可以在其名录中找到对应的4s店,然后根据其销售汽车的品牌提供对应的服务。我们这里构建的工厂可以生产不同品牌的汽车部件,具体生产哪些品牌的汽车部件都是根据工厂名录决定的,4s店在得到具体汽车部件后进行组装,最终提供给用户。由此建立了三者之间的关系:制造、组装销售。

上例中Ferrari更新换代为了Ferrari_911,因此工厂对其修改名录进行更新,当用户来到4s店购买Ferrari时,4s店将最终提供的车型为新款的Ferrari_911,仿真结果如下:

为此我们对上述的购车活动再次进行细化分析。当顾客需要一辆Ferrari汽车的时候,调用4s店的"Ferrari::type_id::build_car",为了生产出具体的汽车,4s店的build_car会通知工厂准备对应的部件(create_object_by_type),工厂收到请求后准备好原材料,通知4s店,4s店通过build完成对应的Ferrari汽车的组装生产,生产组装完成的Ferrari就可以根据其功能进行使用了。整个买车四步走的过程如下图所示:

第一部:注册(宏定义);

第二步:调用对象创建函数(build_car);

第三部:具体示例化对象(build);

第四部:返回实例;


Ferrari更新换代出了一款新车Ferrari_911,这时就需要更新工厂的汽车更新换代名录(override),即对原有车型进行重载。首先调用工厂的car_factory::override_type("Ferrari","Ferrari_911"),因为override_type是静态函数,所以通过类名可以直接调用。override_type将关联数组中相应成员进行替换(修改名录),即override[Ferrari]=Ferrari_911,告诉工厂Ferrari存在更新换代记录,如果后续有Ferrari的需要,就生产新款车型部件。此时4s店对外宣传还是Ferrari,这样消费者就不用被乱七八糟的名字高的头晕脑胀了,而且4s店也不需要为了新车新购买设备或者重新装修进行任何更改,当调用create_object_by_type时,会首先查看产品手册中有没有Ferrari,即调用find_overridefind_override会检查数组override[string_name]中是否存在Ferrari更新换代的纪录,通过查找发现存在更新换代,于是返回新车需要的部件(return m_4s_names[override[Ferrari]],其中override[Ferrari]为调用override_type时的Ferrari_911),这样返回新车的部件后4s店就可以马上拼装汽车销售了。

这里讲buildbuild_car放在对应的4s店中实现,主要是因为每个品牌的汽车都有一些功能外形的不同,所以将这些差异性封装到不同的4s店中,那么工厂在生产不同部件时仅需要根据不同4s的特性进行模具调用即可,保证了同一个工厂可以制造不同品牌的汽车部件,同时不同的4s店可以对工厂返回的部件进行适应性修改,4s店和工厂也具有更大的灵活性。

我们在具体构建UVM的验证平台时,经常会遇到在类定义的开始处调用宏,其实与此例中的"`car_brand_utils(Ferrari)"作用类似,然后都是通过层层调用实现特定对象的实例化,与此例中的"Ferrari::type_id::build_car"工作原理类似,一个验证结构中的组件被一个新的组件重载的过程就类似与此例中的"car_factory::override_type("Ferrari","Ferrari_911")"

【示例】


这里需要注意以下几点:

1.静态函数或者变量可以通过类名直接引用;

2.definetypedef参数的传递;

3.静态变量和初始化发生在编译阶段;

4.关联数组类似于Perl等语言中的hash结构;

5.抽象类不能实例化,其派生类如果需要实例化需要实现抽象类中所有的纯虚方法(pure virtual);

6.抽象类中可以包括纯虚方法(仅存在于抽象类中),也可以包括有定义的非纯虚方法,纯虚方法不包括方法体,仅包括方法原型即可。


全部评论
那个图画的是非常的形象
点赞 回复 分享
发布于 2022-08-09 21:16

相关推荐

评论
1
1
分享

创作者周榜

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