System Verilog OOP 學習筆記


1、OOP術語

a.類(class):包含變量和子程序(函數或者任務)的基本構建塊。
b.對象(object):類的一個實例。
c.句柄(handle):指向對象的指針。
d.屬性(property):存儲數據變量。
e.方法(method):任務或者函數中操作變量的程序性代碼。
f.原型(prototype):程序的頭,包括程序名、返回類型和參數列表。程序體則包含了執行代碼。

類是對象的一個模板,其內部定義了數據和方法。對象是類的一個例化和實現。

注:《SystemVerilog驗證 測試平台編寫指南》中使用 變量(variable)和程序(routine),而沒有使用OOP中的屬性(property)和方法(method)。

2、用戶使用對象的三個步驟:
  a.定義類:

1 class packet;
2 ...
3 endclass:packet
4 
5 class long_packet;
6 ...
7 endclass:long_packet

  b.在module、class、function、task等地方聲明對象:

1 packet my_packet;
2 packet packet_array[32];
3 long_packet my_l_packet;

對象標識符(my_packet/packet_array/my_l_packet)是例化該對象的句柄(指向對象的指針)。當該對象被創建的時候,該句柄有效,默認情況下句柄將為空(null)。

  c.通過構造函數new創建對象的例化
通過new這個構造函數給對象分配內存空間,並且把入口地址賦給對象的句柄:
 1 my_packet=new(168);

2 my_l_packet=new(); 

例5.1 簡單的Transaction類

 1 class Transaction;
 2 bit [31:0] addr,crc,data[8];
 3 
 4 function void display;
 5 $display("Transaction:%h",addr);
 6 endfunction:display
 7 
 8 function void calc_crc;
 9 crc=addr^data.xor;
10 endfunction:calc_crc
11 
12 endclass:Transaction

 

3、在哪里定義類?
program、module、package中。或者在這些塊之外的任何地方。

例5.2 Class in a package

1 //File abc.svh
2 package abc;
3 calss Transaction;
4 //Class body
5 endclass
6 endpackage

例5.3 Importing a package in program

1 program automatic test;
2 import abc::*;
3 Transaction tr;
4 
5 //Test code    
6 endprogram

sv中,激勵對象不斷的被創建並且用來驅動DUT,檢查結果。最后這些對象所占用的內存可以被釋放。以供新的對象使用。

例5.4 聲明和使用一個句柄
 1 Transaction tr;//聲明一個句柄

2 Tr=new(); //為 Transaction對象分配空間 

注:1、調用new函數例化一個對象,即在為該對象申請一個新的內存塊來保存對象的變量。
2、new除了分配內存外,還初始化變量。default 二值為0,四值為X。
3、new函數不能有返回值,因為構造函數是返回一個指向類的對象的句柄,其類型就是本身。

例5.4 簡單的用戶定義的new()函數

1 class Transaction;
2 logic [31:0] addr,crc,data[8];
3 
4 function new;
5 addr = 3;//固定值
6 data= '{default:5};//crc未定義,默認值為X
7 endfunction
8 endclass

例5.5 一個帶有參數的new函數

 1 class Transaction;
 2 logic [31:0] addr,crc,data[8];
 3 
 4 function new(logic [31:0] a=3,d=5);
 5 addr = a;
 6 data = '{default:5};//crc未定義,默認值為X
 7 endfunction
 8 endclass
 9 
10 initial begin
11 Transaction tr;
12 tr = new.(.a(10));//a=10,d uses default of 5 tr=new(10);
13 end

sv如何知道調用哪個new()函數,取決於賦值操作符左邊的句柄類型。tr是 Transaction的句柄,索引會調用 Transaction的new函數。
例5.6 調用正確的new函數

 1 class Transaction;
 2 logic [31:0] addr,csm,data[8];
 3 endclass:Transaction
 4 
 5 class Driver;
 6 Transaction tr;
 7 function new();//Driver's new function
 8 tr = new();//Call the Transaction new function
 9 endfunction
10 endclass:Driver

new()和new[]的區別
調用new()函數僅創建了一個對象,而new[]操作則建立一個含有多個元素的數組。
new()可以使用參數設置對象的值,而new[]只需使用一個數值來設置數組的大小。

通過聲明一個句柄來創建一個對象

例5.7 為多個對象分配地址

