blob: 4e956e21211e98339d75529ad100538f426a6916 [file]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// TL host sequence supports multiple outstanding requests
// It generates 'req_cnt' number of completely random requests
class tl_host_seq #(type REQ_T = tl_seq_item) extends tl_host_base_seq #(REQ_T);
rand int unsigned req_cnt;
// if enabled, req will be aborted if it's not accepted after given valid length
rand bit req_abort_after_a_valid_len;
// chance to abort req
int req_abort_pct = 0;
REQ pending_req[$];
int min_req_delay = 0;
int max_req_delay = 10;
`uvm_object_param_utils(tl_host_seq #(REQ_T))
`uvm_object_new
constraint req_abort_after_a_valid_len_c {
req_abort_after_a_valid_len dist {
1 :/ req_abort_pct,
0 :/ 100 - req_abort_pct
};
}
virtual task body();
set_response_queue_depth(-1);
fork
begin : wait_response_thread
for (int i = 0; i < req_cnt; i++) begin
REQ req;
bit found_req;
get_response(rsp);
`uvm_info(`gfn, $sformatf("Received rsp[%0d] : %0s",
i, rsp.convert2string()), UVM_HIGH)
// in case of out of order rsp, find req that has same source as rsp
foreach (pending_req[i]) begin
if (rsp.d_source == pending_req[i].a_source) begin
req = pending_req[i];
pending_req.delete(i);
process_response(req, rsp);
found_req = 1;
break;
end
end // foreach
if (!found_req && !csr_utils_pkg::under_reset) begin
`uvm_error(`gfn, $sformatf("fail to find matching req for rsp[%0d]: %0s",
i, rsp.convert2string()))
end
end // for
end : wait_response_thread
begin : request_thread
`uvm_info(`gfn, $sformatf("Start sending %0d host requests", req_cnt), UVM_HIGH)
for (int i = 0; i < req_cnt; i++) begin
req = REQ::type_id::create("req");
pre_start_item(req);
start_item(req);
randomize_req(req, i);
post_randomize_req(req, i);
pending_req.push_back(req); // in case of device same cycle response
finish_item(req);
`uvm_info(`gfn, $sformatf("Sent req[%0d] : %0s",
i, req.convert2string()), UVM_HIGH)
end
end : request_thread
join
`uvm_info(`gfn, $sformatf("Finished sending %0d host requests", req_cnt), UVM_HIGH)
endtask
// Invoked after creating the req and before invoking start_item(req). Suitable for inserting
// delays before start_item(). Example: avoid running out of source IDs.
virtual task pre_start_item(REQ req);
endtask
// Request randomization, override this function to do custom request generation. Invoked after
// start_item(). Not suitable for setting a_source, since that is handled in
// `tl_host_base_seq::finish_item()` instead, to facilitate late randomization when accesses are
// initiated from UVM RAL.
virtual function void randomize_req(REQ req, int idx);
if (!(req.randomize() with {
a_valid_delay inside {[min_req_delay:max_req_delay]};})) begin
`uvm_fatal(`gfn, "Cannot randomize req")
end
endfunction
// callback after randomize seq, extened seq can override it to handle some non-rand variables
virtual function void post_randomize_req(REQ req, int idx);
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(req_abort_after_a_valid_len)
req.req_abort_after_a_valid_len = req_abort_after_a_valid_len;
endfunction
// A reserved function that can be extended to process response packet
virtual function void process_response(REQ req, REQ rsp);
endfunction
endclass : tl_host_seq