验证基础-类型转换、虚方法、回调函数、对象拷贝

        这一章是SV学习和UVM学习的过渡,SV的验证思想在很多地方和UVM是共通的,本篇就介绍一些SV和UVM中相似的一些概念及应用。

类型转换

        类型转换可以分为静态转换动态转换。静态转换即需要在转换的表达式前加上单引号即可,该方式并不会对转换值做检查。如果发生转换失败,我们也无从得知。

        动态转换即需要使用系统函数 $cast(tgt,src) 做转换。把右侧的变量转换成左侧的变量类型。 

        静态转换和动态转换均需要操作符号或者系统函数介入,统称为显示转换

        不需要进行转换的一些操作,我们称之为隐式转换。例如赋值语句右侧是4位的矢量,而左侧是5位的矢量,隐式转换会先做位宽扩展(隐式),然后再做赋值。

        动态转换中,当我们使用类的时候,类句柄的向下转换,即从父类句柄转换为子类句柄时,需要使用 $cast( ) 函数进行转换,否则会出现编译错误,把父类句柄转换成子类句柄只有这一种方法,一般是在父类句柄指向子类对象的时候,又想要访问子类的成员变量时,使用cast函数转换。如果父类句柄指向的是父类对象,那么不能用cast函数转换,哪怕转换了也会转换失败,即函数返回0.

        如果将子类的句柄赋值给父类句柄时,编译器认为赋值是合法的,但分别利用子类句柄父类句柄调用相同对象的成员时,可能会有不同的表现。(在面向对象编程笔记中详细解释到。) 

问,下面最后的结果为多少? 

        从代码中我们可以看到,BadTr继承了父类的成员变量和方法,子类中也定义了和父类同名的方法“function display”,那么父类句柄tr的语句,tr.display()调用的是父类的display还是子类的display?答:调用的父类的display,因为父类的句柄指向子类的对象,只能访问子类对象中继承于父类的部分。

虚方法

        虚方法是验证面试的时候经常会问。

        当不同的句柄类型指向同一个对象的时候,它们调用的函数或者变量可能结果会不一样。在父类句柄指向子类对象的时候,如果子类和父类都定义了一个同名的方法,那么这个父类句柄只能访问父类的该方法而不能访问子类的方法,而事实上我们把它指向一个子类的对象更希望的是调用函数的时候它也能调用子类的方法,要想这样做,可以用cast函数把父类的句柄类型转换成子类的句柄,但是如果每次都这么做会使得代码很冗余,还容易出错。

        虚方法要解决的问题就是一个动态绑定,不管句柄类型如何,只要你指向的是子类对象,那么调用方法的时候即使有同名方法,也会调用子类中的方法。虚方法通过virtual声明,只需声明一次即可。注意虚方法解决的是方法的同名索引,不能索引成员变量,没有虚成员的说法。

        我们将已经在编译阶段就可以确定下来调用方法所处作用域的方式称之为静态绑定(static binding),与之相对的是动态绑定,动态绑定指的是,在调用方法时,会在运行时来确定句柄指向对象的类型再动态指向应该调用的方法,在父类里面的方法前面声明一个virtual即可

        这样我们就可以通过虚方法的使用来实现类成员方法调用时的动态查找,用户无需担心使用的是父类句柄还是子类句柄,因为最终都会实现动态方法查找,执行正确的方法。对父类的方法声明了virtual后,在调用父类句柄.方法名时,系统会先判断句柄指向的对象是父类对象还是子类对象,如果是子类对象再判断,子类对象中有无调用的同名方法,如果有则使用子类方法,如果没有则再返回到父类中,调用父类的方法。

        虚方法如果要定义,应该尽量定义在底层父类中。这是因为如果virtual是声明在类集成关系的中间层,那么只有从该中间类层到其子类的调用链中会遵循动态查找,而最底层到该中间类的方法调用仍然会遵循静态查找。

        如果子类和父类中的方法,同名不同参,那么它们之间就没有继承的关系,更没有虚方法的关系。虚方法的继承也需要遵循相同的参数和返回类型,否则,子类定义的方法须归为同名不同参的其它方法。

