UVM(九)之sequencej机制续1
当一个sequence启动起来之后,UVM会自动执行sequence的body任务,所以要产生各种和杨的激励,就要写好body任务。
body这个任务完成的事情与gen_pkt函数相似,只是不同的是,gen_pkt可以直接通过一个ref形式的参数把产生的transaction交给driver,而sequence则需要使用通信的方式来传递,如下入所示:
由于传递方式的改变,所以产生transaction的方式也就有了不同。一个transaction应该这样产生:
要产生一个transaction,要分成四步:第一步就是实例化,第二部就是调用start_item,第三部就是执行randomize过程,第四部就是调用finish_item。由于是牵扯到sequencer和driver的通信,因此这里就有一个主动和被动的过程。当driver中使用seq_item_port.get_next_item主动请求一个item(transaction)时,sequencer会要求sequence产生一个item(transaction);产生完成后,sequence就要等待driver把item(transaction)取走,这需要driver显示调用seq_item_port.item_done()。当此函数被调用后,finish_item才会返回,一个transaction的产生才真正的完成。
仔细观察这四步,其中只有第三部才会有一些差异,而另外的三步则是固定不变的。针对这种情况,UVM推出了uvm_do系列宏来简化产生transaction的过程。如上,使用uvm_do宏就可以简写为:
一个宏封装了产生item的四个步骤,相当于把所有的事情做完了,极大的方便了使用。除了uvm_do宏之外,uvm_do系列宏中另外一个经常使用的就是uvm_do_with。它的使用方式如下:
使用uvm_do_with宏之后,那么产生transaction的第三部中的assert(tr.randomize() with {tr.crc_err == 1};如果需要发送多个包(其中pkt_num是要发送的包的数量):
假设一个产生特定crc_err的包的sequence如下:
另外一个sequence如下:
现在我们要写一个新的sequence,他可以替代上面的两种包,可以这样写:
这样写起来似乎显得特别的麻烦。产生的两种不同的包中,第一个约束条件有两个,第二个约束条件有三个,但是加入约束条件有10个呢?如果我们有整个验证平台中有30个case都用到了这样一个包,那么就要在这30个case中加入10行这样的代码,这是一件非常恐怖的事情,而且特别容易出错。既然我们已经定义好了crc_seq和long_seq,那么可以作为一个sequence的变量为参数。
把定义好的sequence作为uvm_do的参数,这样就实现了sequence的重用。