Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • Start Here4
  • UVM Foundations14
  • UVM Phases & Simulation Lifecycle26
  • Factory & Configuration15
  • Transaction-Level Modeling (TLM)13
  • UVM Sequences & Stimulus21
  • UVM Agents & Protocol VIP21
    • Agent Architecture
    • Reusable VIP: Active, Passive and Protocol Agents
      • Active and Passive in Delivery: What a VIP Owes Its Integrator
      • Two Passive Monitors, One Bus
      • VIP Parameterization: Widths Up Front, Behavior at Runtime
      • Protocol Agent Patterns: APB, AXI and Streaming
      • Versioning, Delivery and Release Readiness
    • Error and Fault Injection
    • Agent Patterns: Slaves, Reset, Interrupts and Pipelines
  • Environment & Test Classes11
  • Checking & Coverage in UVM21
  • UVM Register Abstraction Layer (RAL)22
  • Advanced UVM in Practice13
  • Debug & Regression10
  • Coding Practice47
  • Verification in Industry Practice10
  • Senior Prep: Architecture, Leadership and Interviews32
Loading lesson

‹Reusable VIP: Active, Passive and Protocol Agents
  1. Topics
  2. UVM Verification
  3. UVM Agents & Protocol VIP
  4. Reusable VIP: Active, Passive and Protocol Agents
  5. Versioning, Delivery and Release Readiness

Part 6 · Agents & Protocol IP · Intermediate

Versioning, Delivery and Release Readiness

Semantic versions for VIP, deprecation shims, a UVM-library and VIP-version check in build, encrypted delivery, and the qualification gate before a release.

