RE: [sv-ec] RE: [sv-bc] Can a function contain a fork/join/any/none?

From: Phil Moorby <Philip.Moorby_at_.....>
Date: Mon Feb 27 2006 - 15:09:35 PST
Dave,

We should allow statements contained in a fork/join_none inside a
function have the same rules as for statements contained in a task.
Therefore, all timing controls and calls to tasks are allowed in these
fork/join_none blocks. Otherwise, the fork/join_none would not be able
to do the background activity it needs to do.

I believe where we essentially differ on this issue is whether object
constructors should be functions or tasks.
 
A call to an object constructor:
  object = new(x, y, z);
looks and acts like a function call in that it returns the newly created
handle. If the constructor was a task then the syntax would be clumsy,
and any arbitrary blocking statement would be allowed during the
construction. Constructors not returning in a single evaluation step are
very problematic because they lead to partially constructed objects,
which violate basic object-oriented principles. 
 
Making the constructor a function, allowing functions to spawn off
background activity with a fork/join_none, and making sure that the
constructor returns in a single evaluation step, seem to me to make
everything fit nicely.
 
Other comments embedded below in your email.
 
Phil
 



-----Original Message-----
From: Rich, Dave [mailto:Dave_Rich@mentor.com
<mailto:Dave_Rich@mentor.com> ]
Sent: Sunday, February 26, 2006 12:59 PM
To: Phil Moorby; sv-ec@eda.org
Cc: Mehdi Mohtashemi
Subject: RE: [sv-ec] RE: [sv-bc] Can a function contain a
fork/join/any/none?

Hi Phil,

I don't think most people are questioning the usefulness of allowing a
constructor to create a thread. It's all the additional questions that
this proposed syntactical mechanism opens up. I don't think your
argument about the PLI holds up because there are lots of things you can
do via the PLI that you can't do via the language.

Maybe we need to consider all those things the PLI can do, that can't be
done in SV ;-)

OK. So it's legal to have a fork/join_none in a functional call.

But it's clearly illegal to call a task from a function. Are you
proposing to ignore all rules about functions when the statements are
within a fork/join_none, or just some of them?

Then there are the rules about function calls in other parts of the
language, like calls from assertions and constraints. Is the fork
statement a side effect, or is the task call a side effect?

I would consider a fork/join_none inside a function as a useful and
necessary side effect. A task call would only be allowed inside the
fork/join_none, and therefore part of the fork/join_none side effect.
Calls from assertions and constraints might present some usual
non-determinism, but just as in function calls from the RHS of
cont-assigns, or in variable gate delay expressions, etc., there are no
new problems here.

In the context of the DPI, is a function call with a fork/join_none
thread "pure" or "context".

Not sure what you mean by this.

I have never been opposed to this enhancement. I just have not seen a
clear proposal for what is actually needed to implement it.
 
I would hope that we are working towards a clear proposal.

Dave



> -----Original Message-----
> From: owner-sv-ec@eda.org [mailto:owner-sv-ec@eda.org
<mailto:owner-sv-ec@eda.org> ] On Behalf Of
Phil
> Moorby
> Sent: Sunday, February 26, 2006 9:06 AM
> To: sv-ec@eda.org
> Cc: Mehdi Mohtashemi
> Subject: RE: [sv-ec] RE: [sv-bc] Can a function contain a
> fork/join/any/none?
>
> Functions in Verilog were designed to be different from tasks for one
> very good reason: it was necessary for the evaluation of expressions
to
> complete and have their value returned within a single evaluation
step.
> In other words, the simulator must not context switch to other events
> until it finishes evaluating the expression and obtains the result.
> Functions and function calls must therefore be restricted and not
allow
> their returning thread to block. With this restriction, blocking can
> only occur at a statement level, never at an expression operand level.
> This restriction reduces potential non-deterministic situations, and
> enables the simulator to optimize its runtime code.
>
> Functions have always allowed side effects (both good and bad). My
> definition of side effects includes the ability to modify variables
> outside the function boundary and calling system and PLI tasks and
> functions. Side effects have the potential of effectively spawning off
> additional threads of activity, such as @ triggers on the outside of
the
> function boundary or PLI event creations, but this does not affect the
> requirement of evaluating the function in a single evaluation step.
> Although some side effects are considered to be bad, and certainly a
> source of non-determinism, some side effects are actually quite
useful.
> For instance, PLI calls from functions can setup background activity,
> and this is considered a very useful (and deterministic) feature by
some
> users. This train left the station 21 years ago!
>
> Lets not get confused with the use of functions in code for synthesis;
> we are talking here of code used to simulate the environment or verify
> the design.
>
> Now to SystemVerilog and object creation. Like the evaluation of
> expressions, it is highly desirable that the creation of an object be
> performed in a single step without blocking. Object creation involves
> some behind-the-scene work by the system (to manage memory for
instance)
> in addition to calling and completing the object constructors. It is
> highly desirable that only the object constructor code have access
(read
> or write) to an object under construction, that is, a partially
> initialized object. Otherwise, it may lead to many situations of
> non-determinism that the user did not intend, and that are very hard
to
> debug.
>
> For these reasons it only makes sense to make the constructor a
function
> not a task.
>
> Another highly desirable feature of objects is to be able to setup
some
> background activity that does its work throughout simulation. The
> constructor code is the perfect place to set off this background
> activity, especially when true object-oriented principles are
followed.
> The usual side effect workaround is ugly, overtly complex, and error
> prone, and the fork/join_none is a much better programming feature to
> spawn this activity.
>
> This leads to only one logical conclusion: the constructor must be a
> function, and it must allow fork/join_none statements.
>
> Also, because the constructor function must to be able to call other
> functions (simply for good programming practice), it only makes sense
to
> allow fork/join_none in any and all functions.
>
> In general, when considering these language features, I believe we
> should follow two guiding principles:
> 1) The feature is significantly useful for users
> 2) The simulator can implement the feature without confusing the user
>
> Another SystemVerilog guiding principle is to avoid forcing users to
> code needed functionality using PLI calls, and instead enable the same
> functionality to be written directly in the language.
>
> The ability to have fork/join_none statements in functions satisfies
> these principles.
>
> Phil
Received on Mon Feb 27 15:13:28 2006

This archive was generated by hypermail 2.1.8 : Mon Feb 27 2006 - 15:14:00 PST