uvm - modrpc/info GitHub Wiki

Table of Contents

Websites

UVM: Overview

UVM TB Architecture

Class Diagram

Overall

Sequence

Basic Concepts

Build phase

  • Build phase는 UVM component들의 hierarchy를 만든다 (parent)
  • Dumping topology of UVM environment
class your_test extends uvm_test;
  //...
  virtual function void end_of_elaboration_phase(uvm_phase phase);
    uvm_top.print_topology();
  endfunction
endclass

Configuration

  • Configuration은 기본적으로 build phase에서 만든 hierachy내의 특정 component (hiarchical path) 내의 값을 dynamically update/get할 수 있도록 한다

Sequencer-driver communication

  • Sequencer는 일종의 interepter
  • Sequence는 일종의 program (to be interpreted by sequencer)
  • Sequencer는 sequence로부터 transaction을 발생시킨다
    • e.g. Sequencer는 TLM port-export를 통해 driver에게 transaction을 공급한다
    • Sequencer는 특정 type의 transaction을 generate한다
typedef uvm_sequencer #(my_transaction) my_sequencer;

class my_sequence extends uvm_sequence #(my transaction);
  task body; // generate 8 transaction (uvm_sequence_tem) 
    repeat(8) begin
      req = my_transcation::type_id::create("req");
      start_item(req);
      finish_item(Req);
    end
  endtask
endclass

UVM Class Reference: Foundational Classes

Globals

This category defines a small list of types, variables, functions, and tasks defined in the uvm_pkg scope. These items are accessible from any scope that imports the uvm_pkg.

Base

This basic building blocks for all environments are components, which do the actual work, transactions, which convey information between components, and ports, which provide the interfaces used to convey transactions. The UVM’s core base classes provide these building blocks.

Base classes

uvm_object

All components and transactions derive from uvm_object, which defines an interface of core class-based operations: create, copy, compare, print, sprint, record, etc. It also defines interfaces for instance identification (name, type name, unique id, etc.) and random seeding.

uvm_component

The uvm_component class is the root base class for all UVM components. Components are quasi-static objects that exist throughout simulation. This allows them to establish structural hierarchy much like modules and program blocks. Every component is uniquely addressable via a hierarchical path name, e.g. “env1.pci1.master3.driver”. The uvm_component also defines a phased test flow that components follow during the course of simulation. Each phase-- build, connect, run, etc.-- is defined by a callback that is executed in precise order. Finally, the uvm_component also defines configuration, reporting, transaction recording, and factory interfaces.

The uvm_component class is the root base class for UVM components. In addition to the features inherited from uvm_object and uvm_report_object, uvm_component provides the following interfaces:

  • Hierarchy: provides methods for searching and traversing the component hierarchy.
  • Phasing: defines a phased test flow that all components follow, with a group of standard phase methods and an API for custom phases and multiple independent phasing domains to mirror DUT behavior e.g. power Configuration provides methods for configuring component topology and other parameters ahead of and during component construction.
  • Reporting: provides a convenience interface to the uvm_report_handler. All messages, warnings, and errors are processed through this interface.
  • Transaction recording: provides methods for recording the transactions produced or consumed by the component to a transaction database (vendor specific).
  • Factory: provides a convenience interface to the uvm_factory. The factory is used to create new components and other objects based on type-wide and instance-specific configuration.

uvm_transaction

The uvm_transaction is the root base class for UVM transactions, which, unlike uvm_components, are transient in nature. It extends uvm_object to include a timing and recording interface. Simple transactions can derive directly from uvm_transaction, while sequence-enabled transactions derive from uvm_sequence_item.

This class provides timestamp properties, notification events, and transaction recording support.

Use of this class as a base for user-defined transactions is deprecated. Its subtype, uvm_sequence_item, shall be used as the base class for all user-defined transaction types.

