Using class type defined inside an interface, outside

Hello,
I am trying to create a base driver for my UVM that is capable of doing drive and handling reset in an easy way that is easy for developers. This base driver shall also permit extension, I mean, adding new functionalities to it should be easy. What I thought is to have the class parameterized for the type of transaction it has to drive to the virtual interface. This is pretty easy. The first problem I faced is when I need an interface type that is valid for every possible interface that I want to implement on my driver when extending the base driver.

I have read this paper The Missing Link: The Testbench to DUT Connection of Dave Rich and also this blog entry On SystemVerilog Interface Polymorphism and Extendability of Tudor Timi, and when I read both I decided to use the proxy idea. Now is when my real problem comes across. I cannot access a class defined inside an interface from a class outside this scope.

Look at this to see how my idea looks like:


// Note that this does not compile, it's pseudocode
class base_driver #(type T) extends uvm_driver #(T);
  T trans; // Transaction

  base_if_proxy if_proxy; // Base class for interface proxy
  ...
  function void run_phase(uvm_phase phase);
    do_all();
  endfunction : run_phase
  ...
  task do_all();
    drive_as_usual(); 
    do_something();
  endtask : do_all

  pure virtual task do_something();

endclass : base_driver 

class specific_driver extends base_driver #(my_transaction_type);
  
  specific_if_proxy s_if_proxy; // Proxy extending base_if_proxy

  function void build_phase(uvm_phase phase);
    if (!$cast(this.s_if_proxy, if_proxy)) begin // Get the specific proxy type!!!
      `uvm_fatal(get_type_name(), "Fatal")
    end
    ...
    
  endfunction : build_phase  

  virtual task do_something();
    s_if_proxy.wait_for_clock(); // Tasks implemented in the extended class of the proxy! 
    s_if_proxy.drive_random();
  endtask : do_something
  

endclass : specific_driver

As you can see the problem is that I want to do a $cast in the build_phase of the specific_driver to have the specific class of the proxy for the driver that I am implementing. The cast could work like a charm if the specific proxy class wasn’t defined in the interface for the driver. How is it possible to solve this problem? Any approach?

Hope I made myself clear enough, thanks.

In reply to Marc43:

To be honest, it is comoletely unclear to me what your needs are and why you are dealing with the proxies.
Why do you not use the standard approach, extending your driver from the base class uvm_driver?

In reply to chr_sue:

In reply to Marc43:
To be honest, it is comoletely unclear to me what your needs are and why you are dealing with the proxies.
Why do you not use the standard approach, extending your driver from the base class uvm_driver?

Okay, I already have a UVM, which is composed of 12 sub-interfaces that communicate with each other if needed, more or less in a master-slave fashion. Now, I need a more sophisticated handle for reset than the one that I have implemented first. I want to create a base class for those drivers so I don’t have to change them manually one by one. This will also be great for the drivers that I will have to implement in the future.

In reply to Marc43:

Sorry, but it is confusing what you are writing. A reset should be handled by the same sequencer/driver as the common functionality.
I have a few questions with respect to your DUT.
You say you have 12 sub-interfaces. The components connected to are working like a master/slave configuration.

(1) are your so called sub-interfaces o09f the same type, having the same signals inside? The master-slave would require this.
(2) Your driver should handle also the reset functionality. You might have a reset task in the driver which ias called in the drivers run_phase when the reset sequence is executed.
(3) If you have a master/slave configuration you need only 2 different types of drivers, a master driver and a slave driver. And you might have more than 1 instances of these drivers types.
(4) Why do you believe you need to modify your drivers one by one?

In reply to chr_sue:

In reply to Marc43:
Sorry, but it is confusing what you are writing. A reset should be handled by the same sequencer/driver as the common functionality.
I have a few questions with respect to your DUT.
You say you have 12 sub-interfaces. The components connected to are working like a master/slave configuration.
(1) are your so called sub-interfaces o09f the same type, having the same signals inside? The master-slave would require this.
(2) Your driver should handle also the reset functionality. You might have a reset task in the driver which ias called in the drivers run_phase when the reset sequence is executed.
(3) If you have a master/slave configuration you need only 2 different types of drivers, a master driver and a slave driver. And you might have more than 1 instances of these drivers types.
(4) Why do you believe you need to modify your drivers one by one?

(1) Maybe I confused the terminology of master-slave. In order to reduce complexity, I divided the interface of my DUT into sub-components, that’s it.

(2) Yes, I have a reset task that is different for each driver as it is implemented for a different sub-interface.

(3) Confused, already told you in (1)

(4) Because my drivers don’t have the reset task. I thought that it would be great to have a base class for each driver and the proxy to the base interface.

Without taking into account, why I decided to do this, do you think is possible to do what I am trying to?

In reply to Marc43:

If your sub-interfaces are different you need a specific reset task for each driver.
I do not see how you’ll benefit from a bas class common for all different drivers.

In reply to chr_sue:

The common class is a template that implements the classic “fork join any” with the reset and the retrieve of the sequence. Then, I leave to the user extending the driver to implement methods drive() and reset(). I think you didn’t understand me.

In reply to Marc43:

You are right. I do not understand what you want to do and what the benefit is.

In reply to chr_sue:

Okay, then let’s just drop it here. Thanks for your effort.

In reply to Marc43:

Not sure if this helps, but you might want to look at interface classes which were introduced after these papers were written.

SystemVerilog Interface Classes - More Useful Than You Thought