Fork-join construct is used in the function of member class in OVM

Using fork-join (parallel blocks) construct in functions are not LRM compliant. Here, this construct is used in the member function of class ovm_component.

Code snippet from ovm_component.sv file:

function void ovm_component::do_exit_action(ovm_report_object object);
  if ( ovm_top_levels.size() ) begin
    ovm_component nc;
   **fork**
      global_stop_request();
   **join_none**
    if( $cast(nc, object) ) begin
      if ( nc.m_env != null ) object.die();
    end
  end
  else begin
    object.die();
  end
endfunction

fork…join_none is harmless as it doesn’t block. I vaguely remember this was discussed in SV-EC/BC commitee. VCS has been allowing this for years so it looks like all 3 tools allow this.

Ajeetha, CVC
www.noveldv.com

fork…join_none is harmless as it doesn’t block. I vaguely remember this was discussed in SV-EC/BC commitee. VCS has been allowing this for years so it looks like all 3 tools allow this.
Ajeetha, CVC
www.noveldv.com

Sometimes a bug in a tool is exploited as a feature by a user*.* However if the feature is used in a slightly different context, interaction with the rest of the system is ill-defined.

The proposal to allow fork/join_none in a function(login guest/guest) was approved a year ago, then rejected, then approved, then rejected, then re-approved just a few days ago…

Once the door was opened up for fork/join_none, other restrictions in functions start to become meaningless, like clocking block drives, non-blocking assignments, event triggers. A restriction remains that you can’t fork a process unless the parent process is a process created by an initial or always block. That means it illegal to have a static variable initialization function call fork/join_none.

Dave

Once the door was opened up for fork/join_none, other restrictions in functions start to become meaningless, like clocking block drives, non-blocking assignments, event triggers. A restriction remains that you can’t fork a process unless the parent process is a process created by an initial or always block. That means it illegal to have a static variable initialization function call fork/join_none.
Dave

Can I used the delays in the functions something like:
#20 clk1 = 1’b1;
or
@(posedge clk1);

What are the advantages of allowing these constructs in functions, instead of using the task for achieving this functionality?

Can I used the delays in the functions something like:
#20 clk1 = 1’b1;
or
@(posedge clk1);
What are the advantages of allowing these constructs in functions, instead of using the task for achieving this functionality?

You can neveruse a blocking statement in a function unless it is within a fork/join_none constructAND the other conditions have been met. (must be from a thread started by an initialor alwaysconstruct).

There are a number of advantages by allowing non-blocking statements in a function:

  • The fact that a function is guaranteed not to block is a contract between the caller and the callee, just as the formal argument types are the contract as part of the interface between caller and callee.
  • The construction of a class may spawn a process. This can eliminate a lot of bookkeeping that would otherwise have to be done to keep track of all the constructed classes.
  • You can’t nest task calls. Now, more tasks can be written as functions, and it easier to have a function return a value as part of an expression than to output through an argument.

So this is mainly an small enhancement for the testbench, but with much larger impact to the people that have to implement it.

Dave

Thanks a lot for your reply.

In reply to dave_59:

Hi dave_59,

Please refer below code, here thought fork - join is used with in function there is no error! Would you please clarify this, why there is no error.

**module** sum_function();
int in1, in2, add;

  **function** int sum (in1, in2);
    $display ("initial value of sum = %d", sum);
      **fork** 
        sum = in1 + in2;
        $display ("sum of and b before fork_join = %d",sum);
      **join**
    $display("sum of a and b after fork_join = %d" , sum);
  **endfunction**

initial begin
 in1 = 3;
 in2 = 6; 

**add = sum (in1,in2);**
end

**endmodule**

In reply to prashant.kaushik:

Actually, this is user coding error - the fork/join is being used incorrectly. Because there are no blocking statements inside the fork/join, it behaves just like a begin/end. The LRM requirement that a function cannot block has been met.