在使用AXI-VIP验证时,需要检查AXI的outstanding数,由于VIP的monitor port本身仅监测单笔burst,而outstanding涉及多笔burst,可以采用回调机制实现:
- 从 svt_axi_port_monitor_callback 类扩展用户自定义回调类 cust_svt_axi_monitor_callback。
class cust_svt_axi_monitor_callback extends svt_axi_port_monitor_callback ;
...
endclass
- 在callback类内定义变量如 num_outstanding_xact 来存储上述用户定义类中outstanding事务的总数,或也可定义num_read_outstanding_xact/num_write_outstanding_xact变量分别存储读/写outstanding事务数。
int num_outstanding_xact = 0;
int num_read_outstanding_xact = 0;
int num_write_outstanding_xact = 0;
- 在callback类内实现 new_transaction_started 和 transaction_ended 方法以统计outstanding数,并可添加一些log打印信息:
virtual function void new_transaction_started (svt_axi_port_monitor axi_monitor,
svt_axi_transaction item);
super.new_transaction_started(axi_monitor, item);
num_outstanding_xact++;
if(item.xact_type == svt_axi_transaction::READ) begin
num_read_outstanding_xact++;
end
else if (item.xact_type == svt_axi_transaction::WRITE) begin
num_write_outstanding_xact++;
end
`uvm_info(get_type_name(), $sformatf("num_outstanding_xact %d", num_outstanding_xact), UVM_LOW)
`uvm_info(get_type_name(), $sformatf("num_read_outstanding_xact %d", num_read_outstanding_xact), UVM_LOW)
`uvm_info(get_type_name(), $sformatf("num_write_outstanding_xact %d", num_write_outstanding_xact), UVM_LOW)
endfunction
virtual function void transaction_ended (svt_axi_port_monitor axi_monitor,
svt_axi_transaction item);
super.transaction_ended(axi_monitor, item);
num_outstanding_xact--;
if(item.xact_type == svt_axi_transaction::READ) begin
num_read_outstanding_xact--;
end
else if (item.xact_type == svt_axi_transaction::WRITE) begin
num_write_outstanding_xact--;
end
endfunction
- 现在,变量num_outstanding_xact内存储了相应的outstanding事务数,可以在 new_transaction_started 方法内检查相应outstanding值是否超过规定值了,例如:
if(num_read_outstanding_xact > `REQ_NUM)
`uvm_error(get_type_name(), $sformatf("read outstanding depth exceeds!, num_read_outstanding_xact is %d, the depth is set to %d", num_read_outstanding_xact, `REQ_NUM))
- 最后需要在 axi_basic_env.sv 内为 slave agent 添加callback对象。
virtual function void connect_phase(uvm_phase phase);
cust_svt_axi_monitor_callback cb1;
`uvm_info("connect_phase", "Entered...",UVM_LOW)
cb1 = new("cust_svt_axi_monitor_callback_slave");
uvm_callbacks#(svt_axi_port_monitor)::add(axi_system_env.slave[0].monitor,cb1);
endfunction