pre/post_randomize()
Gün 3: Rastgele Üretim ve Kısıtlamalar | Randomize öncesi ve sonrası otomatik çağrılan fonksiyonlar
Bu derste randomize() çağrısının hemen öncesinde ve sonrasında otomatik olarak tetiklenen iki özel kanca (hook) fonksiyonunu öğreneceğiz: pre_randomize() ve post_randomize(). Bunlar, rastgeleleştirme sürecine kod enjekte etmenin standart yoludur.
pre_randomize() ve post_randomize()
SystemVerilog, her randomize() çağrısında otomatik olarak şu sırayı izler:
pre_randomize()çağrılır — henüz değişkenlere rastgele değer atanmadan önce.- Çözücü, kısıtlamaları çözer ve rastgele değişkenleri günceller.
post_randomize()çağrılır — rastgele değerler artık hazırdır.
Bu fonksiyonları sınıfınızda tanımlamanız zorunlu değildir; tanımlamazsanız boş gövdeli varsayılanları kullanılır. Tanımladığınızda ise randomize() onları sizin için otomatik çağırır; elle çağırmanıza gerek yoktur.
pre_randomize() ne için kullanılır?
- Randomize öncesi durum hazırlığı, sayaç güncelleme, bayrak ayarlama.
- Bazı değişkenleri geçici olarak sabitlemek veya ön koşullar kurmak.
post_randomize() ne için kullanılır?
- Türetilmiş alanları hesaplamak: CRC, checksum, toplam boyut gibi rastgele olmayan ama rastgele değerlere bağlı alanlar.
- Rastgele üretilmiş değerlerde küçük düzeltmeler yapmak (örneğin belirli bitleri zorlamak).
- Üretilen veriyi loglamak veya doğrulamak.
Kaynak Kod
// =============================================================================
// GUN 3 - Konu 5: pre_randomize() ve post_randomize() Fonksiyonlari
// =============================================================================
class EthernetFrame;
rand bit [47:0] dst_mac;
rand bit [47:0] src_mac;
rand bit [15:0] ethertype;
rand bit [7:0] payload [];
rand int payload_len;
// Hesaplanan alanlar (rastgele degil)
bit [31:0] crc;
int frame_size;
int frame_id;
static int frame_count = 0;
constraint c_payload {
payload_len inside {[46:1500]}; // Ethernet min/max
payload.size() == payload_len;
}
constraint c_ethertype {
ethertype inside {16'h0800, // IPv4
16'h0806, // ARP
16'h86DD}; // IPv6
}
// randomize() oncesinde otomatik cagrilir
function void pre_randomize();
frame_id = frame_count++;
$display(" [PRE] Frame #%0d randomize basliyor...", frame_id);
endfunction
// randomize() sonrasinda otomatik cagrilir
function void post_randomize();
// CRC hesapla (basitlestirilmis)
crc = 0;
crc ^= dst_mac[31:0] ^ dst_mac[47:32];
crc ^= src_mac[31:0] ^ src_mac[47:32];
crc ^= {16'h0, ethertype};
foreach (payload[i])
crc ^= {24'h0, payload[i]};
frame_size = 6 + 6 + 2 + payload_len + 4; // dst+src+type+payload+CRC
// MAC adreslerini duzelt: unicast (LSB=0) ve locally administered
dst_mac[0] = 0; // Unicast
src_mac[0] = 0; // Unicast
src_mac[1] = 1; // Locally administered
$display(" [POST] Frame #%0d: CRC=0x%08h, Size=%0d bytes",
frame_id, crc, frame_size);
endfunction
function void display();
$display(" Frame #%0d:", frame_id);
$display(" DST MAC : %012h", dst_mac);
$display(" SRC MAC : %012h", src_mac);
$display(" Type : 0x%04h (%s)", ethertype, get_type_name());
$display(" Payload : %0d bytes", payload_len);
$display(" CRC : 0x%08h", crc);
$display(" Toplam : %0d bytes", frame_size);
endfunction
function string get_type_name();
case (ethertype)
16'h0800: return "IPv4";
16'h0806: return "ARP";
16'h86DD: return "IPv6";
default: return "Bilinmeyen";
endcase
endfunction
endclass
module pre_post_randomize;
initial begin
EthernetFrame frame;
$display("=== pre_randomize() ve post_randomize() ===\n");
frame = new();
repeat (4) begin
$display("--- Randomize cagrisi ---");
assert(frame.randomize()) else $fatal(1, "Randomize hata!");
frame.display();
$display();
end
// Ozel kisitlama ile
$display("--- Sadece IPv4 paketleri ---");
repeat (2) begin
assert(frame.randomize() with {
ethertype == 16'h0800;
payload_len < 100;
}) else $fatal(1, "Randomize hata!");
frame.display();
$display();
end
$display("=== pre/post_randomize Sonu ===");
$finish;
end
endmodule
Kodun Açıklaması
EthernetFramesınıfı rastgele alanları (dst_mac,src_mac,ethertype,payload,payload_len) ve hesaplanan/rastgele olmayan alanları (crc,frame_size,frame_id, statikframe_count) içerir.c_payloadconstraint'ipayload_len'i Ethernet'in geçerli sınırları olan 46–1500 arasına koyar vepayload.size() == payload_lenile dizi boyutunu eşitler.c_ethertypeiseethertype'ı IPv4 (0x0800), ARP (0x0806) ve IPv6 (0x86DD) değerlerinden biriyle sınırlar.pre_randomize()her randomize'dan önce çalışır;frame_id = frame_count++ile her çerçeveye benzersiz bir kimlik atar ve[PRE]etiketli bir mesaj basar. Bu, rastgeleleştirmenin ne zaman başladığını gösterir.post_randomize()rastgele değerler hazır olduktan sonra çalışır ve şunları yapar:dst_mac,src_mac,ethertypeve tümpayloadbaytları üzerinden XOR ile basitleştirilmiş bircrchesaplar.frame_size'ı başlık + payload + CRC toplamı olarak (6 + 6 + 2 + payload_len + 4) hesaplar.- MAC adreslerini düzeltir:
dst_mac[0]=0vesrc_mac[0]=0ile unicast,src_mac[1]=1ile "locally administered" yapar. Bu, rastgele üretilen değerlerin post-randomize ile düzeltilmesine güzel bir örnektir.
get_type_name()yardımcı fonksiyonuethertypedeğerini okunabilir bir isme (IPv4,ARP,IPv6) çevirir.moduleiçinde önce 4 çerçeve serbestçe üretilir; her çağrıda PRE → POST sırası ekrana yansır. Ardındanrandomize() with { ethertype == 16'h0800; payload_len < 100; }ile yalnızca küçük IPv4 paketleri üretilir.
Önemli Noktalar
pre_randomize()vepost_randomize()'ı elle çağırmayın.randomize()bunları otomatik tetikler; elle çağırmak çift çalışmaya ve hatalı duruma yol açar.- Hesaplanan alanları
post_randomize()içinde üretin.crcveframe_sizegibi rastgele olmayan ama rastgele değerlere bağlı alanlar için doğru yer burasıdır; çünkü o aşamada tüm rastgele değerler kesinleşmiştir. post_randomize()içinde değer değiştirmek kısıtlamaları atlatabilir. MAC adres bitlerinin elle ayarlanması gibi düzeltmeler çözücünün dışında gerçekleşir; bu yüzden bu değişikliklerin hiçbir constraint'i ihlal etmediğinden emin olun.pre_randomize()çözücüden önce çalışır, dolayısıyla orada atadığınızranddeğişkenleri çözücü tarafından üzerine yazılabilir; bu fonksiyon daha çok rastgele olmayan hazırlık için uygundur.- Bu kancalar, kısıtlamalarla ifade edilemeyen prosedürel mantığı (karmaşık CRC, koşullu düzeltmeler) eklemenin temiz yoludur; ancak mümkün olan her kuralı önce constraint olarak ifade etmeye çalışın.