文章目录
前言
如果我们用Systemverilog构建验证平台,构建好了之后,想改变平台中的某个组件,例如将driver改成driver_new,我们需要重新定义一下driver_new,当然也可以直接从driver继承。但是我们还需要在driver对象例化的地方将driver drv;改成driver_new drv;,如果需要多个组件的更新、以及多次的平台复用,那代码量巨大,而且每次改变都要深入平台内部,非常繁琐。
基于上述问题,UVM提出了factory机制,译作工厂机制,来源于设计模式中的工厂机制。
factoy机制意思是:通过将拓展类在工厂注册,可实现环境内部组件的创建与对象的重载
factory机制主要针对构成验证环境层次的uvm_component及其子类,以及构成环境配置属性和数据传输的uvm_object及其子类
`
一、注册
使用factory机制的第一步就是将类注册到工厂。这个factory是整个全局仿真中存在且唯一的“机构”,所有被注册的类才能使用factory机制。
使用宏进行注册
`uvm_component_utils(my_agent) //component注册macro
`uvm_component_utils_begin(my_agent) //注册factory的同时,可注册field automation
//...
`uvm_component_utils_end
`uvm_component_param_utils(my_driver) //参数化的component注册,例class my_driver #(int width = 32) extends uvm_driver;
`uvm_component_utils_param_begin(my_driver) //注册factory的同时,可注册field automation
//...
`uvm_component_utils_param_end
`uvm_object_utils(my_transaction) //object注册macro
`uvm_object_utils_begin(my_transaction) //注册factory的同时,可注册field automation
//...
`uvm_object_utils_end
`uvm_object_param_utils(my_sequence) //参数化的object注册,例class my_sequence #(int width = 32) extends uvm_sequence;
`uvm_object_utils_param_begin(my_sequence) //注册factory的同时,可注册field automation
//...
`uvm_object_utils_param_end
UVM-1.2中,这个所谓的全局唯一factory其实存在于uvm_coreservice_t类中,该类包含了UVM核心组件和方法。该类不是uvm_component和uvm_object型的,而是独立于UVM的。
二、创建
创建就是实例化对象,所有注册到factory的类均可通过factory独特的方式实例化对象。
但factory的独特方式,实际上也是调用了new函数,也是先创建句柄再赋予对象。
代码如下(示例):
class my_agent extends uvm_agent;
`uvm_component_utils(my_agent) //注册
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction
//...
endclass
my_agent agt; //创建my_agent句柄
agt = my_agent::type_id::create("agt", env); //factory独特且最常用的例化方式,创建了my_agent实例并返回句柄,本质还是调用的my_agent::new(name,parent);
class my_sequence extends uvm_sequence;
`uvm_object_utils(my_sequence) //注册
function new(string name); //object不属于uvm层次结构,不需要parent
super.new(name);
endfunction
//...
endclass
my_sequence seq; //创建my_sequence句柄
seq = my_sequence::type_id::create("seq"); //factory独特且最常用的例化方式,创建了name为"seq"的my_sequence实例,并返回句柄
2.1. 建议使用 drv = my_driver::type_id::create(“drv”,agt); 创建
简单好用,当然也有其他方法,不过可能涉及到$cast或是引入factory
2.2. 使用factory创建
提供了原型
//...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_factory.svh
pure virtual function
uvm_object create_object_by_type (uvm_object_wrapper requested_type,
string parent_inst_path="",
string name="");
pure virtual function
uvm_component create_component_by_type (uvm_object_wrapper requested_type,
string parent_inst_path="",
string name,
uvm_component parent);
pure virtual function
uvm_object create_object_by_name (string requested_type_name,
string parent_inst_path="",
string name="");
● uvm_object_wrapper requested_type:用于表示对象类型
函数原型为
//...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_object.svh
virtual class uvm_object extends uvm_void;
extern static function uvm_object_wrapper get_type ();
extern virtual function uvm_object_wrapper get_object_type ();
...
endclass
其他形参,string parent_inst_path、string name和uvm_component parent依次表示父节点路径(object不需要)、对象name、父节点句柄
直接使用factory方法创建,注意要用全局唯一uvm_factory类对象factory调用上述方法,并且上述方法返回类型不是uvm_object就是uvm_component,所以要用$cast作类型转换。
例子如下
class my_test extends uvm_test;
`uvm_component_utils(my_test);
my_transaction t;
...
function void build_phase(uvm_phase phase);
super.build_phase(phase);
void'($cast(t,factory.create_object_by_type(my_transaction::get_type(),,"t"))); //注意使用void'()令返回为空
...
endfunction
endclass
2.3. 使用uvm_component方法创建
一般是在component内创建其他component或object,所以uvm_component类也提供了创建的方法
//...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_component.svh
extern function uvm_component create_component (string requested_type_name,
string name);
extern function uvm_object create_object (string requested_type_name,
string name="");
也要注意使用$cast做类型转换
————————————————
版权声明:本文为CSDN博主「Starry丶」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Starry__/article/details/122930959