I have a method inside a concrete class defined in a module to be instantiated in the testbench. The concrete class handle is passed to the UVM agent. I chose this approach over virtual interfaces to minimize the proliferation of parameters, because the interface by definition includes a decent set of parameters. I do need to support a type parameter for modeling the data in any way useful for the verification environment, and a corresponding string parameter that is the type's name for UVM factory reasons that I won't delve into. Anyway, here is example code to illustrate what I'm trying to describe:
module my_bfm#(
parameter type T = byte,
parameter string Tname = "",
parameter BLAH = DEFAULT_BLAH
);
class my_concrete extends my_abstract;
task transact(input my_trans#(T, Tname) trans);
// Do something...
endtask : transact
endclass : my_concrete
endmodule : my_bfm
module testbench;
my_bfm#(.T(my_custom_t), .Tname("my_custom_t"), .BLAH(42));
endmodule : testbench
class my_trans#(type T=byte, string Tname="") extends uvm_sequence_item;
`uvm_object_param_utils(my_trans#(T))
endclass : my_trans
VCS will fail at elaboration with the following:
Error-[ICTTFC] Incompatible complex type usage my_monitor.svh, 42 Incompatible complex type usage in task or function call. The following expression is incompatible with the formal parameter of the task. The type of the actual is 'class my_trans#(my_custom_t,"my_custom_t")', while the type of the formal is 'class my_trans#(byte,"\000")'. Expression: this.trans Source info: my_abstract::collect_transaction (this.m_bfm, this.trans);
Questa passes compilation and elaboration.
It seems that VCS is not propagating the parameter overrides in the testbench to the concrete class where the method using similarly parameterized classes is defined. The UVM classes are overridden from the env with the same type/value as in the testbench.
Anyone have any ideas, perhaps someone from Synopsys?