UVM Agent

In Universal Verification Methodology (UVM), the agent is a key component designed to encapsulate all the elements required to drive and monitor a DUT interface. It streamlines the verification process by integrating drivers, monitors, and sequencers into a single cohesive entity.

A user-defined agent class is extended from uvm_agent. uvm_agent is inherited by uvm_component.

class <agent_name> extends uvm_agent;

A UVM agent is a reusable verification component that represents an interface of the Design Under Test (DUT). It consolidates three main elements:

  1. Driver: Stimulates the DUT by driving signals based on the sequences provided.
  2. Monitor: Passively observes signals on the interface and extracts transactions.
  3. Sequencer: Supplies sequences of transactions to the driver for execution.
  • We need to declare driver, sequencer and monitor instance in agent class.
  • We need to create agent components in the build phase, driver and sequencer will be created only for the active agent.
  • Communication between driver seq_item_port and sequencer seq_item_export happens in the connect phase of the agent.

An agent can be of two types:

Active vs. Passive Agents

Active Agent: Contains all the three components a sequencer, a monitor and a driver to actively generate stimulus for the DUT.

Passive Agent: Contains only a monitor to observe and analyze DUT behavior without applying stimulus.

The set_config_int method is commonly used to set the property of an agent to control its mode either active or passive.

uvm_config_db#(int)::set(this, "<hierarchy_path>", "is_active", UVM_ACTIVE);  // For active mode
uvm_config_db#(int)::set(this, "<hierarchy_path>", "is_active", UVM_PASSIVE); // For passive mode
  • <hierarchy_path>: The hierarchical path to the agent (e.g., "*.my_agent" for all components named my_agent).
  • "is_active": The string key that corresponds to the is_active property of the agent.
  • UVM_ACTIVE and UVM_PASSIVE: Predefined macros in UVM representing the agent’s mode.

For latest version of UVM, uvm_config_db should be use instead of set_config_int.

Example: Configuring an Agent with set_config_int

Here is an example of using set_config_int to configure an agent:

Top-level Testbench Code

import uvm_pkg::*;
`include "uvm_macros.svh"
`include "agent.sv"

class my_test extends uvm_test;
    `uvm_component_utils(my_test)
  
  my_agent agent;

    function new(string name = "my_test", uvm_component parent = null);
        super.new(name, parent);
    endfunction

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
      agent = my_agent::type_id::create("agent",this);
        // Set the agent to active mode
        uvm_config_db#(int)::set(this, "*", "is_active", UVM_ACTIVE);
        
        // Alternatively, set the agent to passive mode
        // uvm_config_db#(int)::set(this, "my_agent", "is_active", UVM_PASSIVE);
    endfunction
endclass

module tb;
  initial begin
    run_test("my_test");
  end 
endmodule

Agent Code:

class my_agent extends uvm_agent;
    `uvm_component_utils(my_agent)

    // Property to track agent mode
    uvm_active_passive_enum is_active;

    function new(string name = "my_agent", uvm_component parent = null);
        super.new(name, parent);
    endfunction

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);

        // Retrieve the "is_active" value from the config DB
        if (!uvm_config_db#(int)::get(this, "", "is_active", is_active)) begin
            `uvm_fatal("CONFIG", "is_active configuration not found")
        end
    endfunction

    virtual function void connect_phase(uvm_phase phase);
      if (is_active == UVM_ACTIVE) begin
            // Connect drivers and sequencers for active mode
            `uvm_info("AGENT", "Agent is active", UVM_LOW)
        end else begin
            // Configure agent for passive mode
            `uvm_info("AGENT", "Agent is passive", UVM_LOW)
        end
    endfunction
endclass

Output:

UVM_INFO @ 0: reporter [RNTST] Running test my_test...
UVM_INFO agent.sv(23) @ 0: uvm_test_top.agent [AGENT] Agent is active
UVM_INFO /apps/vcsmx/vcs/U-2023.03-SP2//etc/uvm-1.2/src/base/uvm_report_server.svh(904) @ 0: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

** Report counts by severity
UVM_INFO :    3
UVM_WARNING :    0
UVM_ERROR :    0
UVM_FATAL :    0
** Report counts by id
[AGENT]     1
[RNTST]     1
[UVM/RELNOTES]     1

get_is_active() Method

The get_is_active() method in UVM agents is a built-in method provided by the uvm_agent base class. It is used to retrieve the current activity mode of an agent (i.e., whether the agent is active or passive).

Example:

A simple active agent example which contains driver, sequencer and monitor instance.

class p_agent extends uvm_agent;
  p_driver driver;
  pt_sequencer sequencer;
  p_monitor monitor;
  
  `uvm_component_utils(p_agent)
  
  //constructor
  function new(string name, uvm_component parent);
    super.new(name,parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
     
    if (get_is_active()==UVM_ACTIVE) begin
      driver = p_driver::type_id::create("driver",this);
      sequencer = pt_sequencer::type_id::create("sequencer",this);
      `uvm_info(get_name(), "This is Active agent", UVM_LOW);
    end
    monitor = p_monitor::type_id::create("monitor",this);
  endfunction
  
  function void connect_phase(uvm_phase phase);
    if(get_is_active()==UVM_ACTIVE) begin
      driver.seq_item_port.connect(sequencer.seq_item_export);
    end
  endfunction
  
endclass