Hi All,
I am writing a sequence for testing outstanding AXI transactions
“Read + write <= 12. All combinations possible”
i.e There could be 12 in-flight writes & 0 in-flight reads
There could be 12 in-flight reads & 0 in-flight writes
There could be x in-flight reads & y in-flight writes such that x + y <= 12
The valid values of AxID are 0 & 1.
Here is my attempt ::
// Within class 'outstanding_reg_seq'
int max_outstanding_txn = 12; // Can be re-assigned from test
bit [4:0] outstanding_txn[bit[1:0]]; // Per ID (0-1) we can have 12 txns. Index would be ID.Elemet would be No. of Oustanding txns !!
bit axid[$]; // Each AxID (0-1) can have 12 Outstanding txns.
typedef enum bit [1:0] { ALL_ZEROES , ALL_ONES , MIX } axid_t;
axid_t axid_type ;
virtual task body();
bit local_ind;
use_response_handler(1);
if( !std::randomize(axid_type) )
`uvm_fatal(get_name(),"Randomization failed!")
else
`uvm_info(get_name(),$sformatf("axid_type chosen as %0s",axid_type.name()),UVM_LOW)
if( axid_type == ALL_ZEROES ) begin
if( ! std::randomize(axid) with { axid.size() == max_outstanding_txn ;
axid.sum() with ( int'( item == 0 ) ) == max_outstanding_txn; } )
`uvm_fatal(get_name(),"Randomization failed!")
end
else if( axid_type == ALL_ONES ) begin
if( ! std::randomize(axid) with { axid.size() == max_outstanding_txn ;
axid.sum() with ( int'( item == 1 ) ) == max_outstanding_txn; } )
`uvm_fatal(get_name(),"Randomization failed!")
end
else begin
`uvm_info(get_type_name(),$sformatf("Sending Mix of AXIDs"),UVM_LOW) // AxID coud be 0/1
if( ! std::randomize(axid) with { axid.size() == max_outstanding_txn ;
axid.sum() with ( int'( item inside {0,1} ) ) == max_outstanding_txn; } )
`uvm_fatal(get_name(),"Randomization failed!")
end
axid.shuffle();
foreach(axid[i]) `uvm_info("AxID",$sformatf("Axid['d%0d]: 'd%0d",i,axid[i]),UVM_LOW)
foreach(reg_addresses[i]) begin
`uvm_info(get_name(),$sformatf("Outstanding txns: 'd%0d",outstanding_txn.sum() with( int'(item) ) ),UVM_LOW)
wait( axid.size() > 0 ); // Else it will pop default value of 0 !!
local_ind = axid.pop_back();
`uvm_create(transfer)
if(!transfer.randomize() with {addr[11:0] == reg_addresses[i]; len == 0; burst == AXI_BURST_TYPE_INCR;
cache == 0; id == local_ind ; prot == 0; qos == 0; region == 0; axuser == 0; size == AXI_SIZE_4BYTE;})
`uvm_fatal(get_name(),"Randomization failed!")
// Call other APIs
outstanding_txn[local_ind]++; // Per ID (0-1) IP can have 12 Outstanding txns.
`uvm_info(get_name(),$sformatf("Outstanding txns: 'd%0d",outstanding_txn.sum() with( int'(item) ) ),UVM_LOW)
`uvm_send(transfer)
end:foreach
// Expectation is that below wait statement ensures that ALL Responses corresponding to transmitted AxID's have been Received
wait( outstanding_txn.sum() with( int'(item) ) == 0 ); // Element for respective ID would be 0 when ALL Responses related to ID have been received
`uvm_info(get_name(), "Completed....",UVM_LOW)
endtask : body
virtual function void response_handler(uvm_sequence_item response);
axi4_transaction resp;
void'($cast(resp,response.clone()));
`uvm_info("Response_handler",$sformatf("Response: %0s",resp.sprint()), UVM_LOW)
// Once response is received for particular ID, it's no longer outstanding for respective ID
outstanding_txn[resp.id]--; // Each Index would be AxID and Each Element would be Outstanding txns for the respective ID
..............
axid.push_back(resp.id); // Available for re-use
endfunction: response_handler
My question is regarding the wait statement at the end of body() task
Would wait( outstanding_txn.sum() with( int’(item) ) == 0 ) ensure that if IP were to send more responses with RID/BID than expected, the wait statement would remain blocked ?