/* $Id: main.c,v 10.1 92/10/06 23:10:33 ca Exp $ */ /* Main routine of the simulator. */ #define MAIN /* This file contains main() */ #include #include "sim.h" #include "component.h" #include "simx.h" #include "event.h" #include "eventdefs.h" #include "comptypes.h" #include "list.h" #ifdef NoX int doXstuff = FALSE; /* if FALSE, don't open any X windows */ #else int doXstuff = TRUE; /* if FALSE, don't open any X windows */ #endif /* NoX */ Log pkt_log; int interactive = FALSE; /* if TRUE ask for continuation at stoptime */ int record_flag = 0; int play_flag = 0; int profile_flag = 0; FILE *record_file; FILE *profilefile; unsigned long int perf_update_dt_usecs = DEFAULT_PERF_UPDATE_DT_USECS; unsigned long int skip_time_in_ticks = DEFAULT_SKIP_TIME_IN_TICKS; #ifdef DEBUG Log debug_log; #endif int seed = 0; char snapname[32]; char eventfilename[32]; char playfilename[128]; char profilefilename[32]; list *read_world(); long time(); void play_file(), save_snap(); #ifdef MOTIF int load_motif_info(char *filename); /* eric */ #endif main(argc, argv) int argc; char *argv[]; { tick_t stoptime = ~0; int i; char *name = NULL; char *prname = NULL; int tmp; #ifdef DEBUG dbg_set_level(DBG_ERR); debug_log = stderr; #endif /* Print Hello Message */ print_start_stat(stderr, argc, argv); /* Process command line looking for options */ prname = (prname = (char *) rindex(argv[0],'/')) ? ++prname : argv[0]; the_environment.pr_name = prname; /* Create snap file name by appending the PID to "sim_snap." */ /* If the simulator runs longer than stoptime, it will snapshot */ /* its current state into this file before exiting */ snapname[0] = '\0'; sprintf(snapname, "sim_snap.%d", getpid()); eventfilename[0] = '\0'; sprintf(eventfilename, "sim_events.%d", getpid()); playfilename[0] = '\0'; for (i = 1; i < argc && *argv[i] == '-'; i++) { if (strcmp(argv[i], "-s") == 0) { i++; if (i >= argc) usage(argv); seed = atoi(argv[i]); continue; } if (strcmp(argv[i], "-x") == 0) { doXstuff = FALSE; continue; } if (strcmp(argv[i], "-i") == 0) { doXstuff = FALSE; interactive = TRUE; continue; } #ifndef NoX if (strcmp (argv[i], "-r") == 0) { the_environment.reverse_video = 1; continue; } #endif /* NoX */ if (strcmp (argv[i], "-record") == 0) { i++; if (i >= argc) usage(argv); strcpy(eventfilename, argv[i]); record_flag = 1; continue; } if (strcmp(argv[i], "-play") == 0) { i++; if (i >= argc) usage(argv); strcpy(playfilename, argv[i]); play_flag = 1; continue; } if (strcmp(argv[i], "-perfdt") == 0) { i++; if (i >= argc) usage(argv); sscanf(argv[i], "%ld", &perf_update_dt_usecs); continue; } if (strcmp(argv[i], "-skipt") == 0) { i++; if (i >= argc) usage(argv); sscanf(argv[i], "%ld", &skip_time_in_ticks); skip_time_in_ticks = USECS_TO_TICKS(skip_time_in_ticks); continue; } if (strcmp(argv[i], "-profile") == 0) { profile_flag = 1; profilefilename[0] = '\0'; sprintf(profilefilename, "sim_profile.%d", getpid()); profilefile = fopen(profilefilename, "w"); print_start_stat(profilefile, argc, argv); get_start_time(); print_rusage(profilefile); continue; } usage(argv); } if (i < argc) /* World file name */ name = argv[i++]; if (i < argc) { /* Stop time */ #define DUSECS_TO_TICKS(time) ((time) / (double) USECS_PER_TICK) double stop, maxd; tick_t max_int = ~0; /* Tick_t is a integer which on most architechtures is 32 bits, max_int is the largest unsigned integer that can be represented */ maxd = (double) max_int; /* lets get stop in a representation that can handle more than 32 bits */ stop = (double) atof (argv[i]); stop = (double) DUSECS_TO_TICKS (stop); /* convert to ticks */ if (stop > maxd) { /* if this can not be represented bail out */ printf ("Stop time %.0f is greater than MaRS can support (%u).\n", stop, max_int); exit( 4); } stoptime = (tick_t) stop; } /* Event manager */ if (!ev_init()) { #ifdef DEBUG dbg_write(debug_log, DBG_ERR, (Component *)NULL, "Dying: ev_init failed"); #endif exit(1); } /* Packet pool */ if (!pk_init()) { #ifdef DEBUG dbg_write(debug_log, DBG_ERR, (Component *)NULL, "Dying: pk_init failed"); #endif exit(1); } #ifndef NoX if (doXstuff) { if (xinit(argc, argv) != OK) { #ifdef DEBUG dbg_write(debug_log, DBG_ERR, (Component *)NULL, "Dying: xinit failed"); #endif /* DEBUG */ exit(1); } } if (record_flag) set_record_flag(doXstuff); #endif /* NoX */ /****************************** by Cengiz Alaettinoglu create peer list **********************************/ if (!peer_create()) { #ifdef DEBUG dbg_write(debug_log, DBG_ERR, (Component *)NULL, "Dying: peer_create failed"); #endif exit(1); } /** Seed the random number generator with the time (or seed from cmd line) */ if (!seed) /* If seed not specified, use the time */ seed = (int)time((long *)NULL); fprintf(stderr, " Seed: %d\n", seed); srandom(seed); if (!make_default_lcostfcn()) { fprintf(stderr, "Could not create a Link Cost Function Component\n"); exit(5); } /* If there is a world file parameter, read the file, else make an empty component list. */ comps = NULL; if (name) { comps = read_world(name); #ifdef MOTIF /* Load the motif stuff. */ if (doXstuff) { if (comps) { extern list *network_components; char *motif_filename; int min_width; int min_height; int result; motif_filename=(char *)sim_malloc(strlen(name)+7); strcpy(motif_filename, name); strcat(motif_filename, ".motif"); result=load_motif_info(motif_filename); free(motif_filename); /* Draw Everything */ if (!result) /* Then we have to make all the component's visible before drawing them. */ MakeComponentsVisible(network_components); DrawComponents(network_components); if (result) OpenInformationWindowsFromFile(); } } #endif if (!comps) { #ifndef NoX if (doXstuff) { char buf[512]; xprintclear(); sprintf(buf, "Couldn't read world file '%s'", name); printx(buf); } else fprintf(stderr, "Couldn't read world file '%s'\n", name); #else fprintf(stderr, "Couldn't read world file '%s'\n", name); #endif } } if (!comps) comps = l_create(); #ifndef NoX #ifndef MOTIF if (doXstuff){ make_line_array(); connect_components(); } #endif #endif the_environment.never_ran = TRUE; /* If not interactive, reset & start this thing immediately */ if (!doXstuff) { sim_reset(comps); sim_start(comps); } for (;;) { #ifndef NoX if (doXstuff) io(); #endif /* NoX */ /* Make all the events that happen at the same time fire. */ switch (the_environment.single_step) { case 1 : ev_fire_first(); break; case 2 : ev_fire_all_first(); break; default : if (ev_now() > stoptime) { if (interactive) { printf("Enter next interval or 0 to stop : "); scanf("%d", &tmp); if (!tmp) { sim_stop(comps); (void) save_snapshot(comps, snapname); print_end_stat(stderr); if (profile_flag) { print_end_stat(profilefile); print_rusage(profilefile); fclose(profilefile); } exit(0); } else stoptime += USECS_TO_TICKS(tmp); } else { sim_stop(comps); (void) save_snap(); print_end_stat(stderr); if (profile_flag) { print_end_stat(profilefile); print_rusage(profilefile); fclose(profilefile); } exit(0); } } if (!ev_fire_all_first()) { if (!doXstuff) { sim_stop(comps); print_end_stat(stderr); if (profile_flag) { print_end_stat(profilefile); print_rusage(profilefile); fclose(profilefile); } exit(0); } } } #ifndef NoX if (doXstuff) update_screen(); #endif /* NoX */ } } usage(argv) char *argv[]; { printf("Usage: %s [-x] [-s seed] [-i] [-r] [-record file] [-play file] [-perfdt usecs] [-skipt usecs] [-profile] [worldfile [stoptime]]\n", argv[0]); exit(1); } sim_reset(comps) list *comps; { Component *c; ev_reset(); /* Clear out any pending events */ pk_free_all(); /* Get rid of all packets */ for (c = (COMPONENT *) comps->l_head; c; c = c->co_next) (*c->co_action)(NULL, c, EV_RESET, NULL, NULL); #ifndef NoX if (doXstuff) x_reset(); #endif /* NoX */ } sim_start(comps) list *comps; { Component *c; /* Start to all components */ for (c = (COMPONENT *) comps->l_head; c; c = c->co_next) (*c->co_action)(NULL, c, EV_START, NULL, NULL); if (play_flag && playfilename[0]) { play_file(playfilename); } } sim_stop(comps) list *comps; { Component *c; /* Stop to all components */ for (c = (COMPONENT *) comps->l_head; c; c = c->co_next) (*c->co_action)(NULL, c, EV_STOP, NULL, NULL); } extern list *read_line(); void play_file(filename) char *filename; { unsigned int time; int opcode; char *who; Component *who_ds; FILE *scnr_file; caddr_t arg; list *l; l_elt *le; char buffer[1024]; #ifndef NoX if (doXstuff) { xprintclear(); printx("Playing events from the file "); printx(filename); sleep(1); } #endif /* NoX */ if ((scnr_file = fopen(filename, "r")) == NULL) { #ifndef NoX if (doXstuff) { printx("File "); printx(filename); printx(" does not exist. Aborting..."); sleep(2); xprintclear(); } else fprintf(stderr, "File %s does not exist. Aborting...\n", filename); #else fprintf(stderr, "File %s does not exist. Aborting...\n", filename); #endif /* NoX */ return; } while (l = read_line(scnr_file, buffer)) { if (l->l_len < 1) { /* Blank line */ lq_delete(l); continue; } time = atoi((char *)l->l_head->le_data); who = (char *)l->l_head->le_next->le_data; opcode = atoi((char *)l->l_head->le_next->le_next->le_data); arg = (caddr_t) atoi((char *)l->l_head->le_next->le_next->le_next->le_data); lq_delete(l); for (who_ds = (Component *) comps->l_head; who_ds != NULL && strcmp(who_ds->co_name, who); who_ds = who_ds->co_next); if (who_ds != NULL && opcode) ev_enqueue(opcode, (Component *)NULL, who_ds, USECS_TO_TICKS(time), who_ds->co_action, (Packet *)NULL, arg); } fclose(scnr_file); #ifndef NoX if (doXstuff) xprintclear(); #endif /* NoX */ } void save_snap() { (void) save_snapshot(comps, snapname); } #ifdef NoX /* the following is defined in files with X and MOTIF interfaces repeated here for NoX */ void set_record_flag(doXstuff) int doXstuff; { record_flag = 1; if ((record_file = fopen(eventfilename, "a")) == NULL) { record_flag = 0; return; } } ENVIRONMENT the_environment; #endif /* NoX */