String İşlemleri
Gün 1: SystemVerilog'a Giriş ve Veri Tipleri | String manipülasyonları ve dönüşüm metodları
⭐⭐Repo Önerisi: ClueLogic'in geliştirmiş olduğu generic bir SystemVerilog kütüphanesi var. Bu kütüphanede string işlemleriyle ilgili çok güzel fonksiyonlar mevcut.
İncelemek isterseniz: ClueLib
Bu derste SystemVerilog'un yerleşik string tipini ve onun zengin metodlarını öğreneceğiz: birleştirme, uzunluk, karşılaştırma, karakter erişimi, alt string, harf dönüşümü ve sayı çevrimleri.
SystemVerilog string Tipi
Verilog'da metinler ham bit vektörlerinde saklanırken, SystemVerilog ayrı bir string tipi sunar. Bu tip dinamik uzunluktadır (boyut yönetimi otomatiktir) ve yazılım dillerine benzer pratik metodlar içerir. Doğrulama dünyasında log mesajları, paket isimleri ve rapor üretimi için sürekli kullanılır.
Temel İşlemler ve Metodlar
- Birleştirme (concatenation):
{str1, " ", str2}sözdizimiyle stringler birleştirilir. - Uzunluk:
.len()karakter sayısını verir. - Karşılaştırma:
==doğrudan eşitlik;.icompare()büyük/küçük harf duyarsız karşılaştırma yapar (0ise eşit). - Karakter erişimi:
.getc(i)i'inci karakterin ASCII kodunu okur,.putc(i, c)o konumdaki karakteri değiştirir. - Alt string:
.substr(a, b)a ile b indeksleri arasındaki (her ikisi dahil) parçayı verir. - Harf dönüşümü:
.toupper()ve.tolower().
Sayı Dönüşümleri ve Formatlama
String ↔ sayı çevrimi doğrulamada sık gerekir:
- String'den sayıya:
.atoi()(decimal),.atohex()(hex),.atobin()(binary),.atooct()(octal) - Sayıdan string'e:
.itoa(val),.hextoa(val) - Formatlı string:
$sformatf(...), tıpkı$displaygibi biçim belirteçleri kullanır ama sonucu ekrana basmak yerine birstringolarak döndürür.
Kaynak Kod
// =============================================================================
// GUN 1 - Konu 7: String Manipulasyonlari
// =============================================================================
module string_manipulasyonlari;
string str1, str2, str3;
string str_arr [$];
initial begin
$display("=== SystemVerilog String Islemleri ===\n");
// --- Temel Atama ve Birlestirme ---
$display("--- Temel Islemler ---");
str1 = "Merhaba";
str2 = "SystemVerilog";
str3 = {str1, " ", str2, "!"}; // Birlestirme (concatenation)
$display(" str1 = %s", str1);
$display(" str2 = %s", str2);
$display(" Birlesik = %s", str3);
// --- Uzunluk ---
$display("\n--- String Uzunlugu ---");
$display(" \"%s\" uzunluk = %0d", str3, str3.len());
// --- Karsilastirma ---
$display("\n--- Karsilastirma ---");
str1 = "ABC";
str2 = "abc";
$display(" \"%s\" == \"%s\" -> %0b", str1, str2, (str1 == str2));
$display(" icompare (buyuk/kucuk harf duyarsiz) -> %0d", str1.icompare(str2));
// icompare: 0 ise esit, negatifse str1 < str2
// --- Alt String ve Karakter Erisimi ---
$display("\n--- Karakter Erisimi ---");
str1 = "SystemVerilog";
$display(" String = %s", str1);
$display(" str[0] = %c (ASCII: %0d)", str1.getc(0), str1.getc(0));
$display(" str[6] = %c", str1.getc(6));
// Karakter degistirme
str1.putc(0, "s"); // S -> s
$display(" putc(0,'s') -> %s", str1);
// --- Substring ---
$display("\n--- Alt String (substr) ---");
str1 = "Dogrulama_Muhendisi";
str2 = str1.substr(0, 8); // 0'dan 8'e kadar (dahil)
$display(" \"%s\".substr(0,8) = \"%s\"", str1, str2);
// --- Buyuk/Kucuk Harf ---
$display("\n--- Harf Donusumu ---");
str1 = "Hello World";
$display(" toupper = %s", str1.toupper());
$display(" tolower = %s", str1.tolower());
// --- Sayi Donusumleri ---
$display("\n--- String <-> Sayi Donusumu ---");
str1 = "255";
$display(" \"%s\".atoi() = %0d (decimal)", str1, str1.atoi());
str1 = "FF";
$display(" \"%s\".atohex() = %0d (hex -> decimal)", str1, str1.atohex());
str1 = "11111111";
$display(" \"%s\".atobin() = %0d (bin -> decimal)", str1, str1.atobin());
str1 = "377";
$display(" \"%s\".atooct() = %0d (oct -> decimal)", str1, str1.atooct());
// Sayidan stringe
begin
int val = 42;
str1.itoa(val);
$display(" itoa(%0d) = \"%s\"", val, str1);
str2.hextoa(val);
$display(" hextoa(%0d) = \"%s\"", val, str2);
end
// --- Formatli String ---
$display("\n--- $sformatf (Formatli String) ---");
begin
int addr = 'hABCD;
int data = 'hDEAD;
string msg;
msg = $sformatf("Adres: 0x%04h, Veri: 0x%04h, Zaman: %0t", addr, data, $time);
$display(" %s", msg);
end
// --- String Kuyruk ---
$display("\n--- String Kuyruk ---");
str_arr = '{"Generator", "Driver", "Monitor", "Scoreboard"};
$display(" Testbench Bilesenleri:");
foreach (str_arr[i])
$display(" [%0d] %s", i, str_arr[i]);
$display("\n=== String Islemleri Sonu ===");
$finish;
end
endmodule
Kodun Açıklaması
str3 = {str1, " ", str2, "!"};birleştirme işlemini gösterir;"Merhaba", boşluk,"SystemVerilog"ve"!"tek bir string'e birleştirilir.str3.len()birleşik string'in karakter sayısını döndürür.- Karşılaştırma bölümünde
str1 = "ABC",str2 = "abc"için(str1 == str2)farklı oldukları için0verir;str1.icompare(str2)ise büyük/küçük harf duyarsız olduğundan0(eşit) döndürür. str1.getc(0)ilk karakterin ASCII kodunu verir;%cile karakter,%0dile sayısal kodu basılır.str1.putc(0, "s");ilk karakteri (S) küçüksile değiştirir.str1.substr(0, 8)"Dogrulama_Muhendisi"içinden 0–8 indeksleri arasını ("Dogrulama") çıkarır; her iki uç da dahildir.str1.toupper()vestr1.tolower()orijinal string'i değiştirmeden büyük/küçük harfe çevrilmiş bir kopya döndürür.- Sayı dönüşümleri:
"255".atoi()→ 255,"FF".atohex()→ 255,"11111111".atobin()→ 255,"377".atooct()→ 255. Dört farklı tabandaki gösterimin aynı değere karşılık gelmesi öğreticidir. str1.itoa(val)42sayısını"42"string'ine;str2.hextoa(val)ise onaltılık gösterimine çevirir. Bu metodlar sonucu çağrıldıkları string değişkenine yazar.$sformatf("Adres: 0x%04h, ...", addr, data, $time)biçimli bir metnimsgdeğişkenine üretir;$displaygibi formatlar ama ekrana basmaz.- Sonda
str_arrstring kuyruğu'{"Generator", "Driver", "Monitor", "Scoreboard"}ile doldurulupforeachile listelenir.
Önemli Noktalar
stringtipi dinamik uzunluktadır; Verilog'daki gibi sabit bit vektörü genişliği ayırmanıza gerek yoktur.==büyük/küçük harf duyarlıdır; harf durumunu yok saymak istiyorsanız.icompare()kullanın (0eşitliği gösterir).getc/putcindeksleri 0 tabanlıdır; sınır dışı erişimden kaçının.substr(a, b)aralığında hemahembdahildir..toupper()/.tolower()yeni bir string döndürür, orijinali değiştirmez; oysa.putc(),.itoa(),.hextoa()çağrıldıkları değişkeni yerinde günceller.atoi/atohex/atobin/atoocttaban seçimini siz yaparsınız; girdinin tabanına uygun metodu seçmek doğru sonucu garanti eder.- Log ve rapor üretiminde
$displayyerine$sformatfile string oluşturup saklamak, mesajları yeniden kullanmayı ve scoreboard'a iletmeyi kolaylaştırır. str1.getc(i)birbytedöndürür; bu yüzden%cile karakter,%0dile ASCII kodu basabilirsiniz. Tek bir karakteri string'e çevirmek içinstring'(str1.getc(i))ya da$sformatf("%c", ...)kullanın.substr(a, b)çağrısındab < aise ya da indeksler sınır dışıysa boş string döner, hata vermez. Bu sessiz davranış, ayrıştırma (parsing) kodunda beklenmedik boş sonuçlara yol açabilir;len()ile sınır kontrolü yapın.
String Metodları Özet Tablosu
| Metod | Açıklama | Örnek | Sonuç |
|---|---|---|---|
len() |
Karakter sayısı | "abc".len() |
3 |
getc(i) |
i. karakterin ASCII kodu | "abc".getc(1) |
98 (b) |
putc(i, c) |
i. karakteri değiştirir (yerinde) | s.putc(0, "X") |
"Xbc" |
substr(a, b) |
a..b arası (dahil) | "SystemVerilog".substr(6, 12) |
"Verilog" |
toupper() / tolower() |
Harf dönüşümü (kopya döndürür) | "Abc".toupper() |
"ABC" |
compare(s) / icompare(s) |
Duyarlı / duyarsız karşılaştırma | "abc".icompare("ABC") |
0 (eşit) |
atoi() / atohex() / atobin() / atooct() |
Metinden sayıya | "FF".atohex() |
255 |
atoreal() |
Metinden gerçek sayıya | "3.14".atoreal() |
3.14 |
itoa(v) / hextoa(v) / bintoa(v) / octtoa(v) / realtoa(r) |
Sayıdan metne (yerinde yazar) | s.hextoa(255) |
"ff" |
{a, b} |
Birleştirme | {"a", "b"} |
"ab" |
==, !=, <, > |
Karşılaştırma operatörleri | "abc" < "abd" |
1 |
$sformatf(fmt, ...) |
Biçimli string üretir | $sformatf("%0d", 42) |
"42" |
Doğrulamada String Nerede Karşımıza Çıkar?
- Bileşen isimleri ve log etiketleri: UVM'de her bileşenin bir
string namevardır veget_full_name()hiyerarşik yolu string olarak döndürür. - Komut satırı argümanları:
$value$plusargs("TEST=%s", test_name)ile test adı string olarak alınır (Gün 7'de göreceksiniz). - Enum ↔ string dönüşümü:
op.name()ile enum değerini metne çevirip raporlarda kullanırız. - Dosya okuma / yazma:
$fgets,$sscanfile dosyadan satır okuyup ayrıştırmak (örneğin beklenen değerler dosyası) tamamen string işlemidir.
Sık Yapılan Hatalar
toupper()sonucunu kullanmamak:str1.toupper();tek başına yazılırsa orijinal değişmez; sonuç yeni bir string'tir.str1 = str1.toupper();yazın.atoi()'ye hex metin vermek:"FF".atoi()→0döner (sayı olmayan ilk karakterde durur). Tabana uygun metodu seçin.- Sayıyı
%sile basmak:$display("%s", 42)anlamsız karakter üretir. Önce$sformatfile biçimlendirin ya da doğru belirteci kullanın. - Sınır dışı
getc/putc:str.getc(str.len())son karakterden bir sonrasıdır;0döndürür.putcsınır dışına yazmak ise hiçbir etki yapmaz.
Kendinizi Deneyin
"192.168.1.10"string'ini noktalardan ayırıp dört sayıyıintolarak elde eden bir döngü yazın (ipucu:getcile"."karakterini arayıpsubstr+atoikullanın)."deadbeef".atohex()sonucunu%hile yazdırın. Ardından aynı değerihextoaile geri string'e çevirin; büyük/küçük harf ne oldu?- Bir
stringkuyruğundaki tüm isimleri{prefix, "_", name}biçiminde birleştirip yeni bir kuyruk üretin. $sformatf("%-10s|", "ab")ve$sformatf("%10s|", "ab")çıktılarını karşılaştırın;-işaretinin hizalamaya etkisini not edin.
Hızlı Kontrol: str.icompare(other) hangi değeri döndürdüğünde string'ler eşittir?
0 döndürdüğünde eşittir. Negatif değer str'nin sözlük sırasında daha önce, pozitif değer daha sonra geldiğini gösterir. == operatörü ise büyük/küçük harfe duyarlıdır; harf durumunu yok saymak için icompare gerekir.