EDA Playground'da Dene

Diziler (Arrays)

Gün 1: SystemVerilog'a Giriş ve Veri Tipleri | Sabit boyutlu, dinamik ve ilişkisel diziler

Bu derste SystemVerilog'un üç temel dizi türünü, hangi senaryoda hangisinin uygun olduğunu ve yerleşik dizi metodlarını (sum, min, max, sort, unique...) öğreneceğiz.

Üç Dizi Türü

SystemVerilog, ihtiyaca göre seçilen üç ana dizi türü sunar:

  • Sabit boyutlu (fixed-size) diziler: Boyut derleme zamanında bellidir (int fixed_arr [5];). Çok boyutlu olabilirler (int matrix [3][4];). Bellek önceden ayrılır, erişim hızlıdır.
  • Dinamik (dynamic) diziler: Boyut çalışma zamanında new[] ile belirlenir (int dyn_arr [];). Gerektiğinde yeniden boyutlandırılabilir ve delete() ile temizlenebilir.
  • İlişkisel (associative) diziler: Anahtar–değer eşlemesi yapar (int assoc_arr [string];). Çok büyük ama seyrek (sparse) adres uzaylarını modellemek için idealdir; yalnızca yazılan girdiler için bellek harcar.

Dizi Metodları

SystemVerilog dizilerde doğrudan kullanılabilen güçlü metodlar sağlar:

  • İndirgeme: sum(), min(), max()
  • Sıralama/düzen: sort(), rsort() (tersten), shuffle() (karıştır)
  • Filtreleme: unique() ile tekrarsız elemanlar
  • Sorgu (associative): num() eleman sayısı, exists() anahtar var mı

foreach döngüsü, indeksleri elle yönetmeden tüm dizi türlerini gezmenin en pratik yoludur; çok boyutlu dizilerde foreach (matrix[i, j]) gibi birden çok indeks kullanılabilir.

Kaynak Kod

// =============================================================================
// GUN 1 - Konu 5: Diziler (Arrays): Sabit, Dinamik, Iliskisel
// =============================================================================

