UVM中Sequence-Sequencer-Driver之间的通信

文摘   2024-10-10 19:17   上海  

We discussed sequece_item, sequence, sequencer, and driver independently. In this section, we will discuss how they talk with each other and provide sequence items from sequence to driver via the sequencer. Before you start reading this section, make sure you are aware of all methods used in sequencer and driver. (Refer: UVM Sequencer and UVM Driver).

Sequencer-Driver Connections

The sequencer and driver communicate with each other using a bidirectional TLM interface to transfer REQ and RSP sequence items.


The driver has uvm_seq_item_pull_port which is connected with uvm_seq_item_pull_export of the associated sequencer. This TLM interface provides a facility to use implemented API to retrieve REQ items and turn RSP items.


Note: 

  1. Both uvm_seq_item_pull_port and uvm_seq_item_pull_export are parameterized classes with REQ and RSP sequence items.

  2. The TLM connection between driver and sequencer is one-to-one. It means neither multiple sequencers are connected to a single driver nor multiple drivers connected to a single sequencer.

Connections: The driver and sequencers are connected in the connect_phase of the UVM agent.

<driver_inst>.seq_item_port.connect(<sequencer_inst>.seq_item_export);

Where,

The seq_item_port and seq_item_export are an instance handle for uvm_seq_item_pull_port and uvm_seq_item_pull_export respectively.


Sequence-Sequencer-Driver

communication Approaches

Based on the varieties of methods available with sequence and driver, all combinations are explained further.

Approach A: Using get_next_item and item_done methods in the driver

Approach B: Using get and put methods in driver

A. Using get_next_item and item_done methods in the driver

Without RSP packet

  1. Create a sequence item and register in the factory using the create_item function call. 

  2. The wait_for_grant issues request to the sequencer and wait for the grant from the sequencer. It returns when the sequencer has granted the sequence. 

  3. Randomize the sequence item and send it to the sequencer using send_request call. There should not be any simulation time delay between wait_for_grant and send_request method call. The sequencer forwards the sequence item to the driver with the help of REQ FIFO. This unblocks the get_next_item() call and the driver receives the sequence item.

  4. The wait_for_item_done() call from sequence gets blocked until the driver responds back.

  5. In the meantime, the driver drives the sequence item to the DUT using a virtual interface handle. Once it is completed, the item_done method is called. This unblocks the wait_for_item_done method from the sequence.

  6. If a response has to be sent from the driver to the sequence, item_done(RSP) is called with the RSP item as an argument. The RSP item is communicated to the sequence by a sequencer with help of RSP FIFO. It is important to call the get_response method to get the response. This step is optional and not required if the RSP item is not sent by the DUT.

// Driver Codeclass 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  endtaskendclass
// Sequence Codeclass 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); endtaskendclass
Output:
UVM_INFO testbench.sv(21) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside BodyUVM_INFO testbench.sv(28) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Before wait_for_item_doneUVM_INFO driver.sv(15) @ 0: uvm_test_top.env_o.agt.drv [driver] After get_next_item callUVM_INFO driver.sv(19) @ 50: uvm_test_top.env_o.agt.drv [driver] After item_done callUVM_INFO testbench.sv(30) @ 50: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] After wait_for_item_done


With RSP packet

When the driver sends the RSP item to the sequence.

// Driver Codeclass 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  endtaskendclass
// Sequence Codeclass 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); endtaskendclass
Output:
UVM_INFO testbench.sv(21) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside BodyUVM_INFO testbench.sv(28) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Before wait_for_item_doneUVM_INFO driver.sv(15) @ 0: uvm_test_top.env_o.agt.drv [driver] After get_next_item callUVM_INFO driver.sv(20) @ 50: uvm_test_top.env_o.agt.drv [driver] After item_done callUVM_INFO testbench.sv(30) @ 50: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] After wait_for_item_doneUVM_INFO testbench.sv(32) @ 50: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] After get_response: rsp_b = 1


B. Using get and put methods in driver

  1. Create a sequence item and register in the factory using the create_item function call.

  2. The wait_for_grant issues the request to the sequencer and wait for the grant from the sequencer. It returns when the sequencer has granted the sequence.

  3. Randomize the sequence item and send it to the sequencer using send_request call. There should not be any simulation time delay between wait_for_grant and send_request method call. The sequencer forwards the sequence item to the driver with the help of REQ FIFO. This unblocks the get() call and the driver receives the sequence item.

  4. The wait_for_item_done() call from the sequence gets blocked until the driver calls the get method.

  5. Once the get method is called, the wait_for_item_done() call from sequence gets unblocked immediately without caring about driving the virtual interface.

  6. The get_response call is necessary to call that completes the communication. The get_response method is blocked until the driver calls put(RSP).

  7. In the meantime, the driver drives the sequence item to the DUT using a virtual interface handle. Once it is completed, the put(RSP) method is called. This unblocks the get_response method from the sequence. The RSP item is communicated to the sequence by a sequencer with help of RSP FIFO.

// Driver Codeclass 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  endtaskendclass
// Sequence Codeclass 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); endtaskendclass
Output:
UVM_INFO testbench.sv(21) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside BodyUVM_INFO testbench.sv(28) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Before wait_for_item_done callUVM_INFO driver.sv(15) @ 0: uvm_test_top.env_o.agt.drv [driver] After get callUVM_INFO testbench.sv(30) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] After wait_for_item_done callUVM_INFO driver.sv(20) @ 50: uvm_test_top.env_o.agt.drv [driver] After put callUVM_INFO testbench.sv(32) @ 50: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] After get_response: rsp_b = 1


欢迎加入知识星球。每天都会解答大家提出的技术问题。欢迎加入知识星球,助您快速成长。
最后,由于TX修改规则,为了不错过后续内容,欢迎加入QQ群,

另外,由于微信群已经超过200人,添加小编的微信,拉你进入WX学习群。

最后的最后,如果对您有帮助,希望点个“在看”。好好学习,天天向上

芯片验证日记
分享芯片验证相关的知识。
 最新文章