1 Transaction t1,t2;//聲明兩個句柄
2 t1=new();    //為第一個 Transaction對象分配地址
3 t2=t1;    //t1和t2都指向該對象
4 t1=new();    //為第2個 Transaction對象分配地址

注:最后t2指向第一次分配的對象,t1指向第二次分配的對象。

對象的解除分配(deallocation)
垃圾回收就是一種自動釋放不在被引用的對象的過程,sv分辨對象不再被引用的辦法就是記住指向它的句柄的數量。當最后一個句柄不再引用某個對象了,sv就釋放該對象的空間。
例5.8 創建多個對象

1 Transaction t;//創建一個句柄
2 t=new();    //分配一個新的 Transaction
3 t=new();    //分配第二個,並且釋放第一個t
4 t=null;    //解除分配第二個

對對象使用“.”符號來引用變量和子程。
直接訪問變量會限制以后對代碼的修改,因此OOP規定只能通過對象的公有方法訪問對象的變量。
例5.9 使用對象的變量和子程序

1 Transaction t;    //聲明一個 Transaction句柄
2 t=new();    //創建一個 Transaction對象
3 t.addr=32'h42;    //設置變量的值
4 t.display();    //調用一個子程序

i++和++i區別:
i++:先引用后增加,先在i所在的表達式中使用i的當前值,后讓i加1

++i:先增加后引用,先讓i加1,然后在i所在的表達式中使用i的新值


靜態屬性與方法
1、每一個類的例化(也就是一個對象)都擁有它自身每個變量的復制,因此OOP規定只能通過對象的公有方法訪問對象的變量。

2、 對象1:變量1,變量2...
對象2:變量1,變量2...
對象1 和 對象2 自身成員變量不和其他對象共享。

3、類的靜態屬性是存在類中的,而不是在每個類的對象中,在類中,使用靜態static方式聲明的屬性可以被多個對象共享。

例5.10 含有一個靜態變量的類

 1 class Transaction;
 2 static int count=0;    //已創建的對象的數目
 3 int id;    //實例的唯一標志
 4 function new();
 5 id=count++;    //設置標志,count遞增
 6 endfunction
 7 endclass
 8 
 9 Transaction t1,t2;
10 initial begin
11 t1=new();    //第一個實例,id=0,count=1
12 t2=new();    //第二個實例,id=1,count=2
13 $display("Second id=%d,count=%d",t2.id,t2.count);
14 end

例5.11 類的作用域操作符 ::

1 class Transaction;
2 static int count=0;    //創建的對象數
3 ...
4 endclass
5 
6 initial begin
7 run_test();
8 $display("%d transaction were creat",Transaction::count);//引用靜態句柄
9 end

靜態變量的初始化
靜態變量通常在聲明時初始化,不能簡單的在類的構造函數中初始化靜態變量,因為每一個新的對象都會調用構造函數。

類的方法——也就是類的作用域定義的內部task或者function

例5.13 類中的方法

 1 class Transaction;
 2 bit [31:0] addr,crc,data[8];
 3 function void display();
 4 $display("@%0t:TR addr=%h,crc=%h",$time,addr,crc);
 5 $write("\tdata[0-7]=");
 6 foreach(data[i]) $write(data[i]);
 7 $display();
 8 endfunction
 9 endclass
10 
11 class PCI_Tran;
12 bit [31:0] addr,data;
13 function void display();
14 $display("@%0t:PCI:addr=%h,data=%h",$time,addr,data);
15 endfunction
16 endclass
17 
18 Transaction t;
19 PCI_Tran pc;
20 
21 initial begin
22 t=new();//創建一個 Transaction對象
23 t.display();//調用 Transaction的方法
24 pc=new();//創建一個PCI事務
25 pc.display();//調用PCI事務的方法
26 end

塊外方法聲明
//在開始處添加關鍵字extern,將整個方法移至類定義后面,並在方法名前面加上類名和::作用域操作符。

 1 class Transaction;
 2 bit [31:0] addr,crc,data[8];
 3 extern function void display();
 4 endclass
 5 
 6 function void Transaction::display();
 7 $display("@%0t:TR addr=%h,crc=%h",$time,addr,crc);
 8 $write("\tdata[0-7]=");
 9 foreach(data[i]) $write(data[i]);
10 $display();
11 endfunction

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM