

Fork/Join capability in SystemC and type safe spawning of new processes.

By Stuart Swan, Cadence Design Systems, Inc.  1 Aug 2001

This example demonstrates a fork/join  and dynamic thread creation
capability on top of SystemC 2.0. A key aspect of this capability
is that it retains C++ type safety for functions called within spawned
threads.

The example code within "demo.cpp" demonstrates how to use the capability.
The information below summarizes how to use the capability.

Note that this capability is NOT currently a part of the SystemC standard.


Summary:
 The proposed user-visible constructs for fork/join and dynamic thread
 creation are:
   sc_spawn_function(...), sc_spawn_method(...), sc_spawn_options(...),
   SC_FORK, SC_JOIN, sc_process_join()

Issue: template specialization to support functions/methods returning 
"void" works with GNU & HP compilers but not Sun CC 6.1
Workaround: For Sun CC 6.1 and other compilers that don't properly support
partial template specialization, uncomment the following line:

   #define SC_FORK_NO_TEMP_SPCL 1

and don't use sc_spawn_method/function for methods/funtions with
void return types.

Current Limitation: Maximum number of arguments to a function/method
is currently 4. This can easily be extended, and probably will be in future.


Initializing the Global Thread Pool

SystemC 2.0 does not yet natively support dynamic thread creation, so
we currently use a global thread pool that is allocated before simulation
starts. The following code outlines how to allocate the global thread pool:

int sc_main (int argc , char *argv[]) 
{
  // Create the global thread pool with a limit of 10 threads
  thread_pool::init(10);

  top top1("Top1");
  sc_start(-1);

  // Optionally delete the thread_pool when done
  thread_pool::destroy();

  return 0;
}

Note that each thread will use 64K of memory for stack space by default,
so the recommendation is to allocate as many threads as is needed, but
allocating significantly more than is needed may be wasteful.


Usage Summary for Fork/Join and Dynamic Thread Creation

Given the following function and method declarations:

  returnT my_function( ARGS );

  returnT my_class::my_method ( ARGS );

To spawn in their own thread, use:

  returnT r;

  sc_join_handle sc_spawn_function( &r, &my_function, ARGS );

  my_class* c;
  c = this; // or point to some other object...

  sc_join_handle sc_spawn_method( &r, c, &my_class::my_method, ARGS );

To specify spawn options (not yet supported), add a sc_spawn_option
object as the first argument to sc_spawn_function/method .

To use fork/join:

SC_FORK sc_spawn_method/function(...) , ...  SC_JOIN

Note use of "comma" to separate the sc_spawn_() calls above.

To use sc_process_join() :

  sc_join_handle h1 = sc_spawn_function(...);
  sc_join_handle h2 = sc_spawn_method(...);

  sc_process_join(h1);
  sc_process_join(h2);


Additional usage notes:

Note that storage for return values for spawned functions/methods is
allocated by the caller and must be maintained until the spawned
function/method completes. If the return value is not needed, pass in
a NULL pointer casted to the appropriate pointer type.

For example:

  int foo() {return 1; }
  sc_spawn_function((int*)0, &foo); // ignore the return value.

If spawned function/method returns void, then specify return type as void 
and pass in NULL ptr for return ptr.

For example:

  void foo() {}
  sc_spawn_function((void*)0, &foo); // function returns void

Note that the C++ compiler will not perform any implicit conversions when
invoking functions/methods via sc_spawn_function/method as would be
the case with a normal function call. Use explicit conversions
if any are needed.

Compiler issues:
1. Partial template specialization to support return types of
void works with GNU 2.95.2 C++ and HP aCC A.3.31 compilers 
but not with Sun CC 6.1 compiler.

2. Spawned functions or methods can be overloaded with GNU C++, but
other compilers can't handle this yet.


