Forever statement does not finish with Objection

I’m trying to finish the forever statement with objection mechanism in UVM.


`include "uvm_macros.svh"
import uvm_pkg::*;

`include "seq_item.sv"
`include "sequencer.sv"
`include "driver.sv"
`include "agent.sv"
`include "env.sv"

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");

    start_item(req);
    assert(req.randomize());
    finish_item(req);
    

    begin
      uvm_sequence_base parent = req.get_parent_sequence();
    end


  fork begin      
    fork          
      //Process-1 
      begin       
        sub_process1();       
      end         
      //Process-2 
      begin       
        sub_process2();       
      end         
    join_any      
    disable fork; 
  end join        
    $display("-----------------------------------------------------------------");
    $display($time,"\tAfter disable-fork");
    $display("-----------------------------------------------------------------");
  endtask

  //Sub-Process   
  task automatic sub_process1;
    forever begin 
    $display($time,"\tSub-Process1 Started");
    #5;
    $display($time,"\tSub-Process1 Finished");
    end
  endtask         
     
  task automatic sub_process2;
    forever begin 
    $display($time,"\tSub-Process2 Started");
    #10;
    $display($time,"\tSub-Process2 Finished");
    end
  endtask         

endclass


class base_test extends uvm_test;
  env env_o;
  base_seq bseq;

  `uvm_component_utils(base_test)
  
  function new(string name = "base_test", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    env_o = env::type_id::create("env_o", this);
    bseq  = base_seq::type_id::create("bseq", this);
    end
  endfunction
 
  task run_phase(uvm_phase phase);
    phase.raise_objection(this);
    fork
      repeat(3) begin
      bseq.start(env_o.agt.seqr);
      end
    join
    phase.drop_objection(this);
  endtask
endclass

module tb_top;
  initial begin
    run_test("base_test");
  end
endmodule

But it does not finish. I thought that the objection governs the whole process of simulation.

In reply to UVM_LOVE:

The sequence is the stimulating part in your UVM environment. If you have there a forever loop inside it will never come to an end.

bseq.start(env_o.agt.seqr);

is running forever. Never the drop_objection will be called.

In reply to chr_sue:

I don’t get it. Which part can have an available forever loop inside it?

In reply to UVM_LOVE:

Your bseq body has a fork/join_any containing two statements that call tasks with forever loops. That means the join_any blocks the body from returning, so the repeat loop in the run_phase only executes the first iteration, and the fork/join never finishes so it never executes the phase drop_objection(this) that follows it.

In reply to dave_59:

I capture the log from the simulation.

              50  Sub-Process1 Started
              50  Sub-Process2 Started
              55  Sub-Process1 Finished
              55  Sub-Process1 Started
              60  Sub-Process2 Finished
              60  Sub-Process2 Started
              60  Sub-Process1 Finished
              60  Sub-Process1 Started
              65  Sub-Process1 Finished
              65  Sub-Process1 Started
              70  Sub-Process2 Finished
              70  Sub-Process2 Started
              70  Sub-Process1 Finished

Both sub_process-1 and sub_Process-2 will start at the same time, sub_Process-1 will finish at 55ns and Process-2 will finish at 60ns.

As I understand the fork-join_any will be unblocked at 55ns.
If sub_process1 has finished then it will disable fork and go to the drop_objection.

If I missed something, could you please help me understand how to properly modify the code?

In reply to UVM_LOVE:

The messages you are displaying “Sub-Process Finished” are not correct. The process does not finish, only one iteration of the forever loop finishes, and then it starts again.

In reply to dave_59:

If the display is wrong, How do I check whether processor finished or not instead of $display?

In reply to UVM_LOVE:

If you remove the forever keywords, you get the behavior it seems you want.