Transaction Sınıfı
Gün 6: Bitirme Projesi - Bölüm 1 | ALU transaction paketi: constraint'ler ve metodlar
Transaction (işlem paketi), testbench içinde dolaşan tek bir ALU işlemini soyutlayan veri sınıfıdır. Generator onu üretir, driver pinlere sürer, monitor DUT'tan toplar ve scoreboard karşılaştırır; yani ALU_Transaction, tüm bileşenler arasında ortak konuşulan "dil"dir.
Transaction Nedir ve Neden Gereklidir
Sinyal seviyesinde düşünmek yerine, doğrulama dünyasında işlemleri nesne olarak ele alırız. Bir ALU_Transaction nesnesi tek bir ALU işleminin hem girişlerini hem de beklenen/gözlenen çıkışlarını taşır:
- Girişler (
randile rastgeleleştirilir):opcode,operand_a,operand_b - Çıkışlar (DUT'tan okunur):
result,flags,out_valid - Meta veri: Her işleme benzersiz bir
idve toplam sayacıcount
Bu sayede bir transaction, mailbox'lar üzerinden bileşenden bileşene tek parça halinde aktarılabilir.
Constraint'ler (Kısıtlamalar) ile Akıllı Rastgelelik
Saf rastgelelik genellikle ilginç durumları yeterince üretmez. Bu sınıf üç kısıtlama kullanır:
c_opcode_dist: İşlem kodlarının dağılımını ağırlıklandırır; toplama/çıkarma daha sık (:= 20), mantıksal işlemler daha seyrek seçilir.c_corner_cases: Operandların köşe değerlerini (0,255,8'h80) bilinçli olarak öne çıkarır; bunlar taşma/işaret hatalarının en sık görüldüğü değerlerdir.c_shift_range: Kaydırma işlemlerindeoperand_b'yi0-7aralığına sınırlar; çünkü 8-bit veride 8'den büyük kaydırma anlamsızdır.
Yardımcı Metotlar
display(): İşlemi okunabilir formatta basar; hata ayıklamada vazgeçilmezdir.copy(): Nesnenin derin bir kopyasını üretir. Driver, scoreboard'a transaction'ın kopyasını gönderir; böylece aynı nesnenin paylaşılmasından doğan referans hataları engellenir.
Kaynak Kod
// =============================================================================
// GUN 6 - Konu 2: Transaction (Islem) Paketi Sinifi
// =============================================================================
class ALU_Transaction;
// Islem kodlari (DUT ile uyumlu)
typedef enum logic [2:0] {
OP_ADD = 3'b000,
OP_SUB = 3'b001,
OP_AND = 3'b010,
OP_OR = 3'b011,
OP_XOR = 3'b100,
OP_NOT = 3'b101,
OP_SHL = 3'b110,
OP_SHR = 3'b111
} opcode_e;
// Rastgele giris degiskenleri
rand opcode_e opcode;
rand logic [7:0] operand_a;
rand logic [7:0] operand_b;
// Cikis degiskenleri (DUT'tan okunacak)
logic [15:0] result;
logic [3:0] flags;
logic out_valid;
// Meta veriler
int id;
static int count = 0;
// --- Kisitlamalar ---
constraint c_opcode_dist {
opcode dist {
OP_ADD := 20,
OP_SUB := 20,
OP_AND := 10,
OP_OR := 10,
OP_XOR := 10,
OP_NOT := 10,
OP_SHL := 10,
OP_SHR := 10
};
}
constraint c_corner_cases {
operand_a dist {
0 := 10,
[1:254] :/ 70,
255 := 10,
8'h80 := 10
};
operand_b dist {
0 := 10,
[1:254] :/ 70,
255 := 10,
8'h80 := 10
};
}
// Shift isleminde B sadece 0-7
constraint c_shift_range {
(opcode inside {OP_SHL, OP_SHR}) -> operand_b inside {[0:7]};
}
function new();
this.id = count++;
endfunction
function void display(string prefix = "");
$display(" %sTXN#%03d | %s | A=0x%02h | B=0x%02h | Res=0x%04h | Flags=%04b | V=%0b",
prefix, id, opcode.name(), operand_a, operand_b, result, flags, out_valid);
endfunction
function ALU_Transaction copy();
ALU_Transaction t = new();
t.opcode = this.opcode;
t.operand_a = this.operand_a;
t.operand_b = this.operand_b;
t.result = this.result;
t.flags = this.flags;
t.out_valid = this.out_valid;
t.id = this.id;
return t;
endfunction
endclass
Kodun Açıklaması
opcode_eenum'u:OP_ADD'denOP_SHR'a kadar 8 işlemilogic [2:0]olarak kodlar. Değerler DUT'takilocalparamopcode'larıyla birebir aynıdır, böylece doğrudan pinlere sürülebilir.randdeğişkenler:opcode,operand_a,operand_brastgeleleştirilebilir alanlardır.randomize()çağrıldığında kısıtlamalara uygun değerler üretilir.- Çıkış alanları:
result,flags,out_validrastgele değildir; DUT'tan veya referans modelden gelen değerlerle doldurulur. static int count: Tüm nesneler arasında paylaşılan sayaç.new()içindethis.id = count++ile her transaction'a artan benzersiz bir kimlik verilir.c_opcode_dist:distoperatörüyle opcode olasılık ağırlıklarını belirler (OP_ADD := 20gibi).c_corner_cases:operand_aveoperand_biçin:=(her değere ayrı ağırlık) ve:/(aralığa toplam ağırlık) operatörlerini birlikte kullanarak köşe değerleri öne çıkarır.c_shift_range:(opcode inside {OP_SHL, OP_SHR}) -> operand_b inside {[0:7]}ile koşullu (implication) kısıtlama uygular.copy(): Yeni bir nesne oluşturup tüm alanları tek tek kopyalar ve döndürür; sığ kopyalamanın yan etkilerinden kaçınır.
Önemli Noktalar
- Transaction enum'u DUT opcode'larıyla senkron olmalıdır; uyumsuzluk tüm karşılaştırmaları sessizce bozar.
assert(txn.randomize())her zaman kontrol edilmelidir; constraint'ler çözülemezse randomize başarısız olur ve sessizce yanlış veriyle devam edilmemelidir.copy()kullanımı kritiktir: Aynı nesne referansı birden çok bileşene gönderilirse, sonradan yapılan değişiklikler beklenen değeri bozabilir. Derin kopya bu tuzağı önler.distağırlıkları kapsamı (coverage) doğrudan etkiler; nadir senaryolara yeterli ağırlık vermek fonksiyonel kapsamı hızlandırır.c_shift_rangegibi koşullu kısıtlamalar, generator'daki yönlendirilmiş üretimle uyumlu olmalıdır; aksi halde solver çakışması (conflict) yaşanır.