Ana içeriğe geç

SystemVerilog'da Polymorphism ve Sanallık (Virtuality)

· loading · loading · ·
Eğitim Doğrulama SystemVerilog SystemVerilog OOP Nesne Yönelimli Programlama Doğrulama Virtuality
Eğitim Doğrulama SystemVerilog
Axolot Logic
Yazar
Axolot Logic
Sayısal Tasarım Mühendisi
Table of Contents
SystemVerilog Tasarım Serisi - This article is part of a series.
Part 28: This Article

SystemVerilog’ta Polymorphism ve Virtuality
#

Bu bölümde, SystemVerilog’ta polymorphism (çok biçimlilik) ve virtuality (sanal yöntemler) kavramlarını inceliyoruz. Ayrıca casting, metod çözümleme ve abstract sınıflar ile ilgili ipuçlarını da detaylandırıyoruz.


1️⃣ Polymorphism ve Virtuality
#

Polymorphism, bir temel sınıf handle’ının çalışma zamanında farklı türetilmiş sınıf nesnelerine işaret etmesine olanak tanır. Bu, dinamik metod çağrılarını mümkün kılar.

Virtuality, SystemVerilog’da metodlara virtual anahtar kelimesi eklenerek sağlanır. Bu, metod çağrısının nesnenin gerçek tipine göre çalıştırılmasını sağlar.

Örnek:

// File: tb_polymorphism.sv

`timescale 1ns/1ps

// Virtual class definition
virtual class Packet;
  // Virtual display function
  virtual function void display();
    $display("Packet Display");
  endfunction
endclass

// DataPacket class extending Packet
class DataPacket extends Packet;
  // Overriding the display function
  function void display();
    $display("DataPacket Display");
  endfunction
endclass

// Testbench module
module tb_polymorphism;

  // Packet handle declared at module level
  Packet pkt;
    DataPacket dpkt;

  initial begin
    DataPacket dpkt;
    dpkt = new();
    pkt = dpkt;      // assign derived class object to base handle
    pkt.display();   // Calls DataPacket's display() method
  end

endmodule

2️⃣ Polymorphism’te Sınıf Üyelerine Erişim
#

Varsayılan olarak, sınıf üyesine erişim her zaman handle’ın tipine göre yapılır, nesnenin içeriğine göre değil.

  • Değişkenlere erişimde her zaman handle’ın statik tipi baz alınır.
  • Yöntemlerde ise virtual kullanılırsa dinamik dispatch yapılır.

Örnek:

// File: tb_inheritance.sv

`timescale 1ns/1ps

// Base class
class Base;
  int id = 1;
endclass

// Derived class
class Derived extends Base;
  int id = 2;
endclass

// Testbench module
module tb_inheritance;

  Base b;
  Derived d;

  initial begin
    d = new();     // Derived nesnesi oluştur
    b = d;         // Base handle'a atama yap
    $display("ID = %0d", b.id); // Base class'ın id'si yazdırılır
  end

endmodule

3️⃣ Sınıf Metodu Çözümleme (Method Resolution)
#

  • Non-virtual (sanal olmayan) metodlar: Handle’ın statik tipine göre çözülür.
  • Virtual metodlar: Nesnenin gerçek tipine göre çözülür.

Virtual metodlar override edilerek dinamik dispatch sağlanır. Virtual olmayan metodlarda her zaman base sınıfın metodu çağrılır.


4️⃣ Virtual Method Kullanımı Neden Önemli?
#

Çünkü varsayılan olarak metod çözümlemesi handle’ın tipine göre yapılır. Nesnenin gerçek tipine göre metodun çağrılmasını sağlamak için virtual kullanılır.

  • Statik çözümleme:
// File: tb_static_resolution.sv

`timescale 1ns/1ps

// Base class
class Packet;
  function void display();
    $display("Packet Display");
  endfunction
endclass

// Derived class
class DataPacket extends Packet;
  function void display();
    $display("DataPacket Display");
  endfunction
endclass

// Testbench module
module tb_static_resolution;

  Packet pkt;
  DataPacket dpkt;

  initial begin
    dpkt = new();
    pkt = dpkt;
    pkt.display(); // Static resolution: calls Packet's display()
  end

endmodule

Bu durumda pkt.display() çalışma zamanında doğru türetilmiş sınıf metodunu çağırır.


5️⃣ Sub-Class Nesnesini Parent Handle’a Kopyalamak
#

  • Bir alt sınıf örneği her zaman doğrudan bir üst sınıfın işaretçisine kopyalanabilir.
  • Ancak, varsayılan olarak bu işaretçiden yalnızca üst sınıf üyelerine erişilebilir:
    • Alt sınıf örneğini içerse bile bu kural geçerlidir.

Bu oldukça basittir:

// File: tb_copy_subclass.sv

`timescale 1ns/1ps

