1.OOP的概念要素
1)Class(类):包含变量和方法的基本模块,是“软件”盒子。
2)Ojbect(对象):类的实例,,在SV中可以使用class来例化,是“软件”例化。
3)Handle(句柄):用来指向对象的指针,来索引对象的变量和方法。
4)Property(属性):在类中声明的存储数据的变量,和Verilog中的wire和reg一样。
5)Method(方法):类中可以使用task或者function来定义方法以便处理自身或者外部传入的数据。
2.第一个事务类(Transaction)
class Transaction;
bit [31:0] addr,crc,data[8];
function void display;
$display("Transaction: %h", addr);
endfunction
function void calc_crc;
crc = addr ^ data.xor;
endfunction
endclass
Transaction tr; //声明句柄
tr = new(); //创建对象
解析:B中类生成对象相当于module在做例化,所以不是只能例化一个,B错。
C中指向对象的句柄可以有很多个,C错。
D中wire和reg只能用于module,D错。答案是BCD
3.创建对象
1)创建对象就是开辟了新的内存空间,用来存放新的成员变量和方法。
2)创建对象时,可以通过构建函数new()或者自定义构建函数(constructor)来完成变量的初始化和其他初始操作,
class Transaction;
logic [31:0] addr,crc,data[8];
function new(); //function和new之间不可以加void,因为他不需要返回值
addr = 3;
foreach (data[i])
data[i] = 5;
endfunction
endclass
3)构建函数new()是系统预定义函数,不需要指定返回值,函数会隐式地返回例化后的对象指针。
例题
class Transaction;
logic [31:0] addr = 'h10;
logic [31:0] crc,data[8];
function new(logic [31:0] a= 3,d = 5);
addr = a;
foreach (data[i])
data[i] = d;
endfunction
endclass
initial begin
Transaction tr; //声明句柄
tr = new(10); //创建空间并给a赋值为10
end
在完成对tr的初始化后,tr.addr的值是多少?
解析:问题说的是初始化之后tr.addr的值是多少,最开始通过logic [31:0] addr = 'h10;开辟空间并赋值为'h10即16,此时还没有进行初始化,然后通过new(10)进行初始化,使a=10,即addr=10.所以初始化后tr.addr值为10.而a=3是默认数据,当没有new(10)而是new()时,即初始化但没赋值,则a为默认值3。
4.句柄的传递
最后t1指向第二个对象,t2指向第一个对象。
5.对象的销毁
即没有任何句柄指向的对象会被自动销毁。
例题
假设wd = new(1)所需要开辟1B的空间,那么在initial_2的display语句处,需要为对象例化开辟多少空间呢?
class word;
byte nb[];
function new (int n);
nb = new[n];
endfunction
endclass
initial begin:initial_1
word wd;
//automatic word wd;
for (int i; i<4; i++) wd = new(i);
end
initial begin:initial_2
#1ps
$display(“How many Bytes are allocated for word instances?”);
end
解析:for循环做了4次,所以4个对象,但句柄只有wd一个,所以前三个对象会被销毁,而new(4)需要的空间为4B.
若文中word wd改成automatic word wd,此时句柄为动态,执行后句柄会自动消失,此时没有句柄指向对象,对象都会被销毁,所以所需空间为0B.
5.句柄的使用
6.类的静态变量
1)class中默认都是动态变量,若想声明静态变量,需要添加关键字“static”。
2)如果在class中声明了静态变量,可以通过class::var进行引用,或者通过例化对象object.var进行引用。
3)无论例化了多少个对象,都可以共享同名的静态变量。
class Transaction
static int couunt = 0;//创建静态变量
int id;
function new();
id = count++;
endfunction
endclass
Transaction t1,t2;
initial begin
t1 = new();//这时id=0,count=1
t2 = new();//这时id=1,count=2
$display("Second id=%d,count=%d",t2.id,t2.count);//或者通过Transaction::count索引
end
7.静态方法
静态方法在自身内部可以声明并使用动态变量,但是不能使用类的动态成员变量。
class Transaction
static Config cfg;//创建静态变量
static int count = 0;
int id;
//通过静态方法来操作静态变量
static function void display_statics();
$display("Transaction cfg.mode=%s,count=%0d",cfg.mode.name(),count);
endfunction
endclass
Config cfg;
initial begin
cfg = new(MODE_ON);
Transaction::cfg = cfg;//静态变量赋值
Transaction::display_statics();//调用静态方法
end