Module 9 — Advanced UVM
Beyond the basics: callbacks for hook-based behavior injection, objections for run_phase lifetime control, virtual sequences for cross-agent coordination, the register model, sequence libraries, report servers, factory overrides, and the resource database.
📑 Table of Contents
76Callbacks
The UVM callback mechanism (uvm_callback) lets you inject additional behavior into a component at predefined hook points, without modifying or subclassing the component itself — ideal for reusable VIP that end users need to extend without touching the VIP's source.
Use a factory override when you want to replace a component's entire behavior with a different class. Use a callback when you want to inject small, targeted behavior at specific points while leaving the rest of the component untouched — callbacks can also be added/removed dynamically during a test.
77Objections
The objection mechanism controls when run_phase (and other task-based phases) is allowed to end — a component "raises" an objection to say "keep the phase alive, I'm still working," and "drops" it when done. The phase ends once all outstanding objections are dropped.
Forgetting to raise an objection: run_phase ends immediately at time 0 because nothing is holding it open, and the test finishes before any stimulus runs. Forgetting to drop an objection: the simulation hangs forever, since run_phase never sees the objection count reach zero. Always pair raise/drop carefully, ideally using try/finally-style patterns or drain time via phase.phase_done.set_drain_time().
78Virtual Sequence
A virtual sequence doesn't drive any single sequencer directly — instead it coordinates multiple sequences across multiple agents/sequencers, enabling cross-interface scenarios (e.g., "inject an error on the AXI bus while simultaneously toggling reset on the config interface").
Wrapping cross-agent coordination in a virtual sequence (rather than forking sequences directly from the test) keeps the scenario itself reusable and composable — a virtual sequence can be started from different tests, or nested inside a larger virtual sequence, just like any other sequence.
79Register Model
The UVM Register Abstraction Layer (RAL) models a DUT's memory-mapped register space as reusable classes (uvm_reg, uvm_reg_block), letting sequences read/write registers by name through an abstract API instead of hand-coding bus transactions for every register access.
UVM_FRONTDOOR access goes through the actual bus protocol (realistic, but slower); UVM_BACKDOOR access uses direct hierarchical DUT signal references (via DPI or hierarchical paths) to read/write register storage instantly, bypassing the bus entirely — useful for fast test setup/initialization that isn't the focus of the test itself.
80Sequence Library
A uvm_sequence_library is a container that groups related sequences and can randomly select and execute one or more of them — useful for building randomized regression scenarios out of a pool of directed and constrained-random sequences.
81Report Server
The uvm_report_server centralizes how uvm_info/uvm_warning/uvm_error/uvm_fatal messages are formatted, filtered, counted, and ultimately reported — it's also the mechanism behind final pass/fail determination based on error counts.
Most engineers never touch the report server directly — it's used out-of-the-box. Customizing it becomes relevant when integrating with a company-wide regression dashboard that needs a specific message format, or when centrally controlling verbosity/severity actions (e.g., promoting specific warnings to errors) across an entire testbench.
82Factory Override
Building on the factory concept from Module 8, overrides come in two flavors — type overrides (replace every instance of a class globally) and instance overrides (replace only a specific instance path) — giving fine-grained control over test-specific component/object substitution.
| Override Type | Scope | Use Case |
|---|---|---|
| Type override | Every instance of the class, testbench-wide | Globally swap a component's implementation for this test |
| Instance override | Only the specified hierarchy path | Modify behavior of one specific agent/component while leaving siblings unchanged |
Factory overrides must be set before the component/object they affect is actually created (typically in the test's build_phase, before super.build_phase() propagates down, or even earlier). Setting an override after the target has already been constructed has no effect on that already-existing instance.
83Resource Database
uvm_resource_db is the lower-level mechanism that uvm_config_db is actually built on top of — a more general-purpose, precedence- and scope-based database for arbitrary named resources, not limited to configuration use.
| Aspect | uvm_config_db | uvm_resource_db |
|---|---|---|
| Relationship | Convenience layer built on top of resource_db | Lower-level, more general engine |
| Typical Use | Virtual interfaces, per-component config objects/knobs | Rarely used directly — mostly config_db underneath |
| Precedence Rules | Simpler, hierarchy-path based | More flexible but more complex (read/write precedence, scope matching) |
In day-to-day UVM code, use uvm_config_db — it's simpler and covers the vast majority of configuration-passing needs. Understanding that it's built on uvm_resource_db underneath is mostly useful for debugging obscure precedence issues or for advanced VIP infrastructure work.
🎯 Module 9 Recap
- Callbacks inject targeted behavior at defined hook points without subclassing — ideal for end-user VIP customization.
- Objections keep run_phase alive until all raised objections are dropped; forgetting to raise ends the test too early, forgetting to drop hangs it forever.
- Virtual sequences coordinate multiple sequences across multiple sequencers/agents for cross-interface scenarios.
- The register model (RAL) abstracts memory-mapped register access away from raw bus transactions, with frontdoor (via the bus) and backdoor (direct signal access) options.
- A sequence library groups related sequences for randomized selection and execution — good for regression-style scenario mixing.
- The report server centralizes message formatting, filtering, and pass/fail determination via severity counts.
- Factory overrides come as type (global) or instance (path-specific) — always set before the target component is constructed.
- uvm_resource_db is the general-purpose engine underlying uvm_config_db — use config_db day-to-day, understand resource_db for debugging edge cases.
📚 You've completed the SystemVerilog / UVM Series! From basics through advanced UVM — Modules 1 through 9 now cover the full stack from data types to register models.
↑ Back to Table of Contents
Comments
Post a Comment