Use Case: AXI DMA控制器有128个独立的通道,可以并行进行读写操作。首先我们对AXI DMA控制器的top level的事务进行建模,如下:
class axi_dmac_transaction extends uvm_transaction;
rand axi_chan_transaction axi_chan[axi_dmac_dec::CHAN_NUM];
function new(string name = "axi_dmac_transaction ");
super.new(name);
`uvm_info("TRACE", $sformatf("%m"), UVM_DEBUG)
endfunction
endclass
那么如何进行多通道事务的例化及随机呢?这里利用到了uvm object的pre_randomize函数:
function void pre_randomize();
foreach(axi_chan[i]) begin
axi_chan[i] = axi_chan_transaction ::type_id::create($sformatf("axi_chan[%0d]",i));
end
endfunction
这样就可以在接下来调用axi_dmac_transaction的随机化,从而实现axi_chan_transaction的各个实例的随机化。
如果开启的DMA的通道数量不确定,我们可以利用队列来进行实现:
class axi_dmac_transaction extends uvm_transaction;
rand int chan_num;
rand axi_chan_transaction axi_chan[$];
constraint c_chan_num {
chan_num inside {[1:128]};
axi_chan.size == chan_num;
}
function new(string name = "axi_dmac_transaction ");
super.new(name);
`uvm_info("TRACE", $sformatf("%m"), UVM_DEBUG)
endfunction
function void pre_randomize();
endfunction
endclass
这时候,调用axi_dmac_transaction
的随机化,队列axi_chan
用chan_num
个axi_chan_transaction
句柄,但是句柄的值是空的,因此我们需要进行实例化,该操作可在post_randomize
函数中完成:
function void post_randomize();
`uvm_info("TRACE", $sformatf("%m"), UVM_DEBUG)
foreach(axi_chan[i]) begin
axi_chan[i] = axi_chan_transaction ::type_id::create($sformatf("axi_chan[%0d]",i));
assert(axi_chan[i].randomize());
end
endfunction