Tek çevrimli RV32I çekirdeğimizi (GC-2025-01) 5 aşamalı bir pipeline'a çevirdiğimizde ilk kırılan şey forwarding oldu. Bu yazı, hazard biriminin nasıl çalıştığını ve hangi testlerle doğruladığımızı anlatıyor.
Sorun
Beş aşama (IF, ID, EX, MEM, WB) arasında bir kayıt, henüz WB aşamasına ulaşmadan bir sonraki komutta okunmaya çalışılabiliyor. Forwarding olmadan şu kod yanlış sonuç veriyordu:
add x1, x2, x3
sub x4, x1, x5 // x1 henüz yazılmadıÇözüm: EX/MEM ve MEM/WB forwarding
Hazard biriminin çekirdeği, EX aşamasındaki kaynak register'ları bir sonraki iki aşamanın hedef register'larıyla karşılaştırıyor:
always @(*) begin
if (ex_mem_rd == id_ex_rs1 && ex_mem_reg_write)
forward_a = 2'b10;
else if (mem_wb_rd == id_ex_rs1 && mem_wb_reg_write)
forward_a = 2'b01;
else
forward_a = 2'b00;
endLoad-use hazard
Forwarding, bir önceki komut lw ise yetmiyor — veri MEM aşamasının
sonunda geliyor, EX aşamasında henüz hazır değil. Bunun için tek çevrimlik
bir stall ekledik: hazard tespit edilince PC ve IF/ID kaydı donduruluyor,
ID/EX'e bir NOP enjekte ediliyor.
Doğrulama
32 komutluk elle yazılmış bir test programını hem tek çevrimli hem pipeline'lı çekirdekte çalıştırıp register dosyasının son halini karşılaştırdık. Farklılık kalmayana kadar hazard birimini düzelttik.