EDA Playground'da Dene

UVM Eğitimi 1. : Temeller ve Testbench Yapısı

Amaç

Bu dersin amacı, okuyanların SystemVerilog kullanarak temel bir UVM sınıf hiyerarşisi oluşturmasını, UVM raporlama mekanizmasını kullanmasını ve UVM fazlarının (phasing) nasıl çalıştığını uygulamalı olarak görmesini sağlamaktır.

Ön Koşullar

  • Temel SystemVerilog Nesne Yönelimli Programlama (OOP) bilgisi.
  • UVM kütüphanesinin derlenebildiği bir simülatör (Örn: Questa, Xcelium, VCS).

Lab 1.1: UVM Raporlama ve Fazların Gözlemlenmesi

Bu adımda basit bir UVM bileşeni (component) oluşturup, temel fazları (build_phase, connect_phase, run_phase) ezeceğiz (override) ve her bir fazın içine UVM raporlama makroları ekleyeceğiz.

Görev: my_agent adında uvm_agent sınıfından türetilen bir bileşen oluşturun.

package my_uvm_pkg;
// Import UVM package and macros
import uvm_pkg::*;
//`include "uvm_macros.svh"

// Define the agent class inheriting from uvm\_agent  
class my_agent extends uvm_agent;  
    
  // Register component to UVM factory  
  `uvm_component_utils(my_agent)  
    
  // Constructor  
  function new(string name = "my_agent", uvm_component parent = null);  
    super.new(name, parent);  
  endfunction  
    
  // Build phase: Executed top-down  
  virtual function void build_phase(uvm_phase phase);  
    super.build_phase(phase);  
    `uvm_info("AGENT_BUILD", "Executing build_phase for my_agent...", UVM_LOW)  
  endfunction  
    
  // Connect phase: Executed bottom-up  
  virtual function void connect_phase(uvm_phase phase);  
    super.connect_phase(phase);  
    `uvm_info("AGENT_CONN", "Executing connect_phase for my_agent...", UVM_LOW)  
  endfunction  
    
  // Run phase: Time-consuming phase, executed as a parallel task  
  virtual task run_phase(uvm_phase phase);  
    super.run_phase(phase);  
    `uvm_info("AGENT_RUN", "Starting run_phase for my_agent...", UVM_LOW)  
      
    // Simulate some delay  
    #10;  
      
    `uvm_info("AGENT_RUN", "Finished run_phase delay for my_agent.", UVM_HIGH)  
  endtask  
    
endclass

Lab 1.2: UVM Hiyerarşisinin (Testbench Ağacı) Kurulması

Agent bileşenimizi oluşturduk. Şimdi bu Agent'ı bir Environment (uvm_env) içine, Environment'ı da bir Test (uvm_test) içine yerleştireceğiz. UVM'de alt bileşenler her zaman bir üst bileşenin build_phase metodu içerisinde yaratılır.

Görev: my_env ve base_test sınıflarını oluşturun ve hiyerarşiyi bağlayın.

// Define the environment class  
class my_env extends uvm_env;  
  `uvm_component_utils(my_env)  
    
  // Handle for our agent  
  my_agent agent_inst;  
    
  function new(string name = "my_env", uvm_component parent = null);  
    super.new(name, parent);  
  endfunction  
    
  // Instantiate the agent in the build_phase using UVM factory  
  virtual function void build_phase(uvm_phase phase);  
    super.build_phase(phase);  
    `uvm_info("ENV_BUILD", "Building my_env...", UVM_LOW)  
      
    // Create the agent using the factory create method  
    agent_inst = my_agent::type_id::create("agent_inst", this);  
  endfunction  
endclass

// Define the base test class  
class base_test extends uvm_test;  
  `uvm_component_utils(base_test)  
    
  // Handle for our environment  
  my_env env_inst;  
    
  function new(string name = "base_test", uvm_component parent = null);  
    super.new(name, parent);  
  endfunction  
    
  // Instantiate the environment  
  virtual function void build_phase(uvm_phase phase);  
    super.build_phase(phase);  
    `uvm_info("TEST_BUILD", "Building base_test...", UVM_LOW)  
      
    // Create the environment  
    env_inst = my_env::type_id::create("env_inst", this);  
  endfunction  
    
  // Print the UVM topology in the end_of_elaboration phase  
  virtual function void end_of_elaboration_phase(uvm_phase phase);  
    super.end_of_elaboration_phase(phase);  
    uvm_top.print_topology();  
  endfunction  
    
  // Raise and drop objections in the run_phase to control simulation time  
  virtual task run_phase(uvm_phase phase);  
    // Raise objection to prevent simulation from ending immediately  
    phase.raise_objection(this);  
      
    `uvm_info("TEST_RUN", "Test is running...", UVM_LOW)  
    #50; // Wait for some simulation time  
    `uvm_info("TEST_RUN", "Test finished.", UVM_LOW)  
      
    // Drop objection to allow simulation to end  
    phase.drop_objection(this);  
  endtask  
endclass

Lab 1.3: Top Modül ve run_test() Çağrısı

UVM sınıfları dinamiktir, donanım (DUT) ve arayüzler (Interfaces) ise statiktir. Simülasyonu başlatmak için standart bir SystemVerilog modülüne ve UVM'in beyni olan run_test() fonksiyonunu çağırmaya ihtiyacımız var.

Görev: tb_top modülünü yazın ve simülasyonu tetikleyin.

// Top level static module  
module tb_top;

  // Import UVM package  
  import uvm_pkg::*;
  import my_uvm_pkg::*;

  // Initial block to start the UVM phasing  
  initial begin  
    // Start the test named "base_test"  
    run_test("base_test");  
  end

endmodule

Çalıştırma ve Beklenen Çıktılar

Bu kodları tek bir testbench.sv dosyası içinde toplayıp simülatörünüzde çalıştırdığınızda, aşağıdaki gibi bir çıktı görmelisiniz:

  1. Önce base_test, ardından my_env ve en son my_agent için build_phase logları (Yukarıdan Aşağıya - Top-Down).
  2. uvm_top.print_topology() sayesinde ekrana çizilmiş testbench ağacı.
  3. connect_phase logları (Aşağıdan Yukarıya - Bottom-Up).
  4. Zamanın akmaya başladığı run_phase logları.
  5. UVM_HIGH verbosity seviyesi ile yazılan logun (Finished run_phase delay...) varsayılan ayarlarda ekranda görünmediğini fark edeceksiniz. Bunu görmek için simülatöre +UVM_VERBOSITY=UVM_HIGH argümanı vermeniz gerekir.