System Verilog总结 第五章 面向对象编程基础

5.1概述
(1)面向对象编程(OOP):创建复杂的数据类型
                    调用函数:执行动作
                    使用事务:代替信号翻转
 (2)优点:高效,可靠,易维护,重复使用
5.2 考虑名词,而非动词
(1)测试平台的结构
         发生器:创建事务,并传给下一级
         驱动器:和设计进行对话
         监视器:捕获设计返回的事务
         计分板:将结果与预期结果进行对比
5.3 编写一个类
(1)通用数据包类:地址、CRC、数组
             两个子程序:输出数据包地址的函数;计算循环冗余校验码的函数
(2)类名:大写字母开头
         变量名:小写字母
5.4 在哪里定义类
(1)类定义:在program、module、package中,或者块之外的任何地方
(2)程序块:包含了测试代码的模块
(3)创建一个项目:将每个类保存在独立的文件中
         文件数目太大:使用包将相关的类和类型定义捆绑   (包与系统的其他部分独立,可单独编译)
                                  其他类应放到不同的文件中
5.5 OOP术语
(1)类:包含变量和子程序的基本结构块
         对象:类的实例
         句柄:指向对象的指针   通过声明句柄创建对象,一个句柄指向很多对象,只能指向一种类型,自动回收垃圾(基础分配)
                    不能回收一个被句柄引用的对象,,需设置所有句柄为null
         属性:存储数据的变量
         方法:任务和函数中操作变量的程序性代码
         原型:程序的头   (程序名、返回类型、参数列表)
5.6 创建新对象
(1)SV类:在运行中测试平台需要才创建
                     激励对象不断被创建,驱动DUT,检查结果
                     内存可被释放,供新对象使用
                     类使用前必须例化
                     句柄可以指向很多对象,一次一个
5.6.1 句柄
(1)声明、使用句柄
         Transaction tr;    //声明一个Transaction句柄
         Tr=new();           //分配空间
      Transaction对象变量:addr、crc、data
5.6.2 定制构造函数
(1)构造函数:分配内存、初始化变量 (变量默认:二值变量(0),四值变量(X)  可以通过自定义new函数设置默认值)
                           返回一个指向类对象的句柄,类型就是类本身
(2)new函数(构造函数):创建对象,无返回值
(3)自定义new函数
          调用哪个new函数:取决于赋值操作符左边的句柄类型
          避免在声明一个句柄的时候调用构造函数
5.6.4 new():创建一个对象,使用参数设置数值
         new[]:建立含有多个元素的数组,使用一个数值来设置数组的大小
5.7 对象的解除分配
(1)回收对象:最后一个句柄不在引用某个对象,释放空间
(2)创建多个对象:
         Transaction t;   //创建一个句柄
         t=new();           //分配第一个新的Transaction        地址放在t中
         t=new();           //分配第二个新的Transaction,并释放第一个t
         t=null;              //解除分配第二个
5.8 使用对象
(1)”.":引用变量和子程序
         t.addr=32'h42;   //设置变量值
         t.diaplay();         //调用子程序
(2)访问对象变量:对象共有方法,变量公有化
5.9 静态变量和全局变量
5.9.1 静态变量
(1)静态变量:在类中创建,被类的所有实例共享,使用范围:类中
(2)通过类名访问:类名+::
(3)在声明时初始化
(4)用途:类的每一个实例都需要从同一个对象获取信息,否则会造成内存浪费
(5)读写静态变量:创建静态方法   或   在第一个实例产生之前读写
5.10 类的方法
(1)方法(程序·):在类内定义task或function
                               自动存储
5.11 在类外定义方法
(1)原型定义(方法名和参数):放在类内,在开始处(function)前添加extern
        程序体:放在类后,类名::方法名
5.12 作用域规则
(1)类应当在program或module外的package中定义
         临时变量:在测试平台最内部的某处定义
         块内使用未声明变量,在程序块中有同名变量,类会使用程序块中的变量,调用函数会改变程序级变量的值:将类移入                 package中查找错误
          package Mistake;
               class Bad; ...  endclass
          endpackage
(2)this:将局部变量赋给类一级变量
           this.oname=oname;
5.13 在类内使用另一个类
(1)在类内使用另一个类:使用指向对象的句柄
          目的:重用和控制复杂度
(2)类越来越大:按逻辑分组   或   重新安排代码(继承)
5.13.2 编译顺序
(1)编译类(包含尚未定义的类):使用typedef声明一个类名
5.14 理解动态对象
每个对象都有一个句柄
5.14.1 将对象传递给方法
(1)调用方法时,传递的是对象的句柄,而非对象本身
(2)调用带有标量变量的方法+使用ref关键字:传递标量地址,修改标量变量的值
                                                    不使用          :标量的值复制到参数变量中,对参数变量的任何改变不影响原变量的值
