Programmatically converting the value of a parameter to a string can't be accomplished using compiler directives. One reason is that it would require inspecting the type of each parameter to determine how to convert the value to a string and that information is not available when the preprocessor resolves the compiler directives. This is why the uvm_(object|component)_param_utils macros don't attempt to add the code necessary to associate a class specialization with a string value.
With that said, it is possible to manually associate a string with a class specialization. The code below shows how to accomplish associating a string with a class specialization.
// The IEEE UVM versions define uvm_type_name_decl and uvm_declare_type_alias macros.
// However, older versions of UVM do not define these macros and will need to have them defined
// in order for the code to work regardless of the UVM version being used.
`ifndef uvm_type_name_decl
`define uvm_type_name_decl(TNAME_STRING) \
const static string type_name = TNAME_STRING; \
virtual function string get_type_name(); \
return TNAME_STRING; \
endfunction : get_type_name
`endif
// The SFX argument to the uvm_declare_type_alias macro must be unique for each usage of the macro in
// a given scope.
`ifndef uvm_declare_type_alias
`define uvm_declare_type_alias(TYPE,NAME,SFX=) \
static uvm_object_wrapper m__alias_declared``SFX = uvm_component_registry #(TYPE, NAME)::get();
`endif
class seq_a #(int param = 10) extends uvm_sequence;
//`uvm_object_utils(seq_a)
`uvm_object_param_utils(seq_a#(param))
// added type name functions so that get_type_name returns a reasonable value.
// For example: seq_a#(10)::get_type_name() returns "seq_a#(10)"
`uvm_type_name_decl($sformatf("seq_a#(%0d)", param))
function new(string name = "my_seq");
super.new(name);
do_not_randomize = 1'b1; // Required for ModelSim
set_automatic_phase_objection(1);
endfunction
task body;
uvm_sequence_state_enum state = get_sequence_state();
// In UVM 1.1d: starting_phase.raise_objection(this);
`uvm_info("SEQ_A", $sformatf("state is %s",
state.name()), UVM_LOW);
while ($time < 10us) begin
#1us;
`uvm_info("SEQ_A", $sformatf("[%d] ping at time %d", param, $time), UVM_LOW);
end
// In UVM 1.1d: starting_phase.drop_objection(this);
endtask
endclass
// Add aliases after the class definition for each class specialization you would like to associate with a string.
// Aliases can always declared manually.
// Depending on the parameter types it may be possibly to declare the aliases in a generate loop .
// Only the declared aliases will be available for lookup in the factory using a string
// Provide unique values to the SFX argument to ensure that variable declared by the macro is not declared more
// than once a given scope.
`uvm_declare_type_alias(seq_a#(10), "seq_a#(1)", seq_a_1)
`uvm_declare_type_alias(seq_a#(10), "seq_a#(10)", seq_a_10)
// Based on the example code this could also be done in a generate loop since the parameter type is an int.
// The module declaring the aliaes must be instanced somewhere in the simulation in order for the aliases to work
// Example using a generate loop:
module tb();
// code assumes seq_a is defined inside package seq_a_package
// No need to provide unique values to the SFX argument as each iteration of the loop is a different scope.
for (genvar i = 0; i < 20; i++) begin : gen_seq_a_specialization
`uvm_declare_type_alias(seq_a_package::seq_a#(i), $sformatf("seq_a#(%0d)", i))
end
endmodule