Ana içeriğe geç

UVM'de _decl Makrosu Kullanımı

· loading · loading · ·
Eğitim UVM Doğrulama UVM Doğrulama SystemVerilog _Decl Makrosu Analysis Port
Eğitim UVM Doğrulama
Axolot Logic
Yazar
Axolot Logic
Sayısal Tasarım Mühendisi
Table of Contents
UVM Serisi - This article is part of a series.
Part 29: This Article

📄 _decl Makrosu Kullanımı
#


📌 Giriş
#

UVM’de transaction seviyesinde veri iletişimi için kullanılan TLM (Transaction-Level Modeling) interface’lerinde genelde tek bir kaynak (uvm_analysis_port) ile tek bir hedef (uvm_analysis_imp) bağlantısı kurarız. Ancak bazen aynı kaynaktan (örneğin bir producer) gelen verileri subscriber tarafında farklı fonksiyonlarla işlemek isteyebiliriz.

İşte bu noktada uvm_*_imp_decl() makrosu devreye girer. Bu makro, interface’lerde birden fazla “imp” tanımlamamızı ve her biri için farklı fonksiyonlar yazmamızı sağlar.


🔎 _decl Makrosunun Amacı
#

  • Bir subscriber içerisinde birden fazla port implementasyonu tanımlamak.
  • Gelen verileri farklı fonksiyonlara yönlendirmek.
  • Testbench’te farklı komponentlerden veya aynı komponentten gelen verileri kolayca ayırmak.

📌 Kullanımı
#

1️⃣ Önce _decl makrosunu tanımla:

`uvm_analysis_imp_decl(_1)
`uvm_analysis_imp_decl(_2)

2️⃣ Subscriber içinde:

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

3️⃣ Farklı write_*() fonksiyonları yaz:

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

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

4️⃣ Producer portunu bu subscriber portlarına bağla:

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

🚀 Örnek Kod
#

Aşağıda _decl kullanımını gösteren tam bir örnek verilmiştir:

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

✨ Özet
#

_decl makrosu ile birden fazla port implementasyonu oluşturabiliriz. ✅ Her implementasyon farklı bir write_*() fonksiyonuna yönlenir. ✅ Bu, verileri kaynağa göre veya port’a göre ayrı ayrı işlemek için idealdir.


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

Related

UVM'de TLM FIFO, Analysis Port ve _decl Makrosu Kullanımı
· loading · loading
Eğitim UVM Doğrulama UVM Doğrulama SystemVerilog TLM FIFO Analysis Port
Eğitim UVM Doğrulama
UVM Temel Sınıfları
· loading · loading
Eğitim UVM Doğrulama UVM Doğrulama SystemVerilog Sınıf Hiyerarşisi
Eğitim UVM Doğrulama
UVM Utility Field Makroları
· loading · loading
Eğitim UVM Doğrulama UVM Doğrulama SystemVerilog Utility Makroları
Eğitim UVM Doğrulama
UVM'de Package Kullanımı ve Önemi
· loading · loading
Eğitim UVM Doğrulama UVM Doğrulama SystemVerilog Package Kullanımı Testbench Organizasyonu
Eğitim UVM Doğrulama
UVM'de Virtual Sequence, Virtual Sequencer, Sequence Library ve Sequence Arbitration
· loading · loading
Eğitim UVM Doğrulama UVM Doğrulama SystemVerilog Virtual Sequence Sequence Arbitration
Eğitim UVM Doğrulama
UVM'de do_ Metodları
· loading · loading
Eğitim UVM Doğrulama UVM Doğrulama SystemVerilog Do_ Metodları
Eğitim UVM Doğrulama