SV_10_面向对象编程(OOP)的类
摘要: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
浙公网安备 33010602011771号