CSIM programming

Extension to C++ (or C, or Java, or ....) available from Mesquite Software
Offers additional language support for:
Uses preprocessor to apply complicated program rewriting rules to
Here is what the trivial "hello world" program looks like in CSIM:

     1  #include <iostream>
     2  #include "cpp.h"
     3  #include <string.h>
     4  using namespace std;
     5
     6  extern "C" void sim()           // main process
     7  {
     8          int i;
     9          create("sim");          // separate from background system
    10          for(i=1;i<10;i++)
    11          {
    12                  cout << "Alice says hello " << i << " times." << endl;
    13          }
    14  }


Preprocessor splits the sim function into two parts at line 9. "Chunk scheduler" begins executing the first chunk as a normal function call until it encounters the replacement code for create. "Chunk scheduler" (a) adds "sim" to the list of simulated processes, (b) schedules "sim" to execute the the second part of the original "sim" function at the current simulated time, and (c) returns from function call. Later, the "chunk scheduler" sets the identity of the active process to "sim" and calls the function made from lines 10-14 of the original source code.  When that that function execution completes, the "chunk scheduler" deletes "sim" from the list of simulated processes.  Since there are no other processes, the main program terminates also terminates.

Here is a simple command line script for compiling CSIM programs.  When compiled, the previous program produces this output:

[mart@bass ~]$ CPP_COMPILE_SCRIPT oneworld.c
[mart@bass ~]$ a.out
Alice says hello 1 times.
Alice says hello 2 times.
Alice says hello 3 times.
Alice says hello 4 times.
Alice says hello 5 times.
Alice says hello 6 times.
Alice says hello 7 times.
Alice says hello 8 times.
Alice says hello 9 times.
[mart@bass ~]$

Here is a slightly more complicated version of the same CSIM program, which includes two processes (Alice and Bob) that each prints a series of "hello world" messages.

     1  #include <iostream>
     2  #include "cpp.h"
     3  #include <string.h>
     4  using namespace std;
     5
     6  void Bob();             // Another process
     7
     8  extern "C" void sim()           // Alice is the main process
     9  {
    10          int i;
    11          create("Alice");        // Alice separates from background system
    12          Bob();                  // Alice gives Bob a chance to do the same
    13          for(i=1;i<10;i++)
    14          {
    15  //              hold(uniform(0,10));
    16                  cout << "Alice says hello " << i << " times." << endl;
    17          }
    18  }
    19
    20  void Bob()
    21  {
    22          int i;
    23          create("Bob");
    24          for(i=1;i<10;i++)
    25          {
    26  //              hold(uniform(0,10));
    27                  cout << "Bob says hello " << i << " times." << endl;
    28          }
    29  }

When compiled exactly as above (with lines 15 and 26 commented out), we obtain the following output:

[mart@bass ~]$ CPP_COMPILE_SCRIPT twoworld.c
[mart@bass ~]$ a.out
Alice says hello 1 times.
Alice says hello 2 times.
Alice says hello 3 times.
Alice says hello 4 times.
Alice says hello 5 times.
Alice says hello 6 times.
Alice says hello 7 times.
Alice says hello 8 times.
Alice says hello 9 times.
[mart@bass ~]$

Notice that process Bob never had a chance to run, even though process Alice called function Bob at line 12 and thus the child process Bob was created when line 23 was executed. However, you must keep in mind that CSIM programs run as a single thread of execution at the operating system level, even if your underlying hardware has multiple CPU cores available and hence could support true parallel execution. The illusion of parallelism in CSIM programs comes about by interleaving the execution of chunks taken from different functions and hence belonging to different (simulated) processes.
If we uncomment lines 15 and 26, then the CSIM statement hold (uniform (0, 10)); is executed by both processes before each  cout statement in their respective loops. Whenever a process executes a CSIM hold( ) function, its execution is suspended until simulated time advances by the amount specified by its parameter. Obviously, the specified time increment must be non-negative, or else executing the model would violate causality! In this case, the time increment is given by the CSIM function uniform (a, b), which randomly choses any real number from the closed interval between a and b.

[mart@bass ~]$ CPP_COMPILE_SCRIPT twoworld.c
[mart@bass ~]$ a.out
Bob says hello 1 times.
Bob says hello 2 times.
Alice says hello 1 times.
Bob says hello 3 times.
Bob says hello 4 times.
Alice says hello 2 times.
Alice says hello 3 times.
Bob says hello 5 times.
Bob says hello 6 times.
Bob says hello 7 times.
Alice says hello 4 times.
Alice says hello 5 times.
Bob says hello 8 times.
Alice says hello 6 times.
Alice says hello 7 times.
Bob says hello 9 times.
Alice says hello 8 times.
Alice says hello 9 times.
[mart@bass ~]$

