noobuntu
noobuntu

Reputation: 913

UVM testbench - What is the "UVM" way to connect two different drivers to same interface?

In my Testbench, I have an interface that I need to drive. The interface can be driven in 2 different modes, with each mode having its own driver protocol and transaction type.

So far, I have designed both uvm_agents separately. Now, I need a way to swap one or the other in, depending on the testcase I am running. I also want to do this in the way that best fits with UVM philosophy.

My best method that I could come up with is: in my uvm_env, getting a uvm_db_config parameter from the test that says either "ModeA" or "ModeB", and based on that, setting is_active for the agents to "UVM_ACTIVE" and "UVM_PASSIVE" appropriately.

I would like an opinion on this method.

A way suggested to me was to keep a common uvm_agent, and instantiate the uvm_driver/uvm_sequencer based on the configuration. Not too sure about this method as it looks messy.

Upvotes: 4

Views: 4274

Answers (2)

eSedano
eSedano

Reputation: 322

I would also suggest, like Tudor, to use only one agent. But then I would use inheritance, declaring a base_driver and a base_sequencer (that may have common functionalities from both ModeA or ModeB drivers and/or sequencers), and ModeA and ModeB units would extend those base ones. Then, in the agent, and using a flag in the uvm_config_db set in each test, you would select between instantiating one or the other:

Base driver:

class my_proj_base_driver extends uvm_driver#(my_proj_tr);
[...]

ModeA driver:

class my_proj_ModeA_driver extends my_proj_base_driver;
[...]

ModeB driver:

class my_proj_ModeB_driver extends my_proj_base_driver;
[...]

In the agent:

[...]

my_proj_base_driver driver;
bit modeAorB // 0 for A, 1 for B

[...]

if (!uvm_config_db#(bit)::get(this,"","modeAorB", modeAorB))
  `uvm_fatal("NOMODE","No mode set for this agent")

if(!modeAorB)
  driver = my_proj_ModeA_driver::type_id::create(.name("driver"), .parent(this));
else
  driver = my_proj_ModeB_driver::type_id::create(.name("driver"), .parent(this));

And the same for the sequencer.

Upvotes: 4

Tudor Timi
Tudor Timi

Reputation: 7573

I would prefer having a common agent class and one concrete classe per mode, then do type overriding based on the test I'm running. This way it's clear that there is only one agent handling that interface (and not 2, of which one is set to passive when it is not used at all). One agent class instantiates a set of driver/sequencers and the other agent class instantiates the others. This way you only have to set one type override (on the agent) and not 2 (on the driver and the sequencer).

If in both modes you use the same monitor, then it would be better to go for the one agent approach, because you only have to connect your scoreboard to the one monitor, instead of either one in agent A or the other in agent B depending on the mode.

Your approach works as well and I don't think there is a standard UVM way of doing it in this case. I've had a colleague do something similar for a GPIO interface and it worked fine.

Upvotes: 2

Related Questions