Generator Modülü
Gün 6: Bitirme Projesi - Bölüm 1 | Rastgele ve yönlendirilmiş test üretici
Generator (üretici), testbench'in uyaranlarını (stimulus) üreten bileşendir. ALU mimarimizde zincirin başında durur: ALU_Transaction nesneleri oluşturur, kısıtlamalara göre rastgeleleştirir ve bir mailbox üzerinden driver'a iletir.
Generator ve Mimarideki Yeri
Generator, "DUT'a hangi senaryoları uygulayalım?" sorusunun cevabını üretir. Driver ile arasındaki iletişim, gen2drv adlı bir mailbox ile sağlanır:
- Generator transaction'ı
gen2drv.put(txn)ile kutuya bırakır. - Driver aynı kutudan
get()ile alır.
Bu yapı producer-consumer (üretici-tüketici) modelidir ve mailbox sayesinde iki bileşen birbirinden bağımsız hızlarda çalışabilir.
Kalıtım ile İki Üretim Stratejisi
Bu derste iki üretici sınıfı vardır:
ALU_Generator(taban sınıf): Belirtilen sayıda tamamen rastgele transaction üretir.run()metoduvirtualtanımlanmıştır; bu sayede türetilmiş sınıflar davranışı ezebilir (override).ALU_Corner_Generator(türetilmiş sınıf):extends ALU_Generatorile yönlendirilmiş (directed) test üretir. Önceden tanımlı köşe değer kümesini (corners) tüm işlemlerle çaprazlayarak sistematik biçimde tarar.
Her iki sınıf da işi bitince -> done ile bir event tetikler; böylece environment, üretimin tamamlandığını anlayabilir.
Kaynak Kod
// =============================================================================
// GUN 6 - Konu 3: Generator - Rastgele Uyarici Uretici
// =============================================================================
class ALU_Generator;
mailbox #(ALU_Transaction) gen2drv;
int num_transactions;
event done;
function new(mailbox #(ALU_Transaction) mbx, int num = 100);
this.gen2drv = mbx;
this.num_transactions = num;
endfunction
// Base run task must be virtual to be overridden
virtual task run();
ALU_Transaction txn;
$display("[Generator] Random tests starting...");
for (int i = 0; i < num_transactions; i++) begin
txn = new();
assert(txn.randomize()) else $fatal(1, "Randomize Error!");
gen2drv.put(txn);
end
-> done;
endtask
endclass
// Derived generator for corner cases
class ALU_Corner_Generator extends ALU_Generator;
function new(mailbox #(ALU_Transaction) mbx, int num = 100);
super.new(mbx, num);
endfunction
virtual task run();
ALU_Transaction txn;
logic [7:0] corners [] = '{0, 1, 8'h7F, 8'h80, 8'hFE, 8'hFF};
$display("[Corner_Generator] Corner cases starting...");
foreach (corners[i]) begin
foreach (corners[j]) begin
for (int op = 0; op < 8; op++) begin
// Skip invalid shift operations where operand_b is greater than 7
// to prevent constraint solver conflicts with c_shift_range
if ((op == ALU_Transaction::OP_SHL || op == ALU_Transaction::OP_SHR) && corners[j] > 7) begin
continue;
end
txn = new();
assert(txn.randomize() with {
operand_a == corners[i];
operand_b == corners[j];
opcode == ALU_Transaction::opcode_e'(op);
}) else $fatal(1, "Randomize Error!");
gen2drv.put(txn);
end
end
end
-> done;
endtask
endclass
Kodun Açıklaması
mailbox #(ALU_Transaction) gen2drv: Üretilen transaction'ların driver'a aktarıldığı tipli kuyruk. Yapıcıda (new) dışarıdan alınır, böylece environment hangi mailbox'ın kullanılacağını kontrol eder.int num_transactionsveevent done: Üretilecek işlem sayısı ve bitiş sinyali.doneevent'i, üretim tamamlandığında-> doneile tetiklenir.virtual task run()(taban): Bir döngüdenum_transactionskadartxn = new()yapar,assert(txn.randomize())ile kısıtlamalara uygun rastgele değerler üretir vegen2drv.put(txn)ile kuyruğa koyar.randomizebaşarısız olursa$fatalile durur.ALU_Corner_Generator: Taban sınıftan türetilir;super.new(mbx, num)ile mailbox'ı miras alır.- Köşe değer dizisi:
logic [7:0] corners [] = '{0, 1, 8'h7F, 8'h80, 8'hFE, 8'hFF}ile kritik operand değerleri tanımlanır. - İç içe
foreach+for: Tüm operand-a × operand-b × opcode kombinasyonları taranır. Kaydırma işlemlerindecorners[j] > 7olan durumlarcontinueile atlanır; bu,c_shift_rangekısıtlamasıyla çakışmayı önler. randomize() with {...}: Operand ve opcode değerleri satır içi kısıtlamayla sabitlenerek tam istenen kombinasyon üretilir.
Önemli Noktalar
run()metodununvirtualolması kalıtımın anahtarıdır; environment aynıgenreferansı üzerinden hem rastgele hem yönlendirilmiş üreticiyi çalıştırabilir (polymorphism).-> doneevent'i ile senkronizasyon: Environment, üretimin bittiğini bu event'i bekleyerek anlar; aksi halde simülasyon erken sonlanabilir veya gereksiz beklenir.- Yönlendirilmiş testte solver çakışmasından kaçınma: Geçersiz shift kombinasyonlarını
continueile atlamak,randomize() withçağrısının başarısız olmasını engeller. - Mailbox'ın dışarıdan enjekte edilmesi (dependency injection), generator'ı test ortamından bağımsız ve yeniden kullanılabilir kılar.
- Köşe değer taraması, saf rastgeleliğin kaçırabileceği sınır durumlarını garanti altına alır; rastgele ve yönlendirilmiş yaklaşımlar birbirini tamamlar.