UVM is a standard, so that means that every company writes their testbenches the same, universally interchangeable, right? Not exactly. I just got back from teaching in Europe. No matter where the engineers grew up, they all spoke English, each with a different accent. I think that I don’t have an accent, having grown up in Alaska, but my coworkers in Texas and London would disagree. Let’s look at some of the different accents and flavors of UVM.
Why are There 31 Flavors?
I’ll describe some differences and explain a little of why Siemens recommends a particular style. I’m not trying to change anyone’s mind, just help you see why some people prefer chocolate vs. vanilla.
There are almost as many reasons for these different styles as there are styles. Every design is unique, and this influences the testbench. Is there legacy code or is this the first of a new breed? Are the engineers SystemVerilog gurus who know UVM, OVM, VMM, and other TLAs, or is a team of VHDL designers learning just enough verification to get this chip into the lab? Finally, each EDA vendor and toolset has its strengths and thus one might push macros for fast adoption while another recommends a code-heavy approach for fine control over the behavior and best performance. A VIP author or verification consultant might create an innovative style.
Cup or Cone?
The starting point for adopting UVM is picking the version. The last one standardized by Accellera with wide adoption was 1.1d, and this is generally recommended by Siemens. There are many bug fixes in 1.2 and I see this in customer testbenches. While the IEEE standardized P1800.2 back in 2017, very few companies have adopted it, and there are some further tweaks for compatibility in the works.
There are some compatibility issues between these, but these are so minor that my course only has one slide showing any difference, the sequencer arbitration enumerated names. The Verification Academy describes these versions and issues with upgrading.
Chocolate, Vanilla, or Strawberry?
The next choice is how you define the behavior of your sequence item classes. For example, the scoreboard calls compare() with the handles to the expected and actual transaction objects. This is a UVM method that sets up the deep compare but knows nothing about your protocol. The quickest way to make the protocol-specific code is with the UVM field macros. They also generate the code to copy, print, and more. Siemens recommends the do_*() methods where you define these actions. The result is very precise and simulates faster than the field macro code but takes longer to write. These two styles are not compatible. If your protocol base class is defined with one flavor, don’t switch when you extend it.
Sprinkles or Jimmies?
Next, how does your sequence talk to the driver? You could learn the four steps of create, start, fill, and finish each item, or you could just call the uvm_do macro. Once again, you can write a new sequence faster with the macro, but you have more control over what is generated and when with the four-step style. Siemens recommends the latter.
Takeout or Dine-in?
When does your component execute? UVM has many phases to build and connect your testbench, plus extract and report the results. Originally, UVM only had one phase to run the test, the run_phase() task. The 1.2 version added the Domain phases, fine-grained tasks to reset, configure, and shutdown the test, and the main phase for the body of the test. Plus there are pre_ and post_ versions of each task, giving you 12 different places for your test code. Oops, too much control! Siemens recommends starting with just the run_phase() task as this is easy to understand. Later, if you need to synchronize high-level activity, try the Domain phases.
Reuse: Sundae, Shake, or Parfait?
UVM is all about reuse – define the components and stimulus classes once and using them throughout this project and the next. This means your classes behavior should be configurable for these different situations. Add variables, sometimes called dials or knobs, to change address values, make an agent active or passive, or hold the virtual interface.
Originally, each value was passed individually through the uvm_config_db down to lower levels. This performs well for a few thousand values. However, the DB is built on run-time string matching with regular expressions and can cause major performance problems for large systems. Most testbenches now group these configuration values into some container. Siemens calls these config objects, extended from uvm_object; other vendors might recommend virtual sequencers, derived from uvm_sequencer. A cleaner OOP style is creating a set_config() method in every component so its parent can directly pass it a config object handle.
The uvm_config_db entries contain a scope based on component instance names such as “uvm_test_top.env.usb_agt”. A sequence is not a component, so how does it get configuration information? Siemens recommends you define your own wrapper around start(), such as init_start(), so you can define your own arguments such as configuration values and return the response. Alternatively, a sequence can get a handle to a component by calling get_sequencer() or the cruder m_sequencer property and pass that to set() and get(). Another style is to pass a virtual sequencer handle through the start() method. There are other approaches – verification engineers can be very devious!
Good to the Last Spoonful
Knowing when to end a test is difficult. UVM will end the run phase unless you have raised an objection. Siemens recommends calling raise_objection() and drop_objection(), at the test level, around starting the top-level sequence. Other vendors enthusiastically call these methods for each sequence, or even each item. If you sprinkle too many of these calls in your testbench, there is a good chance you’ll forget a drop_objection(), and the test never ends.
Engineers have been creating UVM testbenches for over a decade and innovated many ways around issues. For maximum reuse and productivity, start with your company’s style so your code is easily understood. Evolution over revolution.
For more ideas on styles, see the Verification Academy UVM Cookbook https://verificationacademy.com/cookbook/uvm
Send me your comments on your favorite UVM “toppings”!
You can learn more about these topics including Oriented Programming with the Siemens SystemVerilog for Verification course. It is offered in instructor led format by our industry expert instructors, or in a self-paced on-demand format. It can also be tailored to address your specific design goals and show you how to set up an environment for reuse for additional designs. Also, you can now earn a digital badge/level 1 certificate by taking our Advanced Topics Badging Exam. This will enable you to showcase your knowledge of this topic by displaying the badge in your social media and email signature.