看中文版的《systemverilog验证》,总感觉云里雾里。尝试看看官方systemverilog教程,主要是因为页数少。
systemverilog官方文档,是《SystemVerilog 3.1a Language Reference Manual Accellera’s Extensions to Verilog®》。关键词是:SystemVerilog Accellera。建议不要看cadence、synopsys、mentor的文档;但是后续可以参考。
overview
tips
类的数据,叫属性;
类的function/task,叫方法;
codes
class Packet ;
//data or class properties
bit [3:0] command;
bit [40:0] address;
bit [4:0] master_id;
integer time_requested;
integer time_issued;
integer status;
// initialization
function new();
command = IDLE;
address = 41’b0;
master_id = 5’bx;
endfunction // new
// methods
// public access entry points
task clean();
command = 0; address = 0; master_id = 5’bx;
endtask
task issue_request( intdelay );
// send request to bus
endtask
function integer current_status();
current_status = status;
endfunction
endclass
objects(class instance)
tips
类的实例化,跟vhdl类似;但是跟verilog实例化不一样。是分两步骤完成的。
1. 类的声明;
2. 类的实例化;也叫构造函数,new。
3. 父类,又叫超类。所以,继承类里访问父类的属性时,会用super.new这样的方式。
codes
Packet p; // declare a variable of class Packet
p = new; // initialize variable to a new allocated object of the class Packet
class Packet;
integer command;
function new();
command = IDLE;
endfunction
endclass
静态变量
特点:
1. 静态变量,是父类和相关子类的共享变量。类的默认变量,一般都是非静态变量,是独立的,不可共享的;也就是说,静态变量是共用一片存储空间,只要父类或者相关子类对这个静态变量赋值,后续操作,都是基于变化后的变量进行操作的。个人理解,静态变量是全局变量;非静态变量是私有变量。
2. 静态变量的访问,只需要声明类;而不需要构造函数,即实例化。
classPacket ;
static integerfileId = $fopen( "data", "r" );
Packet p;
c = $fgetc( p.fileID );
静态方法
类似静态变量。
1. 能够被当前类及子类访问;存储空间是共享的。
2. 类只需要声明,不需要实例化;即可访问这个类中的静态方法。
3. 静态方法,不能访问非静态变量(以及非静态class属性和非静态方法)。
4. 静态方法,不能设置为虚拟方法,virtual。
class id;
static int current = 0;
static function int next_id();
next_id = ++current; // OK to access static class property
endfunction
endclass
this
- this只能应用于非静态的class method;
- this的用法,不太常用;但是很必要。一般是下述例子会用到;因为class的变量和function的变量是一样名称,用this.x来表示class的变量。
class Demo ;
integer x;
function new(integer x)
this.x = x;
endfunction
endclass
Assignment, re-naming and copying
注意下述两段代码的不同点。
1. 代码段1,只实例化了一个object;
2. 代码段2,实例化了两个object;p2复制了p1的class属性,包括变量和instance handles
Packet p1;
Packet p2;
p1 = new;
p2 = p1;
Packet p1;
Packet p2;
p1 = new;
p2 = new p1;
下例的行为,导致类A的变量j,成为共享变量。如果没有B b2 = new b1;
,而是B b2 = new;
;
那么类A的变量j和类B的变量a.j,应该是独立的。—此为个人理解,还未验证。
class A ;
integer j = 5;
endclass
classB ;
integer i = 1;
A a = new;
endclass
function integer test;
B b1 = new; // Create an object of class B
B b2 = new b1; // Create an object that is a copy of b1
b2.i = 10; // i is changed in b2, but not in b1
b2.a.j = 50; // change a.j, shared by both b1 and b2
test = b1.i; // test is set to 1 (b1.i has not changed)
test = b1.a.j; // test is set to 50 (a.j has changed)
endfunction
Inheritance and subclasses
虚拟方法
- 虚拟方法,可以支持method的override;方法名称一样的话,距离越近,方法名称一致的方法最优调用(注意,方法必须全部声明为virtual)。
- 方法未定义为虚拟属性;那么调用的方法,是基类的方法;而不是距离最近的类方法。
class BasePacket;
int A = 1;
int B = 2;
function void printA;
$display("BasePacket::A is %d", A);
endfunction : printA
virtual function void printB;
$display("BasePacket::B is %d", B);
endfunction : printB
endclass : BasePacket
class My_Packet extends BasePacket;
int A = 3;
int B = 4;
function void printA;
$display("My_Packet::A is %d", A);
endfunction: printA
virtual function void printB;
$display("My_Packet::B is %d", B);
endfunction : printB
endclass : My_Packet
BasePacket P1 = new;
My_Packet P2 = new;
initial begin
P1.printA; // displays 'BasePacket::A is 1'
P1.printB; // displays 'BasePacket::B is 2'
P1 = P2; // P1 has a handle to a My_packet object
P1.printA; // displays 'BasePacket::A is 1'
P1.printB; // displays 'My_Packet::B is 4' – latest derived method
P2.printA; // displays 'My_Packet::A is 3'
P2.printB; // displays 'My_Packet::B is 4'
end
纯虚方法
在父类里定义个方法的原型,没有内容。
具体实际需求,不清楚。
多态
多态的概念引入,针对的是类的句柄可以改变吧?!这个是个人理解,待确认。
假设:
1. 基类是BasePacket,子类是EtherPacket、TokenPacket、GPSPacket。
2. 另外子类,有virtual方法,send、receive、print。
BasePacket packets[100];
EtherPacket ep = new; // extends BasePacket
TokenPacket tp = new; // extends BasePacket
GPSPacket gp = new; // extends EtherPacket
packets[0] = ep;
packets[1] = tp;
packets[2] = gp;
经过如上假设和代码设计,packets[1].send()访问的是TokenPacket类的send方法。
Class scope resolution operator ::
class Outer;
int outerProp;
local int outerLocalProp;
static int outerStaticProp;
static local int outerLocalStaticProp;
class Inner;
function void innerMethod(Outer h);
outerStaticProp = 0;
// Legal, same as Outer::outerStaticProp
outerLocalStaticProp = 0;
// Legal, nested classes may access local's in outer class
outerProp = 0;
// Illegal, unqualified access to non-static outer
h.outerProp = 0;
// Legal, qualified access.
h.outerLocalProp = 0;
// Legal, qualified access and locals to outer class allowed.
endfunction
endclass
endclass