Subject: Re: [sv-ec] fork..join_none/join_any and automatic variables
From: Michael McNamara (mac@verisity.com)
Date: Wed May 21 2003 - 18:12:55 PDT
Randy Misustin writes:
> Mac & Steve,
>
> Truly, your attempts to educate me are appreciated. Alas, though, all
> this is unnecessary. I understand extremely well how traditional Verilog
> works, I've got a pretty solid grasp of Verilog 2001, and an
> ever-expanding appreciation of SystemVerilog's additions to the fray.
> The semantics of fork-join in a static environment are very well
> understood by customers and vendors, alike. The entire discussion/debate
> I intended to launch is limited to semantic quirks around forks in the
> presence of automatic variables and then whether SystemVerilog's
> introduction of a fork-join_none has any bearing on all this. I don't
> believe the discussions about how static variables interact with
> fork-join are pertinent, except to indicate the probable expectations of
> a user coming from a long history of Verilog.
>
> -randy.
Great, I am glad we are in sync, and hop our comentary help some folks
lurking on this list.
Where I am coming from, and I believe Steve as well, and perhaps you
as well, is a basic premise that additions to a living language should
be evaluated against three directives. They must:
a) be backwards compatible.
b) produce few surprizes.
c) add useful value.
So now that we've all convinced each other that we understand the
semantics of fork and join, and static variables, and that automatic
variables cease to exist when their enclosing scope is exited, we can
step to the next page.
Part of the Accellera proposed addition to the language is the
introduction of a fork .. join_none construct; which from the context
I assume (correct me if I am wrong or it has changed) is that it
initiates the various enclosed statements, each in their own flow of
control, and then immediately passes execution to the statement after
the join_none. An example:
initial begin : a
automatic reg [7:0] auto;
reg [7:0] static;
fork : f
task_a;
task_b;
join_none
statement_a;
statement_b;
statement_c;
end
In my mind this is equivalent to:
initial begin : a
automatic reg [7:0] auto;
reg [7:0] static;
fork : f
task_a;
task_b;
begin
statement_a;
statement_b;
statement_c;
end
join
end
with perhaps the distinction that a disable of 'f' would kill
execution of task_a, task_b and which ever of statement_{a,b,c} was
executing in example two; however would only get task_a and task_b
with example 1.
There is no other difference in my mind.
You are concerned with what would happen if there was an automatic
variable in the scope 'a', and statement_{a,b,c} completed before one
or more of task_a and task_b completed.
This question is a very useful way to test whether my assumption of
the mapping of fork..join_none to fork..join is correct.
I believe that what would be most backwards compatible, least
surprising, and most useful would be for the scope named 'a' to exist
and be active until each statement in the fork..join_none has
completed, and each statement in the blocks of code after the
join_none have completed.
Hence any automatics declared in the scope 'a' would continue to exist
for the entire life of each and every thread initiated from the scope
has completed (which could be never), as well as the lives of the
subsequent statements.
If the flow of control multiply enters the scope 'a', then these
silmultaneously active 'a's will each have their own copy of
the variable 'auto', but will share access to the variable named 'static'.
I fully recognize that this then reduces the join_none to be just a
very slight semantic enhancement over the existing fork..join.
I expressed this analysis to Peter Flake and Simon when I was on the
CoDesign technical advisory board many years ago; however it seems
that the constructs lived on.
Don't get me wrong, I do feel that the fork..join_any is a useful
shorthand for:
fork : f
begin
task_a;
disable f;
end
begin
task_b;
disable f;
end
...
begin
task_z;
disable f;
end
join
to
fork
task_a;
task_b;
...
task_z;
join_any
and think it is a good addition, even though it uses up a keyword.
However, in my opinion the join_none adds no value. I believe it is
only there due to a misguided sense of completion; one has a join
which waits for all; one has a join that waits for the first; why not
add a join that waits for no one?
I ask, why add such a thing?
It uses up name space (breaking backwards compatibility), adds no
modeling value (breaking requirement to add value), and is difficult
to understand (provides surprise).
-mac
This archive was generated by hypermail 2b28 : Wed May 21 2003 - 17:40:24 PDT