路科sv练习2-类的继承

这篇笔记探讨了Verilog中类的继承和克隆函数的实现,通过一个实例展示了如何在子类中重写父类的clone方法,以及在实际使用中如何正确调用和理解这些概念。文中还详细分析了为什么不能直接通过父类句柄访问子类的特定成员变量,以及在调用克隆函数时可能出现的问题和解决方案。此外,还介绍了在仿真过程中如何设置断点以进行调试。
摘要由CSDN通过智能技术生成

此笔记是根据路科sv练习2-类的继承的讲解视频整理而成,是对以下代码及其详解,并通过几个常见的疑问来加深对类的继承的理解。


module class_inheritance;

bit b_member_override = 1;

  class trans;
    bit[31:0] data[];
    int pkt_id;
    int data_nidles;
    int pkt_nidles;
    bit rsp;

    function trans clone(trans t = null);
      if(t == null) t = new();//若clone没有传递进来句柄,就创建一个对象;若有,就直接用该句柄
      t.data = data;
      t.pkt_id = pkt_id;
      t.data_nidles = data_nidles;
      t.pkt_nidles = pkt_nidles;
      t.rsp = rsp;
      return t;//若clone有传递进来句柄,那么最后return的t和原来的t是同一个句柄
    endfunction
  endclass

  class chnl_trans extends trans;
    int ch_id; // new member in child class

    // member function override with 
    // same function name, arguments, and return type

    // TODO-1 seperately enable the clone function-1 and function-2, and check
    // if both of them works, and compare which is better, and why?
    // clone function-1
    function trans clone(trans t = null);
      chnl_trans ct;
      if(t == null) 
        ct = new();
      else
        void'($cast(ct, t));
      ct.data = data;
      ct.pkt_id = pkt_id;
      ct.data_nidles = data_nidles;
      ct.pkt_nidles = pkt_nidles;
      ct.rsp = rsp;
      ct.ch_id = ch_id; // new member
      return ct;
    endfunction

    // clone function-2
    // function trans clone(trans t = null);
    //   chnl_trans ct;
    //   if(t == null) 
    //     ct = new();
    //   else
    //     void'($cast(ct, t));
    //   void'(super.clone(ct));
    //   ct.ch_id = ch_id; // new member
    //   return ct;
    // endfunction
  endclass

  initial begin: member_override
    trans t1, t2;
    chnl_trans ct1, ct2;
    wait(b_member_override == 1); $display("b_member_override process block started");

    ct1 = new();
    ct1.pkt_id = 200;
    ct1.ch_id = 2;
    // t1 pointed to ct1's trans class data base
    t1 = ct1;

    // t2 copied ct1's trans class data base
    t2 = ct1.clone();//克隆的返回值都是父类句柄,所以给父类句柄t2
    void'($cast(ct2, t2));
    // TODO-2 why could not clone t1(->ct1) to t2?
    // t2 = t1.clone(); // ERROR clone call:
    // void'($cast(ct2, t2));

    $display("ct1.pkt_id = %0d, ct1.ch_id = %0d", ct1.pkt_id, ct1.ch_id);

    // TODO-3 uncomment the statement below and consider
    //        why t1 could not point to ct1.ch_id?
    // $display("ct1.pkt_id = %0d, ct1.ch_id = %0d", t1.pkt_id, t1.ch_id);

    $display("ct2.pkt_id = %0d, ct2.ch_id = %0d", ct2.pkt_id, ct2.ch_id);
  end

endmodule

首先解释一下父类的克隆函数:
在这里插入图片描述
接着我们来看子类函数给出的第一种写法:
在这里插入图片描述
解析:
这种写法中,如果传递进来的句柄是null,那就会创建一个子类的句柄ct;如果传递进来的句柄非null,由于参数类型是trans,所以传递进来的是父类句柄,但是我们是要对子类对象进行克隆。所以通过cast将父类句柄转换成子类句柄,去访问子类变量。
注意:由于函数定义的返回类型是父类trans,所以此处存在一个隐性的类型转化,也就是把子类句柄转化为父类句柄。最后return的子类句柄ct会被转换成父类句柄。

