One of our UVM agents has a driver + interface where the data-width comes from a parameter package. In this way many of our modules can be pluggged in this testbench without need to alter the driver or interface.
However some modules have a slightly different interface (let’s say a couple of extra signals in the interface definition) and a slightly different driver (it for example needs to create those signals, and the protocol is slightly different).
So for some of our modules we need a testbench that has {driver1+interface1} and for other modules we need a testbench that has {driver2+interface2}.
What would be the adviced way of constructing the 2 kind of testbenches?
to select/instantiate the correct driver, is it best to use a uvm mechanism? (e.g. in the build phase of the agent, build the correct driver), or is it better to try to do this at compilation time (just compile another driver.svh file).
how to instantiate the correct interface? I guess here we can’t use any uvm mechanism, should we just resolve this by compiling different source code or using generate statements.
You are correct in saying that the interface cannot be configured by the UVM, however it is possible for the UVM to be configured (indirectly) by the interface.
You can use polymorphic interfaces to put details of the BFM required within the interface itself.
There’s an interesting paper on the subject here:
Interesting paper, but at first sight this is aimed at instantiating different bfm with a constant set of interface signals (the addr and data in the example). In my case also these signals need to change.
Is there even a point in trying to do something using uvm, when you can just compile in some other code? For a particular module it is always the same interface/driver that has to be used.
Yes but the idea behind the paper could be extended to instantiate BFM wrapper in each of your interfaces, and configured appropriately, leaving the UVM agent free to derive for itself how it should be configured.
As one interface is a superset of the other, you could also perhaps define a single interface, parameterised according to which type you require, and simply not use any unwanted signals. The parameterisation could be used to configure the BRM wrapper.
Of course there are usually plenty of solutions for a given problem - this is just one method which tries to embrace reuse and single-point parameterisation. It may be more appropriate depending on the target audience, level of reuse, level of differences between the drivers, etc to use simpler methods. As always, it is a trade off between time invested upfront and complexity versus reusability, and there is no one right answer for all situations.