EDA Playground'da Dene

randomize() Metodu

Gün 3: Rastgele Üretim ve Kısıtlamalar | Rastgele üretim, inline constraint, hata kontrolü

Bu derste her rastgele sınıfın kalbi olan randomize() metodunu derinlemesine inceleyeceğiz: temel kullanımını, satır içi (inline) kısıtlama ekleyen with sözdizimini, yalnızca seçili değişkenleri rastgeleleştirmeyi ve dönüş değeri ile hata kontrolünü öğreneceğiz.

randomize() Metodu

randomize(), rastgele üyeleri olan her sınıfın otomatik olarak sahip olduğu, yerleşik (built-in) bir sınıf metodudur. Çağrıldığında sınıftaki tüm rand/randc değişkenlerine, tanımlı constraint blokları ve verilen kısıtlamaları sağlayacak şekilde rastgele değerler atar.

Metot bir bit döndürür:

  • 1 → çözüm bulundu, değişkenler güncellendi.
  • 0 → kısıtlamalar çakıştı (çözüm yok), değişkenler değişmeden kalır.

Bu yüzden dönüş değeri asla göz ardı edilmemelidir.

Satır İçi Kısıtlama: with { ... }

randomize() çağrısına with { ... } ekleyerek, sınıfta tanımlı kalıcı kısıtlamalara ek olarak yalnızca o çağrıya özel geçici kısıtlamalar verebilirsiniz. Bu kısıtlamalar sınıf içindeki blocklarla AND ilişkisiyle birleşir.

Seçici Randomize

randomize() metoduna argüman olarak değişken adları verilirse (randomize(data, size) gibi), yalnızca o değişkenler rastgeleleştirilir; geri kalanı o anki değerlerinde sabit tutulur. Bu, belirli bir alanı sabit tutup diğerlerini değiştirmek istediğinizde çok kullanışlıdır.

Hata Kontrolü ve assert

Endüstride yaygın kalıp, randomize çağrısını bir assert(...) else $fatal(...) içine almaktır. Böylece çözülemeyen bir kısıtlama anında ve net bir mesajla yakalanır.

Kaynak Kod

// =============================================================================
// GUN 3 - Konu 2: randomize() Metodu ve Hata Kontrolu
// =============================================================================

class Transaction;
  rand logic [15:0] address;
  rand logic [31:0] data;
  rand bit [2:0]    size;
  rand bit          read_write;  // 0=read, 1=write

  constraint addr_range {
    address inside {[16'h0000 : 16'h0FFF]};
  }

  function void display(string prefix = "");
    $display("  %sAddr=0x%04h, Data=0x%08h, Size=%0d, R/W=%s",
             prefix, address, data, size,
             read_write ? "WRITE" : "READ");
  endfunction
endclass

module randomize_metodu;
  initial begin
    Transaction txn;
    int success;

    $display("=== randomize() Metodu ===\n");
    txn = new();

    // --- Temel randomize ---
    $display("--- Temel randomize() ---");
    repeat (5) begin
      success = txn.randomize();
      if (success)
        txn.display();
      else
        $display("  HATA: Randomize basarisiz!");
    end

    // --- randomize() with (inline constraint) ---
    $display("\n--- randomize() with (Satir ici kisitlama) ---");
    repeat (5) begin
      success = txn.randomize() with {
        address >= 16'h0100 && address <= 16'h01FF;
        data[31:16] == 16'h0000;
        read_write == 1;
      };
      if (success)
        txn.display("inline: ");
      else
        $display("  HATA: Inline randomize basarisiz!");
    end

    // --- Belirli degiskenleri sabit tutma ---
    $display("\n--- Secici Randomize ---");
    txn.address = 16'h0ABC;
    repeat (3) begin
      // address sabit, sadece digerleri rastgele
      success = txn.randomize(data, size, read_write);
      txn.display("addr sabit: ");
    end

    // --- randomize() donus degeri kontrolu ---
    $display("\n--- Hata Kontrolu ---");
    success = txn.randomize() with { address == 16'hFFFF; }; // Constraint ile cakisabilir
    if (!success)
      $display("  Constraint cakismasi: 0xFFFF aralik disi (0x0000-0x0FFF)");

    // Dogru kullanim: assert ile
    $display("\n--- assert ile Kontrol ---");
    // assert(txn.randomize()) else $fatal(1, "Randomize HATA!");
    if (txn.randomize())
      txn.display("assert OK: ");
    else
      $fatal(1, "Randomize basarisiz!");

    $display("\n=== randomize() Sonu ===");
    $finish;
  end
endmodule

Kodun Açıklaması

  • Transaction sınıfında address, data, size ve read_write rastgele üyeleri tanımlanır. addr_range adlı constraint, address değerini inside {[16'h0000 : 16'h0FFF]} aralığına sınırlar — yani adres her zaman 0x0000–0x0FFF arasında kalır.
  • Temel randomize bölümünde success = txn.randomize() çağrısının dönüş değeri bir değişkene atanır ve if (success) ile kontrol edilir; başarısızsa hata basılır.
  • Satır içi kısıtlama bölümünde randomize() with { ... } kullanılarak address 0x0100–0x01FF aralığına, data[31:16] sıfıra ve read_write 1'e (WRITE) sabitlenir. Bu kısıtlamalar addr_range ile çakışmaz çünkü 0x0100–0x01FF, izin verilen 0x0000–0x0FFF aralığının içindedir.
  • Seçici randomize bölümünde önce txn.address = 16'h0ABC ile adres elle ayarlanır, ardından txn.randomize(data, size, read_write) çağrılır. Argüman listesinde address olmadığı için adres 0x0ABC olarak sabit kalır, yalnızca diğer üç alan değişir.
  • Hata kontrolü bölümünde bilinçli olarak çakışan bir kısıtlama (address == 16'hFFFF) verilir. 0xFFFF, addr_range'in izin verdiği aralığın dışında olduğundan randomize() başarısız olur (0 döner) ve değişkenler değişmez.
  • Son bölümde doğru kalıp gösterilir: if (txn.randomize()) ... else $fatal(...). Yorum satırındaki assert(txn.randomize()) else $fatal(...) ise endüstride en yaygın yazım biçimidir.

Önemli Noktalar

  • Çakışan kısıtlamalarda eski değerler kalır. randomize() 0 döndüğünde değişkenler güncellenmez; bu yüzden başarısız bir çağrının ardından "eski" değerlerle çalışma riski vardır.
  • Satır içi kısıtlamalar sınıf kısıtlamalarını ezmez, onlarla birleşir. with içindeki ifadeler mevcut constraint blocklarıyla AND'lenir; bu nedenle sınıf kısıtlamasıyla çelişen bir inline kısıtlama çözümsüzlüğe yol açar.
  • Seçici randomize ile sabit tutulan alanların değerini önceden ayarlayın. randomize(...) argüman listesi dışında kalan rastgele alanlar, mevcut değerlerinde dondurulur.
  • Üretimde assert(...) else $fatal(...) kalıbını tercih edin. Bu, çözülemeyen kısıtlamaları sessizce geçiştirmek yerine hemen, açık bir mesajla raporlar.
  • Hangi değerlerin köşe durum oluşturduğunu test ederken (örneğin aralık sınırları) kasıtlı çakışmalarla constraint mantığınızı doğrulamak iyi bir pratiktir.