Support back to back transactions in UVM driver

In reply to chr_sue:

Hi Chris,

My Sequence body looks like this:
// Sequence body


task some_seq::body();
 // Start item
  start_item(item_h);
  // finish item
  finish_item(item_h);
  // wait reponse
  get_response(item_h);
endtask

My Driver looks like this:


task drv::run_phase(uvm_phase phase);
  @(m_vif.drv_cb iff (m_vif.rst_n === 0));
  // Reset signals
  reset_signals();
  @(m_vif.drv_cb iff (m_vif.rst_n === 1));
 // Start driving 
  get_and_drive();
endtask : run_phase

task drv::get_and_drive();
  process main_thread;
  process rst_mon_thread;

  forever begin
   //Don't drive during reset
   while(m_vif.rst_n !== 1)
     @(m_vif.drv_cb iff (m_vif.rst_n === 1));

   //Get the next item from the sequencer
   seq_item_port.get_next_item(req);
   if(!$cast(rsp, req.clone())) begin
     `uvm_fatal(get_type_name(), "run_phase::Cast rsp<-req failed!")
   end

   rsp.set_id_info(req);

   //Drive current transaction
   fork 
     //Drive the transaction
     begin
       main_thread=process::self();
       drive_item(rsp);
       if(rst_mon_thread) rst_mon_thread.kill();
     end
     // Monitor the reset signal
     begin
       rst_mon_thread=process::self();
       @(negedge m_vif.rst_n) begin
         if(main_thread) main_thread.kill();
         //Do reset
         reset_signals();
       end
     end
   join_any

   //Send item_done and a response to the sequencer
   seq_item_port.item_done();
   seq_item_port.put_response(rsp);
  end // forever
endtask : get_and_drive

task drv::drive_item(ref item_t item_h);
 //Drive the req
 if(item_h.m_trans_type == FIRST_TYPE) begin 
   automatic int delay_cycles = $urandom_range(m_cfg_h.min_dly,m_cfg_h.max_dly);
   repeat (delay_cycles)
     @(m_vif.drv_cb);
   if(some_condition) begin
    m_vif.drv_cb.One_Valid <= 1;
    m_vif.drv_cb.One_Hdr <= item_h.m_hdr;
   end
   else begin
     automatic item_t auto_item_h = item_h;
     check_one_credits_and_drive(auto_item_h); //time consuming task
   end
    @(m_vif.drv_cb);
    m_vif.drv_cb.One_Valid <= 0;
  end
 else if(item_h.m_trans_type == SECOND_TYPE) begin
   automatic int delay_cycles = $urandom_range(m_cfg_h.min_dly,m_cfg_h.max_dly);
   repeat (delay_cycles)
   if(some_condition) begin
     m_vif.drv_cb.Second_Valid <= 1;
     m_vif.drv_cb.Second_Hdr <= item_h.m_hdr;
     m_vif.drv_cb.Second_Data <= item_h.m_data;
   end
   else begin
     automatic item_t auto_item_h = item_h;
     check_two_credits_and_drive(auto_item_h); //time consuming task
   end
   @(m_vif.drv_cb);
   m_vif.drv_cb.Second_Valid <= 0;
 end 
endtask :drive_item