On this page

    You fix a timeout bug in the stream VIP, rename a badly named config field while you are there, and push the release. The next morning three projects report regressions. One set the old field name through config_db, which now matches nothing, so their agents run on defaults. One compiles with a UVM 1.2 library and your new code used a call that only exists in the IEEE 1800.2 library. The third is fine, but cannot tell from anything in the log which VIP version it is running. A VIP release is a contract with people you will never meet. How do you change it without breaking them?

    The idea: versions are promises

    A version number is a promise about compatibility. With semantic versioning, a major release may break the API and comes with migration notes; a minor release adds features without breaking anything; a patch fixes behaviour without changing the interface at all. Consumers can then upgrade patches without reading anything, minors with a glance at the changelog, and majors on purpose. Renaming a config field is a breaking change, so either it waits for a major, or it ships with a shim that keeps the old name working for a while.

    Think of a public library moving a shelf. You do not simply move the books and let readers find empty space; you leave a sign at the old spot pointing to the new one, and take it down only after everyone has had time to learn the new place.

    The picture: a release, from change to consumer

    Step

    What it contains

    What it protects against

    Version constant

    AXIS_VIP_VERSION in the package, printed at build

    Not knowing which VIP a failing log used

    Changelog entry

    Every change, tagged major, minor or patch

    Surprise behaviour changes

    Deprecation shim

    Old names still work, warn once, removal date stated

    Silent breakage of consumer configs

    Compatibility checks

    Library version checks, required-version checks

    Compiling against an unsupported UVM or VIP

    Qualification run

    Smoke, feature and compatibility tiers on every supported simulator

    Shipping something only your bench exercises

    Delivery bundle

    Sources (or encrypted sources), filelist, user guide, examples

    Consumers guessing how to compile and configure

    Build it

    A deprecation shim that actually routes

    The renamed field's old name stays in the config object for one release. The shim must notice that a consumer set it, warn once (not every cycle), and use it. A shim that only exists, and is never consulted, is a silent break with extra steps.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // snippet
    class axis_cfg extends uvm_object;
      `uvm_object_utils(axis_cfg)
      int unsigned ready_timeout = 1000;       // the new name
      int unsigned rdy_tmo       = 0;          // DEPRECATED in 2.3, removed in 3.0; 0 means unset
      local bit    warned;
      function new(string name = "axis_cfg");
        super.new(name);
      endfunction
      virtual function int unsigned effective_ready_timeout();
        if (rdy_tmo != 0) begin                // an old consumer set the old name
          if (!warned) begin
            `uvm_warning("AXIS_DEPRECATED", "rdy_tmo is deprecated and removed in 3.0: set ready_timeout")
            warned = 1;
          end
          return rdy_tmo;
        end
        return ready_timeout;
      endfunction
    endclass

    The agent reads effective_ready_timeout(), never the fields directly. The model below runs the same logic with no UVM library and checks the three cases: the default, a consumer using the new name, and a consumer using the old one, which must warn exactly once.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    class axis_cfg_model;
      int unsigned ready_timeout = 1000;
      int unsigned rdy_tmo = 0;               // deprecated name; 0 means unset
      int unsigned warnings = 0;
      function int unsigned effective_ready_timeout();
        if (rdy_tmo != 0) begin
          if (warnings == 0) warnings++;      // warn once
          return rdy_tmo;
        end
        return ready_timeout;
      endfunction
    endclass
    
    module tb_deprecation_shim;
      axis_cfg_model c;
      int bad = 0;
      initial begin
        c = new();
        if (c.effective_ready_timeout() != 1000) bad++;   // default
        c.ready_timeout = 2000;
        if (c.effective_ready_timeout() != 2000) bad++;   // a consumer on the new name
        c.rdy_tmo = 500;
        if (c.effective_ready_timeout() != 500) bad++;    // a consumer on the old name
        if (c.effective_ready_timeout() != 500) bad++;    // still routed
        if (c.warnings != 1) bad++;                       // but warned only once
        if (bad == 0) $display("PASS: old name routed, new name honoured, one warning");
        else $display("FAIL: %0d shim checks failed", bad);
        $finish;
      end
    endmodule

    Say who you are, and check who you are running with

    The package carries a version constant, and the agent prints it once at build. When a consumer's log arrives with a bug report, the first line you look for says which VIP they ran. The same place checks the library: code that differs between UVM 1.2 and the IEEE 1800.2 reference library is selected at compile time with the library's own defines. The 1800.2 library defines UVM_VERSION_POST_2017; UVM 1.2 does not, and defines UVM_VERSION_1_2 instead.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // snippet: in axis_vip_pkg
    localparam string AXIS_VIP_VERSION = "2.3.1";
    
    // In axis_agent::build_phase, once:
    `uvm_info("AXIS_VIP", $sformatf("axis VIP %s on %s", AXIS_VIP_VERSION, uvm_revision_string()), UVM_LOW)
    
    `ifdef UVM_VERSION_POST_2017
      // IEEE 1800.2 library only
    `else
      // UVM 1.2 path
    `endif

    A consumer env that needs a feature added in a minor release can check the constant in its own build and fail with a clear message ("needs axis VIP 2.2 or later") instead of failing later with a missing method.

    Encrypted delivery and the support matrix

    Commercial VIP is often shipped encrypted with the IEEE 1735 protection pragmas, so consumers can compile and simulate it but not read it. That changes what you owe them: they cannot debug inside your code, so your messages, your print output and your user guide carry the whole load. Whatever the delivery, publish the matrix you actually qualify: simulators and their versions, UVM library versions, and any compile options the VIP needs. A combination not in the matrix is not supported, however likely it is to work.

    The qualification gate

    Tier

    What it runs

    What it proves

    Smoke

    Active, passive and mixed topologies, one test each

    The build shapes are right; passive drives nothing

    Feature

    One test per knob, at its edges

    Every documented option does what the guide says

    Compatibility

    Configurations from previous releases, unchanged

    Old consumer code still builds and passes, with deprecation warnings only

    Matrix

    The smoke tier on every simulator and UVM library in the matrix

    The support claim is true

    A release ships when every tier passes and the changelog, version constant and user guide agree. That list is a checklist with a sign-off, not a feeling of readiness.

    Watch it run

    The model above is compiled and run by the course's checker. A correct shim prints one line:

    Diagram
    PASS: old name routed, new name honoured, one warning

    Delete the warnings == 0 guard and the last check fails (one warning per call); return ready_timeout unconditionally and the old-name checks fail. Those two mistakes are the ones real shims ship with.

    What breaks: the rename that looked like a regression

    A VIP team renamed rdy_tmo to ready_timeout in a minor release, without a shim, judging it too small to matter. Consumers that set the field through the config object got a compile error, which was annoying but honest. Consumers that set it as a separate config_db entry, an older style many still used, got nothing at all: the set with the old name simply matched no get. Their agents ran with the default timeout, and long-latency ports started failing with timeout errors.

    To the consumers it looked exactly like a functional regression in the new VIP. Three teams filed bugs against the timeout logic before anyone diffed the config field names. The VIP team re-released with a shim that also read the old config_db key and warned, and added a compatibility tier that runs the previous release's example configurations unchanged. That tier would have caught the rename the day it was made.

    Interview

    "How do you release a change to a VIP that many projects use?"

    A weak answer: "Update the code, bump the version and tell people to update." That breaks every consumer who relied on what changed and gives them no way to find out why.

    A strong answer: "Semantic versions: patches fix behaviour, minors add compatible features, majors may break and come with migration notes. Renames and removals go through a deprecation shim that routes the old name, warns once and states a removal release. The package has a version constant printed at build, and library differences are selected with the UVM version defines. Before release, a qualification gate runs smoke tests in active, passive and mixed topologies, a test per knob, previous releases' configurations unchanged, and the smoke tier across the simulator and UVM matrix we support. Encrypted deliveries get extra care in messages and documentation because consumers cannot read the code."

    Follow-ups to expect: How long does a shim live? (at least one minor release, with the removal version in the warning) and How does a consumer require a minimum version? (check the version constant in its own build and fail clearly).

    Check yourself A consumer sets the deprecated rdy_tmo and, in the same test, the new ready_timeout. Which value does the shim above use, and is that the right policy?

    rdy_tmo, because any non-zero old value wins. That keeps old consumers working unchanged, but it surprises a consumer half-way through migrating. A stricter shim reports an error when both are set, which forces the conflict to be resolved; whichever policy you choose, write it in the deprecation note.

    Check yourself Which qualification tier catches a passive agent whose interface drives a default value?

    The smoke tier, in the passive topology. It is the cheapest tier and runs first, and an agent that drives anything in passive mode fails it before any feature or compatibility test runs.

    Next: the VIP is reusable and releasable. Error and fault injection uses its hooks to make the DUT's error paths run on purpose.

    Related topics

    • VIP parameterization

    • Agent configuration

    • Error and fault injection

    Previous

    106 / 280

    Next: Error and Fault Injection

    Up next

    Up nextError and Fault Injection

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Active and Passive in Delivery: What a VIP Owes Its Integrator
    • Two Passive Monitors, One Bus
    • VIP Parameterization: Widths Up Front, Behavior at Runtime