EDA Playground'da Dene

UVM Eğitimi 3. Gün Laboratuvar Kılavuzu: TLM Haberleşmesi, Scoreboard ve Çevre (Environment) Kurulumu

Amaç

Bu laboratuvarın amacı, UVM bileşenleri arasında veri aktarımı sağlayan TLM (Transaction Level Modeling) portlarını kullanmak, verileri doğrulamak için bir Scoreboard tasarlamak ve fonksiyonel kapsama (coverage) verilerini toplamak için iki farklı yaklaşımı (Geleneksel TLM Tabanlı ve Modern Handle Tabanlı) karşılaştırmalı olarak uygulamaktır. Ayrıca simülasyon sonunda kapsama raporlarının nasıl alınacağını göreceğiz.

Ön Koşullar

  • 1 ve 2. gün konuları (Agent hiyerarşisi, Sequence Item oluşturma).
  • Nesne yönelimli programlamada (OOP) referanslar (handle) ve write gibi fonksiyonların işleyişi.

Lab 3.1: Monitor'e Analysis Port ve Coverage Handle Eklenmesi

Monitor, arayüzden okuduğu veriyi diğer bileşenlere iletmekle görevlidir. Bu veriyi standart TLM yapısıyla (Scoreboard ve TLM-Coverage için) "yayınlamak" (broadcast) için bir uvm_analysis_port kullanacağız. Ayrıca modern yaklaşımı göstermek için Handle-Based Coverage Collector sınıfımızın referansını da Monitor içine tanımlayacağız.

Görev: 2. Gün yazdığımız my_monitor sınıfını aşağıdaki gibi güncelleyin.

class my_monitor extends uvm_monitor;  
  `uvm_component_utils(my_monitor)  
    
  // 1. Declare the analysis port (Used for Scoreboard and TLM Coverage)  
  uvm_analysis_port #(my_transaction) ap;  
    
  // 2. Declare a handle for direct coverage sampling (Modern approach)  
  my_handle_coverage cov_handle;  
    
  // Constructor  
  function new(string name = "my_monitor", uvm_component parent = null);  
    super.new(name, parent);  
  endfunction  
    
  // Build phase: Instantiate the analysis port  
  virtual function void build_phase(uvm_phase phase);  
    super.build_phase(phase);  
    ap = new("ap", this);  
  endfunction  
    
  // Run phase: Monitor signals and broadcast/sample the transaction  
  virtual task run_phase(uvm_phase phase);  
    my_transaction tr;  
    super.run_phase(phase);  
      
    forever begin  
      #20; // Simulated sampling delay  
        
      // Create a dummy transaction to represent sampled data  
      tr = my_transaction::type_id::create("tr");  
      tr.addr     = 8'hAA;   
      tr.data     = 32'h12345678;  
      tr.write_en = 1'b1;  
        
      `uvm_info("MONITOR", "Sampled data from virtual interface...", UVM_LOW)  
        
      // 1. Broadcast via TLM (Will be received by Scoreboard and TLM Coverage)  
      ap.write(tr);  
        
      // 2. Send to modern coverage collector via direct function call   
      if (cov_handle != null) begin  
        cov_handle.sample_cov(tr.write_en);  
      end  
    end  
  endtask  
endclass

Lab 3.2: UVM Scoreboard Tasarımı

Scoreboard, Monitor'den gelen işlemleri dinler (Analysis Implementation aracılığıyla) ve doğruluğunu kontrol eder.

Görev: my_scoreboard adında bir sınıf oluşturun. Bir uvm_analysis_imp portu ekleyin ve mecburi olan write() fonksiyonunu tanımlayın.

class my_scoreboard extends uvm_scoreboard;  
  `uvm_component_utils(my_scoreboard)  
    
  // Declare the analysis implementation port  
  uvm_analysis_imp #(my_transaction, my_scoreboard) ap_imp;  
    
  // Constructor  
  function new(string name = "my_scoreboard", uvm_component parent = null);  
    super.new(name, parent);  
  endfunction  
    
  // Build phase  
  virtual function void build_phase(uvm_phase phase);  
    super.build_phase(phase);  
    ap_imp = new("ap_imp", this);  
  endfunction  
    
  // The mandatory write() method triggered by ap.write()  
  virtual function void write(my_transaction tr);  
    if(tr.addr == 8'hAA && tr.data == 32'h12345678) begin  
      `uvm_info("SCOREBOARD", "Data matches expected values! [PASS]", UVM_LOW)  
    end else begin  
      `uvm_error("SCOREBOARD", "Data mismatch detected! [FAIL]")  
    end  
  endfunction  
endclass

Lab 3.3: Kapsama (Coverage) Toplayıcıları ve Raporlama

Bu bölümde iki farklı Coverage Collector oluşturacağız ve her ikisine de simülasyon biterken nihai sonuçları ekrana yazdırması için report_phase metodunu ekleyeceğiz.

Yöntem 1: Geleneksel TLM Tabanlı (uvm_subscriber)

uvm_subscriber tek bir porta sahip olduğu için büyük projelerde yetersiz kalabilir.

// APPROACH 1: TLM-based using uvm_subscriber  
class my_tlm_coverage extends uvm_subscriber #(my_transaction);  
  `uvm_component_utils(my_tlm_coverage)  
    
  my_transaction cov_tr;  
    
  covergroup cg;  
    option.per_instance = 1;  
    cp_write_en: coverpoint cov_tr.write_en {  
      bins read_op  = {0};  
      bins write_op = {1};  
    }  
  endgroup  
    
  function new(string name = "my_tlm_coverage", uvm_component parent = null);  
    super.new(name, parent);  
    cg = new();  
  endfunction  
    
  // Mandatory write method for TLM  
  virtual function void write(my_transaction t);  
    cov_tr = t;  
    cg.sample();  
    `uvm_info("TLM_COV", $sformatf("Sampled via TLM. write_en=%0b", cov_tr.write_en), UVM_LOW)  
  endfunction  
    
  // Report phase to print the final coverage at the end of the simulation  
  virtual function void report_phase(uvm_phase phase);  
    super.report_phase(phase);  
    `uvm_info("TLM_COV_REPORT", $sformatf("Final Coverage (TLM-Based): %0.2f%%", cg.get_inst_coverage()), UVM_NONE)  
  endfunction  