// Base class
class Packet;
  function void display();
    $display("Packet Display");
  endfunction
endclass

// Derived class
class DataPacket extends Packet;
  function void display();
    $display("DataPacket Display");
  endfunction
endclass

// Testbench module
module tb_copy_subclass;

  DataPacket dp;
  Packet pkt;

  initial begin
    dp = new();
    pkt = dp;        // Sub-class instance assigned to parent handle (upcasting)
    pkt.display();   // Calls Packet's display() (static resolution)
  end

endmodule

Burada pkt, dp ile aynı nesneyi işaret eder ancak sadece temel sınıf üyelerine erişebilir.


6️⃣ Parent Nesnesini Sub-Class Handle’a Kopyalamak
#

  • Bir üst sınıf işaretçisini doğrudan bir alt sınıf işaretçisine atamak hiçbir zaman geçerli değildir.
  • Bu işlem ancak üst sınıf işaretçisi, hedef alt sınıfın bir örneğine işaret ediyorsa geçerli olabilir.

Bu doğrudan yapılamaz çünkü base sınıfın içinde sub-class’a ait alanlar bulunmayabilir. Bunu güvenli şekilde yapmak için $cast kullanılır.

Örnek:

// File: tb_downcasting.sv

`timescale 1ns/1ps

// Base class
class Packet;
  function void display();
    $display("Packet Display");
  endfunction
endclass

// Derived class
class DataPacket extends Packet;
  function void display();
    $display("DataPacket Display");
  endfunction
endclass

// Testbench module
module tb_downcasting;

  Packet pkt;
  DataPacket dp;

  initial begin
    dp = new();
    pkt = dp; // only parent method visible
    if (!$cast(dp, pkt)) begin
      $display("Cast failed");
    end
    else begin
      dp.display();
    end
  end

endmodule

7️⃣ $cast Kullanımı
#

$cast, bir üst sınıf handle’ını alt sınıf handle’ına güvenli şekilde dönüştürür. Eğer başarılı olursa 1 döner, başarısız olursa 0 döner ve simülasyon hatası oluşmaz.

Sözdizimi:

if (!$cast(child_handle, parent_handle)) begin
  // Cast başarısız
end

8️⃣ Polymorphism’in Avantajları
#

✅ Esnek ve yeniden kullanılabilir doğrulama mimarileri sağlar.
✅ Testbench bileşenlerinin farklı implementasyonlarla çalışmasına izin verir.
✅ Dinamik davranış seçimi sayesinde kod tekrarını azaltır.
✅ UVM gibi doğrulama frameworkleri için gereklidir.


9️⃣ Virtual Method Resolution
#

SystemVerilog’da, virtual metodlar, çalışma zamanında nesnenin gerçek tipi baz alınarak dinamik olarak çözülür; handle’ın statik tipi dikkate alınmaz.

🔍 Çözümleme Kuralları:

  • Simülatör, hangi display() fonksiyonunun çağrılacağına karar verirken gerçek nesne tipini (instantiate edilen sınıf) kullanır.
  • Eğer fonksiyon virtual olarak tanımlanmışsa handle’ın tipi önemli değildir.
  • Eğer bir türetilmiş sınıf virtual fonksiyonu override ederse, base class handle üzerinden çağrılsa bile override edilen fonksiyon çalışır.

Örnek:

// File: tb_virtual_dispatch.sv

`timescale 1ns/1ps

// Base class
class Packet;
  virtual function void display();
    $display("Packet Display");
  endfunction
endclass

// Derived class
class DataPacket extends Packet;
  function void display();
    $display("DataPacket Display");
  endfunction
endclass

// Testbench module
module tb_virtual_dispatch;

  Packet pkt;
  DataPacket dpkt;

  initial begin
    dpkt = new();
    pkt = dpkt;     // Base handle assigned to derived object
    pkt.display();  // Calls DataPacket's display() because display() is virtual
  end

endmodule

1️⃣0️⃣ Abstract Sınıflar ve Pure Virtual Metodlar
#

Abstract sınıflar, doğrudan örneklenemez. Genellikle pure virtual metodlar içerir ve bu metodlar mutlaka türetilmiş sınıflarda override edilmelidir.

  • Pure virtual metodlara sahip olabilir ve sadece prototip olarak tanımlanır, implemente edilmez.
  • Altsınıf implemente etmelidir.

Örnek:

virtual class Packet;
  pure virtual function void display();
endclass

class DataPacket extends Packet;
  function void display();
    $display("DataPacket Display");
  endfunction
endclass

