How you can figure how you configure (a VMM testbench): Part 1
Posted by JL Gray on December 7th, 2010
Jonathan Bromley, Verilab Inc, Austin, Tx
Part 1: Using configuration objects
Each VMM transactor class should have a companion config class, where you create data members for all critical “vital statistics” of the transactor. Just before constructing the transactor object, an enclosing subenv would create one of these config objects and then pass it to the transactor as a constructor argument. Every transactor should also provide a reconfigure method allowing other parts of the environment to set up a new configuration for it at any time.
Objects to control objects
class MagicPacketXactor_cfg;
rand shortint unsigned MaxLength;
rand bit SupportsVoodooMode;
constraint c_valid_packet {
if (SupportsVoodooMode) { MaxLength inside {[64:16384]}; }
else { MaxLength == 1024; }
}
endclass
Note how the class contains rand data members for all the transactor’s configurable attributes, and also has constraints so that it will yield a meaningful and interesting set of configuration values when randomized. Of course, further constraints can easily be added to enforce specific configurations.
The corresponding transactor code might be something like this:
class MagicPacketXactor extends vmm_xactor;
…
local MagicPacketXactor_cfg cfg;
function new( … // usual VMM constructor arguments, and then…
MagicPacketXactor_cfg cfg = null);
…
if (cfg == null) begin
cfg = new;
cfg.randomize();
end
this.cfg = cfg;
…
endfunction
function void reconfigure(MagicPacketXactor_cfg cfg);
this.cfg = cfg;
endfunction
In the transactor’s main() task, or elsewhere, we can now do things like
if (this.cfg.SupportsVoodooMode)
castSpell(…);
It’s really important to note that the transactor takes no responsibility for setting up its own configuration. It merely assumes that a configuration object has been supplied from outside, and then makes use of the values within that configuration object. If the enclosing environment fails to provide a configuration object, as a last resort the transactor constructs its own randomized configuration.
This is a good example of the notion of encapsulating configuration in a single object. By gathering all important attributes of a component into a class:
• we can pass the entire configuration around as a single object or reference;
• it becomes easy to write randomization constraints that establish relationships among configuration attributes;
but most important of all:
• it is straightforward to assemble several configuration objects into a single, larger configuration object suitable for use at the next level up the hierarchy– typically at the vmm_subenv level.
Environment configuration
class MagicToEthernet_subenv_cfg;
rand MagicPacketXactor_cfg magic_cfg;
rand Ethernet_cfg eth_cfg;
endclass
Configuration proceeds in much the same way as for the transactors. The environment’s constructor takes one of these objects as an argument, and then passes on its inner configuration objects to the corresponding transactors as it constructs them. Reconfiguring the environment is equally straightforward:
class MagicToEthernet_subenv extends vmm_subenv;
MagicPacketXactor magic_xactor;
EthernetXactor eth_xactor;
…
function void reconfigure(MagicToEthernet_subenv_cfg cfg);
magic_xactor.reconfigure(cfg.magic_cfg);
eth_xactor.reconfigure(cfg.eth_cfg);
endfunction
Finally, the code that launches your VMM test can create and populate all the necessary configuration objects, assemble them into environment-wide configuration objects, and pass them into constructors as needed. It is also very easy to configure multiple transactors to match a common configuration simply by passing the same configuration object to all of them.
Testbench configuration vs. test configuration
Test environment configuration gets you the right structure – correct number of transactors, correct choice of active vs. passive transactors, choice of reference model or scoreboard – to match the chosen device-under-test. Using that test environment, though, you probably wish to run a large and ever-growing battery of testcases as you develop new stimulus to hit elusive coverage objectives. From a programming point of view, configuring the test is not very different from configuring the testbench –a matter of passing appropriate configuration objects to the constructors of various components. From an organizational point of view, though, there are big differences. Testbench configuration generally needs to be at least partly driven by parameters of the DUT and test harness, whereas testcase configuration is likely to be much more flexible and dynamic, and will vary from run to run.
When using configuration objects in this style, I’ve learnt the value of keeping a strict separation between these two kinds of configuration to simplify those organizational concerns.
In the second part of this article we’ll look at the impact of the extensive new configuration facilities in VMM 1.2, and explore a novel way to manage groups of inter-related configuration options.








December 8th, 2010 at 6:56 am
RT @am_its: How you can figure how you configure (a VMM testbench) – http://bit.ly/hgK7hB #VMM #SystemVerilog
April 9th, 2013 at 11:49 pm
Its like you read my mind! You appear to know so much about this, like you wrote the book in it or something. I think that you could do with some pics to drive the message home a bit, but instead of that, this is great blog. An excellent read. I will definitely be back.
May 6th, 2013 at 1:56 am
Oh and I’m not a Liverpool or Chelsea supporter, even so the way the Liverpool fans were still singing You’ll Never Walk alone when their team was losing and the game was almost finished was pretty. Big respect.