电子说
在构建复杂的sequence序列的时候,我们经常会用到m_sequencer和p_sequencer,并且在很多资料中都提到两者实际指向的是同一个对象,那么为什么要同时存在他们两个,存在一个不就够用了吗?为此,本文通过示例说明下两者之间的关系。
首先,我们先来看看“白皮书”上的一个示例。
【示例】
“白皮书”中讲解在case0_sequence中如果企图通过m_sequencer引用my_sequencer中的变量将会报错,需要通过调用宏声明p_sequencer后通过p_sequencer才能引用my_sequencer中的变量,并且还强调了了m_sequencer和p_sequencer指向同一个对象,那么为什么m_sequencer不能直接访问my_sequencer中的变量呢?这里首先需要明白,在UVM中m_sequencer句柄的类型是uvm_sequencer_base,并且定义在uvm_sequence_item类中,可以理解为其是sequence的member sequencer的简写,是uvm_sequence_item类中的一个成员(如下图),用户编写的sequence大都派生自该类。
在建立sequence和sequencer关系(uvm_sequence::start())时,该成员将指向该sequence将要运行的sequencer。
那么,p_sequencer的类型是什么呢?我们从代码中的宏定义来看一下,这个宏定义展开如下。
在该宏中,SEQUENCER必须为“类型”,当程序中使用该宏时,SEQUENCER为用户自定义的sequencer,即示例中的my_sequencer,而因为宏中p_sequencer指定的类型为SEQUENCER,即也就是调用该宏时传入的参数my_sequencer,所以可以知道p_sequencer的类型为用户自定义的sequencer,即示例中的my_sequencer,而用户自定义的sequencer派生自uvm_sequencer。
至此,我们也就知道了m_sequencer和p_sequencer的句柄类型。我们汇总下上述信息可以得到下图。
在声明p_sequencer的宏中,451行通过$cast将p_sequencer指向了m_sequencer指向的对象,而m_sequencer此时指向对象的类型就是用户自定义的sequencer,即经过一番骚操作之后,p_sequencer和m_sequencer指向了同一个sequencer。既然指向了同一个对象,为什么一个句柄(p_sequencer)可以访问对象的属性而另一个(m_sequencer)不行呢?这里就需要大家理解SystemVerilog中的句柄转换后,父类句柄都可以访问子类对象中的那些属性的问题。为了描述问题方便,我们通过一个简化示例来说明p_sequencer和m_sequencer之间的访问关系。
【示例】
【仿真结果】
示例中,m_sequencer句柄的类型为sequencer_base,p_sequencer句柄类型为sequencer_user,p_sequencer指向创建对象之后,可以访问sequencer_user中的属性user_str,通过显示函数显示出来,但是在18行将m_sequencer指向p_sequencer指向的对象之后,通过m_sequencer访问sequencer_user中的属性user_str析构时报错!这是因为在SystemVerilog中,如果企图使用父类句柄去访问子类对象时,父类句柄是不能直接访问子类对象中的属性成员,其实这也符合人之常情,时代在进步,子类肯定会具有一些父类所不具有的特性,这些特性就是父类所不具有也不能直接进行访问的。
那么,如何实现父类对于子类中属性的访问呢?可以采用曲线救国的策略,我们可以通过父类句柄访问子类中的方法,并且该方法还必须是虚方法,然后在子类中的方法访问子类中的属性实现,只不过这样实现起来有些费劲,所以我们将一些通用的属性都放在父类中,这样可以实现这些资源的共享。
回到UVM中的m_sequencer和p_sequencer中,因为m_sequencer相当于是父类句柄,而p_sequencer是子类句柄,所以不能使用m_sequencer去访问子类句柄指向的子类对象。
如果要实现对于子类对象的访问,那么应该如何实现呢?在SystemVerilog中,我们可以通过将指向子类对象的父类句柄通过$cast转换成具有子类对象类型的子类句柄,从而实现子类对象中属性的访问,我们还是通过上例进行示例说明。
【示例】
【仿真结果】
示例中,虽然m_sequencer句柄具有父类类型,但是其指向的是子类对象,所以此时可以通过$cast成功将p1_sequencer句柄指向m_sequencer指向的子类对象,因为p1_sequencer具有和子类对象相同的类型,所以p1_sequencer可以访问指向对象中所有的属性。
所以我们回到本文开始“白皮书”示例描述的,之所以出现“白皮书”中描述m_sequencer不能访问用户自定义的sequencer中属性的原因就是因为m_sequencer句柄的类型为当前自定义sequencer类型的父类,访问用户自定义sequencer类的对象中属性的方法只能通过具有该类型的句柄p_sequencer才行。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !