Re: [sv-ec] disabling of single threads


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