• systemverilog学习 ---- 类(class)一


    sv还引入了面向对象编程OOP特性,通过类区分不同的单元,每个类都可以封装自己的数据成员和提供对外的操作方法。

    类是一种用户自定义的数据类型,其中包括数据(类的特性),运行在数据上的函数和任务。函数和任务叫做方法,两者都是类的成员。类允许动态的去创建、删除、赋值和访问通过对象的句柄。

    类声明

    以下的类有一个成员x和两个方法set,get。

    class sv_class;
      //class properties
      int x;
     
      //method-1
      task set(int i);
        x = i;
      endtask
     
      //method-2
      function int get();
        return x;
      endfunction
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    类的实例化和构造对象

    声明一个类数据的变量时:

    sv_class class_1;
    
    • 1

    此时class_1包含sv_class实例化的句柄(访问方法)

    sv_class class_1 = new()
    
    • 1

    此时创建了对象。创建时,实例名=new();new()方法会返回一个句柄。
    咱们来看一个简单示例,要调用类方法可以实例名.方法名。另外要注意的是,我们在类外并没有对类数据直接赋值,而是通过方法set对成员x进行赋值,可以保护数据

    module  argument_passing;
    
    int     x       ;
    int     y       ;
    int     z       ;
    
    //function to add two integers numbers
    function automatic int sum(const ref int x, y);
        x = x + y;
        return x+y;
    endfunction
    
    initial begin
        x = 20 ;
        y = 30 ;
        z = sum(x,y);
        $display("-------------------------------------------------");
        $display("\t Value of x = %0d", x);
        $display("\t Value of y = %0d", y);
        $display("\t Value of z = %0d", z);
        $display("-------------------------------------------------");
    end
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    其输出结果是:

    在这里插入图片描述

    this

    this关键字用来指向当前实例的性质和方法,说白了就是要对自身进行操作。当方法的参数名和成员名重复,编译器会困惑是谁??如下图所示,此时使用this可以解决这个问题。这个关键字使能使用在非静态的方法上。
    在这里插入图片描述

    class packet;
    
    // class properties
    bit [31:0]  addr    ;
    bit [31:0]  data    ;
    bit         write   ;
    string      pkt_type;
    
    //constructor
    function new(bit [31:0] addr, data, bit write, string pkt_type);
        addr = addr ;
        data = data ;
        write = write;
        pkt_type = pkt_type;
    endfunction
    
    // method to display class properties
    function void display();
        $display("==================================================");
        $display("\t addr = %0h", addr);
        $display("\t data = %0h", data);
        $display("\t write = %0h", write);
        $display("\t pkt_type = %0s", pkt_type);
        $display("==================================================");
    endfunction
    
    endclass
    
    module sv_constructor;
        packet pkt;
    
        initial begin
            pkt = new(32'h10, 32'hFF, 1, "GOOD_PKT");
            pkt.display();
        end
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    上面的例子想把addr = 32’h10,但是结果却是:
    在这里插入图片描述
    主要原因是new参数名和类的成员名重复,导致编译混乱,因此加上this:
    在这里插入图片描述
    其编译结果是:在这里插入图片描述

    类构造器(class Constructors)

    new函数叫做类构造函数。调用new方法时,编译器会分配内存,并且返回类句柄的地址(类似指针)。
    在这里插入图片描述
    分配内存,会初始化赋值,二值逻辑为0,四值逻辑为x。
    new操作没有返回值,每个类都有内建的new方法,当我们调用没有显式定义(即用户自己写new方法实现)的new方法时,将会调用默认的内建new方法。构造器可以用来初始化类的属性。如下图所示:
    在这里插入图片描述

    static members

    类成员可以用关键词static修饰,就成了静态成员,分为静态属性和静态方法。对于静态成员,多个实例会共享一份静态变量。注意,静态方法只能访问类的静态属性,访问非静态属性是不合法的,编译会报错,静态方法也不能用virtual修饰。声明结构如下:

    static <data_type> <property_name>;
    
    • 1
    static task/function <method_name>;
    
    • 1
    class packet;
       
      //class properties
      byte packet_id;
         
      //static property to keep track of number of pkt's created
      static byte no_of_pkts_created;
       
      //constructor
      function new();
        //incrementing pkt count on creating an object
        no_of_pkts_created++;
        packet_id = no_of_pkts_created;
      endfunction
       
      //method to display class prperties
      function void display();
        $display("--------------------------------------");
        $display("\t packet_id  = %0d",packet_id);
        $display("--------------------------------------");
      endfunction
    endclass
     
    module static_properties;
      packet pkt[3];
     
      initial begin
        foreach(pkt[i]) begin
          pkt[i] = new();
          pkt[i].display();
        end
      end 
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    输出结果为:
    在这里插入图片描述
    静态方法访问类的非静态变量会报错。
    在这里插入图片描述
    另外,静态属性和静态方法,可以直接通过没有构造的句柄访问,看下面实例,pkt类实例数组都使用了new方法,而p却没有完成构造方法,但它依然可以访问静态成员。很好理解,静态成员已经分配好了内存空间,我当然可以找到它,自动变量由于地址未知,就无法访问

    在这里插入图片描述
    其输出结果时:
    在这里插入图片描述

  • 相关阅读:
    给Python漫画分集标题下载工具开发Qt界面
    uniapp+vue3+ts+vite+echarts开发图表类小程序,将echarts导入项目使用的详细步骤,耗时一天终于弄好了
    建模助手 | “双减”落地一周年,建筑师说我也要减负
    Spring基础(3):复习
    Shiro721 反序列化漏洞(CVE-2019-12422)
    小白学习-ElasticSearch教程(5) -批量操作之bulk | 条件查询 | 其它查询
    ROS1云课→28机器人代价地图配置
    IT系统运维管理升级:谈一体化运维的优势
    【信号调理】ADC保护电路/ADC缓冲器
    【Linux常用命令11】Linux文件与权限详解
  • 原文地址:https://blog.csdn.net/weixin_45614076/article/details/126259598