module diziler;

  // -------------------------------------------------------------------------
  // SABIT BOYUTLU DIZILER (Fixed-Size Arrays)
  // -------------------------------------------------------------------------
  int fixed_arr [5];                    // 5 elemanli unpacked dizi
  logic [7:0] packed_arr [3];           // 3 elemanli, her biri 8-bit
  int matrix [3][4];                    // 2 boyutlu dizi (3 satir, 4 sutun)

  // -------------------------------------------------------------------------
  // DINAMIK DIZILER (Dynamic Arrays)
  // -------------------------------------------------------------------------
  int dyn_arr [];                       // Boyut calisma zamaninda belirlenir

  // -------------------------------------------------------------------------
  // ILISKISEL DIZILER (Associative Arrays)
  // -------------------------------------------------------------------------
  int assoc_arr [string];              // String anahtarli
  int sparse_mem [int];                // Int anahtarli

  initial begin
    $display("=== SystemVerilog Diziler ===\n");

    // --- Sabit Boyutlu Dizi ---
    $display("--- Sabit Boyutlu Diziler ---");
    fixed_arr = '{10, 20, 30, 40, 50};
    foreach (fixed_arr[i])
      $display("  fixed_arr[%0d] = %0d", i, fixed_arr[i]);

    // 2D dizi
    $display("\n  2D Matris (3x4):");
    foreach (matrix[i, j])
      matrix[i][j] = (i * 4) + j;
    foreach (matrix[i]) begin
      $write("  Satir %0d: ", i);
      foreach (matrix[i][j])
        $write("%3d ", matrix[i][j]);
      $display();
    end

    // Dizi metodlari
    $display("\n  Dizi Metodlari:");
    $display("  sum     = %0d", fixed_arr.sum());
    $display("  min     = %0d", fixed_arr.min());
    $display("  max     = %0d", fixed_arr.max());
    $display("  unique  = %p",  fixed_arr.unique());

    // Siralama
    fixed_arr.rsort();
    $display("  rsort   = %p", fixed_arr);
    fixed_arr.shuffle();
    $display("  shuffle = %p", fixed_arr);

    // --- Dinamik Dizi ---
    $display("\n--- Dinamik Diziler ---");
    dyn_arr = new[5];
    foreach (dyn_arr[i]) dyn_arr[i] = (i + 1) * 100;
    $display("  Baslangic boyut = %0d", dyn_arr.size());
    foreach (dyn_arr[i]) $display("  dyn_arr[%0d] = %0d", i, dyn_arr[i]);

    // Boyut degistirme (mevcut veriyi koruyarak)
    dyn_arr = new[8](dyn_arr);
    dyn_arr[5] = 600; dyn_arr[6] = 700; dyn_arr[7] = 800;
    $display("\n  Yeni boyut = %0d", dyn_arr.size());
    foreach (dyn_arr[i]) $display("  dyn_arr[%0d] = %0d", i, dyn_arr[i]);

    // Silme
    dyn_arr.delete();
    $display("  Silme sonrasi boyut = %0d", dyn_arr.size());

    // --- Iliskisel Dizi ---
    $display("\n--- Iliskisel Diziler ---");
    
    // String anahtarli
    assoc_arr["sifirlama"]  = 0;
    assoc_arr["baslat"]     = 1;
    assoc_arr["durdur"]     = 2;
    assoc_arr["hata"]       = 99;

    $display("  Eleman sayisi = %0d", assoc_arr.num());
    if (assoc_arr.exists("hata"))
      $display("  'hata' anahtari mevcut, deger = %0d", assoc_arr["hata"]);

    // foreach ile gezinme
    foreach (assoc_arr[key])
      $display("  assoc_arr[\"%s\"] = %0d", key, assoc_arr[key]);

    // Seyrek bellek modeli
    $display("\n  Seyrek Bellek Modeli:");
    sparse_mem[32'h0000] = 'hAA;
    sparse_mem[32'h1000] = 'hBB;
    sparse_mem[32'hFFFF] = 'hCC;
    foreach (sparse_mem[addr])
      $display("  MEM[0x%04h] = 0x%02h", addr, sparse_mem[addr]);

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

endmodule

Kodun Açıklaması

  • fixed_arr = '{10, 20, 30, 40, 50}; ile sabit boyutlu dizi toplu atama (array literal) ile doldurulur ve foreach (fixed_arr[i]) ile yazdırılır.
  • int matrix [3][4]; iki boyutlu dizidir. foreach (matrix[i, j]) matrix[i][j] = (i * 4) + j; tek satırda her iki indeksi birden gezer; ardından satır satır basılır.
  • Dizi metodları fixed_arr üzerinde gösterilir: sum() toplamı, min()/max() uç değerleri, unique() tekrarsız elemanları döndürür. rsort() diziyi büyükten küçüğe sıralar, shuffle() rastgele karıştırır (yerinde değiştirir).
  • dyn_arr = new[5]; dinamik diziyi 5 elemanlı oluşturur; foreach ile (i + 1) * 100 değerleri atanır. dyn_arr.size() anlık boyutu verir.
  • dyn_arr = new[8](dyn_arr); diziyi 8 elemana büyütürken mevcut veriyi korur (parantez içindeki dyn_arr eski içeriği taşır); ardından dyn_arr[5], [6], [7] elle doldurulur.
  • dyn_arr.delete(); diziyi tamamen boşaltır, boyut 0 olur.
  • İlişkisel dizide assoc_arr["hata"] = 99; gibi string anahtarlı girdiler eklenir; assoc_arr.num() eleman sayısını, assoc_arr.exists("hata") anahtarın varlığını sorgular. foreach (assoc_arr[key]) ile anahtar üzerinden gezilir.
  • sparse_mem[32'h0000], [32'h1000], [32'hFFFF] girdileri seyrek bellek modelini gösterir: 64K'lık bir adres uzayında yalnızca 3 girdi için bellek harcanır.

Önemli Noktalar

  • Doğru türü seçin: Boyut sabitse fixed-size, çalışma zamanında değişiyorsa dynamic, anahtar–değer veya seyrek adresleme gerekiyorsa associative dizi kullanın.
  • Dinamik diziyi büyütürken eski veriyi korumak için new[N](eski_dizi) biçimini kullanın; aksi hâlde dizi yeni boyutta sıfırlanır.
  • İlişkisel diziler bellek açısından verimlidir ama erişim sırası tanımlı değildir; sırayı önemsiyorsanız anahtarları ayrıca sıralayın.
  • unique(), min(), max() gibi metodlar yeni bir kuyruk (queue) döndürür; orijinal diziyi değiştirmezler. Buna karşılık sort(), rsort(), shuffle() diziyi yerinde değiştirir.
  • Çok boyutlu dizilerde foreach (matrix[i, j]) sözdizimi, iç içe döngülere göre daha kısa ve okunaklıdır.
  • İlişkisel bir anahtara erişmeden önce exists() ile kontrol etmek, tanımsız girdi okumaktan kaynaklı sürprizleri önler.