Subject: Re: [sv-ec] Comments on Chapter 9
From: "Arturo Salz" <[email-masked]>
To: <[email-masked]>
Date: Mon, 27 Jan 2003 11:02:45 -0800

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