Bu örnekte Packet abstract bir sınıftır ve örneklenemez. Her türetilmiş sınıf display() metodunu implement etmek zorundadır.


1️⃣1️⃣ Shallow Copy ve Deep Copy
#

SystemVerilog’ta sınıf nesnelerinin kopyalanması biraz dikkat ister çünkü sınıflar her zaman referans tipindedir. Yani, bir sınıf nesnesi kopyalandığında aslında handle kopyalanır, tüm nesne değil—bu işleme shallow copy (yüzeysel kopyalama) denir. Eğer nesnenin tüm iç özelliklerini (ve varsa iç içe nesneleri) de kopyalamak istenirse buna deep copy (derin kopyalama) denir.


🔄 Shallow Copy
#

Shallow copy yapıldığında, handle kopyalanır ve her iki referans da aynı nesneyi işaret eder. Yani bir handle ile yapılan değişiklik diğer handle’ı da etkiler.

Örnek:

// File: tb_shallow_copy.sv

`timescale 1ns/1ps

// Base class
class Packet;
  bit [7:0] data;
endclass

// Testbench module
module tb_shallow_copy;

  Packet pkt1;
  Packet pkt2;

  initial begin
    pkt1 = new();
    pkt1.data = 8'hAB;

    pkt2 = pkt1;           // Shallow copy
    pkt2.data = 8'hCD;     // Actually changes pkt1.data too

    $display("pkt1.data = %0h", pkt1.data); // Prints CD
  end

endmodule

Hem pkt1 hem de pkt2 aynı nesneyi işaret eder, dolayısıyla pkt2 ile yapılan değişiklik pkt1’i de etkiler.


📦 Deep Copy
#

Deep copy ise yeni bir nesne oluşturur ve tüm özellikler (ve varsa iç içe nesneler) orijinal nesneden yeni nesneye kopyalanır. Bu sayede kopyalar tamamen bağımsız olur.

SystemVerilog’ta built-in bir deep copy mekanizması yoktur; elle kodlamak gerekir.

Örnek:

// File: tb_deep_copy.sv

`timescale 1ns/1ps

// Base class
class Packet;
  bit [7:0] data;

  // Deep copy function
  function Packet deepCopy();
    Packet copy = new();
    copy.data = this.data;
    return copy;
  endfunction
endclass

// Testbench module
module tb_deep_copy;

  Packet pkt1;
  Packet pkt2;

  initial begin
    pkt1 = new();
    pkt1.data = 8'hAB;

    pkt2 = pkt1.deepCopy(); // Deep copy
    pkt2.data = 8'hCD;

    $display("pkt1.data = %0h", pkt1.data); // Prints AB
    $display("pkt2.data = %0h", pkt2.data); // Prints CD
  end

endmodule

📖 Sonuç
#

SystemVerilog’ta polymorphism ve virtuality, güçlü ve dinamik testbench’ler geliştirmek için kritik öneme sahiptir. Casting, dinamik metod çözümleme ve abstract sınıfları anlamak, doğrulama ortamlarını çok daha esnek hale getirir.


SystemVerilog Tasarım Serisi - This article is part of a series.
Part 28: This Article

Related

SystemVerilog'da İleri Nesne Yönelimli Programlama: Yapıcılar, Handle'lar ve Statik Üyeler
· loading · loading
Eğitim Doğrulama SystemVerilog SystemVerilog OOP Nesne Yönelimli Programlama Doğrulama Sınıflar
Eğitim Doğrulama SystemVerilog
SystemVerilog'da İleri OOP: Aggregation, Kalıtım ve Daha Fazlası
· loading · loading
Eğitim Doğrulama SystemVerilog SystemVerilog OOP Nesne Yönelimli Programlama Doğrulama Sınıflar
Eğitim Doğrulama SystemVerilog
SystemVerilog'da Nesne Yönelimli Programlama
· loading · loading
Eğitim Doğrulama SystemVerilog SystemVerilog OOP Nesne Yönelimli Programlama Verification Sınıflar
Eğitim Doğrulama SystemVerilog
SystemVerilog'da Mailbox Kullanımı
· loading · loading
Eğitim Doğrulama SystemVerilog SystemVerilog IPC Mailboxes Doğrulama Senkronizasyon
Eğitim Doğrulama SystemVerilog
SystemVerilog'da Named Events Kullanımı
· loading · loading
Eğitim Doğrulama SystemVerilog SystemVerilog IPC Named Events Doğrulama Senkronizasyon
Eğitim Doğrulama SystemVerilog
SystemVerilog'da Semaphores Kullanımı
· loading · loading
Eğitim Doğrulama SystemVerilog SystemVerilog IPC Semaphores Doğrulama Senkronizasyon
Eğitim Doğrulama SystemVerilog