Döngüsel Kısıtlamalar
Gün 3: Rastgele Üretim ve Kısıtlamalar | foreach ile dizi kısıtlamaları, unique, matris kısıtlamaları
Bu derste diziler (array) üzerindeki kısıtlamaları öğreneceğiz: foreach ile her elemana kural uygulama, dinamik dizi boyutunu kısıtlama, unique ile benzersizlik garantisi ve çok boyutlu (matris) dizilerde toplam (sum()) tabanlı kısıtlamalar.
Döngüsel (Iterative) Kısıtlamalar
Bir diziyi rastgeleleştirirken, çoğu zaman her elemana ya da elemanlar arası ilişkilere kural koymak isteriz. Bunu foreach ile yaparız. foreach bir constraint bloğu içinde kullanıldığında, döngü değişkeni (örneğin i) tüm indeksler üzerinde gezer ve her indeks için ayrı bir kısıtlama üretilmiş gibi davranır.
Bu yapı şunları mümkün kılar:
- Eleman bazlı kurallar: her
payload[i]belirli bir aralıkta olsun. - Komşu eleman ilişkileri:
payload[i] != payload[i-1]gibi ardışık farklılık ya daheader[i] > header[i-1]gibi sıralama. - Boyut kısıtlamaları: dinamik dizinin
size()değeri başka bir rastgele alana bağlanabilir.
unique
unique { ... } kısıtlaması, küme içindeki tüm elemanların birbirinden farklı olmasını garanti eder. Bu, çakışmasız adresler, benzersiz ID'ler veya tekrar etmeyen veri kümeleri üretmek için idealdir.
sum() ve Genişlik (Width) Tuzağı
Bir dizinin elemanlarının toplamını kısıtlamak için dizi.sum() kullanılır. Ancak sum(), varsayılan olarak sonucu eleman tipinin bit genişliğiyle hesaplar; bu, dar bitli elemanlarda taşmaya (overflow) yol açabilir. Çözüm, sum() with (int'(item)) yazarak her elemanı toplamaya katılmadan önce int'e dönüştürmektir.
Kaynak Kod
// =============================================================================
// GUN 3 - Konu 4: Dongusel Kisitlamalar (Iterative Constraints - foreach)
// =============================================================================
class ArrayPacket;
rand bit [7:0] payload []; // Dinamik dizi
rand int length;
rand bit [3:0] header [4]; // Sabit boyutlu dizi
// Dizi boyutu kisitlamasi
constraint c_length {
length inside {[4:16]};
payload.size() == length;
}
// foreach ile eleman kisitlamalari
constraint c_payload {
foreach (payload[i]) {
payload[i] inside {[8'h01:8'hFE]}; // 0x00 ve 0xFF haric
if (i > 0)
payload[i] != payload[i-1]; // Ardisik elemanlar farkli
}
}
// Header: artan sira
constraint c_header_ordered {
foreach (header[i]) {
if (i > 0)
header[i] > header[i-1]; // Kesin artan
}
header[0] >= 1;
}
function void display();
$display(" Length=%0d", length);
$write(" Header: ");
foreach (header[i]) $write("%0d ", header[i]);
$display();
$write(" Payload: ");
foreach (payload[i]) $write("%02h ", payload[i]);
$display();
endfunction
endclass
class UniqueArray;
rand int data [8];
// Tum elemanlar benzersiz olmali
constraint c_unique {
unique {data};
foreach (data[i])
data[i] inside {[1:100]};
}
function void display();
$write(" Unique data: ");
foreach (data[i]) $write("%0d ", data[i]);
$display();
endfunction
endclass
class Matrix;
rand bit [3:0] grid [4][4];
// Satır toplamı 20'den küçük olsun
// sum() sonucu array'deki item'ın width'i kadar olabiliyor normalde. Bu da toplamın overflow olmasına neden oluyor
// O yüzden with kullanarak toplama dahil edilecek sayıları int'e dönüştürdük
constraint c_row_sum {
foreach (grid[i]) {
grid[i].sum() with (int'(item)) < 20;
}
}
// Koşegenler 0 olmasın
constraint c_diagonal {
foreach (grid[i]) {
grid[i][i] > 0;
}
}
function void display();
$display(" 4x4 Matrix:");
foreach (grid[i]) begin
$write(" [");
foreach (grid[i][j])
$write("%2d ", grid[i][j]);
// sum() sonucu array'deki item'ın width'i kadar olabiliyor normalde. Bu da toplamın overflow olmasına neden oluyor
// O yüzden with kullanarak toplama dahil edilecek sayıları int'e dönüştürdük
$display("] sum=%0d", grid[i].sum() with (int'(item)));
end
endfunction
endclass
module iterative_constraints;
initial begin
ArrayPacket apkt;
UniqueArray uarr;
Matrix mat;
$display("=== Dongusel Kisitlamalar (foreach) ===\n");
// --- Dizi kisitlamalari ---
$display("--- ArrayPacket ---");
apkt = new();
repeat (3) begin
assert(apkt.randomize()) else $fatal(1, "Randomize hata!");
apkt.display();
$display();
end
// --- Benzersiz elemanlar ---
$display("--- UniqueArray ---");
uarr = new();
repeat (3) begin
assert(uarr.randomize()) else $fatal(1, "Randomize hata!");
uarr.display();
end
// --- Matris kisitlamalari ---
$display("\n--- Matrix ---");
mat = new();
repeat (2) begin
assert(mat.randomize()) else $fatal(1, "Randomize hata!");
mat.display();
$display();
end
$display("=== Dongusel Kisitlamalar Sonu ===");
$finish;
end
endmodule
Kodun Açıklaması
ArrayPacketsınıfındapayloaddinamik dizisi,lengthve dört elemanlı sabit boyutluheaderdizisi tanımlıdır.c_lengthconstraint'ilength'i 4–16 arasına sınırlar vepayload.size() == lengthile dizinin uzunluğunu bu rastgele değere eşitler.c_payloadiçindekiforeach (payload[i])her elemanı[8'h01:8'hFE]aralığına koyar (0x00 ve 0xFF hariç) veif (i > 0)koşuluylapayload[i] != payload[i-1]diyerek ardışık elemanların farklı olmasını sağlar.c_header_ordered,headerdizisini kesin artan yapar (header[i] > header[i-1]) veheader[0] >= 1ile başlangıcı sabitler.
UniqueArraysınıfındadatasekiz elemanlı bir dizidir.c_uniqueconstraint'iunique {data}ile tüm elemanları benzersiz kılar veforeachile her elemanı[1:100]aralığına yerleştirir.Matrixsınıfındagrid, 4×4'lük iki boyutlu bir dizidir.c_row_sum, her satır içingrid[i].sum() with (int'(item)) < 20der;int'(item)cast'i toplama sırasında taşmayı önler.c_diagonal,grid[i][i] > 0ile köşegen elemanlarının sıfır olmamasını garanti eder.
moduleiçindeArrayPacket,UniqueArrayveMatrixnesneleri ayrı ayrırandomize()edilipassert(...) else $fatal(...)ile doğrulanır vedisplay()ile yazdırılır.
Önemli Noktalar
foreachconstraint'i her indeks için ayrı bir kural üretir. İndeks değişkeni (i) yalnızca constraint bağlamında geçerlidir ve komşu elemanlara (i-1) erişerek ilişkiler kurmanızı sağlar.- Dinamik dizilerde önce boyutu kısıtlayın.
payload.size() == lengthgibi bir kural olmadan çözücü dizi boyutunu serbestçe seçer; eleman kısıtlamalarının anlamlı olması için boyutun belirlenmesi önemlidir. sum()taşmasına dikkat edin. Dar bitli dizilerdesum() with (int'(item))kullanmazsanız toplam, eleman genişliğinde hesaplanır ve beklenmedik şekilde taşar — kod yorumlarında da bu özellikle vurgulanmıştır.unique, çözücü için maliyetli olabilir. Büyük dizilerde veya dar değer aralıklarında benzersizlik sağlamak çözüm uzayını daraltır; aralığın eleman sayısından yeterince geniş olduğundan emin olun (örneğin 8 eleman için[1:100]).- Kesin artan (
>) gibi sıkı sıralama kısıtlamalarında, değer aralığının eleman sayısını karşılayacak kadar geniş olması gerekir; aksi halde randomize başarısız olur.