Jump to content

Task argument used in new thread?


Recommended Posts

Is an ordinary input argument to an automatic task guaranteed to retain its value in a fork/join_none block even after the task itself has returned? Here is an example:

task automatic foo(int taskArg);
  classItem mine = new();
  fork begin
    #20;
    mine.randomize with { v == taskArg; }
  end join_none
endtask

The task will have returned by the time mine.randomize happens. I can't find anything in the 1800-2009 spec that speaks to whether the variable <taskArg> will retain its value within the fork block.

Section 13.3.2 (Task memory usage and concurrent activation) implies that this code is on shaky ground because the variable is "deallocated" after the task invocation. Quoting from 1800-2009-D8:

Because variables declared in automatic tasks are deallocated at the end of the task invocation, they shall not be used in certain constructs that might refer to them after that point[.]

This section goes on to prohibit use on the LHS of nonblocking and procedural continuous assignments, RHS of procedural continuous assignments and procedural force statements, inter-assignment event controls of nonblocking assignments, and tracing with system tasks like $monitor and $dumpvars. There is no definition in this section of when the "task invocation" ends, and whether the parallel block (fork) spawned by the task is a factor in the end of the "task invocation". One presumes that the invocation ends when the task returns to its caller, but I can't find anything concrete on this point.

In section 9.3.2 (Parallel blocks), the spec sheds light on arguments passed by reference, but says nothing about ordinary input arguments:

Within a fork-join_any or fork-join_none block, it shall be illegal to refer to formal arguments passed by reference other than in the initialization value expressions of variables declared in a block_item_declaration or the fork.

What does the language guarantee in this case, if anything? Am I missing something obvious in the spec?

Link to comment
Share on other sites

The text you quoted in 13.3.2 seems to be leftover from Verilog-2001, which introduced automatic tasks, but not automatic variables in general. That section should be deleted and what is stated in section 6.21 Scope and lifetime should apply instead:

The lifetime of a fork-join block (see 9.3.2) shall encompass the execution of all processes spawned by the

block. The lifetime of a scope enclosing any fork-join block includes the lifetime of the fork-join block.

In your example, the task foo is the enclosing scope that includes a fork-join block. The compiler will extend the life of taskArg to inclide the like of the nested fork/join block. It can do that because it can statically (i.e. at compile time) determine the dependencies. It can't do that across a task call.

Dave

http://www.eda.org/svdb/view.php?id=3548

Edited by dave_59
Added Mantis 3548
Link to comment
Share on other sites

Thanks Dave, great answer as always. It does mean that I need to dig deeper to understand why my colleague's constraint is not working.

I don't mean to be snarky, because I understand that the language is sprawling and still expanding, but can we *please* have an LRM that's worthy? Finding text that's leftover from a prior version which maybe has been superseded -- after the spec has supposedly been fully vetted -- does not exactly inspire confidence.

Link to comment
Share on other sites

  • 1 year later...

Thanks Dave, great answer as always. It does mean that I need to dig deeper to understand why my colleague's constraint is not working.

I don't mean to be snarky, because I understand that the language is sprawling and still expanding, but can we *please* have an LRM that's worthy? Finding text that's leftover from a prior version which maybe has been superseded -- after the spec has supposedly been fully vetted -- does not exactly inspire confidence.

I think the answer is this:

the code in fork-join thred(s) is executed after the enclosing block ends. so if you print the value of mine.v in foo(), even after the fork-join, you will see 0, (again, since the fork-join executes after).

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...