Below information is copied from Mentor Graphics blog. Keeping it in my blog for my reference.
Below is the original link of topic.
http://blogs.mentor.com/verificationhorizons/blog/2011/02/13/parameterized-classes-static-members-and-the-factory-macros/
*********************************************************************************
When you declare a parameterized class, it is more like a template, or generic class than a real class type. Only specializations of parameterized classes are real types. Suppose I have the two class definitions in the table below:
The class A definition by itself creates the static variable A::name 
initialized with the string “packet” without any other reference to 
class A. As soon as you add parameters to a class definition, like the 
parameter w in class B, the class becomes a generic class and the
 static variable name does not get created. As soon as there are 
specializations of the class B, each unique specialization causes the 
static variables inside the class to be instantiated.  The following 
statements create two specializations of class B and two instances of 
the static variable.  B#(2)::name and B#(3)::name are both set to 
“packet”.
The two class variable declarations (B3_1h and B3_2h) represent only 
one unique specialization of B because its parameters have the same 
value in both declarations. The variable B#(1)::name does not exist 
unless there is some other reference to B or B#(1) somewhere else.
What if you wanted the static string variable name to have a different value for each unique specialization of B? You could write something like
Now assuming the previous typedef and variable declarations above, 
B#(2)::name would have the value “packet2” and B#(3)::name would have 
the value “packet3”. There would be no instance B#(1)::name and the 
string “packet1” would never have been generated.
Below gives, complete example of static variable in param class.
_______________________________________________________________________________
module static_in_param_class();
class A#(int w = 1);
static string name = "packet";
    
endclass
initial
begin
A#(2) A1;
// $display("Value of static variable is %s", A::name); // Valid only for un-parameterized class. If class A has no parameters, this works.
$display("Value of static variable is %s", A1.name); // If class A has parameters as shown, It will be generic class, we need to create a handle with specific parameter and can access the static member only with handle.
end
endmodule
_________________________________________________________________________________
Now let us go back to the `ovm_object_utils macro. Suppose we have the following class definition
Looking at just the factory registration statement this macro inserts
 for us (this little one line macro expands to over 100 lines of code 
just to support the field automation macros), we see a typedef for a 
specialization of the parameterized class ovm_object_registry called 
type_id.
The specialized class type_id gives us access to all the static 
declarations inside ovm_object_registry. The code inside that class does
 something similar to what class A did above, except that it builds a 
global list of all string names and their associated types that can be 
used by the factory. The OVM gives you the choice of using the string 
name “packet” or the static function packetA::get_type() to set 
overrides, depending on which factory methods you use. The problem using
 the string names is that there is no type checking until run-time when 
the override statements are executed. We prefer you use type references 
to perform overrides
packetA::type_id::set_inst_override(extended_packetA::get_type(),”env.my_agent.*”);
Finally, let us take a look at a parameterized class, but assume we used the same `ovm_object_utils macro.
There are two problems here. The first is that this is now a generic 
class. The string “packetB#(w)” will not put on the factory registration
 list unless there is a specialization of the class packetB somewhere. 
The second is that if there are more than one specializations of 
packetB, they all will be registered with the same string name, 
producing an error at run time.
The `ovm_object_param_utils macro simply leaves the second parameter to ovm_object_registry as the null string and forces you to use type references for your overrides. These type references also create the specializations needed to create the static methods inside these classes.
packetB#(2)::type_id::set_inst_override(
extended_packetB#(2)::get_type(),”env.my_agent.*”);
The references to packetB#(2) and extended_packetB#(2) are checked at compile time and cause the static methods within these references to be created.
You can use $psprintf to register a string name as long as the string is unique for each specialization of the class. This can be difficult when the parameters are types.
OK, I’m done. If you still need more background information. I recommend another DVCon09 paper I wrote with Adam about Using Parameterized and Factories.
***********************************************************************************
Below is the original link of topic.
http://blogs.mentor.com/verificationhorizons/blog/2011/02/13/parameterized-classes-static-members-and-the-factory-macros/
*********************************************************************************
When you declare a parameterized class, it is more like a template, or generic class than a real class type. Only specializations of parameterized classes are real types. Suppose I have the two class definitions in the table below:
| Un-parameterized | Parameterized | 
| class A; static string name = “packet”; endclass  | 
class B #(int w=1); static string name = “packet”; endclass  | 
| typedef B#(2) B2;  B#(3) B3_1h; B#(3) B3_2h;  | 
What if you wanted the static string variable name to have a different value for each unique specialization of B? You could write something like
| class B #(int w=1);  static string name = $psprintf(“packet%0d”,w); endclass  | 
Below gives, complete example of static variable in param class.
_______________________________________________________________________________
module static_in_param_class();
class A#(int w = 1);
static string name = "packet";
endclass
initial
begin
A#(2) A1;
// $display("Value of static variable is %s", A::name); // Valid only for un-parameterized class. If class A has no parameters, this works.
$display("Value of static variable is %s", A1.name); // If class A has parameters as shown, It will be generic class, we need to create a handle with specific parameter and can access the static member only with handle.
end
endmodule
_________________________________________________________________________________
Now let us go back to the `ovm_object_utils macro. Suppose we have the following class definition
| `include “ovm_macros.svh” import ovm_pkg::*; class packetA extends ovm_object; `ovm_object_utils(packetA) … endclass  | 
| import ovm_pkg::*; class packetA extends ovm_object; typedef ovm_object_registry#(packetA,”packetA”) type_id; static function type_id get_type(); return type_id::get(); endfunction … endclass  | 
packetA::type_id::set_inst_override(extended_packetA::get_type(),”env.my_agent.*”);
Finally, let us take a look at a parameterized class, but assume we used the same `ovm_object_utils macro.
| import ovm_pkg::*; class packetB #(int w=1) extends ovm_object; typedef ovm_object_registry#(packetB#(w),”packetB#(w)”) type_id; static function type_id get_type(); return type_id::get(); endfunction … endclass  | 
The `ovm_object_param_utils macro simply leaves the second parameter to ovm_object_registry as the null string and forces you to use type references for your overrides. These type references also create the specializations needed to create the static methods inside these classes.
packetB#(2)::type_id::set_inst_override(
extended_packetB#(2)::get_type(),”env.my_agent.*”);
The references to packetB#(2) and extended_packetB#(2) are checked at compile time and cause the static methods within these references to be created.
You can use $psprintf to register a string name as long as the string is unique for each specialization of the class. This can be difficult when the parameters are types.
| import ovm_pkg::*; class packetB #(int w=1) extends ovm_object; parameter sting name = $psprintf(“packetB%0d”,w); typedef ovm_object_registry#(packetB#(w),name) type_id;…  | 
***********************************************************************************
No comments:
Post a Comment