对象拷贝

        声明对象和创建对象是两个过程,也可以一步完成。Packet p1;p1=new;

        如果将p1赋值给另一个变量p2,那么依然只有一个对象,只是指向这个对象的句柄有p1和p2。

        p1和p2代表两个不同的对象,在创建p2对象时,将p1拷贝其成员变量例如integer、string和句柄等,这种拷贝方式称为浅拷贝(shallow copy)。

        对象的拷贝无法通过“=”实现,因为这一操作是句柄的赋值,而不是对象的拷贝。 

像上面这种情况,就是典型的句柄的赋值,而不是对象的copy。

        如果要拷贝对象,指的是首先创建一个新的对象(开辟新的空间),再将目标对象的成员变量值拷贝给新对象的成员,这就使得新对象与目标对象的成员变量数值保持一致,即完成了对象的拷贝(成员变量的拷贝)。 

        将成员拷贝函数copy_data()新对象生成函数copy()分为两个方法,这样使得子类继承和方法复用比较容易。为了保证父类和子类的成员均可以完成拷贝,将拷贝方法声明为虚方法,且遵循只拷贝该类的域成员的原则,父类的成员拷贝应该由父类的拷贝方法完成。

        在实现copy_data()过程中应该注意句柄的类型转换,保证转换后的句柄可以访问类成员变量

回调函数

        理想的验证环境是在被移植做水平复用或者垂直复用时,应当尽可能少地修改模块验证本身,只在外部做少量的配置,或者定制化修改就可以嵌入到新的环境中。要做到这点,我们可以通过顶层环境的配置对象自顶向下进行配置参数传递,还可以在测试程序不修改原始类的情况下注入新的代码

        当我们需要修改Stimulator的行为时,有两种选择,一个是修改父类,但针对父类的会传播到其它子类;另一个选择是,在父类定义方法时,预留回调函数入口,使得在继承的子类中填充回调函数,就可以完成对父类方法的修改。 

Driver_cbs是一个虚类,虚类不能例化,但是可以继承 

 

        提前写好回调函数,预留一个坑位,如果后续需要修改,可以直接填回调函数做修改。Driver中定义的cbs为句柄队列。如果drop返回为0的话,因为continue了,所以不会执行transmit(tr),直接跳到forever入口处。

        使用回调函数注意事项:1.预留函数入口。2.定义回调函数和类。 3.例化以及添加回调类的实例。

        在UVM中就有专门的回调函数的内容,和SV的回调函数使用过程一致,掌握SV的回调函数使用方法后,过渡到UVM就很流畅了。

参数化的类

        参数化的使用是为了提高代码的复用率。参数的使用越合理,后期的维护成本就会相应降低。在硬件设计中,参数往往是整形,例如端口数目或者位宽。在验证环境中,参数的使用更加灵活,可以使用各种类型来做类定义时的参数。

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

        在类定义时添加参数#(type T = int),这表示后期类在声明变量时如果不指定参数类型,则默认采用int类型。将源代码的int用参数T代替。

        要修改变量时,调用类的时候,直接在后面 #(type)即可修改类中的变量。 

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
A: 以下是一个简单的回调函数拷贝实现: ```python def deep_copy_with_callback(obj, callback=None): if isinstance(obj, dict): result = {} for key, value in obj.items(): result[key] = deep_copy_with_callback(value, callback) return result elif isinstance(obj, list): result = [] for value in obj: result.append(deep_copy_with_callback(value, callback)) return result elif callback is not None: return callback(obj) else: return obj ``` 这段代码定义了一个`deep_copy_with_callback`函数,它接受两个参数,一个是要深拷贝对象,另一个是可选的回调函数。 如果传入的对象是字典,将遍历字典中的每个键值对,并递归调用`deep_copy_with_callback`函数对每个值进行深拷贝。最终将所有的深拷贝结果合并到一个新的字典中,并返回该字典。 如果传入的对象是列表,将遍历列表中的每个元素,并递归调用`deep_copy_with_callback`函数对每个元素进行深拷贝。最终将所有的深拷贝结果合并到一个新的列表中,并返回该列表。 如果传入的回调函数不为空,将对要拷贝对象进行回调,修改或者替换一些特定的属性或者对象,然后返回新的对象。 如果传入的对象既不是字典也不是列表,将直接返回原始对象。 这个实现可以确保递归深拷贝传入的对象及其所有可迭代子对象,而回调函数是一个可选项,可以在深拷贝对象的同时做一些额外的修改及扩展等操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不吃葱的酸菜鱼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值