目录
摘要:SV引入了面向对象的类数据;类允许通过对象句柄动态地创建、删除、赋值和访问对象,类提供了继承和抽象类建模,从而为对象带来了多态性。
- Objects
- Object members
- Constructors
- Static class members
- Assignments
- Inheritance and subclasses
- this and super
- Data hiding and encapsulation
- Constant class properties
- Abstract classes and virtual methods
- Class scope resolution operator ::
- Parameterized classes
1. 对象
一个类定义了一个数据类型,对象是该类的一个实例,使用对象时,首先声明该类类型的变量(包含对象句柄),然后创建该类的对象(使用new函数),并将其赋值给句柄;
1 class A;
2 A a;
3 a = new();
2. 对象成员
对象的数据字段可以用实例名来限定类属性名。因此,对象内的任何数据字段都称为对象成员
3. 对象方法
对象方法是对对象成员进行操作以完成一些有意义的完整功能的函数和任务。他们是对对象成员的访问。
1 program class_t;
2 class packet;
3 // members in class
4 integer size;
5 integer payload [];
6 integer i;
7 // Constructor
8 function new (integer size);
9 begin
10 this.size = size;
11 payload = new[size];
12 for (i=0; i < this.size; i ++) begin
13 payload[i] = $random;
14 end
15 end
16 endfunction
17 // Task in class (object method)
18 task print ();
19 begin
20 $write("Payload : ");
21 for (i=0; i < size; i ++) begin
22 $write("%x ",payload[i]);
23 end
24 $write("\n");
25 end
26 endtask
27 // Function in class (object method)
28 function integer get_size();
29 begin
30 get_size = this.size;
31 end
32 endfunction
33 endclass
34
35 packet pkt;
36
37 initial begin
38 pkt = new(5);
39 pkt.print();
40 $display ("Size of packet %0d",pkt.get_size());
41 end
42
43 endprogram
44
45 //compile result
46 Payload : 12153524 c0895e81 8484d609 b1f05663 06b97b0d
47 Size of packet 5
4. 构造函数
- 构造函数使用关键字new实现;
- 构造函数不返回值;
- 构造函数可以接收参数;
- 每个类只允许有一个构造函数。
1 `define PRINT task print (); \
2 begin \
3 $write("Size is %0d\n",this.size); \
4 end \
5 endtask
6
7 program class_t;
8 // Class with constructor, with no parameter
9 class A;
10 integer size;
11 // Constructor
12 function new ();
13 begin
14 this.size = 0;
15 end
16 endfunction
17 // Task in class (object method)
18 `PRINT
19 endclass
20 // Class with constructor, with parameter
21 class B;
22 integer size;
23 // Constructor
24 function new (integer size);
25 begin
26 this.size = size;
27 end
28 endfunction
29 // Task in class (object method)
30 `PRINT
31 endclass
32
33 // Class without constructor
34 class C;
35 integer size;
36 task set_size(integer size);
37 begin
38 this.size = size;
39 end
40 endtask
41 // Task in class (object method)
42 `PRINT
43 endclass
44
45 A a;
46 B b;
47 C c;
48
49 initial begin
50 a = new();
51 b = new(5);
52 c = new();
53 a.print();
54 b.print();
55 c.print();
56 end
57
58 endprogram
59
60 //compile result
61 Size is 0
62 Size is 5
63 Size is x
5. 静态类成员
静态类的成员在所有实例中享有相同的值,对改变的反应也是相同的.
1 `define PRINT task print (); \
2 begin \
3 $write("%s -> Size is %0d\n",this.name, this.size); \
4 end \
5 endtask
6
7 program class_static;
8 // Class with constructor, with no parameter
9 class A;
10 // Make size as static
11 static integer size;
12 string name;
13 // Constructor
14 function new (string name);
15 begin
16 this.name = name;
17 this.size = 0;
18 end
19 endfunction
20 // Increment size task
21 task inc_size();
22 begin
23 this.size ++;
24 $write("%s -> size is incremented\n",this.name);
25 end
26 endtask
27 // Task in class (object method)
28 `PRINT
29 endclass
30
31 A a,b,c;
32
33 initial begin
34 a = new("A");
35 b = new("B");
36 c = new("C");
37 a.inc_size();
38 a.print();
39 b.print();
40 c.print();
41 c.inc_size();
42 a.print();
43 b.print();
44 c.print();
45 end
46
47 endprogram
48
49 //compile result
50
51 A -> size is incremented
52 A -> Size is 1
53 B -> Size is 1
54 C -> Size is 1
55 C -> size is incremented
56 A -> Size is 2
57 B -> Size is 2
58 C -> Size is 2
6. 常量类成员
const声明的变量具有只读属性,不可写入;
- 全局常量(global):只能在声明中进行赋值;
- 实例常量(instance):声明中不赋值,但后续的赋值只能在类构造函数中执行一次
1 `define PRINT task print (); \
2 begin \
3 $write("%s -> Size is %0d\n",this.name, this.Lsize); \
4 $write("%s -> Size is %0d\n",this.name, this.Gsize); \
5 end \
6 endtask
7
8 program class_constant;
9 class A;
10 const integer Gsize = 64; // constant value
11 const integer Lsize;
12 string name;
13 // Constructor
14 function new (string name);
15 begin
16 this.name = name;
17 this.Lsize = 100; // only one assignment in new
18 end
19 endfunction
20 // This is not allowed
21 task modify();
22 begin
23 // This is wrong
24 //this.Lsize ++;
25 // This is wrong
26 //this.Gsize ++;
27 end
28 endtask
29
30 `PRINT
31 endclass
32
33 A a;
34
35 initial begin
36 a = new("A");
37 a.print();
38 end
39
40 endprogram
41
42 //compile result
43
44 A -> Size is 100
45 A -> Size is 64
7. 赋值
- 对象之间的赋值与变量之间的赋值相同,且该种赋值是浅复制,不复制任何嵌套对象;
- 为了进行完全的深赋值,需要构建copy任务;
1 program class_copy;
2
3 class A ;
4 integer j = 5;
5 task print();
6 begin
7 $display("j is %0d",j);
8 end
9 endtask
10 endclass
11
12 class B ;
13 integer i = 1;
14 A a = new;
15 task print();
16 begin
17 $display("i is %0d",i);
18 a.print();
19 end
20 endtask
21 // custom deep copy task
22 task copy(ref B bb);
23 begin
24 bb = new this;
25 bb.a = new this.a;
26 end
27 endtask
28 endclass
29
30 initial begin
31 B b1,b2,b3;
32 $display("Testing shallow copy");
33 b1 = new; // Create an object of class B
34 b1.print();
35 b2 = new b1; // Create an object that is a copy of b1
36 b2.print();
37 b2.i = 10; // i is changed in b2, but not in b1
38 b2.a.j = 50; // change a.j, shared by both b1 and b2
39 b2.print();
40 b1.print(); // Updated due to shallow copy
41 // Now do a deep copy
42 $display("Testing deep copy");
43 b1.copy(b3) ; // Create an object that is a deep copy of b1
44 b3.print();
45 b3.i = 100; // i is changed in b3, but not in b1
46 b3.a.j = 500;// j is changes in b3, but not in b1
47 b3.print();
48 // i and J should not change due to deep copy
49 b1.print();
50 end
51
52 endprogram
53
54 //compile result
55 Testing shallow copy
56 i is 1
57 j is 5
58 i is 1
59 j is 5
60 i is 10
61 j is 50
62 i is 1
63 j is 50
64 Testing deep copy
65 i is 1
66 j is 50
67 i is 100
68 j is 500
69 i is 1
70 j is 50
8. 继承和子类
- 继承:SV的OOP可以实现从基类中继承并在子类中扩展其功能的能力;
- 类的继承不会改变类定义,但新的子类可以包含基类的所有属性和方法;
- 继承实现的类可以选择性地添加额外的属性和方法。
- 基类被继承的方法可以在子类中被重写;
1 program class_inherit;
2
3 class A ;
4 integer j = 5;
5 task print();
6 begin
7 $display("j is %0d",j);
8 end
9 endtask
10 endclass
11
12 class B extends A;
13 integer i = 1;
14 // Override the parent class print
15 task print();
16 begin
17 $display("i is %0d",i);
18 $display("j is %0d",j);
19 end
20 endtask
21 endclass
22
23 initial begin
24 B b1;
25 b1 = new;
26 b1.print();
27 end
28
29 endprogram
30
31 //compile result
32
33 i is 1
34 j is 5
9. super关键字调用
- super关键字可以用来在派生类调用父类的属性;
- 当父类的属性已被重写,且不能直接访问时,有必要使用super。
1 program class_super;
2
3 class A ;
4 integer j;
5 function new();
6 begin
7 j = 10;
8 end
9 endfunction
10 task print();
11 begin
12 $display("j is %0d",j);
13 end
14 endtask
15 endclass
16
17 class B extends A;
18 integer i = 1;
19 function new();
20 begin
21 // call the parent new
22 super.new(); // constructor chaining
23 $display("Done calling the parent new");
24 i = 100;
25 end
26 endfunction
27 // Override the parent class print
28 task print();
29 begin
30 $display("i is %0d",i);
31 $display("Call the parent print");
32 super.print();
33 end
34 endtask
35 endclass
36
37 initial begin
38 B b1;
39 b1 = new;
40 b1.print();
41 end
42
43 endprogram
44
45 //compile result
46
47 Done calling the parent new
48 i is 100
49 Call the parent print
50 j is 10
10. 数据隐藏和封装(encapsulation)
- 默认情况下,类的所有方法和成员都可以用句柄从类外访问;
- 如果想限制访问,可以将变量声明为local,protected;
local:父类可见,子类和外部不可见;
protected:父类,子类可见,外部不可见;
static:父类,子类,外部可见。
1 program class_data_hiding;
2 class A;
3 integer data;
4 local integer addr;
5 protected integer cmd;
6 static integer credits;
7 function new();
8 begin
9 data = 100;
10 addr = 200;
11 cmd = 1;
12 credits = 10;
13 end
14 endfunction
15 task printA();
16 begin
17 $write ("value of data %0d in A\n", data);
18 $write ("value of addr %0d in A\n", addr);
19 $write ("value of cmd %0d in A\n", cmd);
20 end
21 endtask
22 endclass
23
24 class B extends A;
25 task printB();
26 begin
27 $write ("value of data %0d in B\n", data);
28 // Below line will give compile error
29 //$write ("value of addr %0d in B\n", addr);
30 $write ("value of cmd %0d in B\n", cmd);
31 end
32 endtask
33 endclass
34
35 class C;
36 A a;
37 B b;
38 function new();
39 begin
40 a = new();
41 b = new();
42 b.data = 2;
43 end
44 endfunction
45 task printC();
46 begin
47 $write ("value of data %0d in C\n", a.data);
48 $write ("value of data %0d in C\n", b.data);
49 // Below line will give compile error
50 //$write ("value of addr %0d in C\n", a.addr);
51 //$write ("value of cmd %0d in C\n", a.cmd);
52 //$write ("value of addr %0d in C\n", b.addr);
53 //$write ("value of cmd %0d in C\n", b.cmd);
54 end
55 endtask
56 endclass
57
58 initial begin
59 C c = new();
60 c.a.printA();
61 c.b.printB();
62 c.printC();
63 $write("value of credits is %0d\n",c.a.credits);
64 $write("value of credits is %0d\n",c.b.credits);
65 c.a.credits ++;
66 $write("value of credits is %0d\n",c.a.credits);
67 $write("value of credits is %0d\n",c.b.credits);
68 c.b.credits ++;
69 $write("value of credits is %0d\n",c.a.credits);
70 $write("value of credits is %0d\n",c.b.credits);
71 end
72
73 endprogram
74
75 //compile result
76
77 value of data 100 in A
78 value of addr 200 in A
79 value of cmd 1 in A
80 value of data 2 in B
81 value of cmd 1 in B
82 value of data 100 in C
83 value of data 2 in C
84 value of credits is 10
85 value of credits is 10
86 value of credits is 11
87 value of credits is 11
88 value of credits is 12
89 value of credits is 12
11. 虚拟类
- 虚拟类包含虚方法;
- 所有的信息通常在方法声明的第一行可以找到:封装标准、参数的类型和数量,以及非必要的返回类型;
- 虚方法的所有版本(包括重写情况)对子类都是相同的。
- 普通类也可以声明为虚方法;
- 这种情况下的方法必须有实体;
1 program class_virtual;
2 // Virtual class for body of any driver
3 virtual class verif;
4 // This starts all the threads
5 virtual task startSim();
6 endtask
7 // This stops all the threads
8 virtual task stopSim();
9 endtask
10 // This prints all the stats
11 virtual task printStats();
12 endtask
13 // This check if driver is done or not
14 virtual function bit isDone ();
15 begin
16 isDone = 0;
17 end
18 endfunction
19 // set the driver config
20 virtual task setConfig(integer item, integer value);
21 endtask
22 virtual function integer getConfig(integer item);
23 begin
24 getConfig = 32'hDEAD_BEAF;
25 end
26 endfunction
27 endclass
28 // ethernet inherits verif
29 class ethernet extends verif;
30 integer min_frame_size;
31 integer max_frame_size;
32 function new();
33 begin
34 min_frame_size = 32'h40;
35 max_frame_size = 32'h200;
36 end
37 endfunction
38 task startSim();
39 begin
40 $write("Starting Simulation\n");
41 end
42 endtask
43 task stopSim();
44 begin
45 $write("Stopping Simulation\n");
46 end
47 endtask
48 task printStats();
49 begin
50 $write("Sent normal frames %d\n",100);
51 $write("Sent runt frames %d\n",1);
52 $write("Sent oversize frames %d\n",1);
53 end
54 endtask
55 function bit isDone();
56 begin
57 isDone = 1;
58 end
59 endfunction
60 task setConfig(integer item, integer value);
61 begin
62 case(item)
63 0 : min_frame_size = value;
64 1 : max_frame_size = value;
65 endcase
66 end
67 endtask
68 function integer getConfig(integer item);
69 begin
70 case(item)
71 0 : getConfig = min_frame_size;
72 1 : getConfig = max_frame_size;
73 default : begin
74 $write("Calling super.setConfig\n");
75 getConfig = super.getConfig(item);
76 end
77 endcase
78 end
79 endfunction
80 endclass
81
82 class ethernet2 extends ethernet;
83 integer min_ipg;
84 function new();
85 begin
86 min_ipg = 32'hc;
87 end
88 endfunction
89 task setConfig(integer item, integer value);
90 begin
91 case(item)
92 2 : min_ipg = value;
93 default : begin
94 $write("Calling super.setConfig\n");
95 super.setConfig(item,value);
96 end
97 endcase
98 end
99 endtask
100 function integer getConfig(integer item);
101 begin
102 case(item)
103 2 : getConfig = min_ipg;
104 default : begin
105 $write("Calling super.setConfig\n");
106 getConfig = super.getConfig(item);
107 end
108 endcase
109 end
110 endfunction
111 endclass
112
113
114 initial begin
115 ethernet2 eth = new();
116 eth.setConfig(0,32'h100);
117 eth.setConfig(2,32'h24);
118 $write ("Value of min_frame is %0x\n", eth.getConfig(0));
119 $write ("Value of max_frame is %0x\n", eth.getConfig(1));
120 $write ("Value of min_ipg is %0x\n", eth.getConfig(2));
121 $write ("Value of unknown is %0x\n", eth.getConfig(3));
122
123 eth.startSim();
124 while (eth.isDone() == 0) begin
125 #1;
126 end
127 eth.stopSim();
128 eth.printStats();
129 end
130
131 endprogram
132 //compile result
133 Calling super.setConfig
134 Calling super.setConfig
135 Value of min_frame is 100
136 Calling super.setConfig
137 Value of max_frame is 200
138 Value of min_ipg is 24
139 Calling super.setConfig
140 Calling super.setConfig
141 Value of unknown is deadbeaf
142 Starting Simulation
143 Stopping Simulation
144 Sent normal frames 100
145 Sent runt frames 1
146 Sent oversize frames 1
12. 多模块分写(Out-of-block)
多次引用,防止重复编译:`ifdef-`define-`endif
Header File
1 `ifndef CLASS_EXTERN_SVI
2 `define CLASS_EXTERN_SVI
3
4 class class_extern;
5 int address;
6 bit [63:0] data;
7 shortint crc;
8
9 extern function new();
10 extern task print();
11 endclass
12
13
14 `endif
Body File
1 `ifndef CLASS_EXTERN_SV
2 `define CLASS_EXTERN_SV
3
4 `include "class_extern.svi"
5
6 function class_extern::new();
7 this.address = $random;
8 this.data = {$random,$random};
9 this.crc = $random;
10 endfunction
11
12 task class_extern::print();
13 $display("Address : %x",address);
14 $display("Data : %x",data);
15 $display("CRC : %x",crc);
16 endtask
17
18 `endif
Program File
1 program class_exterm_prg;
2
3 `include "class_extern.sv"
4
5 class_extern c;
6
7 initial begin
8 c = new();
9 c.print();
10 $finish;
11 end
12
13 endprogram
1 //compile result
2 Address : 12153524
3 Data : c0895e818484d609
4 CRC : 5663