On SystemVerilog Interface Polymorphism and Extendability

A state of the art SystemVerilog simulation environment consists of two separate worlds. There is the static world, where interface and modules (including the DUT) exist. The other one, the dynamic world, consists of object instances that make up the testbench. The most widespread way to connect these two together is using the virtual interface construct, which is just a pompous way of describing a "reference" to an interface. I will assume that everybody is well acquainted with this concept.

This is a companion discussion topic for the original entry at https://verificationgentleman.netlify.app/2015/08/31/sv-if-polymorphism-extendability.html

Hello Tudor,

I have been following the abstract class posts and was searching for a use case that spells a dire necessity to replace interfaces with abstract classes. Your posts clears the air for it in a great deal.

Since you mentioned parametrized interfaces at the start of the topic(reference to parametrised interfaces, whose parameter value is changed at runtime using simulator options, causes issues), Will abtract class usage help us to circumvent it.


Using this approach will help, since from a syntax point of view two interfaces with different parameterizations will be two totally different types. Just like ‘apb_master_interface’ and ‘apb_tri_master_interface’ or ‘apb_ext_master_interface’ are totally different types, for the compiler so are ‘some_interface #(8)’ and ‘some_interface #(16)’.

This is the same methodology espoused by Jonathan Bromley and Dave Rich in their paper presented at DVCon in 2008: Doulos

That’s the “older paper” I reference in the beginning of the post.

I detest interfaces.
did you know that if you had a parametric interface type inside of a parametric class, the type you specify in your class will not get to the interface type???
Instead, you need to parameterize the class on the interface itself , and declare a specialization somewhere in your package.

Here’s what I do - I think interface should give me the protocol handshake, and if there are phases, by functions or I’d rather use events - doesn’t matter
other than that I just want it to give all the information bits: data, address, byte enable all concatenated together.
so the interface is just parametric on the width.
Now the driver and monitor don’t care. all monitor does is @sample_event they take the sampled bits and stream them into the transaction class that is their parameter.
the class itself has the proper pack/unpack, either ovm/uvm or my own, to turn the stream into fields.
(if you do your own pack/unpack, you can have them in a transaction base, and the transaction you use, can inherit the base + parametric on virtual class that contains parameters of the fields widths, enums, etc)
All my monitors are the same base type. my base test, overrides them all to with the proper parameterized monitor.
The driver takes the transaction and streams it to the wires.
Now I’m immune to designers. They can change the structure of the bus, the width, the protocol at the very last minute, I’m not bothered.

That’s an interesting use model. It doesn’t help if you want to maintain the same interface with multiple variants (like the APB, APB tri and APB ext from the post), because you still need 3 interface definitions.

That is unless you have some crazy scheme where you only define one interface variable of a very big length and then do part selects to connect the signals:

interface apb_master_interface #(WIDTH);
logic [WIDTH-1 : 0] signals_bundle;

// in the TB
assign apb.signals_bundle[1:0] = HTRANS;
assign apb.signals_bundle[33:2] = HADDR;

This would be pretty crazy for usability. Granted, you could wrap this interface inside another one that exposes the signals with nice names, but you’ve still got to do those connections yourself. That’s conceptually the same approach as in the post, because you’d add a layer of indirection to decouple the real interface from the driver (because it would see the one with the bundle).

gp or someone else: could you elaborate on "did you know that if you had a parametric interface type inside of a parametric class, the type you specify in your class will not get to the interface type??? "

I think he means something along the lines of:

interface some_param_interface #(int some_param);
// …

class some_class #(int some_param);
virtual some_param_interface #(some_param) vif;

Maybe some simulators take offense at declaring ‘vif’ like that and want something like:

class some_class #(type vif_type);
vif_type vif;

Hi Tudor, thanks for the post.
Do you think I will be able to use this approach to “template” a driver?

I mean, my purpose is to do the following:

class base_driver #(type transaction_type, type interface_type) extends uvm_driver #(T)

endclass : base_driver

With this I would be able to implement functionalities that are present in every driver of my UVM environment.

Thanks again!

What can you do generically on something that has the type interface\_type, though?