问题1:可以只用父类句柄完成对子类成员变量的克隆吗?也就是改成下面这种形式。

在这里插入图片描述
NO!
1、39-43可以成功,因为父类句柄可以访问到子类对象中属于父类的成员变量;
但是44行无法成功,因为父类的句柄无法访问到只属于子类对象的成员变量ch_id。
因此,为了能够访问到子类里的变量,我们需要将指向子类对象的父类句柄转换为子类句柄。

void'($cast(ct,t));

这样可以保证同时访问到父类和子类的变量。

问题2:将返回类型和参数类型设置为子类chnl_trans不是更省事吗?

有人可能会觉得疑惑,为什么要让传进来的句柄是父类的(参数类型是父类),然后将其转换为子类句柄方便对子类的变量进行复制,最后返回了一个子类句柄还要再隐形转换为父类句柄(返回类型是父类)?
直接将返回类型和参数类型设置为子类,不是可以省了很多转化的步骤吗?像下面这样:在这里插入图片描述
注意,如果只是单纯的一个类,不存在继承关系,那么没问题,可以这么写。
而如果你想要对同名函数进行覆盖和继承,那么就会出现问题,因为函数的返回类型和参数类型就不一致了。

另外,我们知道,父类定义方法时,如果该方法日后可能被覆盖或者继承,那么应该声明为虚方法 virtual function。
而虚方法的继承要遵循三个一致——函数名、返回类型、参数类型一致。如果有哪一个不一致,那么就不叫继承了,虚函数对应的功能也就无法出现。

所以,为了让覆盖和继承按照我们的意愿进行,在定义子类函数的时候,要和父类的函数保持函数名、返回类型、参数类型都一致。
在这里插入图片描述
对上面子类函数clone代码的总结:
由于传递进来的父类句柄指向的是子类对象,所以将此父类句柄通过动态转换为子类句柄,利用子类句柄去访问父类和子类的成员变量,然后返回子类的句柄ct。最后再把子类句柄隐性转成父类句柄。

上面的子类克隆函数还有更佳的写法,如下:
在这里插入图片描述
55行相当于替代了39-43行,而且复用性更好,它将子类的句柄ct放入父类的克隆函数中,完成了对父类变量的拷贝。
再通过56行将子类的变量也拷贝一下,完成对整个子类对象成员变量的拷贝。

问题3:可否把55行里的ct换成t?

在这里插入图片描述
会有点问题。
1、如果传进来的句柄t非空,那么就不会产生子类句柄ct,那么数据就会直接通过t句柄传递给t指向的对象,完成数据的复制,没问题;
2、如果没有传进来句柄(也就是调用函数时没有参数,直接写clone()),那么函数内部会创建子类句柄ct。如果写成了void’(super.clone(t)),那么数据就拷贝给了t,而不是我们想给的ct。因此最后的结果只是把ch_id的值复制了而已。
注意:void’(super.clone(t))里的t不是clone函数里的参数t,因为你会发现经过clone函数后,形式参数t还是null,并没有值的改变。
在这里插入图片描述

再来解决initial块的两个问题。

在这里插入图片描述

TODO-2为什么不能写成下面这种形式?

t2 = t1.clone(); // ERROR clone call:
void'($cast(ct2, t2));

因为我们的目的(69行)是为了复制子类的对象,如果写成上面这样,由于t1是一个父类句柄,所以通过t1.clone()只能克隆得到父类的对象,和我们的期望不一样。
在这里插入图片描述

而且将指向父类对象的父类句柄给到t2,那么接下来的动态转换就会失败。不过不会显示,因为void’($cast(ct2, t2))由于void的存在是不返回什么的,可以把void去掉,那么可以看到转换失败的打印信息:
在这里插入图片描述

并且最后85行也会报错,因为ct2.ch_id无效
在这里插入图片描述

TODO-3 既然t1也是指向了子类对象,那可以把79行换成83行吗?

不行,因为我们无法通过父类的句柄去访问子类的成员变量,一定要通过动态转换才行。

Questasim仿真

步骤:
1、仿真命令:

vsim -voptargs=+acc -classdebug work.class_inheritance

