SV 8 OOP高级

本文深入探讨了SystemVerilog(SV)中的面向对象编程(OOP)概念,包括继承、环境类、类型向下转换、虚方法、合成、抽象类、回调任务和参数化类的使用。通过具体的例子,解释了如何利用这些技术来创建复杂的类层次结构,特别是在事务处理和测试平台的构建中,如注入错误、事务复制和自定义回调以实现灵活的干扰注入。
摘要由CSDN通过智能技术生成


前言

怎样才能位总线事务创建于给可以注入错误并带有可变延时的复杂的类呢?
第一种方法:将所有东西放入一个大的、不分层的类,创建和理解简单,开发和调试费时。
第二种方法:合成,一个模块例化另一个模块,搭建层次化的测试平台。
第三种方法:**和原始类很相像的类,增加了一些新的变量和方法,继承!**允许从一个现存的类得到一个新的类并共享其变量和子程序。提供了可重用性。


1. 继承简介

1.1 事务基类

事务基类 含有一些变量和子程序;
变量包含:源地址、目的地址、八个数据字和校验错误用的CRC变量。
子程序包含:用于显示内容和计算CRC的子程序。

class Transaction;
   rand bit [31:0] src, dst,data[8];  // 随机变量
   bit [31:0] crc;  // 计算得到的CRC值
   
   virtual function void calc_crc;
      crc = src^dst^data.xor;
   endfunction
   
   virtual function void display(input string prefix = "");
       $display("%s TR: src=%h, dst=%h, crc=%h", prefix,src,dst,crc);
    endfunction 
endclass

在这里插入图片描述

1.2 Transaction 类的扩展

class badtr extends Transaction;
   rand bit bad_crc;
   
   virtual function void calc_crc;
      super.calc_crc();  // 计算正确的CRC
      if(bad_crc) crc = ~crc; //产生错误的CRC位
   endfunction
   
   virtual function void display(input string prefix = "");
       $write("%s badTR: src=%h, dst=%h, crc=%h", prefix,src,dst,crc);
       super.display();
    endfunction 
endclass

扩展类可以直接方位基类和其本身的所有变量,例如bad_crc。
SV不允许用类似 super.super.new 的方式进行多层调用,因为这种调用跨越了不同的层次,跨越了不同的边界,自然也违反了封装的规则。
virtual需要加在基类的任务和函数,除了new函数。因为new函数在对象创建时调用,所以无法扩展。

1.3 扩展类的构造函数

类的变量称为属性(property);
任务或者函数称为方法(method);
如果你的基类构造函数有参数,那么扩展类必须有一个构造函数而且必须在其构造函数的第一个调用基类的构造函数。

class Base1;
    int var;
    function new(input int var); //带有参数的构造函数
         this.var = var;
    endfunction
endclass

class extended extends Base1;
   function new(input int var); // 需要参数
      super.new(var);    // 必须是new函数的第一个行
      ..
   endfunction
endclass

1.4 OOP规则

OOP的规则:指向基类(Transaction)的句柄也可以用来指向派生类(Badtr)的对象,因为句柄tr 可以引用变量src、dst、crc、data以及函数cala_crc,所以不做修改直接将Badtr对象送入driver。
在调用tr.calc_crc时,是调用父类还是子类的方法,因为calc_crc 在父类声明了虚方法,SV查看tr中的对象类型,如果tr是transaction类型,则选择父类的方法,如果tr是 Badtr类性,则选择派生类的方法。
generator 只能使用 transaction对象,无法使用扩展对象Badtr。 解决办法是:将tr的创建和初始化分开。

1.5 蓝图blueprint模式

OOP一种非常有用的技术。生产标记,并不需要预先知道每个可能的标记形状。

先构建一个对象的蓝图(建材金属模),然后修改他的约束,甚至使用一个扩展对象替换它。然后当你随机化这个蓝图的时候,它就会 具有你想赋予的随机值。接着复制这个对象,并将拷贝值发送给下游的事务处理器。
在这里插入图片描述
将声明和构造分开;
将蓝图对像的构建和随机化分开:

class generator;
    mailbox gen2drv;
    transaction blueprint;
 
    function new(input mailbox gen2drv);
        this.gen2drv = gen2drv;
        blueprint = new();
    endfucntion

    task run;
       transaction  tr;
       forever begin
          assert(blueprint.randomize());
          tr = blueprint.copy(); 复制对象,以便传送
          mbx.put(tr);
       end
    endtask
endclass

2. environment 类

例化测试平台的所有元素,创建build、运行Run、收尾Wrap-up。

2. 1 使用扩展的Transaction类

为了注入错误,你需要将蓝图对象从transaction对象变成Badtr。在环境的创建和运行阶段完成。

在测试平台中增加扩展了的事务
program automatic test;
   Environment env;
   initial begin
      env = new();
      env.build(); //创建generator等

      begin 
         Badtr bad = new();  // 以bad对象取代蓝图
         env.gen.blueprint = bad;
      end

      env.run();
      env.wrap_up();
    end
endprogram

2. 2 使用扩展类 改变 随机约束

class childclass extends transaction
   constraint c_childclass 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值