In reply to verif_learner:
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.