rand ve randc
Gün 3: Rastgele Üretim ve Kısıtlamalar | Rastgele değişkenler: rand (rastgele) ve randc (döngüsel)
Bu derste SystemVerilog'un kısıtlanmış-rastgele (constrained-random) doğrulama altyapısının temel yapı taşı olan rastgele değişkenleri öğreneceğiz: rand ve randc niteleyicileri ile std::randomize fonksiyonunu, bunların farklarını ve nerede kullanılacağını ele alacağız.
Neden Rastgele Üretim?
Modern donanım doğrulamasında, bir tasarımın tüm köşe durumlarını (corner case) elle yazılmış yönlü (directed) testlerle yakalamak neredeyse imkânsızdır. Bunun yerine kısıtlanmış-rastgele doğrulama yaklaşımı kullanılır: değişkenlere rastgele ama anlamlı (kısıtlanmış) değerler atayarak çok sayıda senaryo otomatik olarak üretilir. Bu sayede mühendisin aklına gelmeyen kombinasyonlar da test edilir.
SystemVerilog'da bir sınıf üyesini rastgele yapmak için iki niteleyici vardır:
rand: Herrandomize()çağrısında değişkene, izin verilen aralık içinden bağımsız ve rastgele bir değer atar. Aynı değer arka arkaya birden fazla kez gelebilir (tekrar olabilir).randc(cyclic random / döngüsel rastgele): Olası tüm değerleri bir kez üretmeden hiçbirini tekrar etmez. Tüm değerler tükendiğinde döngü baştan başlar ve yeni bir rastgele sıra ile devam eder. Genellikle dar bit genişlikli alanlar (örneğin adres seçici, kanal numarası) için kullanılır.
rand vs randc
randdeğişkenleri bellek/performans açısından ucuzdur ve çoğu durumda tercih edilir.randcdeğişkenleri tüm değer uzayını tarama garantisi verir; ancak bu uzayın küçük olması beklenir (örneğin 3 bit = 8 değer). Çok genişrandcalanları kaçınılması gereken bir kalıptır.
std::randomize
Sınıf dışındaki yerel değişkenleri rastgeleleştirmek için sınıfa bağlı olmayan std::randomize() fonksiyonu kullanılır. Buna with { ... } ekleyerek satır içi (inline) kısıtlamalar da verilebilir.
Kaynak Kod
// =============================================================================
// GUN 3 - Konu 1: Rastgele Test ve rand/randc Degiskenleri
// =============================================================================
class Packet;
// rand: Her randomize() cagrisinda rastgele deger uretir
rand bit [7:0] data;
rand bit [3:0] addr;
rand bit [1:0] burst_type;
// randc: Tum olasi degerleri tuketmeden tekrar etmez (cyclic random)
randc bit [2:0] prio; // 0-7 arasi, her biri bir kez, sonra tekrar
// Rastgele olmayan degiskenler
int id;
static int count = 0;
function new();
this.id = count++;
endfunction
function void display();
$display(" Paket #%0d: data=0x%02h, addr=0x%01h, burst=%0d, priority=%0d",
id, data, addr, burst_type, prio);
endfunction
endclass
module rand_ve_randc;
initial begin
Packet pkt;
Packet pkt2;//randc gösterimi için
$display("=== rand ve randc Degiskenleri ===\n");
pkt = new();
pkt2 = new();
// --- rand: Her seferinde rastgele ---
$display("--- rand: 10 rastgele paket ---");
repeat (10) begin
if (!pkt.randomize())
$fatal(1, "Randomize basarisiz!");
pkt.display();
end
// --- randc: Dongusel rastgele ---
$display("\n--- randc: priority (0-7 dongusel) ---");
$display(" Ilk dongu (8 deger):");
repeat (8) begin
void'(pkt2.randomize());
$display(" priority = %0d", pkt2.prio);
end
$display(" Ikinci dongu (tekrar 8 deger, farkli sira):");
repeat (8) begin
void'(pkt2.randomize());
$display(" priority = %0d", pkt2.prio);
end
// --- std::randomize (sinif disinda) ---
$display("\n--- std::randomize (Bagimsiz) ---");
begin
int x, y;
repeat (5) begin
if (!std::randomize(x, y) with { x inside {[1:100]}; y < x; })
$fatal(1, "std::randomize basarisiz!");
$display(" x = %0d, y = %0d", x, y);
end
end
$display("\n=== rand ve randc Sonu ===");
$finish;
end
endmodule
Kodun Açıklaması
Packetsınıfında üç adetranddeğişkeni (data,addr,burst_type) ve bir adetrandcdeğişkeni (prio) tanımlanmıştır.idve statikcountise rastgele olmayan, normal üyelerdir.new()kurucusunda her nesne içincount++ile artan biridatanır; bu, üretilen paketleri birbirinden ayırmak için kullanılır.- İlk
repeat (10)döngüsündepkt.randomize()çağrılır. Dönüş değeri kontrol edilir; başarısız olursa$fatalile simülasyon durdurulur. Her çağrıdadata,addrveburst_typebağımsız rastgele değerler alır. - İkinci bölümde
pkt2üzerindekirandcdeğişkenipriogösterilir. İlk 8 çağrıda 0–7 arası her değer tam bir kez üretilir. İkinci 8 çağrıda yine tüm değerler çıkar, ancak farklı bir sırada — döngüsel davranışın kanıtı budur. void'(pkt2.randomize())ifadesindekivoid'(...)cast'i, fonksiyonun dönüş değerini bilinçli olarak yok saymak içindir.- Son bölümde
std::randomize(x, y) with { x inside {[1:100]}; y < x; }kullanılarak sınıfa ait olmayan iki yerelintdeğişkeni satır içi kısıtlamalarla rastgeleleştirilir:x1–100 arasında,yisex'ten küçük olur.
Önemli Noktalar
randomize()dönüş değerini her zaman kontrol edin. Başarısız bir randomize (kısıtlama çakışması) sessizce eski değerleri bırakır; bu yüzdenif (!...)veyaassert(...)kullanmak şarttır.randcalanlarını dar tutun. Geniş bit genişliği, tüm değer uzayının izlenmesi nedeniyle performansı ciddi şekilde düşürür.randc, tüm değerler tükenene kadar tekrar üretmez; bu yüzden "her değeri bir kez gör" tipi senaryolarda idealdir.void'(...)cast'i ile dönüş değerini yok saymak yalnızca randomize'ın başarılı olacağından emin olduğunuz durumlarda tercih edilmelidir.std::randomize, hızlı testlerde veya sınıf tanımlamadan birkaç değişkeni rastgeleleştirmek istediğinizde pratiktir, ancak büyük doğrulama ortamlarında sınıf tabanlı yaklaşım daha sürdürülebilirdir.