der57 Posted May 6, 2011 Report Share Posted May 6, 2011 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? Quote Link to comment Share on other sites More sharing options...
dave_59 Posted May 6, 2011 Report Share Posted May 6, 2011 (edited) 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 February 13, 2013 by dave_59 Added Mantis 3548 Quote Link to comment Share on other sites More sharing options...
der57 Posted May 6, 2011 Author Report Share Posted May 6, 2011 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. Quote Link to comment Share on other sites More sharing options...
dave_59 Posted May 9, 2011 Report Share Posted May 9, 2011 der57. I agree with you 100% See http://go.mentor.com/a-time-for-change . Quote Link to comment Share on other sites More sharing options...
asafg100 Posted February 13, 2013 Report Share Posted February 13, 2013 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). Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.