Lab 3: Generator Sınıfı
Gün 3: Rastgele Üretim ve Kısıtlamalar | Senaryoya uygun rastgele veri üreten Generator tasarımı
Bu lab çalışmasında, Gün 3 boyunca öğrendiğimiz tüm constrained-random tekniklerini tek bir uygulamada birleştiriyoruz: kısıtlamalı bir transaction sınıfı ve onu farklı senaryolarda sürebilen bir Generator sınıfı tasarlayacağız. Bu yapı, gerçek doğrulama ortamlarının (testbench) çekirdeğini oluşturur.
Generator Deseni
Bir Generator (üretici), test sırasında tasarıma uygulanacak rastgele transaction'ları üreten bileşendir. Tipik olarak:
- İçinde bir veya daha fazla transaction nesnesi tutar.
- Belirli sayıda transaction'ı, belirli bir senaryoya göre rastgeleleştirir.
- Senaryolar arasında geçiş yaparken
constraint_mode()ve satır içiwithkısıtlamalarını kullanır.
Bu derste birleştirdiğimiz kavramlar:
rand/randcdeğişkenler ve enum tipleri.distile gerçekçi komut ve hata dağılımları.- implication (
->) ile komut tipine bağlı kurallar. constraint_mode()ile senaryoya özel kısıtlama açma/kapatma.post_randomize()ile türetilmiş alan hesaplama ve hata enjeksiyonu.
Senaryo Tabanlı Doğrulama
Aynı transaction sınıfını birden çok senaryoda yeniden kullanmak, doğrulama ortamlarında temel bir verimlilik kaynağıdır. Generator, her senaryo için ayrı bir task tanımlayarak (normal trafik, sadece okuma, yüksek adres, hata enjeksiyonu) tek bir veri modelinden çok çeşitli test durumları üretir.
Kaynak Kod
// =============================================================================
// GUN 3 - Lab 3: Generator Sinifi - Senaryoya Uygun Rastgele Veri Uretimi
// =============================================================================
class BusTransaction;
typedef enum logic [1:0] {READ=0, WRITE=1, BURST_READ=2, BURST_WRITE=3} cmd_e;
typedef enum {VALID, ADDR_ERROR, DATA_ERROR, PROTOCOL_ERROR} status_e;
rand cmd_e command;
rand logic [31:0] address;
rand logic [31:0] data;
rand int unsigned burst_length;
rand bit [3:0] byte_strobe;
rand bit [2:0] id;
rand status_e status;
bit [31:0] crc;
int txn_id;
static int count = 0;
// --- Temel kisitlamalar ---
constraint c_base {
burst_length inside {[1:16]};
(command inside {READ, WRITE}) -> burst_length == 1;
(command inside {BURST_READ, BURST_WRITE}) -> burst_length inside {[2:16]};
}
// --- Gecerli paket ---
constraint c_valid {
status == VALID;
address[1:0] == 2'b00; // 4-byte hizali
byte_strobe != 0;
}
// --- Adres araliklari ---
constraint c_addr_region_A {
address inside {[32'h0000_0000:32'h0000_FFFF]};
}
constraint c_addr_region_B {
address inside {[32'h1000_0000:32'h1000_FFFF]};
}
constraint c_addr_region_C {
address inside {[32'hFFFF_0000:32'hFFFF_FFFF]};
}
// --- Komut dagilimi ---
constraint c_cmd_dist {
command dist { READ := 30, WRITE := 30, BURST_READ := 20, BURST_WRITE := 20 };
}
// --- Hata enjeksiyonu ---
constraint c_inject_error {
status dist { VALID := 80, ADDR_ERROR := 10, DATA_ERROR := 5, PROTOCOL_ERROR := 5 };
}
function new();
txn_id = count++;
c_addr_region_B.constraint_mode(0);
c_addr_region_C.constraint_mode(0);
c_inject_error.constraint_mode(0);
endfunction
function void post_randomize();
crc = address ^ data ^ {29'h0, command};
if (status == ADDR_ERROR)
address[1:0] = 2'b11; // Hizalamayi boz
else if (status == DATA_ERROR)
data = ~data;
endfunction
function void display();
$display(" TXN#%03d | %-11s | Addr=0x%08h | Data=0x%08h | Burst=%2d | BE=%04b | ID=%0d | %s",
txn_id, command.name(), address, data, burst_length,
byte_strobe, id, status.name());
endfunction
endclass
class Generator;
BusTransaction txn;
int num_transactions;
string scenario_name;
function new(int num = 10);
this.num_transactions = num;
this.txn = new();
endfunction
// Senaryo 1: Normal trafik
task run_normal_traffic();
scenario_name = "Normal Trafik";
$display("\n=== Senaryo: %s (%0d txn) ===", scenario_name, num_transactions);
repeat (num_transactions) begin
assert(txn.randomize()) else $fatal(1, "Randomize hata!");
txn.display();
end
endtask
// Senaryo 2: Sadece okuma
task run_read_only();
scenario_name = "Sadece Okuma";
$display("\n=== Senaryo: %s ===", scenario_name);
repeat (num_transactions) begin
assert(txn.randomize() with { command inside {BusTransaction::READ, BusTransaction::BURST_READ}; })
else $fatal(1, "Randomize hata!");
txn.display();
end
endtask
// Senaryo 3: Yuksek adres bolgesi
task run_high_address();
scenario_name = "Yuksek Adres Bolgesi";
$display("\n=== Senaryo: %s ===", scenario_name);
txn.c_addr_region_A.constraint_mode(0);
txn.c_addr_region_C.constraint_mode(1);
repeat (num_transactions) begin
assert(txn.randomize()) else $fatal(1, "Randomize hata!");
txn.display();
end
txn.c_addr_region_A.constraint_mode(1);
txn.c_addr_region_C.constraint_mode(0);
endtask
// Senaryo 4: Hata enjeksiyonu
task run_error_injection();
scenario_name = "Hata Enjeksiyonu";
$display("\n=== Senaryo: %s ===", scenario_name);
txn.c_valid.constraint_mode(0);
txn.c_inject_error.constraint_mode(1);
repeat (num_transactions) begin
assert(txn.randomize()) else $fatal(1, "Randomize hata!");
txn.display();
end
txn.c_valid.constraint_mode(1);
txn.c_inject_error.constraint_mode(0);
endtask
endclass
module lab3_generator;
initial begin
Generator gen;
$display("============================================================");
$display(" LAB 3: Generator Sinifi - Senaryolu Rastgele Uretim");
$display("============================================================");
gen = new(8);
gen.run_normal_traffic();
gen.run_read_only();
gen.run_high_address();
gen.run_error_injection();
$display("\n============================================================");
$display(" LAB 3 TAMAMLANDI");
$display("============================================================");
$finish;
end
endmodule
Kodun Açıklaması
BusTransactionsınıfı iki enum kullanır: komut tipi içincmd_e(READ,WRITE,BURST_READ,BURST_WRITE) ve durum içinstatus_e(VALID,ADDR_ERROR,DATA_ERROR,PROTOCOL_ERROR). Rastgele alanlar arasındacommand,address,data,burst_length,byte_strobe,idvestatusyer alır.- Kısıtlamalar:
c_base,burst_length'i 1–16 arasına koyar ve implication ile tekil komutlarda (READ,WRITE) uzunluğu 1'e, burst komutlarında 2–16 arasına zorlar.c_valid, geçerli paketler içinstatus == VALID, 4-byte hizalı adres (address[1:0] == 2'b00) vebyte_strobe != 0kurar.c_addr_region_A/B/C, üç farklı adres bölgesi tanımlar; bunlarconstraint_mode()ile teker teker açılıp kapatılacak şekilde kurgulanmıştır.c_cmd_distvec_inject_error, sırasıyla komut ve hata durumu içindistile olasılık dağılımları tanımlar.
new()kurucusutxn_idatar ve çakışmayı önlemek içinc_addr_region_B,c_addr_region_Cilec_inject_error'ı baştan kapatır — yani varsayılan davranış: A bölgesi, geçerli paketler.post_randomize(), türetilmişcrcalanını hesaplar ve hata durumlarına göre değer bozar:ADDR_ERROR'da adres hizasını bozar (address[1:0] = 2'b11),DATA_ERROR'da veriyi tersler (data = ~data). Bu, hatanın rastgeleleştirme sonrası enjekte edilmesinin örneğidir.Generatorsınıfı içinde birBusTransactionnesnesi (txn) ve dört senaryotask'ı bulunur:run_normal_traffic()varsayılan kısıtlamalarla normal trafik üretir.run_read_only(), satır içiwith { command inside {BusTransaction::READ, BusTransaction::BURST_READ}; }ile yalnızca okuma komutları üretir.run_high_address(),c_addr_region_A'yı kapatıpc_addr_region_C'yi açar, senaryo bitince eski duruma döndürür.run_error_injection(),c_valid'i kapatıpc_inject_error'ı açarak dağılımlı hata durumları üretir, sonra geri alır.
moduleiçindeGenerator8 transaction ile oluşturulur ve dört senaryo sırayla çalıştırılır.
Önemli Noktalar
- Senaryo
task'ları durumu geri yükler.run_high_address()verun_error_injection(), değiştirdikleri constraint modlarını sonunda eski haline getirir; bu, senaryoların birbirini etkilememesi için kritik bir pratiktir. - Enum değerlerine sınıf dışından erişirken kapsam belirtin. Satır içi kısıtlamada
BusTransaction::READgibisinif::degerbiçimi kullanılır. - Hata enjeksiyonunu
post_randomize()içinde yapmak güçlüdür. Kısıtlamalarla geçerli bir paket üretip ardından bilinçli olarak bozmak, hem geçerli hem hatalı senaryoları tek modelden türetmeyi sağlar. - Çakışan adres bölgesi kısıtlamalarını aynı anda açmayın. A, B, C bölgeleri ayrık aralıklardır; aynı anda birden fazlası açıkken
randomize()çözümsüz kalır. distağırlıkları gerçekçi trafik modellemek içindir.c_cmd_distvec_inject_errorile üretilen dağılım, gerçek sistem davranışına yakın test senaryoları üretmenizi sağlar; istatistiksel anlamlılık için yeterli sayıda transaction üretin.- Bu Generator deseni, ileride UVM
sequence/sequenceryapılarına geçişin temelini oluşturur; mantık aynıdır, yalnızca altyapı standartlaşır.