Where to Draw the Lines with UVM

In my last blog I covered a split in UVM verification responsibilities. It was pretty popular so I decided to carry on with an example of what it might look like in a little more detail. If you haven’t read that, I’d recommend going back before you carry on. To rehash, I suggested two people work on the same testbench. There’s a how engineer who is a UVM expert that takes care of how the testbench is constructed. The other is the what engineer – a product expert – who understands the product and therefore knows what needs to be built.

How those two people work together might look a little like this…

First, the goal at the outset of the partnership would be enabling a fully functioning skeleton environment with the minimum functional implementation required to support a sanity feature.

A sanity feature to me is some bare minimum (yet production) functionality where a DUT reacts to basic (yet still production) stimulus with an equally basic (yes… production) response. You get to decide what that is but keep it small. Even a single bit would suffice just to get off the ground and get the partnership moving.

An instance of the DUT with partial connectivity is a fundamental first step. Clocks and resets of course. We’d have an environment with skeleton agents. We’d integrate existing IP. Ideally there’d be room for a configuration aspect – though it’s always nice when sanity requires no configuration at all. We’d have a test template. On that we’d add sanity functionality to the skeleton agents with checking and a test to close the loop.

Important to note that everything is coded with an *only if required asterisk (and some wiggle room to ensure the code is extensible). That’s important to have the how and what engineers working in lock step. Remembering that the how engineer is an enabler in this arrangement, they have to be dialed in to the needs of the what engineer. Otherwise, the what engineer is left to sit on their hands.

Along those lines, here’s a possible early days who and when timeline…

The partnership starts immediately in planning a direct path to completing your sanity feature. That includes both how and what. Follow all your normal documentation and scheduling practices. In addition, establish communication and teamwork practices that’ll last through the entire development cycle. Doesn’t have to be super formal, just plan to talk a lot!

Moving on, enablement is a tangible first development step. In our case, enablement is groundwork from the how engineer that enables a chunk of detailed implementation by the what engineer. For example, this could be a skeleton agent and checker (could be as simple as a monitor or a more complicated functional model/scoreboard combo) with scripting to support compile as a minimum.

For main construction activities, the what engineer moves into the skeleton agent and the how engineer turns to testbench and environment construction. This is the uvm_component virtual boundary between how and what that I mentioned previously; more on that in a bit. The construction happens in parallel but communication continues.

Last comes the test that validates our basic sanity response. This is another combination of enablement and implementation. The how engineer would settle on a strategy for test creation and provide the required templates or guidelines or whatever. Then the what engineer fills in the blanks.

Simple enough. But considering our roles split expert knowledge of UVM with expert knowledge of the product, let’s take a look at a few of the hand-off points between how and what engineers.

Getting back to the uvm component boundary… more precisely, I think you could look at processes spawned within the uvm_componet::run_phase as the handoff point.

The what engineer doesn’t need to know much about UVM phasing, just that they put their work in the_what_method. Or for a specialized component like a uvm_driver, the hand-off point could be even lower. For example the how engineer handles the UVM sequencer interactions and adds an empty method for implementation. Kind of like this…

For other components like monitors or scoreboards that use TLM connections, the how engineer can guide the what engineer into consuming and producing transactions with write methods and analysis ports. Those would be identified in the planning and coded as part of the skeleton component creation. A lot of this could be handled by UVM code generators, of course. But there’d still be some manual additions by the how engineer.

Next hand-off point… and this may be a little more contentious… is using the how engineer to handle everything though the UVM config db (or resource db if you prefer) as part of integration. I like that because the config db is tightly linked to DUT connectivity and configuration hierarchy – or lack of hierarchy – which is more of a structural aspect of the environment and thus more in the how engineer’s domain. More generally, you could see this as charging the how engineer with configuration supply and delivery while the what engineer handles demand and usage. I also like this because the config/resource_db is (still) confusing (to me) so fewer people interacting with it means fewer people punching their keyboard when it doesn’t do what they’re expecting 😐.

A transition point where the lines may blur would be reset and configuration. Ideally, the what engineer adds reset and configuration functionality to the reset_phase and configure_phase in each component and the how engineer doesn’t do anything. More likely, ordering out of reset starts to get a little nasty and the how engineer has to build in some synchronization at the environment level. A warning sign you’ve reached this point is heavy use of pre_ and post_ reset, configuration and randomize methods. In my experience, prevalence of pre_/post_ functionality can be a sign of trial-n-error to manage DUT bring up. Trial-n-error is fragile and prone to breakage; deliberate ordering is better.

Saving the trickiest for last, we end with UVM sequences and their relationship to test writing. I think sequences are the bulkiest part of UVM from a usability point of view, also the most dangerous because they often include pointers to the entire world thereby making everything in an environment accessible. I know sequences are good for reuse and all that. But seriously, a lot of the time they just look like old-school verilog procedural tests or extra constraints around an atomic transaction.

To ease test writing for the what engineer… and other/junior engineers with even less UVM experience… our hand-off point is probably a thoughtfully designed test API that (a) enables a procedural test look-n-feel by (b) limiting direct exposure to sequences and (c) providing an easy means for transaction and configuration type override. That’s a blog post on its own.

Finishing with a general comment on hand-off points… low-level hand-off points not only shield the what engineer from UVM, they also give the how engineer opportunities to establish uniform look-n-feel throughout the testbench or refactor structural improvements. Over time, maybe the lines creeps up a bit as the what engineer gains experience, but I don’t think they have too. As likely would be customized code generators that makes template generation easier for the how engineer.

And coming back to the partnership supports for a minute, I see incremental development as a key support between what and how. Meaning a team would go through that set of planning -> enablement -> construction -> verify from the table above many, many times through the course of a project, incrementally layering new features as they go. Nobody gets too far ahead or too far behind; everyone always working toward the same near term goals. Construction should be more intense for the what engineer populating functionality (i.e. the important stuff) while the effort required by the how engineer lessens over time as testbench structures solidify.

There’s other considerations but in terms of where we start to split the how and what aspects of UVM testbench construction I like this as a conversation starter. If there are other hand-off points I’ve missed, by all means bring them up. Or go ahead and disagree completely. I think it’s more productive to disagree about UVM than just carry on with use models that don’t make sense.

-neil

2 thoughts on “Where to Draw the Lines with UVM

  1. This is a lot like what Fred Brooks proposed in his 1975 book “The Mythical Man-Month.” Brooks, of course, was talking about software in general, not testbenches. He said, “Architecture must be carefully distinguished from implementation.” Then he quoted G. A. Blaauw, who said, “Where architecture tells what happens, implementation tells how it is made to happen.”

    Brooks says that a well-built system has “conceptual integrity.” He acknowledges that architectural ideas can come from anyone on the team. However, he believes that it should fall to a single engineer or a small team of “agreeing resonant minds” to make architectural decisions.

  2. I’m a little uncomfortable with both engineers working on the same component like that, unless they’re doing Pair Programming. It’s messy and invites logistical revision control headaches. I’d like to see the ownership be more crisply separated.

    Engr. How can own the uvm_component. Engr. What can own a new class for each process spawned by the component. During planning, Engrs. How and What work out all the interfaces required by each process:
    – Virtual interfaces
    – TLM ports and FIFOs
    – Mailboxes, semaphores, events
    – Value and type parameters

    This way the engineers’ work is decoupled, and can be unit tested independently.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.