/* Student version of SIMLATOR.C for COP 4600 */ /* Revision 1/8/91 */ #include "stdio.h" #include "stdlib.h" #include "time.h" #include "string.h" #include "osdefs.h" #include "externs.h" /* Simulation Control Variable */ int OBJECTIVE = 0; char Lname[9]; /* first 8 letters of last name (config parameter) */ char Outfile[14]; /* output file name --first eight letters of last name */ /* File pointers to files */ FILE *simout, /* file pointer for SIMLATOR.OUT */ *scriptfp, /* file pointer for SCRIPT.DAT */ *logonfp, /* file pointer for LOGON.DAT */ *PROGM_FILE[6]; /* file pointer for program.DAT */ /* program = (see pgmidtab[]) */ /* Strings for input and output matching */ char *pgmidtab[] = {"EDITOR","PRINTER","COMPILER","LINKER","USER", "BOOT","LOGOFF"}; char *eventidtab[] = {"LOGON","SIO","WIO","EIO","END","TIMER", "SEGFAULT", "ADRFAULT"}; char *opidtab[] = {"SIO","WIO","REQ","JUMP","SKIP","END" }; /* note OPCDSIZE = number of opcodes */ /* variables for interrupt registers, clock & switches */ int CPU_SW; /* control switch for the CPU (1 = ON, 0 = OFF) */ int SCHED_SW; /* control switch for the Scheduler(1 = ON, 0 = OFF) */ int AGENT; /* terminal RANGE = 1..TRMSIZE */ /* device RANGE = TRMSIZE+1..TRMSIZE+DEVSIZE */ int EVENT; /* LOGON, SIO, WIO, EIO, PGMEMD, TIMEEVENT, SEGFAULT and ADRFAULT */ struct simtime CLOCK = { 0, 0 }; /* Simulation clock */ /* Variables used for CPU statistics */ int NJOBS = 0; /* Total jobs processed */ struct simtime TOTLOGON = { 0, 0 }; /* Total job processing time */ struct simtime TOTWAIT = { 0, 0 }; /* Total job wait time */ struct simtime TOTBLKED = { 0, 0 }; /* Total job blocked time */ struct simtime TOTRUN = { 0, 0 }; /* Total job execution time */ struct simtime AVERUN = { 0, 0 }; /* Average user execution time */ struct simtime AVEWAIT = { 0, 0 }; /* Average user wait time */ struct simtime AVEBLKED = { 0, 0 }; /* Average user blocked time */ struct simtime AVELOGON = { 0, 0 }; /* Average user logon time */ /* Variables used with Round-Robin scheduling */ struct timer_type TIMER = { /* Simulation timer (used with RR) */ {0,0}, /* struct simtime TIME_OUT */ 0, /* RR quantum in instructions */ {0,0} /* RR quantum in ( SEC, NSEC ) */ }; struct state_type OldState = { /* Interrupt State Save Area */ 0x01, /* priviledged mode */ {0,0} /* Interrupt Handler Entry Point */ }; struct state_type NewState = { /* New Interrupt State */ 0x01, /* priviledged mode */ {0,0} /* Interrupt Handler Entry Point */ }; /* variable for CPU. See osdefs.h for structure details. */ struct cpu_type CPU = {1000, /* CPU rate in nanosec/instr. (rate) */ 1000000, /* CPU rate in instr/sec (CPURATE) */ 0x01, /* CPU mode (priviledged) (mode) */ { 0, 0 }, /* program counter (pc ) */ NULL, /* active pcb (actvpcb) */ { 0, 0 }, /* (qwait) */ { 0, 0 }, /* (busy) */ { 0, 0 }, /* (response) */ { 0, 0 }, /* (idle) */ 0, /* no. served (served) */ 0, /* max queue length (maxq) */ 0, /* current queue length (qlen) */ 0.0, /* utilization (utilize) */ NULL, /* head ready list (ready) */ NULL }; /* tail ready list (tail) */ /* variables for simulator memory structures */ int MAXSEGMENTS = 1; /* Maximum size of Memory Map */ /* (must be a power of 2) */ struct segment_type *MEMMAP = NULL; /* Memory Address Mapping Table */ /* (size = 2*MAXSEGMENTS) */ int MEMSIZE = 1000; /* Memory size */ struct instr_type *MEM = NULL; /* Processor memory array */ struct seg_list *FreeMem = NULL; /* List of free segments ordered */ /* by memory base address. */ unsigned int TotalFree = 1000; /* Total Free Memory(see MEMSIZE) */ struct addr_type MAR; /* Operating System tables for device and terminal management */ struct device_type *devtable = NULL; /* Device Table(array of devices) */ struct pcb_type **termtable = NULL; /* Terminal Table (array of *pcb) */ struct event_type *new_events = NULL; /* pointer to head of event list */ /* Control variables */ int DEVSIZE = 0; /* Number of devices */ int TRMSIZE = 0; /* Number of terminals */ int MAXSCRIPT = 10; /* ten programs */ /* variables used for scheduling alogrithms */ int SCHED = FCFS; /* Current CPU scheduling algorithm */ unsigned long ONEOVRBETA; /* expected CPU burst (SJN) */ unsigned long LOGON_T = SEC; /* Time units for LOGON events */ double RHO = 0.0; /* SJN Smoothing factor */ /* Debugging flags. Use them! */ int DEBUG_MEM = 0 ; /* flag that controls MEMORY DEBUG OUTPUT */ int DEBUG_EVTQ = 0; /* flag that controls EVENT_Q DEBUG OUTPUT */ int DEBUG_PCB = 0; /* flag that controls PCB DEBUG OUTPUT */ int DEBUG_RBLIST = 0; /* flag that controls RBLIST DEBUG OUTPUT */ int DEBUG_RBQ = 0; /* flag that controls RB_Q DEBUG OUTPUT */ int DEBUG_CPUQ = 0; /* flag that controls CPUQ DEBUG OUTPUT */ /****************************************************************************/ /* This is the SIMULATION DRIVER */ /****************************************************************************/ main(int argc, char *argv[]) { Init(); /* read config.dat */ Load_events(); /* Initialize new_events list */ Open_output( Outfile ); /* Open simulation output file */ Boot(); printf("\nSimulation begins...\n"); while( new_events != NULL ) { CPU_SW = SCHED_SW = 0; Interrupt(); /* Action of the interrupt hardware */ /* get next event; update system clock; output event */ if( Interrupt_Handler() ) break; /* Diagnose and service interrupt. */ /* Exit on Memory fault for OBJ 2 */ if( OBJECTIVE >= 4 && SCHED_SW ) CPU.actvpcb = Scheduler(); if( OBJECTIVE >= 4 && CPU.actvpcb != NULL ) if( CPU_SW ) Dispatcher(); else { CPU.mode = CPU.actvpcb->cpu_save.mode; CPU.pc = CPU.actvpcb->cpu_save.pc; } if( OBJECTIVE == 2 ) XPGM( &OldState ); } /* While */ Wrapup(); /* Write statistics. Close files, etc. */ printf("\n...Simulation ends.\n"); exit(0); } /* main */ /***************************** Given Functions ******************************/ int Interrupt_Handler(void) /* ------------------------------------------------------------------------- */ /* Interrupt handler is in control (with all interrupts inhibited). */ /* Save the state of the interrupted program (if the CPU is busy): */ /* (a) OldState is copied into CPU.actvpcb->cpu_save */ /* (b) UserMap is copied into *CPU.actvpcb->segtable; (optional) */ /* Give control to interrupt service routine. */ /* ------------------------------------------------------------------------- */ { if (CPU.actvpcb != NULL) /* CPU is busy */ { CPU.actvpcb->cpu_save = OldState; } switch( EVENT ) { case LOGON : Logon_Service(); break; case STARTIO : Sio_Service(); break; case WAITIO : Wio_Service(); break; case ENDIO : Eio_Service(); break; case PGMEND : if (OBJECTIVE == 2) return(1); End_Service(); break; case SEGFAULT : case ADRFAULT : Abend_Service(); if( OBJECTIVE == 2) return(1); break; case TIMEEVENT : Timer_Service(); break; default : printf(" INVALID EVENT CODE IN MAIN LOOP!!! "); exit(0); } /* switch */ return(0); } void Write_stats(void) /* ------------------------------------------------------------------------- */ /* This function writes the statistics summary to DATA*.OUT */ /* ------------------------------------------------------------------------- */ { int i, flag; struct simtime t; fprintf(simout,"\n\n\n TERMINAL SUMMARY "); fprintf(simout, "\n ==========================================================================="); fprintf(simout, "\n TERMNL| EXEC | WAIT | BLOCKED | ELAPSED | EFF"); fprintf(simout, "\n ======|================|==============|==============|==============|======"); for(i = 0, flag = 0; i < TRMSIZE ; i++ ){ if( termtable[i] == NULL ) continue; if( flag ) fprintf(simout, "\n ------|----------------|--------------|--------------|--------------|------"); fprintf(simout,"\n %s | %10lu SC |%10lu SC |%10lu SC |%10lu SC | %.3f", termtable[i]->user, termtable[i]->trun.seconds, termtable[i]->tready.seconds, termtable[i]->tblocked.seconds, termtable[i]->tlogon.seconds, termtable[i]->efficncy); fprintf(simout,"\n | %10lu NS |%10lu NS |%10lu NS |%10lu NS |", termtable[i]->trun.nanosec, termtable[i]->tready.nanosec, termtable[i]->tblocked.nanosec, termtable[i]->tlogon.nanosec); flag = 1; } fprintf(simout, "\n ==========================================================================="); fprintf(simout, "\n TOTALS| %10lu SC |%10lu SC |%10lu SC |%10lu SC |", TOTRUN.seconds, TOTWAIT.seconds, TOTBLKED.seconds, TOTLOGON.seconds); fprintf(simout, "\n | %10lu NS |%10lu NS |%10lu NS |%10lu NS |", TOTRUN.nanosec, TOTWAIT.nanosec, TOTBLKED.nanosec, TOTLOGON.nanosec); fprintf(simout, "\n ------|----------------|--------------|--------------|--------------|"); fprintf(simout, "\n AVERGE| %10lu SC |%10lu SC |%10lu SC |%10lu SC |", AVERUN.seconds, AVEWAIT.seconds, AVEBLKED.seconds, AVELOGON.seconds); fprintf(simout, "\n | %10lu NS |%10lu NS |%10lu NS |%10lu NS |", AVERUN.nanosec, AVEWAIT.nanosec, AVEBLKED.nanosec, AVELOGON.nanosec); fprintf(simout, "\n ====================================================================="); /* Write out DEVICE statistics */ fprintf(simout,"\n\n\n DEVICE SUMMARY "); fprintf(simout, "\n ==========================================================================="); fprintf(simout, "\n DEVICE| BUSY | WAIT | IDLE | RESPONSE | %UTIL"); fprintf(simout, "\n ======|================|==============|==============|==============|======"); fprintf(simout, "\n CPU | %10lu SC |%10lu SC |%10lu SC |%10lu SC | %.2f", CPU.busy.seconds, CPU.qwait.seconds, CPU.idle.seconds, CPU.response.seconds, CPU.utilize); fprintf(simout,"\n | %10lu NS |%10lu NS |%10lu NS |%10lu NS |", CPU.busy.nanosec, CPU.qwait.nanosec, CPU.idle.nanosec, CPU.response.nanosec); for(i=0; i < DEVSIZE; i++ ){ if( !devtable[i].served ) continue; fprintf(simout, "\n ------|----------------|--------------|--------------|--------------|"); fprintf(simout, "\n %s | %10lu SC |%10lu SC |%10lu SC |%10lu SC | %.2f", devtable[i].devid, devtable[i].busy.seconds, devtable[i].qwait.seconds, devtable[i].idle.seconds, devtable[i].response.seconds, devtable[i].utilize); fprintf(simout,"\n | %10lu NS |%10lu NS |%10lu NS |%10lu NS |", devtable[i].busy.nanosec, devtable[i].qwait.nanosec, devtable[i].idle.nanosec, devtable[i].response.nanosec); } fprintf(simout, "\n ====================================================================="); } /* Write_stats */ void Init(void) /* ------------------------------------------------------------------------- */ /* This function reads CONFIG.DAT files */ /* and initializes the simulator environment. */ /* ------------------------------------------------------------------------- */ { FILE *cp, *fp, *lp; char ident[15]; int scancode,i,err,oneovrbeta,quantum, objective, lname; unsigned long hr, min, sec, milsec, msec, nsec; oneovrbeta = quantum = objective = lname = 0; /* boolean flags */ if( (fp = fopen("config.dat","r")) == NULL ) { printf(" CONFIG.DAT file does not exit! \n"); exit(0); } while( fscanf(fp,"%s",ident) != EOF ) { if( !strcmp(ident,"TIME=")){ if( (scancode = fscanf(fp,"%s",ident)) == EOF || scancode < 1) { printf(" MISSING TIME= PARAMETER \n"); exit(0); } if( !strcmp(ident,"MIN")){ LOGON_T = MIN; }else if( !strcmp(ident,"SEC")){ LOGON_T = SEC; }else if( !strcmp(ident,"MSEC")){ LOGON_T = MSEC; }else if( !strcmp(ident,"mSEC")){ LOGON_T = mSEC; }else if( !strcmp(ident,"NSEC")){ LOGON_T = NSEC; }else { printf(" UNRECOGNIZABLE TIME= PARAMETER \n"); exit(0); } /* else */ }else if( !strcmp(ident,"OBJECTIVE=")){ if( (scancode = fscanf(fp,"%d",&OBJECTIVE)) == EOF || scancode < 1) { printf(" MISSING OBJECTIVE= PARAMETER \n"); exit(0); } objective = 1; }else if( !strcmp(ident,"RRQUANTUM=")){ if( (scancode = fscanf(fp,"%U",&TIMER.QUANTUM)) == EOF || scancode < 1) { printf(" MISSING RRQUANTUM= PARAMETER \n"); exit(0); } quantum = 1; }else if( !strcmp(ident,"1/BETA=")){ if( (scancode = fscanf(fp,"%U",&ONEOVRBETA)) == EOF || scancode < 1) { printf(" MISSING 1/BETA= PARAMETER \n"); exit(0); } oneovrbeta = 1; }else if( !strcmp(ident,"RHO=")){ float temp; if( (scancode = fscanf(fp,"%f",&temp)) == EOF || scancode < 1) { printf(" MISSING RHO= PARAMETER \n"); exit(0); } RHO = (double)temp; if( RHO < 0.0 || RHO > 1.0 ) { printf(" INVALID RHO= PARAMETER \n"); exit(0); } }else if( !strcmp(ident,"TERMINALS=")){ if( (scancode = fscanf(fp,"%d",&TRMSIZE)) == EOF || scancode < 1) { printf(" MISSING TERMINALS= PARAMETER \n"); exit(0); } if( TRMSIZE <= 0 ) { printf(" INVALID TERMINALS= PARAMETER \n"); exit(0); } }else if( !strcmp(ident,"DEVICES=")){ if( (scancode = fscanf(fp,"%d",&DEVSIZE)) == EOF || scancode < 1) { printf(" MISSING DEVICES= PARAMETER \n"); exit(0); } if( DEVSIZE <= 0 ) { printf(" INVALID DEVICES= PARAMETER \n"); exit(0); } /* allocate Device Table */ devtable = calloc(DEVSIZE, sizeof(struct device_type)); if( devtable == NULL) { printf(" DEVICE TABLE ALLOCATION FAILURE! \n"); exit(0); } { /* block */ unsigned long bytes_per_sec; /* read device description and enter in Device Table */ for(i=0; i< DEVSIZE; i++){ if( (scancode = fscanf(fp,"\nID= %4c RATE= %U ", devtable[i].devid, &bytes_per_sec)) == EOF || scancode < 2) { printf(" MISSING DEVICE= SPECIFICATION PARAMETER(s) \n"); exit(0); } /* if */ devtable[i].byps = bytes_per_sec; devtable[i].npb = (double)1.0e9/(double)bytes_per_sec; devtable[i].qwait.seconds = 0; devtable[i].qwait.nanosec = 0; devtable[i].busy = devtable[i].qwait; devtable[i].served = 0; devtable[i].maxq = 0; devtable[i].qlen = 0; } /* for */ } /* end block */ }else if( !strcmp(ident,"MEMSIZE=")){ if( (scancode = fscanf(fp,"%U",&MEMSIZE)) == EOF || scancode < 1) { printf(" MISSING MEMSIZE= PARAMETER \n"); exit(0); } }else if( !strcmp(ident,"CPURATE=")){ if( (scancode = fscanf(fp,"%U",&CPU.rate)) == EOF || scancode < 1) { printf(" MISSING CPURATE= PARAMETER \n"); exit(0); } }else if( !strcmp(ident,"MAXSCRIPT=")){ if( (scancode = fscanf(fp,"%d",&MAXSCRIPT)) == EOF || scancode < 1) { printf(" MISSING MAXSCRIPT= PARAMETER \n"); exit(0); } if( MAXSCRIPT <= 0 ) { printf(" INVALID MAXSCRIPT= PARAMETER \n"); exit(0); } }else if( !strcmp(ident,"LNAME=")){ if( (scancode = fscanf(fp,"%s",ident)) == EOF || scancode < 1){ printf(" MISSING LNAME= PARAMETER \n"); exit(0); } lname = 1; strcpy(Lname,ident); }else if( !strcmp(ident,"SCHED=")){ if( (scancode = fscanf(fp,"%s",ident)) == EOF || scancode < 1) { printf(" MISSING SCHED= PARAMETER \n"); exit(0); } if( !strcmp(ident,"FCFS")) { SCHED = FCFS; }else if( !strcmp(ident,"SJN")) { SCHED = SJN; }else if( !strcmp(ident,"HPRN")) { SCHED = HPRN; }else if( !strcmp(ident,"RNDRBN")){ SCHED = RNDRBN; }else { printf(" UNRECOGNIZABLE SCHED= PARAMETER \n"); exit(0); } /* else */ }else if( !strcmp(ident,"MAXSEGMENTS=")){ if( (scancode = fscanf(fp,"%d",&MAXSEGMENTS)) == EOF || scancode < 1) { printf(" MISSING MAXSEGMENTS= PARAMETER \n"); exit(0); } if( MAXSEGMENTS < 1) { printf(" INVALID MAXSEGMENTS= PARAMETER \n"); exit(0); } }else if( !strcmp(ident,"DEBUG_MEM=")){ if( (scancode = fscanf(fp,"%s",ident)) == EOF || scancode < 1) { printf(" MISSING DEBUG_MEM= PARAMETER \n"); exit(0); } if( !strcmp(ident,"ON" ) ) DEBUG_MEM = 1; else if( !strcmp(ident,"OFF") ) DEBUG_MEM = 0; else { printf(" INVALID DEBUG_MEM= PARAMETER \n"); exit(0); } }else if( !strcmp(ident,"DEBUG_EVTQ=")){ if( (scancode = fscanf(fp,"%s",ident)) == EOF || scancode < 1) { printf(" MISSING DEBUG_EVTQ= PARAMETER \n"); exit(0); } if( !strcmp(ident,"ON" ) ) DEBUG_EVTQ = 1; else if( !strcmp(ident,"OFF") ) DEBUG_EVTQ = 0; else { printf(" INVALID DEBUG_EVTQ= PARAMETER \n"); exit(0); } }else if( !strcmp(ident,"DEBUG_PCB=")){ if( (scancode = fscanf(fp,"%s",ident)) == EOF || scancode < 1) { printf(" MISSING DEBUG_PCB= PARAMETER \n"); exit(0); } if( !strcmp(ident,"ON" ) ) DEBUG_PCB = 1; else if( !strcmp(ident,"OFF") ) DEBUG_PCB = 0; else { printf(" INVALID DEBUG_PCB= PARAMETER \n"); exit(0); } }else if( !strcmp(ident,"DEBUG_RBLIST=")){ if( (scancode = fscanf(fp,"%s",ident)) == EOF || scancode < 1) { printf(" MISSING DEBUG_RBLIST= PARAMETER \n"); exit(0); } if( !strcmp(ident,"ON" ) ) DEBUG_RBLIST = 1; else if( !strcmp(ident,"OFF") ) DEBUG_RBLIST = 0; else { printf(" INVALID DEBUG_RBLIST= PARAMETER \n"); exit(0); } }else if( !strcmp(ident,"DEBUG_RBQ=")){ if( (scancode = fscanf(fp,"%s",ident)) == EOF || scancode < 1) { printf(" MISSING DEBUG_RBQ= PARAMETER \n"); exit(0); } if( !strcmp(ident,"ON" ) ) DEBUG_RBQ = 1; else if( !strcmp(ident,"OFF") ) DEBUG_RBQ = 0; else { printf(" INVALID DEBUG_RBQ= PARAMETER \n"); exit(0); } }else if( !strcmp(ident,"DEBUG_CPUQ=")){ if( (scancode = fscanf(fp,"%s",ident)) == EOF || scancode < 1) { printf(" MISSING DEBUG_CPUQ= PARAMETER \n"); exit(0); } if( !strcmp(ident,"ON" ) ) DEBUG_CPUQ = 1; else if( !strcmp(ident,"OFF") ) DEBUG_CPUQ = 0; else { printf(" INVALID DEBUG_CPUQ= PARAMETER \n"); exit(0); } }else { /* unrecognizable input */ printf(" Warning: Unrecognizable parameter %s in CONFIG.DAT!\n",ident); while( fgetc(fp) != '\n'); } /* else */ } /* while */ /* validate config.dat parameters */ err = 0; /* Do NOT put your LASTNAME.OUT as the output file name */ if( lname ){ strcpy ( Outfile, Lname ); strcat ( Outfile, ".out"); strlwr ( Outfile ); }else{ err = 1; printf(" LNAME= PARAMETER NOT DEFINED! \n"); } if( !objective ){ err = 1; printf(" OBJECTIVE= PARAMETER NOT DEFINED! \n"); } if( !oneovrbeta && (SCHED == HPRN || SCHED == SJN) ){ err = 1; printf(" 1/BETA= PARAMETER NOT DEFINED! \n"); } if( !quantum && SCHED == RNDRBN ){ err = 1; printf(" RRQUANTUM= PARAMETER NOT DEFINED! \n"); } if( devtable == NULL ) { printf(" DEVICES= PARAMETER NOT DEFINED! \n"); err = 1; } if( (lp = fopen("logon.dat","r")) == NULL ){ printf(" LOGON.DAT does not exist! \n"); err = 1; }else fclose(lp); if( (scriptfp = fopen("script.dat","r")) == NULL ){ printf(" SCRIPT.DAT does not exist! \n"); err = 1; } if( (PROGM_FILE[EDITOR] = fopen("editor.dat","r")) == NULL ) printf(" Warning: EDITOR.DAT does not exist! \n"); if( (PROGM_FILE[PRINTER] = fopen("printer.dat","r")) == NULL ) printf(" Warning: PRINTER.DAT does not exist! \n"); if( (PROGM_FILE[COMPILER] = fopen("compiler.dat","r")) == NULL ) printf(" Warning: COMPILER.DAT does not exist! \n"); if( (PROGM_FILE[LINKER] = fopen("linker.dat","r")) == NULL ) printf(" Warning: LINKER.DAT does not exist! \n"); if( (PROGM_FILE[USER] = fopen("user.dat","r")) == NULL ) printf(" Warning: USER.DAT does not exist! \n"); if( (PROGM_FILE[BOOT] = fopen("boot.dat","r")) == NULL ) printf(" Warning: BOOT.DAT does not exist! \n"); /* COMPUTE indirect configuration parameters */ CPU.CPU_burst = SEC/CPU.rate; /* instructions per sec */ /* allocate memory map hardware */ MEMMAP = calloc(2*MAXSEGMENTS, sizeof(struct segment_type)); if( MEMMAP == NULL ) { printf(" MEMORY ADDRESS MAP ALLOCATION FAILURE! \n"); err = 1; } /* allocate memory */ MEM = calloc(MEMSIZE, sizeof(struct instr_type)); if( MEM == NULL) { printf(" MEMORY ARRAY ALLOCATION FAILURE! \n"); err = 1; } /* initialize list of free memory segments */ FreeMem = calloc(1, sizeof(struct seg_list)); if( FreeMem == NULL ) { printf(" FREE LIST ALLOCATION FAILURE! \n"); err = 1; } TotalFree = MEMSIZE; FreeMem->segsize = MEMSIZE; FreeMem->segptr = 0; FreeMem->next = NULL; /* allocate terminal table */ termtable = calloc(TRMSIZE, sizeof(struct pcb_type *)); if( termtable == NULL) { printf(" TERMINAL TABLE ALLOCATION FAILURE! \n"); err = 1; } for(i=0; i nanosec < (SEC - time1->nanosec) ) time2->nanosec += time1->nanosec; else{ time2->seconds++; time2->nanosec -= SEC - time1->nanosec; } time2->seconds += time1->seconds; } /* Add_time */ void Diff_time(struct simtime *time1, struct simtime *time2) /* ------------------------------------------------------------------------- */ /* This function computes: time2 = time2 - time1 */ /* Assuming: time2 >= time1 */ /* ------------------------------------------------------------------------- */ { if( time2->seconds == time1->seconds ){ time2->seconds = 0; time2->nanosec -= time1->nanosec; }else{ time2->seconds -= time1->seconds + 1; if( time2->nanosec >= time1->nanosec ){ ++time2->seconds; time2->nanosec -= time1->nanosec; }else time2->nanosec += SEC - time1->nanosec; } } /* Diff_time */ int Cmpr_time(struct simtime *p, struct simtime *q) /* ------------------------------------------------------------------------- */ /* This function compares two simulation times: p,q */ /* IF p < q RETURN -1 */ /* IF p = q RETURN 0 */ /* IF p > q RETURN +1 */ /* ------------------------------------------------------------------------- */ { int result; if( p->seconds < q->seconds ) { result = -1; goto done; } if( p->seconds > q->seconds ) { result = +1; goto done; } if( p->nanosec < q->nanosec ) { result = -1; goto done; } if( p->nanosec > q->nanosec ) { result = +1; goto done; } result = 0; done: return(result); } /* Cmpr_time */ void Convrt_time(struct simtime *s, unsigned long t) /* ------------------------------------------------------------------------- */ /* This function converts external time units (defined by LOGON_T) */ /* to internal seconds and nanosec. */ /* ------------------------------------------------------------------------- */ { switch(LOGON_T){ case MIN: s->seconds = t*60; s->nanosec = 0; break; case SEC: s->seconds = t; s->nanosec = 0; break; case MSEC:s->seconds = t/1000; s->nanosec = (t - 1000*s->seconds)*MSEC; break; case mSEC:s->seconds = t/1000000; s->nanosec = (t - 1000000*s->seconds)*mSEC; break; case NSEC:s->seconds = t/1000000000; s->nanosec = t - 1000000000*s->seconds; } } /* Convrt_time */ double Divd_time(struct simtime *t1, struct simtime *t2) /* ------------------------------------------------------------------------- */ /* This function divides two simulation times (t1/t2) by first converting */ /* both to seconds and fractions of a second. */ /* ------------------------------------------------------------------------- */ { double x1,x2; x1 = (double)t1->seconds + (double)t1->nanosec/DSEC; x2 = (double)t2->seconds + (double)t2->nanosec/DSEC; return( x1/x2 ); } /* Divd_time */ void Ave_time(struct simtime *t1, struct simtime *t2, int n) /* ------------------------------------------------------------------------- */ /* This function computes t1 = t2/n */ /* Where t1 and t2 are simulation times, and n is a positive integer. */ /* ------------------------------------------------------------------------- */ { double x, dn; dn = (double)n; x = ((double)t2->seconds/dn) + ((double)t2->nanosec/dn)*1.0e-9; t1->seconds = x; t1->nanosec = (x - (double)t1->seconds) * DSEC; } /* Ave_time */ void Burst_time(struct simtime *t, unsigned long b) /* ------------------------------------------------------------------------ */ /* This function converts a cpu burst into simulation time. The time */ /* depends on the cpu rate and length of the burst. */ /* ------------------------------------------------------------------------ */ { t->seconds = b / CPU.CPU_burst; t->nanosec = ( b - CPU.CPU_burst * t->seconds ) * CPU.rate; } /* Burst_time */ /*void strlwr(char *what_str) { while (*what_str) { *what_str = tolower(*what_str); what_str++; } }*/ /* strlwr */ /*void strupr(char *what_str) { while (*what_str) { *what_str = toupper(*what_str); what_str++; } } */ /* strupr */ double SimTimeToDouble(struct simtime *time1) { double ctime, nano; nano = time1->nanosec/(double)SEC; ctime = time1->seconds + nano; return(ctime); }