Register parameterized callback class using `uvm_register_cb macro

Hi All,

→ I have created parameterized callback class(ijtag_driver_callback#(int IJTAG_WIDTH = 396)) which is extended from the uvm_callback.
In my driver class, I have registered callback class with `uvm_register_cb macro as below.

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class ijtag_driver_callback#(int IJTAG_WIDTH = 396) extends uvm_callback;


`uvm_object_param_utils(ijtag_driver_callback#(IJTAG_WIDTH))


endclass : ijtag_driver_callback

class ijtag_receiver_driver#(int IJTAG_WIDTH = 396) extends uvm_driver #(ijtag_receiver_trans#(IJTAG_WIDTH));


uvm_component_param_utils(ijtag_receiver_driver#(IJTAG_WIDTH)) **uvm_register_cb(ijtag_receiver_driver#(IJTAG_WIDTH),ijtag_driver_callback#(IJTAG_WIDTH))**


endclass : ijtag_receiver_driver
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Getting compilation error: Here, ijtag_driver_callback#(IJTAG_WIDTH) is appended to “m_register_cb_``CB” and define name as,
static local bit m_register_cb_ijtag_driver_callback#(IJTAG_WIDTH)
Below is the error description,
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
#0, uvm_register_cb(T=ijtag_receiver_driver#(IJTAG_WIDTH), CB=ijtag_driver_callback#(IJTAG_WIDTH)) : “/tools/vcs/2016.06-SP2/etc/uvm-1.1/macros/uvm_callback_defines.svh”:60
full expansion of macro (uvm_register_cb), error at line 1
=>static local bit m_register_cb_ijtag_driver_callback#(IJTAG_WIDTH) = uvm_callbacks#(ijtag_receiver_driver#(IJTAG_WIDTH),ijtag_driver_callback#(IJTAG_WIDTH))::m_register_pair(“ijtag_receiver_driver#(IJTAG_WIDTH)”,“ijtag_driver_callback#(IJTAG_WIDTH)”);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

→ When I have made following modification in my code, calling the m_register_pair function directly without using uvm_register_cb macro. It is working as expected. ////////////////////////////////////////////////////////////////////////////////////////////////////////////// class ijtag_driver_callback#(int IJTAG_WIDTH = 396) extends uvm_callback; ... ... uvm_object_param_utils(ijtag_driver_callback#(IJTAG_WIDTH))


endclass : ijtag_driver_callback

class ijtag_receiver_driver#(int IJTAG_WIDTH = 396) extends uvm_driver #(ijtag_receiver_trans#(IJTAG_WIDTH));


`uvm_component_param_utils(ijtag_receiver_driver#(IJTAG_WIDTH))

static local bit m_register_cb_ijtag_driver_callback = uvm_callbacks#(ijtag_receiver_driver#(IJTAG_WIDTH),ijtag_driver_callback#(IJTAG_WIDTH))::m_register_pair("ijtag_receiver_driver#(IJTAG_WIDTH)“,"ijtag_driver_callback#(IJTAG_WIDTH)”);


endclass : ijtag_receiver_driver
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

I wanted to know that, do we have any other way to register parameterized callback class. Or if it is the only way to register with `uvm_register_cb then I think so it is creating the problem with parameterized callback class.

Please provide your thought on this.

Thanks,
Shrujal

In reply to shrujal.shah:

You need to look at the code created by the macro and try modifying it to suit your needs.

For an idea, see http://go.mentor.com/mcem

In reply to dave_59:

In reply to shrujal.shah:
You need to look at the code created by the macro and try modifying it to suit your needs.
For an idea, see http://go.mentor.com/mcem

Hi Dave,

Thank you for your quick response on this.

I have already used your suggestion in my current example as shown above and it is working fine but as it is kind of internal to UVM.

As a user-friendly way, don’t you think that there should be a separate macro for parameterized callback similar to object/component?

Or

As per current implementation of uvm_register_cb macro, it should take only callback class name with parameter value(ijtag_driver_callbackIJTAG_WIDTH) to define “m_register_cb_``CB” field. Instead of taking the full name with the special character like “#” (m_register_cb_ijtag_driver_callback#(IJTAG_WIDTH)). So it won’t give the compilation error.

define uvm_register_cb(T,CB) \ static local bit m_register_cb_``CB = uvm_callbacks#(T,CB)::m_register_pair("T",“CB`”);

Thanks,
Shrujal

In reply to shrujal.shah:

The problem with a string-based registration is there needs to unique string for every unique specialization of your parameterized callback class. The UVM factory registration uses both type and string based registration. The `uvm_*_param_utils macros only registers the type for parameterized classes because there is no generic way to create a unique string using a macro. If you only plan to use one specialization of a parameterized class and use the default values, then the macro works registering a single string name, but that defeats the purpose of a parameterized class.

The link I gave you shows one way of creating unique string names for parameterized classes. Since your class has only one integer parameter, you could do the following:

define jtag_register_cb(T,CB) \ parameter string CBname`` = $sformatf(“CB%0d", IJTAG_WIDTH); \ static local bit m_register_cb_CB = uvm_callbacks#(T,CB)::m_register_pair("T”,CBname);

In reply to dave_59:

In reply to shrujal.shah:
The problem with a string-based registration is there needs to unique string for every unique specialization of your parameterized callback class. The UVM factory registration uses both type and string based registration. The uvm_*_param_utils macros only registers the type for parameterized classes because there is no generic way to create a unique string using a macro. If you only plan to use one specialization of a parameterized class and use the default values, then the macro works registering a single string name, but that defeats the purpose of a parameterized class. The link I gave you shows one way of creating unique string names for parameterized classes. Since your class has only one integer parameter, you could do the following: define jtag_register_cb(T,CB)
parameter string CBname = $sformatf(`"CB%0d", IJTAG_WIDTH);
static local bit m_register_cb_``CB = uvm_callbacks#(T,CB)::m_register_pair("T",CBname);

Hi Dave,

I have created a macro as you have suggested and it is working fine.
Still, I feel that UVM should have a macro with this functionality that you have suggested.
Thank you for your support on this.

Thanks,
Shrujal

In reply to shrujal.shah:

Macros do not work well with parameterization. You had one parameter with a fixed type. Just like the field macros, the number of macros would explode for multiple parameters and types.