Hi Andrew,
Sorry, I misunderstood what you were asking. I see now that Dave’s example actually is allowing the factory to work with a parameterized type without having to create an extended specialization.
I can simply use the macros
`ovm_component_utils(myClass#(WIDTH))
Actually, this won’t work like you expect. The component_utils macro “stringifies” its argument, then substitutes it as the second parameter in an ovm_component_registry declaration. What this means is that it will be registered, but the string name is literally “myClass#(WIDTH)” The specialized value for WIDTH is not substituted.
Now, this will actually work if you have something like
myClass #(4) c;
…
$cast(c, create_component(“myClass#(WIDTH)”,“c”));
However, if you try to create two different specializations, like
myClass #(4) c1;
myClass #(6) c2;
You will get an error from the factory that “myClass#(WIDTH)” is being registered twice.
I’ve worked up an example that works with QuestaSim using your idea of a static function. The reason that Dave had to create an itoa function is that you have to somehow convert numeric parameters into a string for the registry type name. He could not just use $itoa because system functions are not allowed in parameter expressions.
If you don’t like having an itoa function, you still have to somehow convert the number to a string, so I created a macro ITOA that is used inside the static function to do the conversion.
With this method, you are free to use whatever type string naming convention you like in your my_type() function, but you have to make sure that each specialization is unique, and you have to follow that convention when specifying the argument to create_component.
Here’s the example:
import ovm_pkg::*;
`include "ovm_macros.svh"
`define ITOA(i,s) \
string conv = "0123456789"; \
do s = {conv[i%10],s};\
while ((i /= 10));
class param_class #(int W=8) extends ovm_threaded_component;
typedef param_class #(W) this_type;
parameter string TYPE_NAME = my_type();
ovm_component_registry #(this_type, TYPE_NAME) is_auto_registered;
function string get_param();
return TYPE_NAME;
endfunction
static function string my_type();
string str;
int j = W;
`ITOA(j,str)
return {"param_class #(", str, ")"};
endfunction
function new(string name, ovm_component parent);
super.new(name, parent);
endfunction
task run();
ovm_report_message("PARAM_CLASS", $psprintf("Message from class with parameter = %0d",W));
endtask
endclass
class env extends ovm_env;
`ovm_component_utils(env);
param_class #(4) pc;
param_class #(6) pc2;
function new(string name, ovm_component parent);
super.new(name, parent);
endfunction
function void build();
$cast(pc, create_component("param_class #(4)", "pc"));
$cast(pc2, create_component("param_class #(6)", "pc2"));
endfunction
task run();
#1;
ovm_top.stop_request();
endtask
endclass
module top;
initial begin
run_test("env");
end
endmodule
Regards,
-Kurt