In reply to jianfeng.he:
You can create a lookup table that associates a transaction type with a driver type. uvm_object_wrapper is a proxy class that serves as an object representing a uvm_class type without actually creating an object of that type.
uvm_object_wrapper lookup[uvm_object_wrapper];
initial begin
lookup[base_trans::get_type()] = drv#(base_trans)::get_type();
lookup[user_def_trans::get_type()] = drv#(user_def_trans)::get_type();
lookup[user_def_abn_trans::get_type()] = drv#(user_def_abn_trans)::get_type();
tr0 = new;
tr1 = new;
tr2 = new;
$display("--------------------");
create_drv(tr0);
$display("--------------------");
create_drv(tr1);
$display("--------------------");
create_drv(tr2);
end
function void create_drv(base_trans tr0);
$cast(driver,lookup[tr0.get_object_type()].create_component($sformatf("drv_%0s",tr0.get_type_name()),null));
driver.create_tr();
endfunction
It's very unusual to be creating transaction objects in the UVM's build_phase. You can apply this technique for create transaction proxy objects instead of transaction objects directly.
uvm_object_wrapper lookup[uvm_object_wrapper];
uvm_object_wrapper tr0, tr1,tr2
initial begin
lookup[base_trans::get_type()] = drv#(base_trans)::get_type();
lookup[user_def_trans::get_type()] = drv#(user_def_trans)::get_type();
lookup[user_def_abn_trans::get_type()] = drv#(user_def_abn_trans)::get_type();
tr0 = base_trans::get_type();
tr1 = user_def_trans::get_type();
tr2 = user_def_abn_trans::get_type()
$display("--------------------");
create_drv(tr0);
$display("--------------------");
create_drv(tr1);
$display("--------------------");
create_drv(tr2);
end
function void create_drv(uvm_object_wrapper tr0);
$cast(driver,lookup[tr0].create_component($sformatf("drv_%0s",tr0.get_type_name()),null));
driver.create_tr();
endfunction