Agent support for on the fly configuration changes

Some UVM agents will require configuration settings to tell the agent driver how to operate.

For example, SPI devices have settings for things like clock phase (CPHA) and clock polarity (CPOL).

These settings are not necessarily static during a simulation. For example, I could have a test that iterates though the various SPI settings, in which case I would reconfigure the DUT and the agent prior to sending SPI transactions.

I have seen two approaches to handle the agent implementation.

1. Use the agent config object

  • In addition to the virtual interface, the config object also includes members for CPHA and CPOL.
  • The agent contains a thread that is triggered when there is an update to the object in the config_db (like using uvm_config_db#()::wait_modified(…)

2. Use a sequence item to configure the agent

  • transaction sequence item includes a “configure” opcode (transaction type) and class members for the configuration settings (i.e., CPHA,CPOL)

Questions
Is one of these approaches preferred over the other?

I’m interested to hear others views, opinions,experiences on this topic.

Thanks!

In reply to michpriv:

I started with #1, but I’ve grown to prefer #2.

I think #2,

  1. creates a well defined mechanism to control when the configuration change is applied.
  2. feels more consistent with UVM’s use of sequences for doing dynamic things.

Most interfaces don’t allow you to reconfigure at any old time, so there needs to be a mechanism to control when the change is applied. When using the config_db approach it’s easy to end up having no consistency in how that’s done between agents. You could, of course, come up with rules. However, as soon as you switch to using a configuration transaction, solutions tend to naturally converge. So that might as well be the rule.

The one place that could be a problem, is if you really have an interface that support reconfiguration in the middle of a transaction. I’ve never had this case, but I’ve thought about adding an additional configuration sequencer to my driver if I ever encountered it. You’d have an additional thread in the driver to handle that.

Configuration transactions also feel more UVM-like to me. Although in your testbench, it may only amount to reconfiguring your driver, what happens when real hardware is driving it? Some interface drivers could decide on their own to change modes, for power or performance reasons. But it’s very likely that the hardware driving the interface receives some kind of configuration command that comes from either other hardware, or from firmware.

So, in that testbench the reconfiguration would be modeled as a transaction of some sort. Modeling it as such in your testbench is then consistent. It might also make it possible to create layered scenarios that allow you to run higher levels scenario on you testbench.

In reply to warnerrs:

Thank you for your response and examples. I find I’m also starting to lean towards #2.