1. 从“单兵作战”到“集团军指挥”:为什么我们需要virtual sequence和virtual sequencer?
刚开始接触UVM验证的时候,我们写的sequence通常都很“单纯”。比如,你有一个AXI总线的主设备,那么你就写一个AXI的sequence,里面用uvm_do宏生成几个transaction,然后通过start()方法挂载到对应的AXI sequencer上。这个sequencer再把transaction交给driver,驱动到接口上。整个过程清晰明了,就像是一个士兵(sequence)听从一个班长(sequencer)的指挥,完成一项具体的任务。
但是,真实的芯片验证场景,哪有这么简单?想象一下,你现在要验证一个复杂的SoC子系统,比如一个数据通路模块。这个模块一头连着几个数据输入通道(Channel),另一头连着一个格式化输出单元(Formatter),中间还受控于一个配置寄存器(Register)模块。验证这个模块,你需要同时做几件事:给几个通道发送不同模式的数据包;动态配置格式化器的参数;还要时不时地读写寄存器来改变模块的工作模式。
这时候,如果你还用“单兵作战”的思路,问题就来了。你写了三个sequence:一个发数据的data_seq,一个配寄存器的reg_cfg_seq,一个控制格式化器的fmt_seq。你怎么让它们协同工作?难道在测试用例(test)里,一个一个地start,然后用fork...join把它们并行起来?且不说代码会变得臃肿混乱,更关键的是,它们之间的时序和逻辑依赖关系很难优雅地描述。比如,你必须先完成寄存器的基本配置,才能启动数据流;或者,在测试的某个阶段,需要暂停通道0的数据,单独对通道1进行压力测试。
这种需要跨多个sequencer、协调多种类型sequence执行流程的场景,就是virtual sequence和virtual sequencer大显身手的地方。你可以把virtual sequencer想象成集团军的“指挥部”,它本身不直接带兵打仗(不产生具体的transaction),但它手里掌握着所有一线作战部队(各个底层sequencer)的通讯录(句柄)。而virtual sequence,就是坐在这个指挥部里的“总指挥”,它根据作战计划(测试场景),通过指挥部里的通讯录,向不同的部队下达精确的、有时序要求的命令(启动具体的sequence)。
我刚开始在项目里用这组机制时,感觉就像打开了新世界的大门。以前那种在test里手忙脚乱协调多个sequence的“土办法”被彻底抛弃了,测试场景的抽象度和可控性上了好几个台阶。接下来,我就结合一个具体的案例,带你看看这个“指挥部”和“总指挥”是怎么搭建和工作的。
2. 核心角色拆解:virtual sequencer如何成为“路由枢纽”?
我们先来深入看看virtual sequencer。很多新手容易把它想复杂了,其实它的定义非常简单。从代码继承关系上说,它就是一个普通的uvm_sequencer,并没有什么特殊的基类。
class mcdf_virtual_sequencer extends uvm_sequencer;
// 1. 声明各个底层sequencer的句柄
cr_master_sequencer cr_sqr;
reg_master_sequencer reg_sqr;
chnl_master_sequencer chnl_sqr0;
chnl_master_sequencer chnl_sqr1;
chnl_master_sequencer chnl_sqr2;
fmt_slave_sequencer fmt_sqr;
`uvm_component_utils(mcdf_virtual_sequencer)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass
看上面的代码,mcdf_virtual_sequencer的核心作用就一点:声明并容纳多个底层sequencer的句柄。你可以把它看作一个“句柄容器”或者“路由表”。cr_sqr、reg_sqr、chnl_sqr0等等,这些句柄在virtual sequencer创建之初都是空的(null)。它自己并不知道这些cr_sqr具体对应环境中的哪个agent下面的sequencer实体。
那么,谁来把这些“名字”和“真人”对上号呢?答案是顶层的环境类(uvm_env)。这步操作通常发生在环境的connect_phase。这个阶段,环境中所有的组件都已经构建(build)好了,实体对象都存在于内存中,正是进行“连线”的好时机。
class mcdf_env extends uvm_env;
// 声明各个具体的agent
cr_master_agent cr_agt;
reg_master_agent reg_agt;
chnl_master_agent chnl_agt0;
chnl_master_agent chnl_agt1;
chnl_master_agent chnl_agt2;
fmt_slave_agent fmt_agt;
// 声明virtual sequencer
mcdf_virtual_sequencer virt_sqr;
`uvm_component_utils(mcdf_env)
// ... new和build_phase省略,其中需


917

被折叠的 条评论
为什么被折叠?



