Phases vs. Threads
Posted by JL Gray on November 4th, 2009
JL Gray, Consultant, Verilab, Austin, Texas, and Author of Cool Verification
Building a testbench for personal use is easy. Building a testbench that can be used by others is much more difficult. To make it easier for verification IP written by different people to interoperate, modern verification methodologies support the concept of standardized “phases” during a simulation run. Phases are a way to help verification engineers communicate in a standard language about what is meant to be taking place at any given time during a simulation. For example, an explicitly phased VMM testbench built using vmm_env contains the following phases of execution:
· gen_cfg
· build
· reset
· config_dut
· start
· wait_for_end
· stop
· cleanup
· report
Ideally, each of these phases serves a clear purpose. If I want to reset the DUT, a good way to do it is to instrument the reset phase with the appropriate reset logic. Similarly, the bulk of the simulation activity will likely occur during the wait_for_end phase. The VMM now has support for implicit phasing. In an implicitly-phased system, components in the verification environment are stepped through each phase automatically by a global controller called vmm_simulation (and its associated “timelines”). I will discuss timelines in a separate post. In both the explicit and implicitly phased cases, the phases serve as guides through the simulation. However, most of the real work of the testbench will be accomplished by threads spawned off from these phases.
It is easy to spawn threads using a simple fork/join, but the VMM provides tools to make managing threads easier. In the VMM, the vmm_xactor base class provides support for managing threads and is at the same time phase-aware. How does it do this? For starters, vmm_xactor is now implicitly phased by the top level vmm_simulation controller. However, users maintain full control over the ability to start and stop the transactor, just as they did in earlier versions of the VMM. That means that a user could start a transactor during any VMM phase, and stop the transactor during the same or a later phase. The transactor could then query the current phase and change its behavior depending on the state of the simulation. Users can also modify their behavior via the use of callbacks.
Here is a diagram demonstrating the interaction between threads and an example subset of the new VMM implicit phases.
The diagram demonstrates activities that take place during specific phases of the testbench. It also shows that threads may start in one phase (such as the host generator starting in the reset phase) and stop in another (in this case, the shutdown phase). The astute reader will note that I didn’t really need standardized phases at all to handle this. I could have done all of the activities described above in the “run” phase. In fact, that’s what many people do, even today where other phases are available. The issue, as I stated at the beginning of the article, is that by standardizing when we do specific types of activities, our verification IP will be easier to reuse in other compatible environments.
