1. m_sequener 来源于哪里?
2. p_sequencer又来源于哪里?
搞懂上面两个问题才能理解为什么会存在 p_sequencer,而且为什么需要p_sequencer
m_sequencer 是uvm_sequencer_base类型,而p_sequencer是uvm_sequencer类型,也就是说,m_sequencer 是 p_sequencer的父类,因为uvm_sequencer 间接继承于uvm_sequencer_base,现在就理清楚了上面的两个问题。
知识背景:关于子类和父类之间如何通过父类去用子类对象中的成员方法和变量的问题。SV
提供两种方法去实现父类句柄去使用子类的成员变量和方法
1. 使用virtual
2. 使用$cast(sub,sup)转化成功之后就可以使用父类里的句柄去调用子类里的成员变量和方法。
3. m_sequencer 的使用介绍:不知道大家有没有个疑问,m_sequencer好像在我们的环境中几乎没有出现过,他的意义在哪里。m_sequencer是uvm_sequence_item的成员变量,也就是每一个sequence都有一个类型为uvm_sequencer_base的成员变量m_sequencer,且里面存放的是启动该sequence的sequencer的指针。这就是m_sequencer的作用,指向的是启动对应sequence 的 sequencer的指针。
4. 为什么要引入p_sequencer,当一个新的东西被引入的时候,一定是为了解决某一个指定的问题。首先介绍一下p_sequencer 源码介绍:UVM里定义了一个宏 `uvm_declare_p_sequencer(SEQUENCER),这里的SEQUENCER就被认为是一个p_sequencer,在这个宏里的参数就是p_sequencer,一般来说,我们自己定义的sequencer将会作为参数传给这个宏。这里传入my_sequencer.此时,my_sequencer 就是p_sequencer。
源码里介绍了这个宏,总的来说这个宏只干了一件事 $cast(p_sequencer,m_sequencer),没错只干了这一件事。
上面提到,m_sequencer是某个sequence启动的时后的对应的sequencer的指针,此时比如我的sequence启动的时候就是在my_sequencer上启动的,那么此时,m_sequencer和p_sequencer都是指向同一个对象就是我的my_sequencer。
使用意义:
现在知道了,m_sequncer和p_sequencer都是指向my_sequencer的,那么假设我的sequence想要去使用my_sequencer里面定义的某一个成员变量,由于sequence不在uvm树形结构里,没办法直接通过my_sequencer去直接引入,所以,才有m_sequencer和p_sequencer的存在。两者都是my_sequencer的指针,这样就可以通过m_sequencer.*** 或者是p_sequencer.***去引用my_sequencer里面的成员变量了,但是,问题就来了,到底是通过m_sequencer还是p_sequencer,就是一个问题,因为只有一个会成功,要不然也不会多次一举搞两个。回到最开始提到的,my_sequencer是来源于uvm_sequencer,m_sequencer是uvm_sequencer_base 类型,我们在声明p_sequencer的时候将my_sequencer传进去,也就是现在我提到的p_sequencer就是my_sequencer,如果是通过m_sequencer.**去引用my_sequencer中的成员变量可行吗?答案是不行,因为,m_sequencer类型是uvm_sequencer_base,而my_sequencer是uvm_sequencer,m_sequencer是my_sequencer的父类,SV规定,无法直接通过父类去调用子类的成员变量和方法,除非通过$cast(p_sequencer,m_sequencer),这样动态转化之后就可以通过父类句柄去访问子类的成员变量和方法了。这样就可以只用p_sequencer.***去调用my_sequencer的成员变量和方法了。
解释的很复杂,其实目的就是为了实现在sequence中去使用sequencer中的某些成员变量,由于结构问题,只能通过m_sequencer去调用,虽然m_sequencer指向的是my_sequencer的指针,但是m_sequencer又是my_sequencer的父类,所以无法直接去调用,只能通过$cast(my_sequencer,m_sequencer)转化之后才行,这里肯定可以转化成功,因为,上面解释过m_sequencer指向的是my_sequencer,而使用p_sequencer就是UVM里面通过 在sequence里加了这个宏 去自动实现了上面的$cast ()转化,简化了步骤。
在virtual sequencer里使用的更多,因为,virtual sequencer里存放了很多实际的 sequencer,所以现在这些实际的sequencer作为成员变量,在sequence启动的时候肯定要通过virtual sequencer去调用里实际的sequencer,所以,常常将virtual sequencer作为参数传递到 `uvm_declare_p_sequencer()作为p_sequencer。
解释的有点繁杂,看不明白是我的原因。