Subject: Re: [sv-ec] disabling of single threads
From: Arturo Salz (Arturo.Salz@synopsys.com)
Date: Mon Mar 24 2003 - 23:40:55 PST
Simon,
The actual syntax was just an idea, the key concept was the introduction
of process objects. Also, my description clearly states that the process
id's are setup before the newly spawned processes begin to execute so
in this case the fork statement itself is not a blocking statement. Still, I
agree that the syntax needs work to fit better within Verilog. For example,
we could devise a construct re-using the assign keyword:
fork assign pids
p1();
p2();
join
These are all just syntactical ideas. The main point is the fork's ability to
assign the process handles in an atomic fashion. The sarcasm is not
really warranted. I agree that having begin/end return something is a rather
ugly construct.
Arturo
----- Original Message -----
From: Simon Davidmann
To: Arturo Salz
Cc: sv-ec@eda.org
Sent: Monday, March 24, 2003 11:21 PM
Subject: Re: [sv-ec] disabling of single threads
Arturo,
begin :-)
I note your new idea below and have a question: where does this fit with the spirit of Verilog?:
--- insert --
pids = fork
p1();
p2();
p3();
join any
--- end insert --
I cannot recall this language procedural style in any existing Verilog construct.
Value returning statements were thrown out with Verilog (we had them in HILO, but Phil left them out of Verilog saying you always need a function call) - next we will have the return of the dreaded valcase... eg
a = valcase (i)
j: 3;
k: 2;
endcase
i.e. if i == j then a = 3, etc
if you want to add this processid stuff, then you need to change the fork to be more like it, ie something like this:
pids = fork (any)
p1 ();
p2 ();
p3 ();
join
and then there are also several other things we should change to make them into this new syntax style - but in fact it is not a nice style:
for example could I have
val = begin
if (a) return (1); else return (0);
end
i.e. a begin block as well that returns a value? - would make sense right?
and then we could have
if (begin if (a) return (1); else return (0); end) $display ("returns 0); else $display ("returns 0");
and then because the begin end only is one statement we could do without it, etc, like this:
if (if (a) return (1); else return (0);) $display... - and it can get quite messy
of course we could just say that process assignment from a fork join block is an exception - and we dig a bigger hole - as then whole language just becomes a collection of strange constructs that are only allowed in certain conditions in certain places... and we end up with a bad language
I recommend not adding new styles away from the spirit of Verilog - unless you overhaul many things properly - adding new styles for each new type of operation just makes the language more and more complex and more and more difficult as a user can never remember exactly how the syntax and semantics of each construct or grouping of constructs works.
end :-)
Simon
At 03:15 AM 3/25/2003, Arturo Salz wrote:
Michael,
My proposal for thread control is attached. Unfortunately, it didn't get in
this version.
Your comments are welcome.
Arturo
----- Original Message -----
From: "Michael Burns" <Michael.Burns@motorola.com>
To: <sv-ec@eda.org>
Cc: <rob.slater@motorola.com>
Sent: Monday, March 24, 2003 3:24 PM
Subject: [sv-ec] disabling of single threads
Hi folks,
I have a question about disabling/terminating threads. There does not
appear to be a syntax for terminating a specific thread; you can only
terminate all child threads of the current thread, or terminate all
threads from a named block. Does anyone know of a handy way to start
a bunch of threads, then terminate specific ones under various
conditions? There are folks here in Motorola who are very intereseted
in having this ability - does anyone else have opinions on the
desireability or lack thereof for this feature? If there's a "thread"
on the reflector about this, feel free to just point me there.
Thanks,
Mike
From: "Arturo Salz" <salz@synopsys.com>
To: <sv-ec@eda.org>
References: <5.1.0.14.0.20030124102321.029e0000@orange.he.net>
Subject: Re: [sv-ec] Comments on Chapter 9
Date: Mon, 27 Jan 2003 11:02:45 -0800
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="----=_NextPart_000_18B9_01C2C5F3.9F1910A0"
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 5.50.4807.1700
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4807.1700
I believe that Kevin and Stefen have brought up very good points. If we
need to provide fine granularity control for SystemVerilog processes then
these mechanisms need to be intuitive, general, and robust.
After reviewing Kevin's proposal I came up with the following proposal.
Process Control
Use the process keyword to denote a new built-in class. This way, users can
declare objects of type process and safely pass them around through tasks or
incorporate them into other objects.
Objects of type process include several built-in methods:
task terminate - Terminates the process
function int status - Returns process status (0 dead, 1 ready, -1 created, 2 waiting...).
(A cleaner way might be an enum but that would add top-level identifiers)
task suspend - Suspend execution of the process (process is still ready)
task wait - Wait until process terminates
The key to the process class is that (a) it's an object and therefore subject to
the same type-checking rules as other objects, (b) it can be garbage collected
like any other object, and (c) it's a built-in class, and only the fork..join construct
creates these types of objects. The statement "process e = new()" could be
disallowed altogether, or it could be used to retrieve a handle to the calling process.
Also required is an atomic mechanism for assigning all process'es created by a
fork..join. Atomic means a mechanism whereby all processes are initialized before
the calling process or any of the sub-processes has had a chance to execute and
perhaps terminate. One way to provide for this would be to modify the grammar of
the fork construct to accomplish this:
process pids[*];
pids = fork
p1();
p2();
p3();
join any
// user implementation of fork ... join
// and terminate all remaining processes.
// Like a priority fork .. join
for( int i = 0; i < pids.size; i++ ) begin
if( pids[i].status != 0 )
pids[i].terminate();
end
The example shows using a dynamic array to receive the process objects, but one
could also use a fixed-size array (i.e., pids[1:3]). The basic concept is that the pids
array is initialized by fork before any of the sub-processes begin executing. This way
the parent process, or any of the sub-processes has access to all the process objects
and avoids a situation where a process executes and terminates before one has had a
chance to monitor the process externally.
Also, by making this an explicit part of the fork..join, the compiler can decide if all the
process objects are needed and optimize accordingly.
Arturo
This archive was generated by hypermail 2b28 : Mon Mar 24 2003 - 23:38:24 PST