I have a packet generator component. The component is a pure SV code and does not have any UVM usage in it.
Now, I am enhancing this to add new features. One of the things to be added is call backs in the class so that users can add needed changes if existing features are not sufficient.
For example, I have code segments, where functional coverage code is present.
To make the packet generator extensible, I am planning to add call backs so that users can extend it later and add additional functional coverage code.
This is the flow to be followed by the users of packet generator in case they want to implement call backs
extend the packet generator class
add necessary call back functions
create instances of the derived packet generator class wherever needed
Is this the best way to implement call backs?
Any inputs on this is highly appreciated …
PS1: I am posting this question on SV forum as my question is not specific to UVM
PS2: I don’t have code to show for call back as I don’t want to go down in the implementation path and realize that, there is a better way of doing this
It’s better to add callbacks using composition and not inheritance. This way you can have multiple sets of callbacks active at the same time.
Example:
class packet_generator_callbacks;
pure virtual task pre_drive(packet p);
pure virtual task post_drive(packet p);
// ... callbacks for other methods
endclass
class packet_generator;
local packet_generator_callbacks callbacks[$];
function add_callbacks(packet_generator_callbacks cbs);
callbacks.push_back(cbs);
endfunction
task drive(packet p);
foreach (callbacks*)
callbacks[i].pre_drive(p);
// base code for 'drive'
foreach (callbacks[i])
callbacks[i].post_drive(p);
endtask
// ... other methods
endclass
You might want to have a [i]post_drive(…)* callback that collects coverage after a drive. Someone else might want to write a callback that waits for a certain state before driving the packet. If you would have implemented callbacks using inheritance, you would need multiple inheritance to get this, because you would need a new packet_generator class that extends from packet_generator_with_coverage and packet_generator_that_waits_for_state. Using callback objects you can combine the two easily.
A request:
Please help me work this up into a more complete functioning example.
I started something here which is not functional.
Maybe you could tweak this one. It compiles but does not do anything.
As an update I got it to run.
Maybe you could take a look and see if this is consistent with your vision for how the callback should work as you proposed.