/* file: main.c */ /* * This is the main.c code program to be used in the event driven simulation * module. It is the program which will require the most extensive * modifications to test a protocol. * * This program is to be used in conjunction with 2 UNIX scripts called: * sim.sh * sim.gnuplot.sh * * and a UNIX makefile called: * makefile * * Type: "sim.sh" to compile the program using the "makefile" and the * UNIX utility "make", and then run the program. This script will * also call the "sim.gnuplot.sh" script to help generate a GNUplot * data plot. * * written by Tom Laramee - 11/95 * */ #include #include #include #include "main.h" #include "event.h" /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Some defines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ #define SHOWREPORT stdout /* These 2 are either "NULL" or "stdout". If they're NULL */ #define SHOWPARAMS stdout /* you will not see the Parameters when the program begins */ /* or the final report when the program is done. If */ /* If either/or is "stdout", you'll see it on the screen */ #define MAXNODES 60 /* Maximum number of nodes in the system */ #define MAXPACK 1000 /* Maximum number of packets to simulate for */ #define MAXEVENTS 1000 /* Maximum number of events to simulate for */ #define LIGHT 3E+8 /* The speed of light (m/s) */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Global variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~ (naturally, there are not enough here) ~~~~~~~~~~~~~~~~~~~~~~~ */ tEventPtr evList; /* Head of the event list */ tEventPtr newEvent; /* A new event to be malloc()d and inserted onto event list */ tEventPtr currEvent; /* A pointer to the current event */ tProcPtr qptr[MAXNODES]; /* Each nodes proc queue */ tProcPtr currProc; /* The current proc */ FILE * fEvent; /* Pointer to file of events */ short DEBUGGING, /* Are we debugging? */ done; /* Are we done with the simulation yet? */ int numNodes, /* number of nodes in the system */ totalPackets, /* Total number of packets sent so far... */ loopcounter, /* Count the total number of events */ iseed; /* Seed of random number generator */ double channelCapacity, /* Capacity of the channel (bits/sec) */ timeNextEvent, /* Time of next event occurance */ lambdaN, /* Node arrival rate */ lambdaS, /* System arrival rate */ sysTime; /* Global clock */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~ initParams() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ short initParams(int argc, char * argv[]) { /* This function read in all command line parameters and assigns * the proper values to the corresponding variables */ int counter; /* set default values for the global variables */ /* in case not all command line args are present */ /* these vary from simulation to simulation */ numNodes=1; /* The number of nodes in the system */ channelCapacity=2000000; /* the capacity of the channel (bits/second) */ lambdaS=1.0; /* The system/channel arrival rate */ DEBUGGING=1; /* Are we DEBUGGING? */ /* Go through all of the commnad line options and set the appropriate */ /* variable to the value which is supplied on the command line */ if (argc==1) { printf ("\nNo parameters specified on command line..."); printf ("\nUsing the default parameters..."); return (1); } for (counter=1; counterMAXNODES) fatal ("initParms", "too many nodes (<50 or 60 is good)"); if (channelCapacity<=0) fatal ("initParms", "need positive channel capacity"); /* etc */ } /* End of initAll; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~ showParams() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void showParams(FILE * fp) { /* This function shows all of the values of the command line * argument variables after they have been entered and processed */ if (fp!=NULL) { fprintf (fp, "\n\nInitial simulation parameters..."); fprintf (fp, "\nNumber of Nodes............: %d", numNodes); fprintf (fp, "\nChannel capacity...........: %1.3e", channelCapacity); fprintf (fp, "\nSystem packet arrival rate.: %lf", lambdaS); fprintf (fp, "\nNodal packet arrival rate..: %lf", lambdaN); } } /* showParams */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~ showEventList ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void showEventList(FILE * fp) { /* This function shows all of the events which are currently * on the event list */ tEventPtr q=NULL; /* local event pointer */ if (!evList) fatal("showEventList", "No events on the list"); if (fp != NULL) { fprintf (fp, "\nEvent list for system time: %1.8lf", sysTime); fprintf (fp, "\nEVtime EVcode NODEcode JOBdest"); for (q=evList; q!=NULL; q=q->next) { fprintf (fp, "\n%1.8lf %s %2d %2d", q->evtime, printEVENT(q->evcode), q->nodecode, q->jobdest); } } /* End of if (fp !=NULL) */ } /* End of showEventList */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~ showCurrentEvent()~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void showCurrentEvent(FILE * fp) { /* This function shows the current event being processed */ tEventPtr q=NULL; if (currEvent==NULL) fatal("showCurrentEvent", "No event to show"); q=currEvent; if (fp != NULL) { fprintf (fp, "\nCurrent event for system time: %1.8lf", sysTime); fprintf (fp, "\nEVtime EVcode NODEcode JOBdest"); fprintf (fp, "\n%1.8lf %s %2d %2d", q->evtime, printEVENT(q->evcode), q->nodecode, q->jobdest ); } /* End of if (fp !=NULL) */ } /* End of showCurrentEvent */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~~~~showReport ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void showReport ( FILE * fp ) { /* This function displays summary information at the end of a simulation */ /* local vars for summary information */ double throughput, /* throughput of the system */ avgPacketDelay; /* average delay incurred by a packet */ FILE * fp1; /* A file pointer to write the results to...the results will */ /* be something like: */ /* Channel arrival rate vs. Utilization */ /* calculate the throughput (you enter equation) */ throughput=1.0; /* collect statistics to external file for plotting */ fp1=fopen("a", "w"); if ((!fp1)) fatal ("showReport", "Cannot open file to write to "); fprintf (fp1, "\n%lf %lf", lambdaS, throughput); fclose(fp1); /* collect statistics to the screeen */ if (fp != NULL) { fprintf (fp, "\n\nSimulation results..."); fprintf (fp, "\nNumber of Nodes.................: %d", numNodes); fprintf (fp, "\nChannel capacity................: %1.3e", channelCapacity); fprintf (fp, "\nThroughput......................: %1.3lf", throughput); } } /* End of report() */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ printStatus() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void printStatus( void ) { /* This function is used only for debugging purposes. It prints out summary * information @ the end of each event * * Types of things to print out: * o A node's queue contents * o The list of events in the event list * o Number of packets transmitted for a node * */ tProcPtr p; /* temporary proc pointer to print out queues */ if (DEBUGGING) { fprintf (fEvent, "\n\nPost-cycle information "); } } /* End of printStatus */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void gen_arrival(int node) { /* This function assigns a time to an arrival based on the nodal * arrival rate and the poisson assumption. It also fills the * required fields of the structure */ double timeArrival; nextarrival(); /* Calculate a poisson arrival time */ timeArrival = timeNextEvent; /* Assign arrival time (poisson) */ newEvent = alloc_evrec(); /* Allocate room for an event */ newEvent->evtime = timeArrival; /* Set it's time to occur randomly */ newEvent->evcode = ARRIVAL; /* Set the type of event */ newEvent->nodecode = node; /* Attach ownership to a node */ newEvent->jobdest=node; /* we don't care who the dest is */ newEvent->next=NULL; /* initialize pointers */ newEvent->prev=NULL; insertevent(newEvent); /* Add the event to the event list */ } /* End of gen_arrival() */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void genEvent1(int node) { /* Code the generation of a new event here */ } /* End of genEvent1 */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void genEvent2(int node ) { /* Code the generation of a new event here */ } /* End of genEvent2 */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void genEvent3( int node ) { /* Code the generation of a new event here */ } /* End of genEvent3 */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ short processEvent1( void ) { } /* End of processEvent1() */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ short processEvent2( void ) { } /* End of processEvent2 */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ short processEvent3( void ) { } /* End of processEvent3 */ /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ main ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ short main(int argc, char * argv[]) { int i; /* dummy counter */ long int eventNum=0; /* the number of the event */ initParams(argc, argv); /* Process command line arguments */ initAll(); /* Set system parameters */ showParams(SHOWPARAMS); /* Show what we're starting out with */ /* Seed a node or nodes with arrivals here - to begin processing events */ /* use the gen_arrival() function */ gen_arrival(0); while (!done) { if (DEBUGGING) showEventList(fEvent); /* Output the event list */ currEvent=get_next_event(); /* Get the next event off of the event list */ sysTime = currEvent->evtime; /* Update the system clock */ if (DEBUGGING) if (fEvent) fprintf (fEvent, "\n\n>>>>>>>>>>>>>>>> Current Event No: %d", ++eventNum); if (DEBUGGING) showCurrentEvent(fEvent); /* Output the current event */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ process events */ switch(currEvent->evcode) { case ARRIVAL: /* Arrival of a node to the channel */ /* <----- need a "processArrival()" function here */ break; case EVENT1: /* Event 1 */ processEvent1(); break; case EVENT2: /* Event 2 */ processEvent2(); break; case EVENT3: /* Event 3 */ processEvent3(); break; default: fatal("main", "unknown event to process"); } /* End of switch(currEvent->evcode) */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ free_evrec(currEvent); /* Free up the memory */ currEvent=NULL; /* point current event to NULL */ if (DEBUGGING) printStatus(); /* Debugging info */ if (totalPackets > MAXPACK) done=TRUE; /* Are we done ? */ if (eventNum < MAXEVENTS) done=TRUE; /* Are we done ? */ } /* End of the "while !done" loop */ showReport( SHOWREPORT ); /* Show the results */ /* Close up any files that are open */ if ((DEBUGGING) && (fEvent!=NULL)) { fprintf (fEvent, "\n\n"); fclose(fEvent); } printf ("\n"); } /* End of main */