Task execution not blocked when invoked in fork join_none

Written a driver logic and somehow it does not behaves as per my expectation.

Base driver class run_phase:

    //Base driver class run_phase:
    virtual task run_phase(uvm_phase phase);
      forever
        begin : forever_loop
         seq_item_port.get_next_item(txn);
         access(txn);
         if (configuration.return_transaction_response) 
            seq_item_port.item_done(txn);
         else
            seq_item_port.item_done();
      end : forever_loop
    endtask

I extended my driver class from this class and overwritten the access task as below:

   virtual task access( inout REQ txn );
     fork
       //Handle multiple outstanding transaction invoked this task in fork join_none
       handle_write_txns(txn);
     join_none
endtask

handle_write_txns implementation:

 task automatic axi4_if_driver::handle_write_txns(input REQ txn);
   bit done=0;
   
   $display("DEBUG_0");
   repeat(500) @(posedge bfm.a_clk_i);
   $display("DEBUG_1");
   
   wait(done == 1'b1);
   $display("DEBUG_2");
 endtask

I am expecting the simulation should hang even if i send a single sequence item from my sequence. But neither it prints DEBUG_1 message and it does not hangs also. It seems the simulation time is not elapsed in this task at all and the simulation finishes.

Does your test raise any objections?

Why are you using inout argument?

Yes i am raising and dropping objection in my test as below:

task ta_new_axi_vip::main_phase(uvm_phase phase);
simple_reg_seq simple_reg_seq_s = new(“simple_reg_seq_s”);

super.main_phase(phase);
phase.raise_objection(this);
simple_reg_seq_s.start(drv_env_cfg.new_cfg_axi_cfg_s.sequencer);
phase.drop_objection(this);
endtask : main_phase

Also i am using UVM framework code generator to generate the code. And the access task there has the argument as inout. So it is something which comes from UVMF.

Did you check your clock signal is there. It looks like you do not see the posedge of your clock.

Sorry for the delay in communication but it was resolved at my end. I think the issue was with not raising the objection correctly.

So i was raising and dropping the objection only in the test. So as soon as i send all the sequence item from the testcase the test ends because handle_write_txns is starts multiple threads in fork join_none and in the driver component i did not raised any objection to wait until all those threads are completed.
So now i created a queue of all the transactions and raise the objection when queue has some element and wait until the queue is empty to drop the objection. It works okay now.

Your solutions sounds complicated. nd the test is never sending transactions.

Did something like this. Because i believe that the responsibility of the test is to send the transaction item and it may or may not wait for the responses from driver. But still it is the responsibility of the driver to complete all the transactions which it has received. Hence i opted for this solution. But do you think otherwise? Or how better it can be handled?

I am creating the transaction item in the test and sending it. It is just not showed here. Here i have just pasted the driver code.

Inside the run_phase:

fork
begin
forever begin
wait(aw_ch_status.size()>0 || w_ch_status.size()>0 || b_ch_status.size()>0 ||
ar_ch_status.size()>0 || r_ch_status.size()>0);
phase.raise_objection(this, {report_id, “_TXN_START”});
wait(aw_ch_status.size()==0 && w_ch_status.size()==0 && b_ch_status.size()==0 &&
ar_ch_status.size()==0 && r_ch_status.size()==0);
phase.drop_objection(this, {report_id, “_TXN_DONE”});
end
end
join_none

In your code snippet I do not see any transaction. It seems you are checking the size of some queues or dynamic arrays. The transactions are generated from the sequencer when executing a sequence. And the test will end when the sequnce has been completed. We are starting in the test the sequence, This allows us to rais an objecction befor starting the sequence and dropping the objection when the sequence has finished.