5.14.2 在任务中修改句柄
(1)修改参数值,应在参数前加ref
5.14.3 在程序中修改对象
(1)为每个事务创建一个新的对象
    task generator();
           Transaction ta[10];
           foreach (ta[i])
               begin
               ta[i]=new();     //创建每一个对象
              Transaction(ta[i]);
              end
    endtask
  ta由句柄构成,需要在使用之前创建对象
5.15 对象的复制
目的:防止对象的方法修改原始对象的值,或在一个发生器中保留约束
5.15.1 使用new操作符复制一个对象
(1)new:创建一个新对象,复制现有对象的所有变量
                    不被调用
            若类中包含一个指向另一个类的句柄,只有最高一级的对象被复制,下层对象不复制
(2)使用new复制对象,不会调用内部的new函数
5.15.2 编写自己的简单复制函数  p126
5.15.3 编写自己的深层复制函数
5.15.4 使用流操作符从数组到打包对象,或者从打包对象到数组
(1)流操作符:传输字节:需将对象中的变量打包成一个字节数组
                           接收字节:解包到一个Transaction对象中
(2)编写自己的pack函数,仅打包所需成员变量
5.16 共有和私有
(1)OOP核心概念:把数据和相关方法封装成一个类
(2)类中:数据为私有      (防止其他类对内部数据成员的随意访问)
         SV中:所有成员为共有(除非标记为local或protected)
5.17 题外话
(1)将接口封装成一个事务类:保存数据及相关信息,将该对象传给测试平台其他部分
5.18 建立一个测试平台

第七章 面向对象编程的高级技巧指南
7.1 继承

(1)继承:从一个类得到一个新类,并共享其变量和子程序
         基类:原始类
         扩展类:新类
(2)事务基类:
         变量:源地址、目的地址、八个数据字、CRC变量(校验错误)
         子程序:显示内容、计算CRC
         将类中的子程序定义为virtual型,可以在扩展类中重新定义  (适用于所有任务和函数,除了new函数,因为new函数在对                  象创建时调用,无法扩展,始终基于句柄类型来调用new函数)
          super.crc   //super调用基类中的crc函数,不能super.super.crc多层调用
(3)OOP术语:
         属性:类的变量
         方法:任务 或 函数
         原始类:父类 或 超类
         扩展类:派生类 或子类
         基类:不从其他任何类派生得到的类
         子程序的原型:指明了参数列表、返回类型的第一行
(4)若基类构造函数(new)有参数,扩展类必须有一个构造函数,在构造函数的第一行调用基类的构造函数  p218
(5)指向基类的句柄可以指向派生类的对象
8.2 蓝图模式
(1)蓝图模式:改变发生器的行为,无需改变其类代码
(2)步骤:构建一个对象的蓝图,修改约束,甚至使用一个扩展对象替换它;随机化蓝图;赋值并将拷贝值发送给下游的事务                        处理器
         注:蓝图对象在一个地方构建(new函数),在另一个地方(run)使用,需要将构建与随机化分开
(3)copy:将它加到Transaction、BadTr类中
(4)执行的三个阶段:创建(Build)、运行(Run)、收尾(Wrap-up)
(5)扩展类与基类的约束名相同,扩展类约束会替代基类的约束
8.3 类型向下转换(downcasting)和虚方法
(1)使用$cast作类型向下转换
         类型向下转换(类型转换):将一个指向基类的指针转换成一个指向派生类的指针
(2)将一个基类对象拷贝到一个扩展类的句柄中时,会失败,因为有些属性仅在扩展类中,基类无
         当基类句柄确实指向一个派生类对象时是允许的。
(3)$cast(bad2,tr)    //检查句柄所指向的对象类型并拷贝。若成功,bad2就指向tr所引用的对象;失败,在仿真时报错
                   若源对象跟目的对象(扩展类)是同一类型,可以从基类句柄中拷贝扩展对象的地址给句柄。
        若作为任务,不匹配,报错;作为函数,不匹配,不报错,类型不兼容:0,兼容:非零
(4)虚方法
         句柄调用子程序:
         tr=bad;    //句柄->扩展对象
         决定调用哪个虚方法:根据对象类型
        不使用virtual:根据句柄类型(可能不是想要的结果)
(5)多态:让处理器能够对一个很大的地址空间寻址
         虚拟内存:程序的代码和数据可保存在内存中或磁盘上
          一个虚拟地址可以映射到一块RAM芯片上。
          处理器在程序运行时一定会找到代码和数据

         






 

你可能感兴趣的:(SV)