Events (Olaylar)
Gün 4: Süreçler Arası İletişim (IPC) | Olay tetikleme (->), bekleme (@, wait) ve senkronizasyon
Bu derste SystemVerilog'un event veri tipini öğreneceksiniz. Olaylar (events), paralel süreçleri birbirine veri vermeden ya da el sıkışma (handshake) yaparak senkronize etmenin en hafif ve en temel yoludur.
Event (Olay) Nedir?
Bir event, SystemVerilog'da herhangi bir veri taşımayan, yalnızca "bir şey oldu" sinyalini bir süreçten diğerine ileten özel bir tiptir. Üç temel işlemle kullanılır:
- Tanımlama:
event ad;ile bir olay nesnesi oluşturulur. - Tetikleme (trigger):
-> ad;ifadesi olayı tetikler ve o an o olayı bekleyen tüm süreçleri uyandırır. - Bekleme:
@(ad)veyawait(ad.triggered)ile bir süreç, olay tetiklenene kadar bloklanır.
Neden Önemli ve Nerede Kullanılır?
- Senkronizasyon: "Reset bitmeden hiçbir bileşen çalışmaya başlamasın" gibi kuralları kolayca kurarsınız.
- El sıkışma (handshake): Üretici (producer) "veri hazır" der, tüketici (consumer) işleyip "onay" geri gönderir. Bu çift yönlü senkronizasyon olaylarla zarif biçimde yazılır.
- Faz kontrolü: Bir işin tüm aşamalarının bittiğini haber vermek için
phase_completegibi olaylar kullanılır.
@(olay) kenar tetiklemeli (edge-sensitive) çalışır: yani sürecin olayı yakalayabilmesi için, beklemeye olay tetiklenmeden önce geçmiş olması gerekir. wait(olay.triggered) ise olayın o zaman adımında tetiklenip tetiklenmediğini de görür; bu ince fark bir sonraki derste detaylıca incelenir.
Kaynak Kod
// =============================================================================
// GUN 4 - Konu 3: Event'ler - Olay Tetikleme ve Bekleme
// =============================================================================
module events;
// Event tanimla
event data_ready;
event ack_received;
event reset_done;
event phase_complete;
int shared_data;
// --- Uretici (Producer) ---
initial begin : producer
$display("=== Events (Olay Tetikleme) ===\n");
// Reset bekle
@(reset_done);
$display(" [%0t] Uretici: Reset tamamlandi, calismaya basliyor", $time);
repeat (5) begin
#10;
shared_data = $urandom_range(1, 100);
$display(" [%0t] Uretici: Veri uretildi = %0d", $time, shared_data);
-> data_ready; // Olayi tetikle
@(ack_received); // Tuketici onayini bekle
$display(" [%0t] Uretici: Onay alindi", $time);
end
$display("\n [%0t] Uretici: Tum veriler gonderildi", $time);
-> phase_complete;
end
// --- Tuketici (Consumer) ---
initial begin : consumer
@(reset_done);
$display(" [%0t] Tuketici: Reset tamamlandi", $time);
forever begin
@(data_ready); // Veri hazir olayini bekle
$display(" [%0t] Tuketici: Veri alindi = %0d", $time, shared_data);
#5; // Isleme suresi
-> ack_received; // Onay gonder
end
end
// --- Reset sureci ---
initial begin : reset_gen
$display(" [%0t] Reset basladi...", $time);
#20;
$display(" [%0t] Reset tamamlandi!", $time);
-> reset_done;
end
// --- wait() ile event bekleme ---
initial begin
wait(phase_complete.triggered);
$display("\n [%0t] Phase tamamlandi (wait ile algilandi)", $time);
end
// --- Triggered ozelligi ---
initial begin
#200; // Zaman asimi
$display("\n=== Events Sonu ===");
$finish;
end
endmodule
Kodun Açıklaması
- Modülün başında dört olay tanımlanır:
data_ready,ack_received,reset_donevephase_complete.shared_dataise üretici ile tüketici arasında paylaşılan veridir. reset_genbloğu: 20ns boyunca reset uygular, ardından-> reset_done;ile reset bitişini duyurur. Hemproducerhemconsumerblokları başında@(reset_done)ile beklediği için, ikisi de ancak reset bittikten sonra çalışmaya başlar.producerbloğu: Bir döngü içinde 5 kez veri üretir. Her seferindeshared_data'yı$urandom_range(1, 100)ile rastgele doldurur,-> data_ready;ile "veri hazır" der ve sonra@(ack_received)ile tüketicinin onayını bekler. Bu, klasik bir el sıkışma döngüsüdür.consumerbloğu:foreverdöngüsü içinde@(data_ready)ile veri beklenir,shared_dataokunur,#5işleme süresi geçer ve-> ack_received;ile onay geri gönderilir. Üretici ve tüketici bu sayede birbirini kilitlemeden, sırayla ilerler.wait(phase_complete.triggered): Ayrı birinitialblok, üreticinin tüm verileri gönderip tetiklediğiphase_completeolayını bekler ve fazın bittiğini bildirir.- Son
initialblok ise#200zaman aşımıyla simülasyonu$finishile sonlandırır.
Önemli Noktalar
@(olay)kenar tetiklemelidir: bekleyen süreç, olay tetiklenmeden önce beklemeye geçmiş olmalıdır. Aksi halde tetiklemeyi kaçırır ve sonsuza kadar bekleyebilir (race condition).- Üretici-tüketici el sıkışmasında
data_readyveack_receivedolaylarının sırası kritiktir; her iki taraf da karşılıklı beklediği için döngü kilitlenmeden ilerler. - Birden çok süreç aynı reset olayını (
reset_done) beklediğinde,-> reset_done;ile yapılan tek bir tetikleme hepsini aynı anda uyandırır. wait(olay.triggered), olayın o zaman adımında tetiklenip tetiklenmediğini de algılar; bu yüzdenphase_completegibi tek seferlik bayraklarda@yerine genellikle daha güvenlidir.- Olaylar veri taşımaz; aktarılacak gerçek veri için (burada
shared_datagibi) ayrı bir paylaşılan değişken ya da mailbox kullanılır.