我们分别讨论了sequece_item、sequence、sequencer和driver。在本节中,我们将讨论他们如何相互talk,sequencer如何给driver提供从sequence里的sequence item。在开始阅读本节之前,请确保您了解sequencer和driver中使用的所有方法。(参考:UVM seqeuencer和UVM driver ).
sequencer和driver使用双向TLM接口相互通信,以传输REQ和RSP序列项。
driver的uvm_seq_iem_pull _port和相应的sequencer的uvm_seq_item_pull_export连接。这个TLM接口提供了一个工具,可以使用实现的API检索REQ item并返回RSP项。
注:
connections:driver和sequence在UVM agent的connect_phase中连接。
.seq_item_port.connect(.seq_item_export);
seq_item_port和seq_iem_export分别是uvm_seq_itemp_pull_port和uvm_sseq_tem_pull_export的实例句柄(instance handle)。
基于sequence和driver可用的各种方法,进一步解释所有组合。
方法A:Using get_next_item and item_done methods in the driver
方法B:Using get and put methods in driver
// Driver Code
class driver extends uvm_driver#(seq_item);
`uvm_component_utils(driver)
function new(string name = "driver", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
task run_phase (uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
`uvm_info(get_type_name(), "After get_next_item call", UVM_LOW);
#50; // Driving delay. Assuming time taken to drive RTL signals
seq_item_port.item_done();
`uvm_info(get_type_name(), "After item_done call", UVM_LOW);
end
endtask
endclass
// Sequence Code
class base_seq extends uvm_sequence #(seq_item);
seq_item req;
`uvm_object_utils(base_seq)
function new (string name = "base_seq");
super.new(name);
endfunction
task body();
`uvm_info(get_type_name(), "Base seq: Inside Body", UVM_LOW);
//req = seq_item::type_id::create("req");
// or
$cast(req, create_item(seq_item::get_type(), m_sequencer, "req"));
wait_for_grant();
assert(req.randomize());
send_request(req);
`uvm_info(get_type_name(), "Before wait_for_item_done", UVM_LOW);
wait_for_item_done();
`uvm_info(get_type_name(), "After wait_for_item_done", UVM_LOW);
endtask
endclass
Output:
UVM_INFO testbench.sv(21) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO testbench.sv(28) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Before wait_for_item_done
UVM_INFO driver.sv(15) @ 0: uvm_test_top.env_o.agt.drv [driver] After get_next_item call
UVM_INFO driver.sv(19) @ 50: uvm_test_top.env_o.agt.drv [driver] After item_done call
UVM_INFO testbench.sv(30) @ 50: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] After wait_for_item_done
// Driver Code
class driver extends uvm_driver#(seq_item);
`uvm_component_utils(driver)
function new(string name = "driver", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
task run_phase (uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
`uvm_info(get_type_name(), "After get_next_item call", UVM_LOW);
#50; // Driving delay. Assuming time taken to drive RTL signals
req.rsp_b = 1;
seq_item_port.item_done(req);
`uvm_info(get_type_name(), "After item_done call", UVM_LOW);
end
endtask
endclass
// Sequence Code
class base_seq extends uvm_sequence #(seq_item);
seq_item req;
`uvm_object_utils(base_seq)
function new (string name = "base_seq");
super.new(name);
endfunction
task body();
`uvm_info(get_type_name(), "Base seq: Inside Body", UVM_LOW);
//req = seq_item::type_id::create("req");
// or
$cast(req, create_item(seq_item::get_type(), m_sequencer, "req"));
wait_for_grant();
assert(req.randomize());
send_request(req);
`uvm_info(get_type_name(), "Before wait_for_item_done", UVM_LOW);
wait_for_item_done();
`uvm_info(get_type_name(), "After wait_for_item_done", UVM_LOW);
get_response(req);
`uvm_info(get_type_name(), $sformatf("After get_response: rsp_b = %0d", req.rsp_b), UVM_LOW);
endtask
endclass
Output:
UVM_INFO testbench.sv(21) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO testbench.sv(28) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Before wait_for_item_done
UVM_INFO driver.sv(15) @ 0: uvm_test_top.env_o.agt.drv [driver] After get_next_item call
UVM_INFO driver.sv(20) @ 50: uvm_test_top.env_o.agt.drv [driver] After item_done call
UVM_INFO testbench.sv(30) @ 50: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] After wait_for_item_done
UVM_INFO testbench.sv(32) @ 50: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] After get_response: rsp_b = 1
// Driver Code
class driver extends uvm_driver#(seq_item);
`uvm_component_utils(driver)
function new(string name = "driver", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
task run_phase (uvm_phase phase);
forever begin
seq_item_port.get(req);
`uvm_info(get_type_name(), "After get call", UVM_LOW);
#50; // Driving delay. Assuming time taken to drive RTL signals
req.rsp_b = 1;
seq_item_port.put(req);
`uvm_info(get_type_name(), "After put call", UVM_LOW);
end
endtask
endclass
// Sequence Code
class base_seq extends uvm_sequence #(seq_item);
seq_item req;
`uvm_object_utils(base_seq)
function new (string name = "base_seq");
super.new(name);
endfunction
task body();
`uvm_info(get_type_name(), "Base seq: Inside Body", UVM_LOW);
//req = seq_item::type_id::create("req");
// or
$cast(req, create_item(seq_item::get_type(), m_sequencer, "req"));
wait_for_grant();
assert(req.randomize());
send_request(req);
`uvm_info(get_type_name(), "Before wait_for_item_done call", UVM_LOW);
wait_for_item_done();
`uvm_info(get_type_name(), "After wait_for_item_done call", UVM_LOW);
get_response(req);
`uvm_info(get_type_name(), $sformatf("After get_response: rsp_b = %0d", req.rsp_b), UVM_LOW);
endtask
endclass
Output:
UVM_INFO testbench.sv(21) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO testbench.sv(28) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Before wait_for_item_done call
UVM_INFO driver.sv(15) @ 0: uvm_test_top.env_o.agt.drv [driver] After get call
UVM_INFO testbench.sv(30) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] After wait_for_item_done call
UVM_INFO driver.sv(20) @ 50: uvm_test_top.env_o.agt.drv [driver] After put call
UVM_INFO testbench.sv(32) @ 50: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] After get_response: rsp_b = 1