story · 2020年05月11日

SystemVerilog Classes Part-I

SystemVerilog引入了面向对象(object-oriented)的类(class) 抽象数据类型。

可以通过对象句柄动态创建,删除,赋值和访问对象。

类中包含了数据和对该数据进行操作的子例程(functions 和tasks)。类中的数据称为类属性(properties),其子例程称为方法(methods)。类属性和方法一起定义了某种对象的内容和功能。

Objects

对象(object )是类的实例(instance )。

对象的使用首先需要声明对象所属的类的类型(包含object handle),然后创建该类的对象(使用new函数),并对其进行赋值和访问。

program class_t;
  class packet;
     // members in class
     integer size;
     integer payload [];
     integer i;
     // Constructor
     function new (integer size);
       begin
         this.size = size;
         payload = new[size];
         for (i=0; i < this.size; i ++) begin
           payload[i] = $random;
         end
       end
     endfunction
     // Task in class (object method)
     task print ();
       begin
         $write("Payload : ");
         for (i=0; i < size; i ++) begin
           $write("%x ",payload[i]);
         end
         $write("\n");
       end
     endtask
     // Function in class (object method)
     function integer get_size();
       begin
         get_size = this.size;
       end
     endfunction
   endclass

   packet pkt;

   initial begin
     pkt = new(5);
     pkt.print();
     $display ("Size of packet %0d",pkt.get_size());
   end

endprogram

输出

Payload : 12153524 c0895e81 8484d609 b1f05663 06b97b0d
Size of packet 5

Static class members

当一个对象在多个地方使用并且我们希望该对象的某个成员在所有实例中具有相同的值。假设我们在第一个对象实例中修改了变量,并且我们希望将值反映在其余实例中。为此,SystemVerilog提供了静态类成员。

前面有static的任何成员都成为静态(static)类成员

`define PRINT task print (); \
  begin \
    $write("%s -> Size is %0d\n",this.name, this.size); \
 end \
endtask

program class_static;
  // Class with constructor, with no parameter
  class A;
     // Make size as static
     static integer size;
     string name;
     // Constructor
     function new (string name);
       begin
         this.name = name;
         this.size = 0;
       end
     endfunction
     // Increment size task
     task inc_size();
       begin
         this.size ++;
         $write("%s -> size is incremented\n",this.name);
       end
     endtask
     // Task in class (object method)
     `PRINT
   endclass

   A a,b,c;

   initial begin
     a = new("A");
     b = new("B");
     c = new("C");
     a.inc_size();
     a.print();
     b.print();
     c.print();
     c.inc_size();
     a.print();
     b.print();
     c.print();
   end

endprogram

输出

A -> size is incremented
 A -> Size is 1
 B -> Size is 1
 C -> Size is 1
 C -> size is incremented
 A -> Size is 2
 B -> Size is 2
 C -> Size is 2

constant class members

类属性可以像任何其他SystemVerilog变量一样通过const声明read-onlyconstants 变量只能在声明时或者类构造函数中赋值。

`define PRINT task print (); \
   begin \
      $write("%s -> Size is %0d\n",this.name, this.Lsize); \
      $write("%s -> Size is %0d\n",this.name, this.Gsize); \
   end \
endtask

program class_constant;
  class A;
     const integer Gsize = 64; // constant value
     const integer Lsize;
     string name;
     // Constructor
     function new (string name);
       begin
         this.name = name;
         this.Lsize = 100; // only one assignment in new
       end
     endfunction
     // This is not allowed
     task modify();
       begin
         // This is wrong
         //this.Lsize ++;
         // This is wrong
         //this.Gsize ++;
       end
     endtask

     `PRINT
   endclass

   A a;

   initial begin
     a = new("A");
     a.print();
   end

endprogram

输出

A -> Size is 100
A -> Size is 64

Assignments

将一个对象复制给另一个对象与将变量复制给另一个变量相同。在对象复制中,副本是shallow copy,因为它不会复制任何嵌套对象。

要进行deep copy,需要自定义task。 下面的示例显示了如何进行自定义复制。

program class_copy;

  class A ;
    integer j = 5;
    task print();
      begin
        $display("j is %0d",j);
      end
    endtask
  endclass

  class B ;
    integer i = 1;
    A a = new;
    task print();
      begin
        $display("i is %0d",i);
        a.print();
      end
    endtask
    // custom deep copy task
    task copy(ref B bb);
      begin
        bb = new this;
        bb.a = new this.a;
      end
    endtask
  endclass

  initial begin
    B b1,b2,b3;
    $display("Testing shallow copy");
    b1 = new; // Create an object of class B
    b1.print();
    b2 = new b1; // Create an object that is a copy of b1
    b2.print();
    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
    b2.print();
    b1.print(); // Updated due to shallow copy
    // Now do a deep copy
    $display("Testing deep copy");
    b1.copy(b3) ; // Create an object that is a deep copy of b1
    b3.print();
    b3.i = 100; // i is changed in b3, but not in b1
    b3.a.j = 500;// j is changes in b3, but not in b1
    b3.print();
    // i and J should not change due to deep copy
    b1.print();
  end

endprogram

输出

Testing shallow copy
 i is 1
 j is 5
 i is 1
 j is 5
 i is 10
 j is 50
 i is 1
 j is 50
 Testing deep copy
 i is 1
 j is 50
 i is 100
 j is 500
 i is 1
 j is 50

本文转载自公众号:芯片数字实验室
原文链接:https://mp.weixin.qq.com/s/y8bbYmnM7aNS\_VjTLrEUDA
未经作者同意,请勿转载!

推荐阅读

想了解更多内容,欢迎关注芯片数字实验室专栏
推荐阅读
关注数
12276
内容数
201
前瞻性的眼光,和持之以恒的学习~
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息