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

类的实例化和构造对象

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

sv_class class_1;

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

sv_class class_1 = new()

此时创建了对象。创建时,实例名=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

其输出结果是:

在这里插入图片描述

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

上面的例子想把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>;
static task/function <method_name>;
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

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

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

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值