It is instructive (but tediously verbose!) to see what happens when we insert the CSIM statement trace_on( ); between lines 10 and 11 in source code for the sim function. From this point onwards (or until the CSIM statement trace_off( ); is encountered), the hidden "chunk scheduler" prints one line of diagnostic output whenever it runs, as shown below.

Such trace output provides a lot of detail about model execution details.

[mart@bass ~]$ CPP_COMPILE_SCRIPT twoworld.c
[mart@bass ~]$ a.out

   time       process    id   pri    status
     0.000        Alice   1     1    create Alice 1
     0.000        Alice   1     1    join class default
     0.000        Alice   1     1    sched proc: t = 0.000, id = 2
     0.000        Alice   1     1    create Bob 2
     0.000          Bob   2     1    join class default
     0.000        Alice   1     1    hold for 5.139
     0.000        Alice   1     1    sched proc: t = 5.139, id = 1
     0.000          Bob   2     1    hold for 1.757
     0.000          Bob   2     1    sched proc: t = 1.757, id = 2
Bob says hello 1 times.
     1.757          Bob   2     1    hold for 3.087
     1.757          Bob   2     1    sched proc: t = 3.087, id = 2
Bob says hello 2 times.
     4.844          Bob   2     1    hold for 5.345
     4.844          Bob   2     1    sched proc: t = 5.345, id = 2
Alice says hello 1 times.
     5.139        Alice   1     1    hold for 9.476
     5.139        Alice   1     1    sched proc: t = 9.476, id = 1
Bob says hello 3 times.
    10.189          Bob   2     1    hold for 1.717
    10.189          Bob   2     1    sched proc: t = 1.717, id = 2
Bob says hello 4 times.
    11.907          Bob   2     1    hold for 7.022
    11.907          Bob   2     1    sched proc: t = 7.022, id = 2
Alice says hello 2 times.
    14.615        Alice   1     1    hold for 2.264
    14.615        Alice   1     1    sched proc: t = 2.264, id = 1
Alice says hello 3 times.
    16.879        Alice   1     1    hold for 4.948
    16.879        Alice   1     1    sched proc: t = 4.948, id = 1
Bob says hello 5 times.
    18.929          Bob   2     1    hold for 1.247
    18.929          Bob   2     1    sched proc: t = 1.247, id = 2
Bob says hello 6 times.
    20.176          Bob   2     1    hold for 0.839
    20.176          Bob   2     1    sched proc: t = 0.839, id = 2
Bob says hello 7 times.
    21.015          Bob   2     1    hold for 3.896
    21.015          Bob   2     1    sched proc: t = 3.896, id = 2
Alice says hello 4 times.
    21.827        Alice   1     1    hold for 2.772
    21.827        Alice   1     1    sched proc: t = 2.772, id = 1
Alice says hello 5 times.
    24.599        Alice   1     1    hold for 3.681
    24.599        Alice   1     1    sched proc: t = 3.681, id = 1
Bob says hello 8 times.
    24.912          Bob   2     1    hold for 9.834
    24.912          Bob   2     1    sched proc: t = 9.834, id = 2
Alice says hello 6 times.
    28.280        Alice   1     1    hold for 5.354
    28.280        Alice   1     1    sched proc: t = 5.354, id = 1
Alice says hello 7 times.
    33.634        Alice   1     1    hold for 7.657
    33.634        Alice   1     1    sched proc: t = 7.657, id = 1
Bob says hello 9 times.
    34.746          Bob   2     1    terminate process
Alice says hello 8 times.
    41.291        Alice   1     1    hold for 6.465
    41.291        Alice   1     1    sched proc: t = 6.465, id = 1
Alice says hello 9 times.
    47.756        Alice   1     1    sim exited
    47.756        Alice   1     1    rerun model
     0.000        Alice   1     1    delete all pcb's
     0.000        Alice   1     1    delete all events
     0.000        Alice   1     1    delete all facilities
     0.000        Alice   1     1    delete all storages
     0.000        Alice   1     1    delete all mailboxes
     0.000        Alice   1     1    delete all meters
     0.000        Alice   1     1    delete all boxes
     0.000        Alice   1     1    delete all tables
     0.000        Alice   1     1    delete all qtables
     0.000        Alice   1     1    delete event list

   time       process    id   pri    status
     0.000        Alice   1     1    delete all classes
[mart@bass ~]$