怎么在sequence中调用agent中的函数以及如何快速实验你的想法?

2021-09-10 15:36:30 浏览数 (2)

来源| 杰瑞IC验证(ID:Jerry_IC)

|原创作者| Jerry

最近略忙,今天就给大家表演个胸口碎……码一段代码。

通过本篇文章主要想送给广大验证初学者和爱好者2件礼物:“一条鱼”和“一只鱼竿”。希望大家连吃带拿,开开心心地。

“一条鱼”就是题目中的那个问题本身:“UVM中怎么在sequence中调用agent中的函数”。这个问题很多同学猛的听到可能还是会有一些懵,反应不出一个优雅的解决方法。

“一只鱼竿”就是当你遇到这样一个问题的时候,怎么快速写一段代码验证你的想法是不是可以实现,也就是Jerry今天带你解决这个问题的过程。

好了,我们开车~

本文由“壹伴编辑器”提供技术支持

众所周知,在UVM中一个标准的agent里面例化着driver、monitor、sequencer组件,发激励时通过“游离”在agent中的sequence产生transaction,借助sequencer给driver进而发出激励。

但是“游离”在agent中的sequence怎么访问agent中的函数呢?

有人说可以使用config_db机制:在某个地方如env中把agent set出去,然后在sequence中用config_db机制的get拿到agent的资源,进一步在sequence中调用agent中的函数。

这样确实可以实现功能,但是不太优雅,他需要借助除了sequence本身的“外力”, 需要在别处多写几行代码来set agent。

当然了,对于这种函数调用需求我们其实还可以通过之前讲的单例模式(IC验证er一起学点设计模式(1)---单例模式),做成全局组件来实现,本文就不提了,大家自己探索。

那怎么做才能比较优雅呢?

先说结论:p_sequencer机制 get_parent()“两步跳跃法”。

第一步,通过UVM中的p_sequencer机制,sequence可以通过p_sequencer访问到它对应的sequencer一层的成员。

第二步,到了sequencer这一层,我们发现sequencer属于UVM树结构中的一个节点,例化它的agent也属于UVM树的节点,那就好办了。通过get_parent()函数可以得到UVM树中当前实例的parent。而我们要的agent正好就是sequencer的parent。

话不多说,试验下这个玩法~

我们怎么才能快速的写一段代码来验证这个想法呢?

想想我们的目的就是写一段代码跑起来实验下能不能搞定我们的问题,不是做一个验证项目,所以没必要写一个完整的UVM验证平台,甚至没有必要维护多个文件。我们需要能快速建立一个极简的又能达到实验目的“最小化验证平台”。

想清楚需求我们就开始设计我们代码结构了,我们的“最小化验证平台”肯定没必要加DUT了,那interface也肯定不需要了,env也不要了,直接例化agent,我们验证的问题对于agent中的driver和monitor没啥关系也都直接舍弃,transaction我们也用不到,也扔了。所以我们的UVM平台的结构就是:base_test中例化agent,agent中只例化一个sequencer,然后一个sequence,最后再加一个top module即可。

好了,4个class和1个module,基本上已经做到“最小化”了,再多再少不差那两三行了,上代码~

代码段1

首先,如代码段1,我们定义了一个极简的jerry_sequencer,其中第11行,定义了名叫hello()的函数,这个函数就一句打印信息,便于我们后面调用实验。

代码段2

接着,代码段2定义了一个极简的jerry_agent,在这里声明和例化了jerry_sequencer,此外在25行依然定义了名叫hi()的函数,也就是一句打印信息。

代码段3

然后,代码段3中我们定义了名叫jerry_seq的sequence。这个是我们实现今天功能的重点代码。

代码段4

最后,在代码段4中定义了jerry_base_test来例化jerry_agent,同时通过default_seq机制启动jerry_sequence。并且定义了名叫top的module,核心就58行一句话,通过run_test启动jerry_base_test。

我们再明确下要解决的问题是“怎么在sequence中调用agent中的函数?” ,基于这几个代码段,具体化为:“怎么在jerry_sequence中调用jerry_agent中的hi()函数?”

我们重点看下前面提到的“两步跳跃法”的功能实现:

1.

在代码段3的33行,我们使用了`uvm_declare_p_sequencer宏,声明类型为jerry_sequencer。顺便提一下,在37行,通过p_sequencer调用了jerry_sequencer(代码段1)中定义的hello()函数。如果其中的句子打印成功,说明我们此时p_sequencer机制触发成功。

2.

在代码段的34行,我们声明了一个更加原始的uvm_component类型的句柄parent,在38行中把它指向了jerry_agent的对象上。

tips1:通过get_parent()函数,指向了jerry_sequencer的parent 即jerry_agent。

tips2:顺便提一嘴为什么它parent是jerry_agent?因为代码段2的22行例化时传入的“this”参数)

在39行通过$cast函数,我们让35行声明的jerry_agent类型的句柄agt,通过和parent句柄的类型匹配,指向了jerry_agent的对象上。

终于,在40行,我们通过agt句柄,调用jerry_agent中的函数hi()。如果成功打印其中的字符串就说明我们实现了我们的目标。

上面的所有代码片段,按照正确的顺序写到文件里,在前面include进来 uvm_macros.svh,以及include且import uvm_pkg后,便可以直接运行。运行成功后,屏幕上果然会打出hello()和hi()函数中的字符串:

hello,how are you!

hi,I’m fine,thank you~and you?

结语

今天jerry送给大家“一条鱼”和“一只鱼竿”;

“一条鱼”是解决了“UVM里怎么在sequence中调用agent中的函数”的问题;

更重要的“一只鱼竿”,即传递了“最小化验证平台”的实现思想和代码实现过程;

有了“最小化验证平台”的思想,可以最快最简单的把你的想法跑起来,验证它的正确性,提高学习与实验的效率。

顺便说一个题外话,有问题和想技术交流的小伙伴建议在公众号内点击“关于我们”—>“联系我们”,加杰瑞IC验证小助手的微信来留言和交流,后台直接提问有时候Jerry会漏掉和错过回复时间导致超时无法回复,和之前后台提问没给回复的同学说一声sorry。

哈哈,时光如水,又到了说再见的时候,祝愿大家越来越牛逼,加油!

——The End——

0 人点赞