UVM实战 卷I学习笔记11——UVM中的factory机制(3)


factory机制的实现

创建一个类的实例的方法

前面UVM根据run_test的参数my_driver创建一个my_driver的实例,这是factory机制的一大功能。

一般的面向对象的编程语言要创建一个类的实例有两种方法,一种是在类的可见的作用范围之内直接创建

class A
	… 
endclass
class B;
	A a;
	function new();
		a = new();
	endfunction
endclass

另外一种是使用参数化的类

class parameterized_class # (type T)
	T t;
	function new();
		t = new();
	endfunction
endclass
class A;
	… 
endclass
class B;
	parameterized_classs#(A) pa;
	function new();
		pa = new();
	endfunction
endclass

这样pa实例化时,其内部就创建了一个属于A类型的实例t。但如何通过一个字符串来创建一个类?这里的前提是这个字符串代表一个类的名字

class A;
	… 
endclass
class B;
	string type_string;
	function new();
		type_string = "A";
		//how to create an instance of A according to type_string
	endfunction
endclass

没有任何语言会内建一种如上的机制:即通过一个字符串来创建此字符串所代表的类的一个实例。如果要实现这种功能需要自己做,factory机制正是用于实现上述功能。

*根据字符串来创建一个类

factory机制根据字符串创建类的实例是如何实现的呢?要实现这个功能,需要用到参数化的类。假设有如下的类:

class registry#(type T=uvm_object, string Tname="");
	T inst;
	string name = Tname;
endclass

在定义一个类(如my_driver)时,同时声明一个相应的registry类及其成员变量:

class my_driver
	typedef registry#(my_driver, "my_driver") this_type;
	local static this_type me = get();
	static function this_type get();
		if(me != null) begin
			me = new();
			global_tab[me.name] = me;
		end
		return me;
	enfunction

向这个registry类传递了新定义类的类型及类的名称,并创建了这个registry类的一个实例。在创建实例时,把实例的指针和“my_driver”的名字放在一个联合数组global_tab中。上述的操作基本就是uvm_*_utils宏所实现的功能,只是uvm_*_utils宏做得更多、更好

当要根据类名“my_driver”创建一个my_driver的实例时,先从global_tab中找到“my_driver”索引对应的registry#(my_driver,“my_driver”)实例的指针me_ptr,然后调用me_ptr.inst=new()函数,最终返回me_ptr.inst。整个过程如下:

function uvm_component create_component_by_name(string name)
	registry#(uvm_object, "") me_ptr;
	me_ptr = global_tab[name];
	me_ptr.inst = new("uvm_test_top", null);
	return me_ptr.inst;
endfunction

基本上使用factory机制根据类名创建一个类的实例的方式就是这样。真正的factory机制实现起来会复杂很多,这里只是为了说明而将它们简化到了极致。

用factory机制创建实例的接口

factory机制提供了一系列接口来创建实例。

create_object_by_name用于根据类名字创建一个object,其原型为:

function uvm_object uvm_factory::create_object_by_name (string
														requested_type_name,
														string parent_inst_path="",
														string name="");

一般只使用第一个参数

my_transaction tr;
void'($cast(tr, factory.create_object_by_name("my_transaction")));

create_object_by_type,根据类型创建一个object,其原型为:

function uvm_object uvm_factory::create_object_by_type (uvm_object_wrapper
														requested_type,
														string parent_inst_path="",
														string name="");

一般也只使用第一个参数

my_transaction tr;
void'($cast(tr, factory.create_object_by_type(my_transaction::get_type())));

create_component_by_name,根据类名创建一个component,其原型为:

function uvm_component uvm_factory::create_component_by_name (string
															requested_type_name,
															string parent_inst_path="",
															string name,
															uvm_component parent);

第一个参数是字符串类型的类名,第二个是父结点的全名,第三个是为这个新component起的名字,第四个是父结点的指针。调用这个函数时这四个参数都要使用:

my_scoreboard scb;
void' ($cast(scb, factory.create_component_by_name("my_transaction", 
													get_full_name(), "scb", this)));

这个函数一般只在一个component的new或build_phase中使用

如果是在一个object中被调用则很难确认parent参数

如果是在connect_phase之后调用,由于UVM要求component在build_phase及之前实例化完毕,所以会调用失败。

uvm_component内部有一个函数是create_component,就是调用的这个函数:

function uvm_component uvm_component::create_component (string requested_type_name, 
														string name);

只有两个参数,factory.create_component_by_name中剩余的两个参数分别就是this和this.get_full_name()。

create_component_by_type,根据类型创建一个component,其原型为:

function uvm_component uvm_factory::create_component_by_type (uvm_object_wrap per
															requested_type,
															string parent_inst_path="",
															string name,
															uvm_component parent);

其参数与create_component_by_name类似,也需要四个参数齐全:

my_scoreboard scb;
void' ($cast(scb, factory.create_component_by_type(my_transaction::get_type(), 
													get_full_name(), "scb", this)));

factory机制的本质

在没有factory机制之前要创建一个类的实例,只能使用new函数。

但有了factory机制之后,可以根据类名创建这个类的一个实例;还可以在创建类的实例时根据是否有重载记录来决定是创建原始的类,还是创建重载的类的实例。

所以从本质上来看,factory机制其实是对SV中new函数的重载。因为这个原始的new函数实在太简单且功能太少。经过factory机制的改良之后,进行实例化的方法多了很多。这也体现了UVM编写的一个原则,一个好的库应该提供更多方便实用的接口,这种接口一方面是库自己写出来并开放给用户的,另外一方面就是改良语言原始的接口,使得更加方便用户的使用。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值