system verilog 路科验证每周练习第2208期部分代码讲解

package data_pkg;
  class transction;
    int unsigned data;
    int unsigned addr;

    function new(int unsigned val);//带有参数的构造函数,则例化的时候new()要传参,比如t1 = new(10);
      data = val;
      addr = 'h4;
    endfunction

    virtual function bit get_data_xored();//virtual作用:即虚方法,使得指向子类对象的父类句柄真正能调用子类对象,除了new函数,父类和子类的其他函数都加下虚方法,此时子类与父类保持动态绑定,三个地方要一致,即函数名、参数和返回值
      return ^data;//^a操作就是将a中的每一位按位逐一进行异或,例如a=4'b1010,则b=1^0^1^0=0,由此可以判断a中为1的位数是奇数还是偶数,是一个便捷的操作。
    endfunction

    virtual function int unsigned get_addr_shifted(int bits = 2);
      return addr << bits;//左移两位,相当于*d4,d2112(即h210)*d4=h840(或b0010 0001 0000左移两位=h840),继续左移4位是h8400,最后一个h0是b0000,或者d2112(即h840)*d16=h8400
    endfunction
  endclass

  class user_trans extends transction;
    int unsigned shifted = 3;

    function new(int unsigned val);//可以将int unsigned val去掉,例化不传new(20),但是最好与父类保持一致,包括new函数名、函数参数、返回值,加虚方法就要保持一致,不加就不用
      super.new(val);//先执行父类对象的初始化
      data = val<<1;//再执行子类对象的初始化
      //super.new();
    endfunction

    function bit get_data_xored();
      return !(^data);
    endfunction

    function int unsigned get_addr_shifted(int bits = 2);//int bits = 2与父类保持一致,sv同一个类不能有多个同名不同参数的函数
      addr <<= shifted;//即addr = addr << shifted,因为这里没用return,所以要赋值给自身
      return super.get_addr_shifted(bits);
    endfunction
  endclass

endpackage

module tb;
import data_pkg::*;

transction t1, t2;
user_trans u1, u2;

initial begin
  int unsigned addr;
  bit xored;
  int unsigned addr_u2;
  bit xored_u2;
  t1 = new(10);
  t1.addr = 'h210;
  t1.data = 'h111;
  xored = t1.get_data_xored();
  addr = t1.get_addr_shifted();
  
  u1 = new(20);
  u1.addr = t1.addr;
  u1.data = t1.data;
  u1.shifted = 4;
  xored = u1.get_data_xored();
  addr = u1.get_addr_shifted();
  //u1 = t2 父类句柄赋给(转为)子类,子类句柄指向父类对象(错误)
  t2 = u1;//等同于$cast(t2, u1),子类句柄可直接赋值(转为)给父类句柄,父类句柄指向子类对象(正确),此时都指向子类的对象,父类句柄t2也指向子类对象,但是不加虚方法只能调用父类对象,加虚方法才能调用子类对象
  t2.addr = 'h120;
  t2.data = 'h345;
  //t2.shifted = 1;//但是父类句柄找不到子类的变量shifted,只能找到父类的成员变量
  xored = t2.get_data_xored();//也是调用父类的方法,要在父类方法前加virtual即虚方法,才会调用子类方法,只有子类方法没有时才会调用父类的
  addr = t2.get_addr_shifted();
  //不加虚方法virtural的情况,可以将父类句柄转化为子类句柄访问子类对象(这么理解而已),(实际上)此时t2是父类句柄指向子类对象(正确),u2是子类句柄指向子类对象
  if(!$cast(u2, t2))//$cast(u2, t2)转化成功/失败返回1/0,注意不能直接把$cast(u2, t2),前提是子类赋给(转化为)父类,即t2=u1,这是向上类型转换,安全,将独特的子类转换为父类的类型,更注重通用性,共性越多,重用性越好。
    //父类句柄赋给(转为)子类类型,才能访问子类特有的资源。
    $fatal("TYPE CASTING ERROR!");
  u2.addr = 'h230;
  u2.data = 'h456;
  u2.shifted = 1;
  xored_u2 = u2.get_data_xored();
  addr_u2 = u2.get_addr_shifted();//为啥不是xored_t2 = t2.get_addr_shifted?$cast(u2, t2)类似于u2 = t2,当然是用u2,但questasim中的t2、u2变量确实都指向u1的子类对象,但不加虚方法t2依然进入父类中调用父类对象。在68行addr = t2.get_addr_shifted()那里,如果没虚方法,那调用的是自己父类的对象,和此处调用子类对象不一致不同

  $finish();
end

endmodule
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值