Sunday, February 14, 2016

type_id::create simplified.

With UVM we use type_id::create to create object of any class. We do not use new. It is because we can override that class without changing single line of your code by help of uvm_factory.

How type_id::create works, that I will try to show you by very simple example.

class u_object; // Think of it as uvm_object
endclass
class u_registry #(type T=u_object); // Think of it as uvm_object_registry #(type T=uvm_object, string Tname="<unknown>")
  static function T create();
    u_object obj;
    u_registry#(T) me;
    me = new();
    obj = me.create_object();
    $cast(create,obj);
  endfunction
  function u_object create_object();
    T obj;
    obj = new();
    return obj;
  endfunction
endclass
class transaction extends u_object;
  int i;
  typedef u_registry #(transaction) type_id; // Assume this line will be added when we write `uvm_object_utils(transaction)
  virtual function display();
    i = 25;
    $display("i is %0d",i);
  endfunction
endclass
module test();
transaction pkt;
initial
begin
  pkt = transaction::type_id::create(); // transaction::type_id is 
                                        // u_registry #(transaction)
                                        // u_registry #(transaction)::create()
                                        // so we called static function create which will
                                        // return object of type transaction.
  pkt.display();
end
endmodule
Output :
i is 25 (run here)

1. pkt = transaction::type_id::create() will do pkt=u_registry #(transaction)::create()
2. create is a static method. In this method we have created object of own class type "me"
3. "me.create_object" will return handle of "transaction" object of type u_object
4. As return type of create_object is u_object, we will downcast it with "transaction" type by $cast in "create" method.
5. Retrun type of "create" is T ("transaction"), so finally object of type "transaction" returned to "pkt"

Now, how can we override transaction class with another class (say transaction_1) by factory.

UVM Factory method is
transaction::type_id::set_type_override(transaction_1::get_type());

Without going in to the details of factory, I will just give an essence that how factory will override pkt to contain handle of transaction_1 instead of transaction.

Check out below code. I have just changed (keeping rest of the code same)
pkt = transaction::type_id::create(); to
pkt = transaction_1::type_id::create();
(Above change will be done by factory when we call set_type_override, 
 this change is just for explanation purpose)

class u_object;
endclass
class u_registry #(type T=u_object);
  static function T create();
    u_object obj;
    u_registry#(T) me;
    me = new();
    obj = me.create_object();
 //create = me.create_object();
 $cast(create,obj);
  endfunction
  function u_object create_object();
 T obj;
    obj = new();
    return obj;
  endfunction
endclass
class transaction extends u_object;
  int i;
  typedef u_registry #(transaction) type_id;
  virtual function display();
    i = 25;
    $display("i is %0d",i);
  endfunction
endclass
class transaction_1 extends transaction; // derived transaction class
  typedef u_registry #(transaction_1) type_id;
  function display();
    i = 50;
    $display("i is %0d",i);
  endfunction
endclass
module test();
transaction pkt;
initial
begin
  pkt = transaction_1::type_id::create(); // Check this change
  pkt.display();
end
endmodule
Output
i is 50 (run here) 
Now create will return object of type transaction_1 instead of transaction.
Check the output.

No comments:

Post a Comment