systemverilog绿皮书随记(七)-- 面向对象编程的高级技巧指南

8.1继承

8.2蓝图模式

8.3类型向下转换和虚方法

例8.11 基类和派生类

class Transaction;
  rand bit[31:0] src;
  virtual function void display(input string prefix="");
    $display("%sTransaction: src=%0d", prefix, src);
  endfunction
endclass

class BadTr extends Transaction;
  bit bad_crc;
  virtual function void display(input string prefix="");
    $display("%sBadTr: bad_crc=%b", prefix, bad_crc);
    super.display(prefix);
  endfunction
endclass

例8.12 将一个扩展类的句柄拷贝成基类句柄
Transaction tr;
BadTr bad;

bad = new(); // 构建BadTr扩展对象
tr = bad;    // 基类句柄指向扩展对象

$display(tr.src);  // 显示基类对象的变量成员
tr.display();      // 调用BadTr::display

当需要决定调用哪个虚方法的时候,sv根据对象的类型,而非句柄的类型来决定调用什么方法;前提是方法加上了virtual

子类句柄可以直接赋值给父类句柄;

父类句柄指向子类对象时,可以用$cast,将父类句柄转换为子类句柄

深拷贝:如之前所述,使用两个函数 copy和copy_data;次方法每次克隆时都会创建一个新的对象;当你想重用一个现有的对象而不是分配一个新的对象的时候,下示方法奏效;

class Transaction;
  virtual function Transaction copy(Transaction to = null);
    if (to == null) begin
      copy = new();
      // 创建新对象
    end else begin
      copy = to;
      // 或者使用现有对象
      copy_data(copy);
    end
  endfunction
endclass


class BadTr extends Transaction;
  virtual function Transaction copy(Transaction to = null);
    BadTr bad;
    if (to == null) begin
      bad = new();
      // 创建一个新对象
    end else begin
      assert($cast(bad, to));
      // 重用已有对象
    end
    copy_data(bad);  // 复制数据域
    return bad;
  endfunction
endclass BadTr

Ps:这里的句柄to应该是指向子类对象的父类句柄;

8.4抽象类和纯虚方法:

抽象类:使用virtual关键词进行定义,是一种可以被扩展但是不能被直接实例化的类;

纯虚方法:是一种没有实体的方法原型;

一个由抽象类扩展而来的类只有在所有虚方法都是实体的时候才能被例化

例8.26 使用纯虚方法的抽象类
virtual class BaseTr:
  static int count;  // 需要创建的实例数
  int id;            // 唯一的事务id

  function new();
    id = count++;
    // 每一个对象对应一个ID
  endfunction

  pure virtual function bit compare(input BaseTr to);
  pure virtual function BaseTr copy(input BaseTr to = null);
  pure virtual function void display(input string prefix = "");

endclass:BaseTr

例8.27 Transaction类扩展了抽象类
class Transaction extends BaseTr;
  rand bit [31:0] src, dst, crc,data[8];
  extern virtual function bit compare(input BaseTr to);
  extern virtual function BaseTr copy(input BaseTr to = null);
  extern virtual function void copy_data(input Transaction copy);
  extern virtual function void display(input string prefix = "");
  extern function new();
endclass




例8.28 Transaction方法的实现
function bit Transaction::compare(input BaseTr to);
  Transaction tr;
  assert($cast(tr, to));
  // 检查to是否为正确类型
  return ((this.src == tr.src) &&
          (this.dst == tr.dst) &&
          (this.crc == tr.crc) &&
          (this.data == tr.data));
endfunction:compare

function BaseTr Transaction::copy(input BaseTr to = null) :
  Transaction cp;
  if (to == null) cp = new();
  else cp = $cast(cp, to);
  copy_data(cp);
  return cp;
endfunction

function void Transaction::copy_data(Transaction copy);
  copy.src = src;
  copy.dst = dst;
  copy.data = data;
  copy.crc = crc;
endfunction

function void Transaction::display(input string prefix = "");
  $display("Transaction %s id=%d src=%x, dst=%x, crc=%x", prefix, id, src, dst, crc);
endfunction:display

function Transaction::new();
  super.new();
endfunction:new

Basetr不能直接用来创建对象;Transaction对所有的纯虚方法都有实体定义,所以可以在测试平台中使用它;

8.5回调函数

计分板:包含一个将输入的事物转换成期望值的传输函数、用来保存这些值的内存空间以及一个进行比较的子程序。一个处理器的设计需要一个参考模型来预测期望输出,而对期望值和实际值的比较可能会在仿真的末尾进行;

8.6参数化的类

在sv中,可以为类增加一个数据类型参数,并在声明类句柄的时候指定类型。

参数化的类

class Stack #(type T = int);
  local T stack[100]; // 保存数据值
  local int top;
  function void push(input T i);
    // 从顶部压栈
    stack[++top] = i;
  endfunction: push
  function T pop();
    // 从顶部出栈
    return stack[top--];
  endfunction
endclass: Stack

使用: Stack #(new type) rStack

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值