为了遵循验证计划完成不同的验证任务,用户可能需要扩展原始的通用验证环境。验证过程是动态的,可重用验证环境的开发人员无法预见未来每一个corner case验证的项目需求。
UVM factory是经典软件开发中工厂设计模式(factory design pattern)的实现,该模式用于创建通用代码,从而在运行时(run-time)确定对象的确切子类型。对于以下可重用的类定义:
//UVM Non-Factory Allocation
class driver extends uvm_component
`uvm_component_utils(driver)
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction
virtual task drive_transfer();
...
endtask
endclass:driver
class agent extends uvm_component; // bad example that uses new()
`uvm_component_utils(agent)
driver my_driver;
function new(string name, uvm_component parent);
super.new(name,parent);
// create the driver
my_driver= new ("my_driver", this) ; // using new()
endfunction
endclass:agent
这个示例直接使用new()创建对象。假设用户希望将agent集成到验证平台中并希望使用drive_transfer()任务打印信息,我们需要实现新的driver组件:
class my_project_driver extends driver;
`uvm_component_utils(my_project_driver)
virtual task drive_transfer();
super.drive_transfer();
`uvm_info("MYIHF01","Finisheddriving transfer", UVM_LOW)
endtask
function new(string name, uvm_component parent);
. . .
endfunction
endclass:my_project_driver
agent会实例化先前定义的driver而不是扩展的my_project_driver,验证平台集成人员需要修改agent类等所有直接或者间接实例化driver的类定义,这会造成代码修改的连锁反应。
UVM factory引入了一种优雅的解决方案(elegant solution),允许对当前的类进行覆盖。UVM factory不是使用new()而是使用create()方法进行对象创建:
//Using the UVM Factor
class agent extends uvm_component;
`uvm_component_utils(agent)
driver my_driver;
function new(string name, uvm_component parent);
super.new(name,parent);
// create the driver
my_driver= driver::type_id::create("my_driver",this);
endfunction
endclass:agent
创建此代码后,用户可以使用以下方法覆盖所有driver:
set_type_override_by_type(driver::get_type(),my_project_driver::get_type());
或者用户可以使用以下方法替换driver的特定实例:
set_inst_override_by_type("env0.agent0.driver",driver::get_type(),
my_project driver::get_type();
要使用UVM factory,应遵循以下步骤:
1.在factory内注册所有类。
通过使用宏`uvm_object_utils和`uvm_component_utils自动实现objects和components的注册。
2.使用API创建objects和components。
my_driver = driver :: type_id :: create(“ my_driver”,this);
3.在创建(create)对象之前,使用类型(type)和实例(instance)替换当前类。
class state extends uvm_component;
`uvm_component_utils(state)
function new(string name, uvm_componentparent);
super.new(name, parent);
endfunction : new
function void end_of_elaboration();
this.print();
endfunction : end_of_elaboration
endclass : state
class florida extends state;
`uvm_component_utils(florida)
function new(string name, uvm_componentparent);
super.new(name, parent);
endfunction : new
endclass : florida
class new_york extends state;
`uvm_component_utils(new_york)
function new(string name, uvm_componentparent);
super.new(name, parent);
endfunction : new
endclass : new_york
state my_state1, my_state2;
// Start UVM Phases
initial begin
my_state1 =state::type_id::create("my_state1", null);
`uvm_info("INF01",{“my_state1.type=",my_state1.get_type_name()},UVM_LOW)
// set factory to allocate new_yorkstate whenever a state is created
factory.set_type_override_by_type(state::get_type(),new_york::get_type());
my_state2 =state::type_id::create("my_state2", null);
`uvm_info("INF02",{"my_state2.type=",my_state2.get_type_name()},UVM_LOW)
#100 $finish;
end
Line1:定义state基类
Lines10-21: 从基类派生florida和new_york类
Line 22: 声明两个state句柄state1和state2.
Lines 25-26: 使用factory API state::type_id::create(...)创建state对象
Line28: 使用factory 机制替换当前基类
Line29:创建新对象
最终打印结果是:
UVM_INFO ./test.sv(51)@0: reporter [INFO1] my_state1.type=state
UVM_INFO ./test.sv(54)@0: reporter [INFO2]my_state2.type=new_york
往期精彩