🔑 SystemVerilog’ta Semaforlar#
Semaforlar, SystemVerilog’ta paylaşılan kaynaklara erişimi kontrol etmek ve süreçler arası senkronizasyon sağlamak için kullanılan yerleşik bir sınıftır. Doğrulama ortamlarında kritik bölgeleri yönetmek, eşzamanlılık kontrolü sağlamak ve eşzamanlı threadler arası etkileşimleri koordine etmek için sıklıkla kullanılır.
🗂️ Semafor Nedir?#
Kavramsal olarak semafor, bir anahtar kovası gibidir:
- Bir semafor, başlangıçta belirli sayıda anahtarla oluşturulur.
- Süreçler, çalışmaya başlamadan önce semafordan bir anahtar almak zorundadır (
get()
kullanarak). - Süreç işini bitirdiğinde anahtarı tekrar kovaya koyar (
put()
kullanarak).
Tüm anahtarlar alındığında, ek anahtar isteyen bir süreç bloklanır ve ancak bir anahtar iade edildiğinde çalışmaya devam eder. Bu yapı sayesinde mutual exclusion (karşılıklı dışlama) veya eşzamanlılık kontrolü sağlanır.
🛠️ Semafor Oluşturmak#
Semaforlar, semaphore
sınıfı ve new()
yapıcısı ile oluşturulur.
semaphore sem;
// 2 anahtarlı semafor oluşturma
initial begin
sem = new(2);
end
new()
fonksiyonuna argüman verilmezse varsayılan olarak 0 anahtar ile oluşturulur (tüm süreçler bloklanır ve bir anahtar koyulana kadar bekler).
🚦 Semafor Kullanımı#
🗝️ Anahtar Almak#
Semafordan bir anahtar almak için get()
metodu kullanılır.
sem.get(); // anahtar müsait olana kadar bloklar
Birden fazla anahtar istenebilir:
sem.get(3); // 3 anahtar için bekler
🔓 Anahtar İade Etmek#
Anahtarları semafora geri koymak için put()
metodu kullanılır.
sem.put(); // varsayılan olarak 1 anahtar iade eder
sem.put(2); // 2 anahtar iade eder
⏳ Bloklamadan Anahtar Denemek#
Anahtarı bloklamadan almak için try_get()
metodu kullanılır.
if (sem.try_get()) begin
// Anahtar alındı, işlem yapılabilir
end else begin
// Anahtar yok, alternatif yol izlenebilir
end
🔍 Temel Metodların Özeti#
Metod | Açıklama |
---|---|
new() | Belirtilen anahtar sayısı ile semafor oluşturur. |
get() | Anahtar müsait olana kadar bloklar. |
put() | Anahtarları semafora iade eder. |
try_get() | Anahtarları bloklamadan almaya çalışır. |
🛡️ Yaygın Kullanım Alanları#
- Mutual Exclusion: Paylaşılan kaynaklara aynı anda erişimi sınırlamak (örneğin, scoreboard, coverage collector).
- Eşzamanlılık Kontrolü: Aynı anda çalışan işlem sayısını sınırlamak (örneğin, bellek modeline erişim).
- Kaynak Yönetimi: Sınırlı sayıda testbench objesi veya bus driver yönetimi.
💡 En İyi Uygulamalar#
✅ Her get()
çağrısının sonunda mutlaka bir put()
çağrısı koyarak deadlock oluşumunu engelle.
✅ Test ortamının eşzamanlılık gereksinimlerine uygun anahtar sayısı belirle.
✅ try_get()
metodunu, bloklamayan senaryolar (ör. kaynak müsait mi diye kontrol) için kullan.
✅ Testbench içinde semaforların kullanım amacını mutlaka dokümante et, bakım ve hata ayıklamayı kolaylaştır.
📖 Sonuç#
Semaforlar, SystemVerilog’ta eşzamanlılık ve senkronizasyon kontrolü için güçlü bir mekanizmadır. Semaforları doğru şekilde kullanarak, mühendisler paylaşılan kaynakları verimli bir şekilde yöneten ve ölçeklenebilir testbenchler tasarlayabilir.
module tb_semaphore_demo;
// Semaphore nesnesi tanımı
semaphore sem;
// Paylaşılan veri (kritik bölge kaynağı)
logic [7:0] shared_data = 8'h00;
// Saat sinyali üretimi
logic clk = 0;
always #5 clk = ~clk;
// Semaphore'u 1 anahtar ile başlat
initial begin
sem = new(1);
end
// Process A: shared_data'yı arttırır
initial begin
repeat (3) begin
sem.get(); // Semaphore'dan anahtar al (kritik bölgeye gir)
$display("[Process A] Lock acquired at %0t", $time);
// Kritik bölge: shared_data üzerinde değişiklik yap
shared_data += 8'h01;
$display("[Process A] shared_data = %0h", shared_data);
sem.put(); // Semaphore'a anahtar iade et (kritik bölgeden çık)
$display("[Process A] Lock released at %0t", $time);
#10; // Bir süre bekle, diğer süreçlere fırsat ver
end
end
// Process B: shared_data'yı azaltır
initial begin
repeat (3) begin
sem.get(); // Semaphore'dan anahtar al (kritik bölgeye gir)
$display("[Process B] Lock acquired at %0t", $time);
// Kritik bölge: shared_data üzerinde değişiklik yap
shared_data -= 8'h01;
$display("[Process B] shared_data = %0h", shared_data);
sem.put(); // Semaphore'a anahtar iade et (kritik bölgeden çık)
$display("[Process B] Lock released at %0t", $time);
#15; // Bir süre bekle, diğer süreçlere fırsat ver
end
end
// Simülasyonu bitir
initial begin
#100;
$finish;
end
endmodule