【路科V0】systemVerilog基础9——类的继承

继承和子类

描述子类继承父类的关键词extends

之前定义过的类Packet,可以进一步扩展构成一个它的子类LinkedPacket。

通过extends,子类LinkedPacket继承于其父类Packet,包括继承其所有的成员(变量/方法)。

class LinkedPacket extends Packet;//父类名Packet,子类名LinkedPacket
//在子类继承父类的成员变量和方法基础上,定义新的成员next和成员函数get_next()
    LinkedPacket next ;
    function LinkedPacket get_next();
        get_next = next;
    endfunction
endclass

成员覆盖

        子类可以继承父类的成员,所以LinkedPacket对象中也包含Packet类的成员。
        由此,父类句柄可以指向子类的对象。

LinkedPacket lp = new ;
Packet p = lp;

注意: 

        父类句柄如果指向子类对象 ,那么将无法访问子类的成员变量(这是由于父类句柄可访问范围所限制的)

注意: 

        虽然在子类中可以新定义子类成员 ,但如果子类中声明了与父类同名的成员(变量/方法),那么子类对其同名成员的访问都将指向子类,而父类的成员将被隐藏。

示例: 

        下面的代码经过简化,父类和子类只保留了各自同名成员变量i和成员变量get 

//创建父类Packet
class Packet;
    integer i = 1;
    function integer get() ;
        get = i ;
    endfunction
endclass
//创建子类LinkedPacket
class LinkedPacket extends Packet;
    integer i = 2;
    function integer get() ;
        get = -i ;
    endfunction
endclass
//创建一个子类对象,并将句柄赋值给lp
LinkedPacket lp = new;
Packet p = lp; //将子类句柄lp赋值给父类句柄p
//虽然子类句柄和父类句柄此时都指向同一个子类,但是
//由于句柄类型,限制了其访问范围
//所以通过父类句柄p,可以访问的成员变量和成员方法都是父类范围的
j = p.i; // j = 1,不是2
i = p.get() : //i = 1,不是-1或者-2

      虽然子类句柄和父类句柄此时都指向同一个子类,但是由于句柄类型,限制了其访问范围
,所以通过父类句柄p,可以访问的成员变量和成员方法都是父类范围的 ,而不是子类范围。 

        如果使用子类句柄lp,去访问同名成员,访问的都是子类范围的。

子类继承父类成员方法——super

        由于继承的关系,如果子类成员方法想要继承父类成员方法,那么可以在子类代码中通过super关键词来访问当前对象的父类成员。 

        super是用来访问当前对象其父类的成员。
        尤其子类的成员如果与父类的成员同名,那么需要使用super来指定访问其父类成员,而非默认的子类成员。

class Packet; //父类
    integer value;
    function integer delay () ;
        delay = value * value;
    endfunction
endclass

class LinkedPacket extends Packet; //子类integer value;
    function integer delay () ;
        delay = super.delay ()+ value * super.value;
//子类通过super,访问与父类同名的delay函数,和同名成员变量value
    endfunction
endclass

        super对于类的继承和对域作用范围的指定都有帮助 。

验证环境中的案例

 这个验证环境已经有了generator和driver的两个组件:

  • generator(激励产生器):是单纯产生激励数据,
  • driver(驱动器):是单纯使用激励数据来发送时序激励。

     这种单一职责的划分,使得各个组件的任务十分明确,那么一个简单环境构建就有了。

        在验证环境中,描述测试环境的部分由test来实现。按照test要求来生成激励,并且传递给driver组件由generator实现。在最后,通过激励的数据内容,将其按照时钟周期,将数据驱动到硬件接口上的是driver。最后激励数据通过信号的方式,抵达了DUT边界端口。

        如果要将数据发送到DUT,那么需要有以下的基本元素和数据处理方法,我们将它们封装到Transaction类中。

        从generator产生的激励中,包括source、dst、data和crc等变量,将它们和有关的处理函数calc_crc()和display()封装在 Transaction类中。  driver获取这个类之后,将从中提取变量值,再将其驱动到DUT端口上面。

class Transaction;
    rand bit [31:0] src, dst, data[8] ;//随机成员变量
    bit [31 :0] crc; //二次处理后的成员数据
    virtual function void calc_crc () ;
        crc = src ^ dst ^ data.xor;
    endfunction
    virtual function void display(input string prefix="");
        $display("%sTr: src=%h, dst=%h, crc=%h",prefix,src, dst,crc);
    endfunction
