类的方法
类中的程序也称为方法,也就是在类的作用域内定义的内部task或者function。
class Transaction;
bit [31:0] addr,crc,data[8];
function void display();
$display("@%0t: TR addr = %h,crc = %h",$time,addr,crc);
$write("\tdata[0-7]=");
foreach (data[i]) $write(data[i]);
$display();
endfunction
endclass
class PCI_Tran;
bit [31:0] addr,data;
function void display();
$display("@%0t: PCI: addr = %h,data = %h",$time,addr,data);
endfunction
endclass
module class_tb;
Transaction t;
PCI_Tran pc;
initial begin
t = new();
t.display();
pc = new();
pc.display();
end
endmodule
# @0: TR addr = 00000000,crc = 00000000
# data[0-7]= 0 0 0 0 0 0 0 0
# @0: PCI: addr = 00000000,data = 00000000
this是什么
当你使用一个变量名的时候,SV将先在当前作用域内寻找,接着坐在上一级作用域内寻找,直到找到该变量为止。这也是Verilog所采用的算法。但是如果你在类的很深的底层作用域,却明确的引用类一级的对象呢?这个时候需要使用到this。
class Scoping;
string oname;
function new(string oname);
this.oname = oname; //类变量 oname = 局部变量 oname
endfunction
endclass
在任务中修改句柄
一个常见的编码错误是当你想修改参数的值的时候,忘记在方法的参数前ref关键词,尤其是句柄。参数tr没有被声明为ref,所以在方法内部对tr的修改不会被调用该方法的代码看到。参数tr默认的信号方向是input。
错误的事务生成任务,句柄前缺少关键词ref
function void creat(Transaction tr); //错误,缺少ref
tr = new();
tr.addr = 42;
...
endfunction
Transaction t;
initial begin
creat(t);
$display(t.addr);
end
正确的事务发送器,参数是带有ref的句柄
function void creat(ref Transaction tr);
...
endfunction
在程序中修改对象
在测试平台中一个常见的错误是忘记为每个事务创建一个新的对象。
错误的发生器,只创建了一个对象。
task generator_bad(int n);
Transaction t;
t = new();
repeat (n) begin
t.addr = $random();
$display("sending addr = %h",t.addr); //每次打印的addr随机
transmit(t); //传输出去的addr相同
end
endtask
正确的产生器,创建多个对象
task generator_bad(int n);
Transaction t;
repeat (n) begin
t = new();
t.addr = $random();
$display("sending addr = %h",t.addr); //每次打印的addr随机
transmit(t); //传输出去的addr跟随打印的数据
end
endtask
句柄数组
在写测试平台的时候,可能需要保存并且引用许多对象。你可以创建句柄数组,数组的每一个元素指向一个对象。
task generator();
transmit tarray[10];
foreach (tarray[i])
begin
tarray[i] = new(); //创建每一个对象
transmit(tarray[i]);
end
endtask
对象的复制
使用new复制一个简单类
class Transaction;
bit [31:0] addr,crc,data[8];
endclass
Transaction src,dst;
initial begin
src = new; //创建第一个对象
dst = new src; //使用new操作符进行复制
end
这是一种简易复制,原对象的值被盲目地抄写到目的对象中。如果类中包含一个指向另一个类的句柄,那么只有最高一级的对象被new操作符复制,下层对象都不会被复制。
class Transaction;
bit [31:0] addr,crc,data[8];
static int count = 0;
int id;
Statistics stats;
function new;
stats = new();
id = count++;
endfunction
endclass
Transaction src,dst;
initial begin
src = new();
src.stats.startT = 42;
dst = new src;
dst.stats.startT = 96;
$display(src.stats.startT) //dst与src的startT值都指向96
end
深层次复制函数是通过调用类所包含的所有对象的copy函数。