8.1继承
8.2蓝图模式
8.3类型向下转换和虚方法
例8.11 基类和派生类
class Transaction;
rand bit[31:0] src;
virtual function void display(input string prefix="");
$display("%sTransaction: src=%0d", prefix, src);
endfunction
endclass
class BadTr extends Transaction;
bit bad_crc;
virtual function void display(input string prefix="");
$display("%sBadTr: bad_crc=%b", prefix, bad_crc);
super.display(prefix);
endfunction
endclass
例8.12 将一个扩展类的句柄拷贝成基类句柄
Transaction tr;
BadTr bad;
bad = new(); // 构建BadTr扩展对象
tr = bad; // 基类句柄指向扩展对象
$display(tr.src); // 显示基类对象的变量成员
tr.display(); // 调用BadTr::display
当需要决定调用哪个虚方法的时候,sv根据对象的类型,而非句柄的类型来决定调用什么方法;前提是方法加上了virtual
子类句柄可以直接赋值给父类句柄;
父类句柄指向子类对象时,可以用$cast,将父类句柄转换为子类句柄;
深拷贝:如之前所述,使用两个函数 copy和copy_data;次方法每次克隆时都会创建一个新的对象;当你想重用一个现有的对象而不是分配一个新的对象的时候,下示方法奏效;
class Transaction;
virtual function Transaction copy(Transaction to = null);
if (to == null) begin
copy = new();
// 创建新对象
end else begin
copy = to;
// 或者使用现有对象
copy_data(copy);
end
endfunction
endclass
class BadTr extends Transaction;
virtual function Transaction copy(Transaction to = null);
BadTr bad;
if (to == null) begin
bad = new();
// 创建一个新对象
end else begin
assert($cast(bad, to));
// 重用已有对象
end
copy_data(bad); // 复制数据域
return bad;
endfunction
endclass BadTr
Ps:这里的句柄to应该是指向子类对象的父类句柄;
8.4抽象类和纯虚方法:
抽象类:使用virtual关键词进行定义,是一种可以被扩展但是不能被直接实例化的类;
纯虚方法:是一种没有实体的方法原型;
一个由抽象类扩展而来的类只有在所有虚方法都是实体的时候才能被例化;
例8.26 使用纯虚方法的抽象类
virtual class BaseTr:
static int count; // 需要创建的实例数
int id; // 唯一的事务id
function new();
id = count++;
// 每一个对象对应一个ID
endfunction
pure virtual function bit compare(input BaseTr to);
pure virtual function BaseTr copy(input BaseTr to = null);
pure virtual function void display(input string prefix = "");
endclass:BaseTr
例8.27 Transaction类扩展了抽象类
class Transaction extends BaseTr;
rand bit [31:0] src, dst, crc,data[8];
extern virtual function bit compare(input BaseTr to);
extern virtual function BaseTr copy(input BaseTr to = null);
extern virtual function void copy_data(input Transaction copy);
extern virtual function void display(input string prefix = "");
extern function new();
endclass
例8.28 Transaction方法的实现
function bit Transaction::compare(input BaseTr to);
Transaction tr;
assert($cast(tr, to));
// 检查to是否为正确类型
return ((this.src == tr.src) &&
(this.dst == tr.dst) &&
(this.crc == tr.crc) &&
(this.data == tr.data));
endfunction:compare
function BaseTr Transaction::copy(input BaseTr to = null) :
Transaction cp;
if (to == null) cp = new();
else cp = $cast(cp, to);
copy_data(cp);
return cp;
endfunction
function void Transaction::copy_data(Transaction copy);
copy.src = src;
copy.dst = dst;
copy.data = data;
copy.crc = crc;
endfunction
function void Transaction::display(input string prefix = "");
$display("Transaction %s id=%d src=%x, dst=%x, crc=%x", prefix, id, src, dst, crc);
endfunction:display
function Transaction::new();
super.new();
endfunction:new
Basetr不能直接用来创建对象;Transaction对所有的纯虚方法都有实体定义,所以可以在测试平台中使用它;
8.5回调函数
计分板:包含一个将输入的事物转换成期望值的传输函数、用来保存这些值的内存空间以及一个进行比较的子程序。一个处理器的设计需要一个参考模型来预测期望输出,而对期望值和实际值的比较可能会在仿真的末尾进行;
8.6参数化的类
在sv中,可以为类增加一个数据类型参数,并在声明类句柄的时候指定类型。
参数化的类
class Stack #(type T = int);
local T stack[100]; // 保存数据值
local int top;
function void push(input T i);
// 从顶部压栈
stack[++top] = i;
endfunction: push
function T pop();
// 从顶部出栈
return stack[top--];
endfunction
endclass: Stack
使用: Stack #(new type) rStack