endclass

测试DUT的稳定性 

         如果我们为了测试DUT的稳定性,需要加入一些错误的数据来测试DUT的反馈,但我们又想尽量复用原有的验证环境(也包括已经定义好的类),那么我们就可以考虑使用继承的方式来新创建一个类BadTr。

// BadTr是Transaction的子类,Transaction是BadTr的父类。
class BadTr extends Transaction;
    rand bit bad_crc;
// BadTr重新定义了函数calc_crc()和display(),
//而在其内部通过super来索引父类的同名函数。
    virtual function void calc_crc;
        super.calc_crc() ; // 计算crc
        if (bad_crc) crc = ~crc; //破坏crc
    endfunction

    virtual function void display(input string prefi x="");
        $write("%sBadTr: bad_crc=%b, ", prefix, bad_crc);
        super.display () ;
    endfunction

endclass : BadTr

        在定义了这两个激励类型以后,它们将可以被激励发生器产生,并送往驱动器。

观察以下继承关系图,可以看到:

        BadTr是Transaction的子类,Transaction是BadTr的父类。

        BadTr重新定义了函数calc_crc()和display(),而在其内部通过super来索引父类的同名函数。

        如果创建一个子类对象,那么该对象的空间可以划分父类成员的空间子类成员的空间。即便父类和子类有同名的成员变量和成员方法,但是它们的空间都是独立的。

        需要注意的是,如果是父类的句柄指向了子类的对象,那么它访问的空间将会受到父类句柄可访问范围的影响,只能访问父类成员 

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SystemVerilog的听课学习笔记,包括讲义截取、知识点记录、注意事项等细节的标注。 目录如下: 第一章 SV环境构建常识 1 1.1 数据型 1 四、二值逻辑 4 定宽数组 9 foreach 13 动态数组 16 队列 19 关联数组 21 枚举型 23 字符串 25 1.2 过程块和方法 27 initial和always 30 function逻辑电路 33 task时序电路 35 动态 静态变量 39 1.3 设计例化和连接 45 第二章 验证的方法 393 动态仿真 395 静态检查 397 虚拟模型 403 硬件加速 405 效能验证 408 性能验证 410 第三章 SV组件实现 99 3.1 接口 100 什么是interface 101 接口的优势 108 3.2 采样和数据驱动 112 竞争问题 113 接口中的时序块clocking 123 利于clocking的驱动 133 3.3 测试的开始和结束 136 仿真开始 139 program隐式结束 143 program显式结束 145 软件域program 147 3.4 调试方法 150 第四章 验证的计划 166 4.1 计划概述 166 4.2 计划的内容 173 4.3 计划的实现 185 4.4 计划的进程评估 194 第五章 验证的管理 277 6.1 验证的周期检查 277 6.2 管理三要素 291 6.3 验证的收敛 303 6.4 问题追踪 314 6.5 团队建设 321 6.6 验证的专业化 330 第六章 验证平台的结构 48 2.1 测试平台 49 2.2 硬件设计描述 55 MCDF接口描述 58 MCDF接口时序 62 MCDF寄存器描述 65 2.3 激励发生器 67 channel initiator 72 register initiator 73 2.4 监测器 74 2.5 比较器 81 2.6 验证结构 95 第七章 激励发生封装: 209 5.1 概述 209 5.2 的成员 233 5.3 继承 245 三种型权限 protected/local/public 247 this super 253 成员覆盖 257 5.4 句柄的使用 263 5.5 包的使用 269 第八章 激励发生的随机化 340 7.1 随机约束和分布 340 权重分布 353 条件约束 355 7.2 约束块控制 358 7.3 随机函数 366 7.4 数组约束 373 7.5 随机控制 388 第九章 线程与通信 432 9.1 线程的使用 432 9.2 线程的控制 441 三个fork...join 443 等待衍生线程 451 停止线程disable 451 9.3 线程的通信 458 第十章 进程评估:覆盖率 495 10.1 覆盖率型 495 10.2 功能覆盖策略 510 10.3 覆盖组 516 10.4 数据采样 524 10.5 覆盖选项 544 10.6 数据分析 550 第十一章 SV语言核心进阶 552 11.1 型转换 552 11.2 虚方法 564 11.3 对象拷贝 575 11.4 回调函数 584 11.5 参数化的 590 第十二章 UVM简介 392 8.2 UVM简介 414 8.3 UVM组件 420 8.4 UVM环境 425
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值