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.
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.
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.
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.
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**
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.