SystemVerilog面向对象编程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

面向对象编程作为systemVerilog的关键,包含类的封装、继承和多态。将方法封装在类中供对象调用,通过类的继承可以实现基类和派生类中方法的调用和覆盖,从而在不同的子类中实现所需功能。


提示:以下是本篇文章正文内容,下面案例可供参考

一、类的封装、继承和多态

类的封装
声明数据成员和方法成员,并封装在类中,供对象调用其中方法。
类作为封装容器来定义和储存。
类的继承
比如,共有属性的大类cat和具有特定属性的小类black_cat、white_cat
使用extends来继承;
若子类重新定义了函数,在其内部通过super索引父类的同名函数。
在父类和子类中可以定义相同的变量和方法,在引用时按照句柄类型来确定作用域。
基类与派生类(父类和子类):
① 派生类中的约束会覆盖基类中约束,同名覆盖;
② 在约束中不允许调用方向为ref的函数,,使用const ref保证函数内部不被修改。
③ 基类中使用的virtual成员会被派生类继承;
④ 基类句柄可以指向派生类对象(由上到下转换),反过来不允许。
⑤ 对于类中方法的调用,需要注意句柄是基类的还是派生类,方法是否为虚方法;
⑥ 注意基类和派生类中的成员变量的作用域。
类的多态
多态也就是众多类中抽象出共性的一个方法,它在不同的子类中会表现出不一样的行为。

接下来通过大概过程来详细介绍类的用法:

1、创建对象

SV 中的class例化和Verilog 中的例化的区别:Verilog例化是静态的,即编译链接时就已经完成,而SV class例化是动态的,可以在仿真0时刻和其他任意时刻例化。
在这里插入图片描述
注意:类中定义的变量不能是wire和reg,也不能出现initial和always;即硬件世界的部分不能在软件世界中定义。
调用new( )创建对象时,系统的步骤:
系统开辟空间;
将开辟的空间分配给变量,进入new()函数对变量初始化。
退出new( )时,将当前对象的句柄返回。
注意:new()函数创建对象时,会为对象分配地址,将类中变量初始化(二值变量为0,四值变量为x)。

2、对象的销毁

SV采取自动回收空间的处理方式。当一个对象,在整个程序中没有任何一个地方再“需要”(没有句柄指向它)它时,便会被“销毁”,即回收其空间。

3、类的成员

在class中声明的变量默认是动态变量(这跟module恰恰相反),但可以用static来声明静态变量(可以看:静态变量和静态方法)。
注:在类里面声明一个接口的指针,必须要加virtual。
在这里插入图片描述
3.2 成员变量类型
类包含的成员变量,有以下三种类型:
Public 该成员在class内外部都可以访问,在派生类中可见。
Private 该成员只能在class内部访问,在派生类中不可见。
Protect 该成员只能在class内部访问,在派生类中可见。
3.1 成员的访问权限
为了提高类封装后的安全性,即类中的有些成员方法和变量不希望被外部或子类访问,就可以通过关键词修饰,设置变量和方法的访问权限:
默认情况是子类和外部都可以访问;
protected只有该类和子类可以访问,外部不可访问
local只有该类可以访问,子类和外部都不可访问
3.2 this 和 super的区别
有的时候我们会使用this 和 super调用成员变量和方法,this 和 super的区别在于:
this 会先在当前作用域中查找,如果当前作用中没有,则会去上一级作用域中查找,知道找到该变量为止;
super首先会先在该类的父类中查找。

4、类的继承

如果父类的构造函数有参数,那么子类必须有一个构造函数,而且必须在其构造函数的第一行调用父类的构造函数(super.new( ))。
在这里插入图片描述
对象创建时初始化的顺序:
1、子类的实例对象在初始化之前会先调用父类的构造函数;
2、当父类构造函数完成时,会将子类实例对象中各个成员变量按照他们定义时显式的默认值初始化;
在成员变量默认值赋予后,才会最后进入用户定义的new函数中执行剩余的初始化代码。

二、对象与句柄

1、对象:对象是类的一个实例。
2、句柄:指向对象的指针。
在程序执行时,可以在任何时刻为句柄创建对象,并将新的指针赋值给句柄;
在这里插入图片描述
用句柄实现动态类型转换:
在这里插入图片描述

三、虚方法

合法的动态类型转换::父类转换为子类(父类句柄指向子类对象)::为了使子类中方法对父类可见,通过将其定义为虚方法。
子类继承父类的成员变量和成员方法。默认情况下,子类中重写的方法对父类是不可见的。子类对象中,即有从父类继承而来的,也有子类扩展的方法和变量。而子类所扩展的方法默认对父类是不可见的。
要想子类重写父类的方法能被父类看到,那就需要虚方法。虚方法就是一个基本的多态结构。
在父类中使用virtual定义的方法和函数,父类句柄在指向子类对象时,可以动态索引到子类重写的子类方法。
通过在父类里定义虚方法(task or function),可以在当父类句柄调用一个方法时候,前提是若是这个句柄指向了子类对象,则调用的方法为子类的方法而不是父类的方法。
在这里插入图片描述

四、回调函数

在父类中为函数占位,但并没有写明函数具体操作,在子类调用该函数时才补充。
在这里插入图片描述
例如,
子类继承父类并完善方法:
在这里插入图片描述
在这里插入图片描述
在测试环境env中声明父类slave_driver句柄并实例化对象:
在这里插入图片描述
在测试中实例化环境env和子类err_driver,并用子类err_driver覆盖原来环境中是父类slave_driver,实现了类中方法的覆盖。
在这里插入图片描述

五、包package

用于解决类的归属问题
Package将软件(类、类型、方法等)封装在不同的命名空间。
Library是编译的产物,包含软件类型和硬件类型。
变量-方法-类-包-模块,之间的关系:
Include完成类在包中的封装;Import完成包中类的导入。
在这里插入图片描述


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值