在UVM中,我们不应该一直使用new()构造新的components和transactions,而应该从某个查找表中申请创建新的components和transactions,这种创建方式称为factory机制。
首先在定义components和transactions的时候同时将其注册到查找表中,然后使用create()方法创建components和transactions。也就是说,通过UVM factory机制可以无需更改测试平台代码就可以完成components和transactions的替换
STEP1:Factory Registration
每个UVM components和transactions都必须进行注册,如下代码所示:
注册components
// Registration ofa UVM Component
class my_driver extends uvm_driver;
`uvm_component_utils(my_driver)
//Default Constructor
function new (string name = "my_driver",uvm_component parent = null);
super.new(name, parent);
endfunction
...
endclass: my_driver
注册transactions
// Registration of a transaction
class my_transaction extends uvm_sequence_item;
`uvm_object_utils(my_transaction)
//Default Constructor
function new (string name = "my_ transaction ");
super.new(name);
endfunction
...
endclass: my_transaction
上述代码中的new()只是用作创建默认的components和transactions
STEP2:Component & Object Creation:
在UVM的factory机制中在较高层级components和transactions中创建较低层次的components和transactions。
class my_driver extends uvm_driver #(my_transaction);
`uvm_component_utils(my_driver)
function new (string name = "my_driver",uvm_component parent = null);
super.new(name, parent);
endfunction
task run_phase (uvm_phase phase);
my_transaction transaction;
transaction = my_transaction::type_id::create("transaction",this);
...
endtask: run_phase
endclass: my_driver
class my_agent extends uvm_agent;
`uvm_component_utils(my_agent)
my_driver drv;
function new (string name = "my_agent",uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase (uvm_phase phase);
super.build_phase(phase);
drv = my_driver::type_id::create("drv",this);
endfunction: build_phase
endclass: my_agent
在上面的代码中,在my_driver类中的run phase完成my_transaction的创建,在my_agent类中的build_phase完成my_driver的创建,这是因为transactions和components在仿真过程中生命周期的区别
STEP3:Type Overriding(set_type_override)
上述STEP1和STEP2只是换了种方式完成transactions和components的创建工作,factory机制中更精髓的地方是在test case中通过set_type_override替换经过factory注册过的transactions和components,而不需更改整个验证环境
class my_base_testextends uvm_test;
`uvm_component_utils(my_base_test)
my_env env;
function new (string name, uvm_componentparent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
my_driver::type_id::set_type_override(my_new_driver::get_type(),1);
env = my_env::type_id::create("env",this);
endfunction: build_phase
task run_phase (uvm_phase phase);
...
endtask: run_phase
endclass: my_base_test