wait(event.triggered) ve @(event) Karşılaştırması
Gün 4: Süreçler Arası İletişim (IPC) | Olay tetikleme (->), bekleme (@, wait) ve senkronizasyon
Özellikle karmaşık doğrulama ortamlarında (örneğin UVM tabanlı bir VIP geliştirirken veya katı standartlara tabi projelerin testbench'lerinde), simülatörün delta döngüleri (delta cycles) üzerinde tam kontrolümüz yoktur. Farklı bileşenlerin (sequence, monitor, scoreboard vb.) aynı zaman adımında (time step) hangi sırayla çalışacağı belirsizdir (non-deterministic). Bu belirsizlik, @(event) kullanıldığında "race condition" (yarış durumu) yaratır ve simülasyonların nedensiz yere kilitlenmesine (hang) yol açar.
Altın Kural:
- State / Durum Kontrolü: "Bu olay oldu mu? (Olduysa devam et, geride kalmayayım)" mantığı varsa -> wait(event.triggered)
- Zamanlama / Gecikme: "Bir sonraki tetiklemeye kadar (örneğin sonraki clock cycle) dur ve kesinlikle bekle" mantığı varsa -> @(event)
UVM mimarisinde daha gelişmiş componentler arası haberleşme için standart SystemVerilog event'leri yerine uvm_event ve uvm_event_pool kullanımı da çok yaygındır. Bu konuya da ilerideki derslerde değineceğiz.
İki Bekleme Yönteminin Farkı
Bir olayı (event) beklemenin iki yolu vardır ve aralarındaki fark race condition'ların kaynağıdır:
@(event)(kenar tetiklemeli): Sürecin olayı yakalayabilmesi için tetiklemeden önce beklemeye geçmiş olması gerekir. Aynı zaman adımında (time step) önce tetikleyip sonra@ile beklerseniz, tetiklemeyi kaçırırsınız ve süreç asılı kalır.wait(event.triggered)(durum/seviye kontrolü): Olayın o zaman adımında tetiklenip tetiklenmediğini sorgular. Tetiklemewait'ten hemen önce, hatta aynı anda gerçekleşse bile bunu algılar ve süreç bloklanmadan devam eder.
Neden Önemli?
Karmaşık testbench'lerde hangi sürecin aynı zaman adımında önce çalışacağı belirsizdir (non-deterministic). Eğer bir bileşen "olay zaten oldu mu?" sorusunu @(event) ile sorarsa, olayı bir delta döngüsü farkıyla kaçırıp simülasyonu kilitleyebilir. Bu yüzden durum kontrolü için wait(event.triggered), belirgin bir sonraki tetiklemeyi beklemek için @(event) tercih edilir.
Kaynak Kod
module wait_triggered_usage;
event sync_event;
initial begin
#10;
// Önce event'i tetikleyelim
$display("[%0t] Triggering the event.", $time);
-> sync_event;
// wait(.triggered), event aynı time step'te tetiklense bile çalışır
wait(sync_event.triggered);
$display("[%0t] wait(sync_event.triggered) caught the event successfully.", $time);
-> sync_event;
// NOT:Bir de bunu dene, Line 15'i yoruma al:
/*fork
begin
#5;
$display("[%0t] Parallel thread: Triggering the event again.", $time);
-> sync_event;
end
join_none*/
$display("[%0t] Now waiting with @(sync_event).", $time);
@(sync_event);
// Bu satırı göremezsin. Çünkü aynı thread'de aynı time slotta event'i
// tetikledin ve bekledin. @ operatoru thread'i blokladı.
// Yukarıdaki fork join_none'ı denediğinde paralel thread'de tetiklemiş oldun
$display("[%0t] @(sync_event) caught the second trigger successfully!", $time);
end
endmodule
Kodun Açıklaması
- Modül tek bir
sync_eventolayı ve tek birinitialblok içerir; böylece tüm işlemler aynı süreçte ve çoğu aynı zaman adımında gerçekleşir. #10gecikmesinden sonra-> sync_event;ile olay tetiklenir.- Hemen ardından
wait(sync_event.triggered);çağrılır. Olay aynı zaman adımında tetiklendiği halde,.triggeredözelliği bunu algılar ve süreç takılmadan devam eder; "caught the event successfully" mesajı yazılır. İştewait(...triggered)'ın gücü budur. - Sonra ikinci kez
-> sync_event;tetiklenir ve hemen@(sync_event);ile beklemeye geçilir. Burada kritik nokta şudur: tetikleme@'ten önce ve aynı zaman adımında olduğu için,@operatörü bu tetiklemeyi yakalayamaz. Süreç bu satırda sonsuza kadar bloklanır. - Bu yüzden son
$displaysatırı ("@(sync_event) caught the second trigger") asla çalışmaz. Yorum içindekifork...join_nonebloğunu etkinleştirip ikinci-> sync_event;'i yorum satırı yaparsanız, olay paralel bir süreçten ve farklı bir anda tetikleneceği için@artık yakalayabilir.
Önemli Noktalar
- Aynı süreçte aynı zaman adımında bir olayı önce tetikleyip sonra
@ile beklemek klasik bir hatadır;@o tetiklemeyi kaçırır ve süreç asılı kalır. - "Bu olay zaten oldu mu?" mantığı için her zaman
wait(event.triggered)kullanın; durum kontrolünde delta döngüsü yarışlarına karşı güvenlidir. @(event)'i, olayı başka bir süreçten ve gelecekte tetiklenecek şekilde beklerken kullanın (örneğin saat kenarı, monitör sinyali).- Koddaki yorumlu
fork...join_noneörneği, tetiklemeyi paralel bir sürece taşıyarak@'in nasıl çalışır hale geldiğini göstermek için bilinçli olarak konmuştur; deneyerek farkı kendiniz gözlemleyin. - Gerçek doğrulama ortamlarında bu tür kilitlenmeler saatler kaybettirebilir; bekleme yöntemini niyetinize (durum mu, kenar mı?) göre seçmek en iyi pratiktir.