endclass

Yöntem 2: Modern Handle Tabanlı (Doğrudan Fonksiyon Çağrısı)

Sektörde tavsiye edilen, port kısıtlaması olmayan yöntem. Covergroup argümanları doğrudan fonksiyonla toplanır.

// APPROACH 2: Handle-based using standard uvm_component  
class my_handle_coverage extends uvm_component;  
  `uvm_component_utils(my_handle_coverage)  
    
  // Covergroup with arguments passed to its sample function  
  covergroup cg with function sample(bit w_en);  
    option.per_instance = 1;  
    cp_write_en: coverpoint w_en {  
      bins read_op  = {0};  
      bins write_op = {1};  
    }  
  endgroup  
    
  function new(string name = "my_handle_coverage", uvm_component parent = null);  
    super.new(name, parent);  
    cg = new();  
  endfunction  
    
  // Custom function to be called directly from anywhere  
  function void sample_cov(bit w_en);  
    cg.sample(w_en);  
    `uvm_info("HANDLE_COV", $sformatf("Sampled via Handle. write_en=%0b", w_en), UVM_LOW)  
  endfunction  
    
  // Report phase to print the final coverage at the end of the simulation  
  virtual function void report_phase(uvm_phase phase);  
    super.report_phase(phase);  
    `uvm_info("HANDLE_COV_REPORT", $sformatf("Final Coverage (Handle-Based): %0.2f%%", cg.get_inst_coverage()), UVM_NONE)  
  endfunction  
endclass

Lab 3.4: Çevre (Environment) İçinde Bağlantıların Yapılması

Scoreboard ve TLM tabanlı Coverage için geleneksel port bağlantılarını (connect) kullanacağız. Handle tabanlı modern Coverage sınıfı için ise referans ataması (=) yapacağız.

Görev: my_env sınıfını güncelleyerek build_phase ve connect_phase mekanizmalarını kurun.

class my_env extends uvm_env;  
  `uvm_component_utils(my_env)  
    
  // Component handles  
  my_agent           agent_inst;  
  my_scoreboard      sb_inst;  
  my_tlm_coverage    tlm_cov_inst;  
  my_handle_coverage handle_cov_inst;  
    
  // Constructor  
  function new(string name = "my_env", uvm_component parent = null);  
    super.new(name, parent);  
  endfunction  
    
  // Build phase  
  virtual function void build_phase(uvm_phase phase);  
    super.build_phase(phase);  
    agent_inst      = my_agent::type_id::create("agent_inst", this);  
    sb_inst         = my_scoreboard::type_id::create("sb_inst", this);  
    tlm_cov_inst    = my_tlm_coverage::type_id::create("tlm_cov_inst", this);  
    handle_cov_inst = my_handle_coverage::type_id::create("handle_cov_inst", this);  
  endfunction  
    
  // Connect phase  
  virtual function void connect_phase(uvm_phase phase);  
    super.connect_phase(phase);  
      
    // 1. TLM Connections: ap is a broadcast port, it can connect to multiple destinations  
    agent_inst.mon.ap.connect(sb_inst.ap_imp);  
    agent_inst.mon.ap.connect(tlm_cov_inst.analysis_export);  
      
    // 2. Handle Passing: Pass the coverage collector handle directly to the monitor  
    agent_inst.mon.cov_handle = this.handle_cov_inst;  
      
    `uvm_info("ENV_CONN", "TLM connections and handle passing completed successfully.", UVM_LOW)  
  endfunction  
endclass

Özet ve Beklenen Sonuç

base_test içerisinde #100 zaman birimi boyunca beklenildiğinde, Monitor (her 20 birimde bir çalıştığı için) 5 adet işlem (transaction) üretecektir.

Simülasyon çalıştırıldığında testin run_phase'i süresince ekranda Scoreboard eşleşmeleri [PASS] ve her iki Coverage örneklendirme [TLM_COV], [HANDLE_COV] logları art arda düşecektir.

Simülasyon kapatılırken (UVM report_phase'e geçtiğinde), terminalde aşağıdaki nihai rapor çıktılarını görmelisiniz:

UVM_INFO @ 100: uvm_test_top.env_inst.tlm_cov_inst [TLM_COV_REPORT] Final Coverage (TLM-Based): 50.00%
UVM_INFO @ 100: uvm_test_top.env_inst.handle_cov_inst [HANDLE_COV_REPORT] Final Coverage (Handle-Based): 50.00%

(Not: Dummy verimiz sürekli write_en = 1 ürettiği için coverpoint içindeki "write" durumu %100, "read" durumu %0 kapsanmıştır. İkisinin ortalaması %50'dir.)