[CU]factory机制4-factory机制重载的前提,方式,复杂重载,常用重载(factory机制重载)
1. factory机制重载的前提
(1) 无论是重载的类(extended class)还是被重载的类(base class),都要在定义时注册到factory机制中.
(2) 被重载的类(base class)在实例化时,需要使用factory机制式的实例化方式,而不是传统的new方式.
(3) 重载的类与被重载的类有派生关系. 重载的类必须派生自被重载的类,被重载的类必须是重载类的父类.
(4) component与object之间互相不能重载(二者new函数的参数也不同).
注1:重载语句一定要放在例化之前,注意build_phase中重载语句与例化语句的先后顺序;
2. factory机制重载的方式
2.1. 代码中重载
2.1.1 使用uvm_component内的重载函数
(1) set_type_override_by_type
1 function void uvm_component::set_type_override_by_type (uvm_object_wrapper original_type, 2 uvm_object_wrapper override_type, 3 bit replace=1); 4 uvm_coreservice_t cs = uvm_coreservice_t::get(); 5 uvm_factory factory=cs.get_factory(); 6 factory.set_type_override_by_type(original_type, override_type, replace); 7 endfunction
1 //示例 2 class my_component extends uvm_component; 3 my_driver driver; 4 ... 5 virtual function void build_phase(uvm_phase phase); 6 super.build_phase(phase); 7 driver=new("driver",this); //new函数实例方式不能实现覆盖; 8 ... 9 endfunction 10 11 endclass 12 13 class my_component extends uvm_component; 14 my_driver driver; 15 ... 16 virtual function void build_phase(uvm_phase phase); 17 super.build_phase(phase); 18 driver=my_driver::type_id::create("driver",this); 19 ... 20 endfunction 21 22 endclass 23 24 class new_driver extends my_driver; 25 ...//add more functionality here; 26 endclass 27 28 //test.sv or env.sv 29 virtual function void build_phase(uvm_phase phase); 30 super.build_phase(phase); 31 set_type_override_by_type(my_driver::get_type(), new_driver::get_type()); 32 endfunction
(2) set_type_override
1 function void uvm_component::set_type_override (string original_type_name, 2 string override_type_name, 3 bit replace=1); 4 uvm_coreservice_t cs = uvm_coreservice_t::get(); 5 uvm_factory factory=cs.get_factory(); 6 factory.set_type_override_by_name(original_type_name,override_type_name, replace); 7 endfunction
(3) set_inst_override_by_type
1 function void uvm_component::set_inst_override_by_type (string relative_inst_path, 2 uvm_object_wrapper original_type, 3 uvm_object_wrapper override_type); 4 string full_inst_path; 5 uvm_coreservice_t cs = uvm_coreservice_t::get(); 6 uvm_factory factory=cs.get_factory(); 7 8 if (relative_inst_path == "") 9 full_inst_path = get_full_name(); 10 else 11 full_inst_path = {get_full_name(), ".", relative_inst_path}; 12 13 factory.set_inst_override_by_type(original_type, override_type, full_inst_path); 14 15 endfunction
注1:注意transaction的层次路径;
1 //示例 2 class test_da_3_inst extends test_base; 3 //utils and constructor not shown; 4 virtual function void build_phase(uvm_phase phase); 5 super.build_phase(phase); 6 //set_inst_override("env.i_agent*.seqr.*","transaction","packet_da_3"); 7 set_inst_override_by_type("env.i_agent*.seqr.*",transaction::get_type(),packet_da_3::get_type()); 8 endfunction 9 10 endclass
(4) set_inst_override
1 function void uvm_component::set_inst_override (string relative_inst_path, 2 string original_type_name, 3 string override_type_name); 4 string full_inst_path; 5 uvm_coreservice_t cs = uvm_coreservice_t::get(); 6 uvm_factory factory=cs.get_factory(); 7 8 if (relative_inst_path == "") 9 full_inst_path = get_full_name(); 10 else 11 full_inst_path = {get_full_name(), ".", relative_inst_path}; 12 13 factory.set_inst_override_by_name( 14 original_type_name, 15 override_type_name, 16 full_inst_path); 17 endfunction
2.1.2 使用uvm_factory类的重载函数
(1) set_type_override_by_type(uvm_object_wrapper orignial_type, uvm_object_wrapper override_type, bit replace=1)
(2) set_type_override_by_name (string original_type_name, string override_type_name, bit replace=1)
(3) set_inst_override_by_type(uvm_object_wrapper original_type, uvm_object_wrapper override_type, string full_inst_path)
(4) set_inst_override_by_name(string original_type_name, string override_type_name, string full_inst_path)
注1:系统中存在uvm_factory类型的全局变量factory,可以在initial语句中使用如下方式调用:
1 //示例 2 initial begin 3 factory.set_type_override_by_type(bird::get_type(),parrot::get_type()); 4 end
2.1.3 使用uvm_component_registry#(T,Tname)/uvm_object_registry#(T,Tname)的set_type_override函数
1 class uvm_object_registry #(type T=uvm_object, string Tname="<unknown>") 2 extends uvm_object_wrapper; 3 ... 4 static function void set_type_override (uvm_object_wrapper override_type, 5 bit replace=1); 6 uvm_coreservice_t cs = uvm_coreservice_t::get(); 7 uvm_factory factory=cs.get_factory(); 8 factory.set_type_override_by_type(get(),override_type,replace); 9 endfunction 10 ... 11 endclass
1 class uvm_component_registry #(type T=uvm_component, string Tname="<unknown>") 2 extends uvm_object_wrapper; 3 ... 4 static function void set_type_override (uvm_object_wrapper override_type, 5 bit replace=1); 6 uvm_coreservice_t cs = uvm_coreservice_t::get(); 7 uvm_factory factory=cs.get_factory(); 8 factory.set_type_override_by_type(get(),override_type,replace); 9 endfunction 10 ... 11 endclas
1 //示例 2 class user_agent_base extends uvm_agent; 3 `uvm_component_utils(user_agent_base) 4 ... 5 endclass 6 7 class user_agent extends user_agent_base; 8 `uvm_component_utils(user_agent) 9 ... 10 endclass 11 12 class user_env extends uvm_env; 13 `uvm_component_utils(user_env) 14 user_agent_base agent_base; 15 ... 16 function void build_phase(uvm_phase phase); 17 super.build_phase(.phase(phase)); 18 agent_base=user_agent_base::type_id::create("agent_base",this); 19 endfunction 20 ... 21 endclass 22 23 class user_test extends uvm_test; 24 `uvm_component_utils(user_test) 25 ... 26 27 function void build_phase(uvm_phase phase); 28 user_agent_base::type_id::set_type_override(user_agent::get_type()); 29 super.build_phase(.phase(phase)); 30 endfunction 31 32 endclass
2.2. 命令行中重载
注1:使用时,不要随意引入空格;
1 <sim cmd> +uvm_set_inst_override=<req_type>,<override_type>,<full_inst_path> 2 <sim cmd> +uvm_set_type_override=<req_type>,<override_type>[,<replace>]
3.factory机制之复杂重载
3.1 连续重载
1 //示例 2 class parrot extends bird; 3 class big_parrot extends parrot; 4 5 function void my_case0::build_phase(uvm_phase phase); 6 bird bird_inst; 7 parrot parrot_inst; 8 super.build_phase(phase); 9 10 set_type_override_by_type(bird::get_type(), parrot::get_type()); 11 set_type_override_by_type(parrot::get_type(), big_parrot::get_type()); 12 13 bird_inst=bird::type_id::create("bird_inst"); //big_parrot 14 parrot_inst=parrot::type_id::create("parrot_inst"); //big_parrot 15 endfunction
3.2 替换重载
(1)在有多个重载时,最终重载的类要与最初被重载的类有派生关系. 最终重载的类必须派生自最初被重载的类, 最初被重载的类必须是最终重载类的父类.
1 //示例 2 class parrot extends bird; 3 class sparrow extends bird; 4 5 //example1: 6 function void my_case0::build_phase(uvm_phase phase); 7 bird bird_inst; 8 parrot parrot_inst; 9 super.build_phase(phase); 10 11 set_type_override_by_type(bird::get_type(),parrot::get_type()); 12 set_type_override_by_type(bird::get_type(),sparrow::get_type()); 13 14 bird_inst=bird::type_id::create("bird_inst"); //sparrow 15 parrot_inst=parrot::type_id::create("parrot_inst"); //parrot 16 endfunction 17 18 19 //example2: 20 function void my_case0::build_phase(uvm_phase phase); 21 bird bird_inst; 22 parrot parrot_inst; 23 super.build_phase(phase); 24 25 set_type_override_by_type(bird::get_type(),parrot::get_type()); 26 set_type_override_by_type(parrot::get_type(),sparrow::get_type()); 27 28 bird_inst=bird::type_id::create("bird_inst"); //sparrow 29 endfunction
4.factory机制之常用重载
4.1. 重载transaction
1 function void my_case0::build_phase(uvm_phase phase); 2 3 super.build_phase(phase); 4 factory.set_type_override_by_type(my_transaction::get_type(),crc_err_tr::get_type()); 5 uvm_config_db#(uvm_object_wrapper)::set(this,"env.i_agt.sqr.main_phase","default_sequence",normal_sequence::type_id::get()); 6 7 endfunction
4.2. 重载sequence
1 class case_sequence extends uvm_sequence #(my_transaction); 2 ... 3 virtual task body(); 4 normal_sequence nseq; 5 repeat(10) begin 6 `uvm_do(nseq) 7 end 8 endtask 9 ... 10 endclass 11 12 function void my_case0::build_phase(uvm_phase phase); 13 super.build_phase(phase); 14 factory.set_type_override_by_type(normal_sequence::get_type(), abnormal_sequence::get_type()); 15 uvm_config_db#(uvm_object_wrapper)::set(thi,"env.i_agt.sqr.main_phase","default_sequence",case_sequence::type_id::get()); 16 17 endfunction
4.3. 重载component
scoreboard与参考模型等都可以重载;尤其对于参考模型而言,处理异常的激励源是比较耗时的事情; 可能对于一个DUT来说,其80%的代码都是用于处理异常情况,作为模拟DUT的参考模型来说,更是如此;
(1) 如果将所有的异常情况都用一个参考模型实现,那这个参考模型的代码量将会非常大;
(2) 如果将参考模型分散为数十个参考模型,每一个处理一种异常情况,当建立相应异常的测试用例时,将正常的参考模型由它替换掉;这样,可使代码清晰,并增加了可读性;