1. Introduction

    The SystemVerilog2 UVM1 objections solve a problem—how to coordinate processes. Two processes P1, and P2 are running. But they can only exit together—they must synchronize their exit.

    The UVM is built of processes—the phases from uvm_components, the body task from a uvm_sequence and any threads from these processes. These processes often need to synchronize—for example a request is sent out, and the processing on collecting responses should not exit until the response is received.

    The UVM provides phases which are synchronized automatically. Those phases are pre-defined and can be extended. Sticking with the pre-defined phases is the best approach. A phase has an objection which is used to coordinate all the objects that are currently in the current phase. No object can exit the phase when the objection is raised. Each phase that wants to participate in the phase objection must raise an objection and later drop that objection. Synchronization with objections is conceptually simple—raise an objection to “passing the barrier” and drop an objection to “passing the barrier.”

    But the UVM phasing and objection code quickly become intertwined. There’s complexity there that can be problematic to debug and understand. Simple synchronization can be implemented with something much simpler.

    In5 the author proposes a simpler mechanism that end tests—a simple barrier. It has some bells and whistles and is worth consideration for a different way to exit testbenches. In4 the authors have created a great treatise on OVM and UVM and how to terminate tests. It’s much more than just terminating tests, and worth a look. The example code included in this paper is even simpler still—perhaps too simple—with no bells and whistles—with no debug hooks or callbacks. But that’s the point—transparent and boringly simple.

    Background

    Synchronization primitives3 exist in process control theory and operating system design among other places. There are many uses for them.

    In the UVM, the run_phase normally raises an objection to exiting. Later the objection will be dropped. At least one objection must be raised—usually in the test. Without the objection, simulation will end immediately. A typical run_phase is below. Most tests have one objection, used in this simple way.

    task run_phase(uvm_phase phase);
      phase.raise_objection(this);
      `uvm_info(get_type_name(), "...running", UVM_MEDIUM)
      ...
      phase.drop_objection(this);
    endtask

    The UVM offers some debug built-in, but this debug will generate lots of information with even the simplest usage. Using +UVM_OBJECTION_TRACE on the command line for just the simple usage above generates more than 100 lines of output.

  2. Download Paper