Implementing callback

Hi,

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

  1. extend the packet generator class
  2. add necessary call back functions
  3. 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

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.

In reply to Tudor Timi:

Thanks, Tudor. I guess this is how callbacks in UVM are implemented. I looked at it but did not understand. Thanks.

In reply to Tudor Timi:

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.

Thanks
Mike