命令解释:
(1)、vopt命令可以加快仿真的速度
-voptargs=“参数”
如果参数为+acc,也就是-voptargs=+acc,意思就是优化部分参数,用于保留某些类别的对象的可见性,否则这些对象可能会被优化掉。被优化掉的对象会使您的调试和分析工作更加困难

如果想全部优化参数,就用-vopt
不想优化参数,那么就用-novopt

ps.关于什么时候需要优化,可见下面链接,这里做部分摘抄
https://blog.csdn.net/u010170039/article/details/79159563

设计优化包括:
①不优化:完全不进行设计优化,所有信号可见,但仿真速度较慢(小工程也无所谓了)

②优化,信号不可见:进行设计优化,但信号都不可见,速度最快。调试完全依赖于testbench的打印输出。

③优化,具有完全可见性:进行设计优化,但又保证所有信号可见,速度较快,调试必备。

④优化,自定义可见性:进行设计优化,自定义哪些模块及信号可见。

(2)、-classdebug
添加上可以看到更多和类相关的调试内容

2、仿真后设置断点,来了解程序的运行
在这里插入图片描述
数值默认为16进制,可以通过右击信号,选择Global Signal Radix来设置为十进制。
在这里插入图片描述

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 实验2的核心目标是验证SV路科验证V2Pro的性能和功能。SV路科验证V2Pro是一种设备或系统,用于对特定产品或技术进行验证和测试,以确保其达到预期的安全性、可靠性和性能要求。 在实验2中,我们将对SV路科验证V2Pro进行一系列测试,以验证其在实际应用中的性能和功能。这些测试可能包括但不限于以下方面: 1. 安全性测试:我们将对SV路科验证V2Pro的安全功能进行测试,以确保其能够有效地保护系统和数据的机密性、完整性和可用性。 2. 性能测试:我们将对SV路科验证V2Pro的性能进行定量测试,包括处理速度、响应时间等指标,以确保其能够在实际应用中提供足够的性能。 3. 兼容性测试:我们将测试SV路科验证V2Pro与其他设备或系统的兼容性,以保证其能够与其他设备或系统进行有效的协同工作。 4. 可靠性测试:我们将对SV路科验证V2Pro的可靠性进行测试,包括长期运行测试和容错测试,以确保其能够在不同环境条件下保持稳定的运行。 5. 功能测试:我们将对SV路科验证V2Pro的各项功能进行测试,包括但不限于数据采集、数据分析、故障诊断等,以确保其能够满足用户的需求。 通过上述测试,我们将能够全面评估SV路科验证V2Pro的性能和功能,从而确定其是否符合预期要求。这对于确保产品或技术的质量和可靠性至关重要,也能够为用户提供更好的使用体验。 ### 回答2: SV路科验证V2Pro 实验2是一项验证科学研究中常用的实验方法,可以用于检验某种新的药物或理论的有效性和安全性。该实验主要包括以下步骤: 首先,实验人员需要准备好实验所需的材料和设备。这包括药物样品、动物模型或细胞培养基等。 然后,实验人员按照一定的实验设计将动物模型或细胞培养基分为实验组和对照组。实验组会接受要验证的药物或理论的处理,而对照组则接受安慰剂或常规处理。 接下来,实验人员根据实验设计的要求,给予实验组和对照组不同的处理或操作。这可以包括给动物模型注射药物、观察细胞培养基的变化等。 在给予不同处理后,实验人员通过观察和记录实验组和对照组的变化,来评估要验证的药物或理论的效果和安全性。 最后,实验人员根据实验数据进行数据分析和统计,以确定要验证的药物或理论是否达到预期的效果。分析包括比较实验组和对照组之间的差异,以及与先前的实验结果进行比较。 总之,SV路科验证V2Pro 实验2是一种常用的验证新药物或理论有效性和安全性的实验方法。通过严格的实验设计和数据分析,可以评估要验证的药物或理论的效果,并为进一步的研究和应用提供参考依据。 ### 回答3: SV路科验证V2Pro实验2的具体内容是什么,没有提供详细信息,无法进行具体回答。SV路科验证V2Pro实验2可能是一个科学实验或者项目,需要提供更多的背景信息和细节才能进行回答。请提供更多详细信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hardworking_IC_boy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值