目录
RM(reference model)主要使用main phase
在最开始,我想先抛出一句自己的总结,下面的理解就围绕着这个点进行展开:UVM验证环境中所有的组件都是uvm_component,所有组件间传递的信息都是uvm_object。
这一节主要从宏观上讲解uvm_phase,uvm_phase存在于uvm_component中,也就是说,所有的uvm组件都遵循按phase的顺序执行。前几篇简单带过,在仿真时间内,一般按照这样的顺序:初始化环境,初始化配置,发激励,dut出口检查,仿真结束。
因此,UVM提供了phase机制,在不同的phase进行不同的动作,只有当上一个phase执行结束之后,才能进入下一个phase。我们在搭建环境中如何使用呢?以build_phase为例,代码如下:我们定义一个function,名字为build_phase,括号里的参数是uvm_phase,在function内部,调用super.build_phase,super是指向父类的意思,即表示调用父类的build_phase。
UVM中的phase
下图列出了uvm所有的phase,有的phase是function phase,有的phase是task phase。
那么每个phase都做些什么事情呢?根据phase的命名我们可以大致了解到,比如build,是建立阶段,因此这个phase处理组件、变量的实例化。后面还有连接,检查,打印等phase。我们在搭建环境中找到相应的phase去实现功能即可。但是,比如我想在check phase 去输出一些打印信息,相当于做了report phase的事情,实际上也是可以的,只要控制好先后顺序即可,所以使用上还是灵活的。实际上搭建UVM环境,不一定用到所有的phase,比如env主要处理组件之间的连接,那么必定用到connect_phase;参考模型rm主要模拟dut的行为,那么必定要用到main phase。
ENV主要使用哪些phase
下面是一段标准的env代码:主要用了build phase,connect phase,configure phase。
1、build phase
创建ral(寄存器模型),配置ral。(ral在后续章节讲解)
实例化fifo用于连接两个组件的port。
实例化组件:agent,rm,v_sqr。
使用config_db传递参数,这个例子中将cfg传递给v_sqr。
2、connect phase
将ral连接到sequencer。
将fifo的一侧连接到data_in_agent的port,一侧连接到rm的port。
将data_in_agent的sqr连接到vsqr。
3、configure phase
在这个phase,一般进行dut的初始化配置,在这个例子中,调用了configure_dut,这是一个用户自己编写的task,一般是寄存器配置。
RM(reference model)主要使用main phase
下面列出了rm中典型的main phase的代码,当然在rm中,main phase前面的其他phase也要有实例化参数和port的操作。
简单介绍main phase:
首先要执行super.main_phase,这是每个phase中必备的代码。
在while循环中,从port中不断拿到transaction;
使用field automation机制的copy函数将tr赋值到tr.copy。这里会使用复制后的tr_copy进行后续操作,进行复制是为了后续的操作不会改变原始激励。对于比较复杂的设计,原始的激励可能用于进行多个处理,为了不互相干扰,我们会产生tr_copy1,tr_copy2,...tr_copyn等。
产生一个tr_o的实例,将其内部信号进行赋值;
调用tr_o.pack。
最后将预期的tr_o放到对应的port中。
整个平台的phase是怎么配合的
在前几节讲到整个环境的运行从仿真器指定tc开始,在tc中使用如下代码启动env。
env启动之后根据上面env的代码执行build phase,依次执行function phase,当进入run_phase,各个组件是如何配合产生激励和配置的呢?
回看上文的rm代码,在while循环中从port中拿到transaction,只要有transaction放过来就一直取。这是由于data_in_agent只要采样到interface上的信号就会放到port上,而agent的port和rm的port在此前已经建立了连接。同理,sequencer和driver的port也建立好了连接,因此只要sequencer的port中有激励进入,所有的port就会逐级拿到transaction(port与fifo的特性后面讲解)。
激励的产生由sequence的body函数产生,body是在sequencer的run_phase执行的(这里讲到body的时候详细讲解,这里只需要知道body是在run_phase执行)。因此,当环境执行到run_phase,sequence产生的激励发送到driver的seq_item_port,由于已经建立的port的连接,transaction就在各个组件之间不断传递了。