Skip to main content

Using the _decl Macro in UVM

· loading · loading · ·
Education UVM Verification UVM Verification SystemVerilog _Decl Macro Analysis Port
Education UVM Verification
Axolot Logic
Author
Axolot Logic
Digital Design Engineer
Table of Contents
UVM Series - This article is part of a series.
Part 29: This Article

📄 Using the _decl Macro
#


📌 Introduction
#

In UVM, when modeling transaction-level data transfer using TLM (Transaction-Level Modeling) interfaces, we often connect a single source (e.g. uvm_analysis_port) to a single target (uvm_analysis_imp). However, sometimes we might want to process data from the same source (for example, a producer) in different functions within the subscriber.

This is where the uvm_*_imp_decl() macro comes in. This macro allows us to define multiple “imp” implementations within interfaces, each of which can direct data to a different function.


🔎 Purpose of _decl Macro
#

  • To define multiple port implementations inside a single subscriber.
  • To direct incoming data to different functions.
  • To easily separate data from different components or even from the same component in a testbench.

📌 How to Use
#

1️⃣ First, declare the _decl macro:

`uvm_analysis_imp_decl(_1)
`uvm_analysis_imp_decl(_2)

2️⃣ Inside the subscriber:

uvm_analysis_imp_1 #(my_transaction, my_subscriber) analysis_imp1;
uvm_analysis_imp_2 #(my_transaction, my_subscriber) analysis_imp2;

3️⃣ Write different write_*() functions:

virtual function void write_1(my_transaction t);
  ...
endfunction

virtual function void write_2(my_transaction t);
  ...
endfunction

4️⃣ Connect the producer port to these subscriber ports:

producer.analysis_port.connect(subscriber.analysis_imp1);
producer.analysis_port.connect(subscriber.analysis_imp2);

🚀 Example Code
#

Below is a complete example showing _decl usage:

package my_pkg;
  `include "uvm_macros.svh"
  import uvm_pkg::*;

  `uvm_analysis_imp_decl(_1)
  `uvm_analysis_imp_decl(_2)

  // Transaction
  class my_transaction extends uvm_sequence_item;
    int data;
    `uvm_object_utils(my_transaction)
    function new(string name = "my_transaction");
      super.new(name);
    endfunction
  endclass

  // Producer
  class my_producer extends uvm_component;
    uvm_analysis_port #(my_transaction) analysis_port;
    `uvm_component_utils(my_producer)

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

    task run_phase(uvm_phase phase);
      my_transaction tr;
      phase.raise_objection(this);
      for (int i = 0; i < 5; i++) begin
        tr = my_transaction::type_id::create("tr");
        tr.data = i;
        `uvm_info("PRODUCER", $sformatf("Sending data: %0d", tr.data), UVM_LOW)
        analysis_port.write(tr);
        #100;
      end
      phase.drop_objection(this);
    endtask
  endclass

  // Subscriber
  class my_subscriber extends uvm_component;
    `uvm_component_utils(my_subscriber)

    uvm_analysis_imp_1 #(my_transaction, my_subscriber) analysis_imp1;
    uvm_analysis_imp_2 #(my_transaction, my_subscriber) analysis_imp2;

    function new(string name = "my_subscriber", uvm_component parent = null);
      super.new(name, parent);
      analysis_imp1 = new("analysis_imp1", this);
      analysis_imp2 = new("analysis_imp2", this);
    endfunction

    virtual function void write_1(my_transaction t);
      `uvm_info("SUBSCRIBER", $sformatf("write_1: Received data: %0d", t.data), UVM_LOW)
    endfunction

    virtual function void write_2(my_transaction t);
      `uvm_info("SUBSCRIBER", $sformatf("write_2: Received data: %0d", t.data), UVM_LOW)
    endfunction
  endclass

  // Environment
  class my_env extends uvm_env;
    my_producer producer;
    my_subscriber subscriber;
    `uvm_component_utils(my_env)

    function new(string name = "my_env", uvm_component parent = null);
      super.new(name, parent);
      producer = my_producer::type_id::create("producer", this);
      subscriber = my_subscriber::type_id::create("subscriber", this);
    endfunction

    function void connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      producer.analysis_port.connect(subscriber.analysis_imp1);
      producer.analysis_port.connect(subscriber.analysis_imp2);
    endfunction
  endclass

  // Test
  class my_test extends uvm_test;
    my_env env;
    `uvm_component_utils(my_test)

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

    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      env = my_env::type_id::create("env", this);
    endfunction
  endclass

endpackage

// Top module
module top;
  import uvm_pkg::*;
  import my_pkg::*;

  initial begin
    uvm_top.enable_print_topology = 1;
    run_test("my_test");
  end
endmodule

✨ Summary
#

✅ With the _decl macro, we can create multiple port implementations. ✅ Each implementation directs calls to a different write_*() function. ✅ This is ideal for processing data separately by source or by port.


UVM Series - This article is part of a series.
Part 29: This Article

Related

Using TLM FIFO, Analysis Port, and _decl Macro in UVM
· loading · loading
Education UVM Verification UVM Verification SystemVerilog TLM FIFO Analysis Port
Education UVM Verification
UVM Agent Usage and Adder Example
· loading · loading
Education UVM Verification UVM Verification SystemVerilog Uvm_agent Testbench Structure
Education UVM Verification
UVM Base Classes
· loading · loading
Education UVM Verification UVM Verification SystemVerilog Class Hierarchy
Education UVM Verification
UVM Driver Usage and Adder Example
· loading · loading
Education UVM Verification UVM Verification SystemVerilog Uvm_driver Stimulus Driving
Education UVM Verification
UVM Environment Usage and adder_env Example
· loading · loading
Education UVM Verification UVM Verification SystemVerilog Uvm_env Testbench Structure
Education UVM Verification
UVM Monitor Usage and Adder Example
· loading · loading
Education UVM Verification UVM Verification SystemVerilog Uvm_monitor Coverage
Education UVM Verification