The intended use of this API is via a uvm_driver to call uvm_component::accept_tr, uvm_component::begin_tr, and uvm_component::end_tr during the course of sequence item execution. These methods in the component base class will call into the corresponding methods in this class to set the corresponding timestamps (accept_time, begin_time, and end_tr), trigger the corresponding event (begin_event and end_event, and, if enabled, record the transaction contents to a vendor-specific transaction database.

Note that start_item/finish_item (or `uvm_do* macro) executed from a uvm_sequence #(REQ,RSP) will automatically trigger the begin_event and end_events via calls to begin_tr and end_tr. While convenient, it is generally the responsibility of drivers to mark a transaction’s progress during execution. To allow the driver to control sequence item timestamps, events, and recording, you must add +define+UVM_DISABLE_AUTO_ITEM_RECORDING when compiling the UVM package. Alternatively, users may use the transaction’s event pool, events, to define custom events for the driver to trigger and the sequences to wait on. Any in-between events such as marking the begining of the address and data phases of transaction execution could be implemented via the events pool.

uvm_root

The uvm_root class is special uvm_component that serves as the top-level component for all UVM components, provides phasing control for all UVM components, and other global services.

Reporting

The reporting classes provide a facility for issuing reports (messages) with consistent formatting and configurable side effects, such as logging to a file or exiting simulation. Users can also filter out reports based on their verbosity , unique ID, or severity.

Factory

As the name implies, the UVM factory is used to manufacture (create) UVM objects and components. Users can configure the factory to produce an object of a given type on a global or instance basis. Use of the factory allows dynamically configurable component hierarchies and object substitutions without having to modify their code and without breaking encapsulation.

Phasing

UVM implements an automated mechanism for phasing the execution of the various components in a testbench.

The API described here provides a general purpose testbench phasing solution, consisting of a phaser machine, traversing a master schedule graph, which is built by the integrator from one or more instances of template schedules provided by UVM or by 3rd-party VIP, and which supports implicit or explicit synchronization, runtime control of threads and jumps.

Each schedule leaf node refers to a single phase that is compatible with that VIP’s components and which executes the required behavior via a functor or delegate extending the phase into component context as required.

Execution threads are tracked on a per-component basis.

Phasing classes

uvm_phase

The base class for defining a phase’s behavior, state, context

uvm_domain

Phasing schedule node representing an independent branch of the schedule

uvm_bottomup_phase

A phase implemenation for bottom up function phases.

uvm_topdown_phase

A phase implemenation for topdown function phases.

uvm_task_phase

A phase implemenation for task phases.

UVM Common Phases

The common phases are the set of function and task phases that all uvm_components execute together.

  • uvm_build_phase: Create and configure of testbench structure
  • uvm_connect_phase: Establish cross-component connections.
  • uvm_end_of_elaboration_phase: Fine-tune the testbench.
  • uvm_start_of_simulation_phase: Get ready for DUT to be simulated.
  • uvm_run_phase: Stimulate the DUT.
  • uvm_extract_phase: Extract data from different points of the verficiation environment.
  • uvm_check_phase: Check for any unexpected conditions in the verification environment.
  • uvm_report_phase: Report results of the test.
  • uvm_final_phase: Tie up loose ends.

UVM Run-Time Phases

The run-time schedule is the pre-defined phase schedule which runs concurrently to the

  • uvm_run_phase: global run phase.
  • uvm_pre_reset_phase: Before reset is asserted.
  • uvm_reset_phase: Reset is asserted.
  • uvm_post_reset_phase: After reset is de-asserted.
  • uvm_pre_configure_phase: Before the DUT is configured by the SW.
  • uvm_configure_phase: The SW configures the DUT.
  • uvm_post_configure_phase: After the SW has configured the DUT.
  • uvm_pre_main_phase: Before the primary test stimulus starts.
  • uvm_main_phase: Primary test stimulus.
  • uvm_post_main_phase: After enough of the primary test stimulus.
  • uvm_pre_shutdown_phase: Before things settle down.
  • uvm_shutdown_phase: Letting things settle down.
  • uvm_post_shutdown_phase: After things have settled down.

Configuration and Resources

The Configuration and Resource Classes are a set of classes which provide a configuration database. The configuration database is used to store and retrieve both configuration time and run time properties.

UVM Class Reference: Verification Classes

Verification Components

Verification components form the foundation of the UVM. They encapsulate behavior of drivers, scoreboards, and other objects in a testbench. The UVM library provides a set of predefined component types, all derived directly or indirectly from uvm_component.

uvm_test

The UVM Test is the top-level UVM Component in the UVM Testbench. The UVM Test typically performs three main functions: Instantiates the top-level environment, configures the environment (via factory overrides or the configuration database), and applies stimulus by invoking UVM Sequences through the environment to the DUT.

Typically, there is one base UVM Test with the UVM Environment instantiation and other common items. Then, other individual tests will extend this base test and configure the environment differently or select different sequences to run.

uvm_env

The UVM Environment is a hierarchical component that groups together other verification components that are interrelated. Typical components that are usually instantiated inside the UVM Environment are UVM Agents, UVM Scoreboards, or even other UVM Environments. The top-level UVM Environment encapsulates all the verification components targeting the DUT.

For example: In a typical system on a chip (SoC) UVM Environment, you will find one UVM Environment per IP (e.g., PCIe Environment, USB Environment, Memory Controller Environment, etc.). Sometimes, those IP Environments are grouped together into Cluster Environments (e.g., IO Environment, Processor Environment, etc.) that are grouped together eventually in the to- level SoC Environment.

uvm_agent

The UVM Agent is a hierarchical component that groups together other verification components that are dealing with a specific DUT interface. A typical UVM Agent includes a UVM Sequencer to manage stimulus flow, a UVM Driver to apply stimulus on the DUT interface, and a UVM Monitor to monitor the DUT interface. UVM Agents might include other components, like coverage collectors, protocol checkers, a TLM model, etc.

uvm_monitor

The UVM Monitor samples the DUT interface and captures the information there in transactions that are sent out to the rest of the UVM Testbench for further analysis. Thus, similar to the UVM Driver, it spans abstraction levels by converting pin-level activity to transactions. In order to achieve that, the UVM Monitor typically has access to the DUT interface and also has a TLM analysis port to broadcast the created transactions through.

The UVM Monitor can perform internally some processing on the transactions produced (such as coverage collection, checking, logging, recording, etc.) or can delegate that to dedicated components connected to the monitor's analysis port.

uvm_scoreboard

The UVM Scoreboard’s main function is to check the behavior of a certain DUT. The UVM Scoreboard usually receives transactions carrying inputs and outputs of the DUT through UVM Agent analysis ports (connections are not depicted in Figure 1), runs the input transactions through some kind of a reference model (also known as the predictor) to produce expected transactions, and then compares the expected output versus the actual output. There are different methodologies on how to implement the scoreboard, the nature of the reference model, and how to communicate between the scoreboard and the rest of the testbench.

uvm_driver

The UVM Driver receives individual UVM Sequence Item transactions from the UVM Sequencer and applies (drives) it on the DUT Interface. Thus, a UVM Driver spans abstraction levels by converting transaction-level stimulus into pin-level stimulus. It also has a TLM port to receive transactions from the Sequencer and access to the DUT interface in order to drive the signals.

uvm_push_driver

uvm_random_stimulus

uvm_subscriber

Sequencers

The sequencer serves as an arbiter for controlling transaction flow from multiple stimulus generators. More specifically, the sequencer controls the flow of uvm_sequence_item-based transactions generated by one or more uvm_sequence #(REQ,RSP)-based sequences.

uvm_sequencer #(REQ, RSP)

Requests for new sequence items are initiated by the driver. Upon such requests, the sequencer selects a sequence from a list of available sequences to produce and deliver the next item to execute. This sequencer is typically connected to a user-extension of uvm_driver #(REQ,RSP).

uvm_push_sequencer #(REQ, RSP)

Sequence items (from the currently running sequences) are pushed by the sequencer to the driver, which blocks item flow when it is not ready to accept new transactions. This sequencer is typically connected to a user-extension of uvm_push_driver #(REQ,RSP).

Sequences

Sequences encapsulate user-defined procedures that generate multiple uvm_sequence_item-based transactions. Such sequences can be reused, extended, randomized, and combined sequentially and hierarchically in interesting ways to produce realistic stimulus to your DUT.

With uvm_sequence objects, users can encapsulate DUT initializaton code, bus-based stress tests, network protocol stacks-- anything procedural-- then have them all execute in specific or random order to more quickly reach corner cases and coverage goals.

uvm_sequence_item

The uvm_sequence_item is the base class for user-defined transactions that leverage the stimulus generation and control capabilities of the sequence-sequencer mechanism.

uvm_sequence #(REQ,RSP)

The uvm_sequence extends uvm_sequence_item to add the ability to generate streams of uvm_sequence_items, either directly or by recursively execting other uvm_sequences.

Register Layer

The Register abstraction classes, when properly extended, abstract the read/write operations to registers and memories in a design-under verification.

A register model is typically composed of a hierarchy of blocks that usually map to the design hierarchy. Blocks contain registers, register files and memories.

The UVM register layer classes are not usable as-is. They only provide generic and introspection capabilities. They must be specialized via extensions to provide an abstract view that corresponds to the actual registers and memories in a design. Due to the large number of registers in a design and the numerous small details involved in properly configuring the UVM register layer classes, this specialization is normally done by a model generator. Model generators work from a specification of the registers and memories in a design and are thus able to provide an up-to-date, correct-by-construction register model. Model generators are outside the scope of the UVM library.

Command Line Processor

The command line processor provides a general interface to the command line arguments that were provided for the given simulation.

⚠️ **GitHub.com Fallback** ⚠️