/* find and delete any mac addresses that have not been refreshed since * the expiration time for the mac_list. * (time granularity is usecs.) */ int mac_list_expire_timed_macs(mac_list_t *mac_list) { struct timeval tv; struct timezone tz; if (mac_list->timeout == -1) { return 0; } if (gettimeofday(&tv, &tz)) { fprintf(stderr, "expire_timed_macs: gettimeofday failed\n"); return -1; } while (1) { int i; int did_something = 0; for (i = 0; i < mac_list->next_beacon; i++) { if (usec_diff(tv.tv_sec, tv.tv_usec, mac_list->beacons[i].tv_sec, mac_list->beacons[i].tv_usec) > mac_list->timeout) { int j; #ifdef DEBUG if (debug_file_inited) { fprintf(debug_file, "%s; timeout ", mac_list->fname); mac_print_no_eoln(debug_file, mac_list->beacons[i].mac_addr); fprintf(debug_file, " at "); util_print_time(debug_file, &tv); fprintf(debug_file, "\n"); fflush(debug_file); } #endif for (j = i; j < mac_list->next_beacon - 1; j++) { mac_list->beacons[j] = mac_list->beacons[j + 1]; } mac_list->next_beacon--; did_something = 1; break; } } if (!did_something) break; } return 0; }
/* print "msg" to debug_file, together with time */ void mac_list_db_msg(char *msg) { #ifdef DEBUG struct timeval tv; struct timezone tz; if (gettimeofday(&tv, &tz)) { fprintf(stderr, "mac_list_db_msg; gettimeofday failed\n"); return; } if (debug_file_inited) { fprintf(debug_file, "%s at ", msg); util_print_time(debug_file, &tv); fprintf(debug_file, "\n"); fflush(debug_file); } #endif }
/**Function******************************************************************** Synopsis [Main function for testcudd.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ int main(int argc, char **argv) { FILE *fp; /* pointer to input file */ char *file = (char *) ""; /* input file name */ FILE *dfp = NULL; /* pointer to dump file */ char *dfile; /* file for DD dump */ DdNode *dfunc[2]; /* addresses of the functions to be dumped */ DdManager *dd; /* pointer to DD manager */ DdNode *_true; /* fast access to constant function */ DdNode *M; DdNode **x; /* pointers to variables */ DdNode **y; /* pointers to variables */ DdNode **xn; /* complements of row variables */ DdNode **yn_; /* complements of column variables */ DdNode **xvars; DdNode **yvars; DdNode *C; /* result of converting from ADD to BDD */ DdNode *ess; /* cube of essential variables */ DdNode *shortP; /* BDD cube of shortest path */ DdNode *largest; /* BDD of largest cube */ DdNode *shortA; /* ADD cube of shortest path */ DdNode *constN; /* value returned by evaluation of ADD */ DdNode *ycube; /* cube of the negated y vars for c-proj */ DdNode *CP; /* C-Projection of C */ DdNode *CPr; /* C-Selection of C */ int length; /* length of the shortest path */ int nx; /* number of variables */ int ny; int maxnx; int maxny; int m; int n; int N; int cmu; /* use CMU multiplication */ int pr; /* verbose printout level */ int harwell; int multiple; /* read multiple matrices */ int ok; int c; /* variable to read in options */ int approach; /* reordering approach */ int autodyn; /* automatic reordering */ int groupcheck; /* option for group sifting */ int profile; /* print heap profile if != 0 */ int keepperm; /* keep track of permutation */ int clearcache; /* clear the cache after each matrix */ int blifOrDot; /* dump format: 0 -> dot, 1 -> blif, ... */ int retval; /* return value */ int i; /* loop index */ long startTime; /* initial time */ long lapTime; int size; unsigned int cacheSize, maxMemory; unsigned int nvars,nslots; startTime = util_cpu_time(); approach = CUDD_REORDER_NONE; autodyn = 0; pr = 0; harwell = 0; multiple = 0; profile = 0; keepperm = 0; cmu = 0; N = 4; nvars = 4; cacheSize = 127; maxMemory = 0; nslots = CUDD_UNIQUE_SLOTS; clearcache = 0; groupcheck = CUDD_GROUP_CHECK7; dfile = NULL; blifOrDot = 0; /* dot format */ /* Parse command line. */ while ((c = util_getopt(argc, argv, (char *) "CDHMPS:a:bcd:g:hkmn:p:v:x:X:")) != EOF) { switch(c) { case 'C': cmu = 1; break; case 'D': autodyn = 1; break; case 'H': harwell = 1; break; case 'M': #ifdef MNEMOSYNE (void) mnem_setrecording(0); #endif break; case 'P': profile = 1; break; case 'S': nslots = atoi(util_optarg); break; case 'X': maxMemory = atoi(util_optarg); break; case 'a': approach = atoi(util_optarg); break; case 'b': blifOrDot = 1; /* blif format */ break; case 'c': clearcache = 1; break; case 'd': dfile = util_optarg; break; case 'g': groupcheck = atoi(util_optarg); break; case 'k': keepperm = 1; break; case 'm': multiple = 1; break; case 'n': N = atoi(util_optarg); break; case 'p': pr = atoi(util_optarg); break; case 'v': nvars = atoi(util_optarg); break; case 'x': cacheSize = atoi(util_optarg); break; case 'h': default: usage(argv[0]); break; } } if (argc - util_optind == 0) { file = (char *) "-"; } else if (argc - util_optind == 1) { file = argv[util_optind]; } else { usage(argv[0]); } if ((approach<0) || (approach>17)) { (void) fprintf(stderr,"Invalid approach: %d \n",approach); usage(argv[0]); } if (pr >= 0) { (void) printf("# %s\n", TESTCUDD_VERSION); /* Echo command line and arguments. */ (void) printf("#"); for (i = 0; i < argc; i++) { (void) printf(" %s", argv[i]); } (void) printf("\n"); (void) fflush(stdout); } /* Initialize manager and provide easy reference to terminals. */ dd = Cudd_Init(nvars,0,nslots,cacheSize,maxMemory); _true = DD_TRUE(dd); dd->groupcheck = (Cudd_AggregationType) groupcheck; if (autodyn) Cudd_AutodynEnable(dd,CUDD_REORDER_SAME); /* Open input file. */ fp = open_file(file, "r"); /* Open dump file if requested */ if (dfile != NULL) { dfp = open_file(dfile, "w"); } x = y = xn = yn_ = NULL; do { /* We want to start anew for every matrix. */ maxnx = maxny = 0; nx = maxnx; ny = maxny; if (pr>0) lapTime = util_cpu_time(); if (harwell) { if (pr >= 0) (void) printf(":name: "); ok = Cudd_addHarwell(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny, &m, &n, 0, 2, 1, 2, pr); } else { ok = Cudd_addRead(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny, &m, &n, 0, 2, 1, 2); if (pr >= 0) (void) printf(":name: %s: %d rows %d columns\n", file, m, n); } if (!ok) { (void) fprintf(stderr, "Error reading matrix\n"); exit(1); } if (nx > maxnx) maxnx = nx; if (ny > maxny) maxny = ny; /* Build cube of negated y's. */ ycube = DD_TRUE(dd); Cudd_Ref(ycube); for (i = maxny - 1; i >= 0; i--) { DdNode *tmpp; tmpp = Cudd_bddAnd(dd,Cudd_Not(dd->vars[y[i]->index]),ycube); if (tmpp == NULL) exit(2); Cudd_Ref(tmpp); Cudd_RecursiveDeref(dd,ycube); ycube = tmpp; } /* Initialize vectors of BDD variables used by priority func. */ xvars = ALLOC(DdNode *, nx); if (xvars == NULL) exit(2); for (i = 0; i < nx; i++) { xvars[i] = dd->vars[x[i]->index]; } yvars = ALLOC(DdNode *, ny); if (yvars == NULL) exit(2); for (i = 0; i < ny; i++) { yvars[i] = dd->vars[y[i]->index]; } /* Clean up */ for (i=0; i < maxnx; i++) { Cudd_RecursiveDeref(dd, x[i]); Cudd_RecursiveDeref(dd, xn[i]); } FREE(x); FREE(xn); for (i=0; i < maxny; i++) { Cudd_RecursiveDeref(dd, y[i]); Cudd_RecursiveDeref(dd, yn_[i]); } FREE(y); FREE(yn_); if (pr>0) {(void) printf(":1: M"); Cudd_PrintDebug(dd,M,nx+ny,pr);} if (pr>0) (void) printf(":2: time to read the matrix = %s\n", util_print_time(util_cpu_time() - lapTime)); C = Cudd_addBddPattern(dd, M); if (C == 0) exit(2); Cudd_Ref(C); if (pr>0) {(void) printf(":3: C"); Cudd_PrintDebug(dd,C,nx+ny,pr);} /* Test iterators. */ retval = testIterators(dd,M,C,pr); if (retval == 0) exit(2); cuddCacheProfile(dd,stdout); /* Test XOR */ retval = testXor(dd,C,pr,nx+ny); if (retval == 0) exit(2); /* Test Hamming distance functions. */ retval = testHamming(dd,C,pr); if (retval == 0) exit(2); /* Test selection functions. */ CP = Cudd_CProjection(dd,C,ycube); if (CP == NULL) exit(2); Cudd_Ref(CP); if (pr>0) {(void) printf("ycube"); Cudd_PrintDebug(dd,ycube,nx+ny,pr);} if (pr>0) {(void) printf("CP"); Cudd_PrintDebug(dd,CP,nx+ny,pr);} if (nx == ny) { CPr = Cudd_PrioritySelect(dd,C,xvars,yvars,(DdNode **)NULL, (DdNode *)NULL,ny,Cudd_Xgty); if (CPr == NULL) exit(2); Cudd_Ref(CPr); if (pr>0) {(void) printf(":4: CPr"); Cudd_PrintDebug(dd,CPr,nx+ny,pr);} if (CP != CPr) { (void) printf("CP != CPr!\n"); } Cudd_RecursiveDeref(dd, CPr); } FREE(xvars); FREE(yvars); Cudd_RecursiveDeref(dd, CP); Cudd_RecursiveDeref(dd, ycube); /* Test functions for essential variables. */ ess = Cudd_FindEssential(dd,C); if (ess == NULL) exit(2); Cudd_Ref(ess); if (pr>0) {(void) printf(":4: ess"); Cudd_PrintDebug(dd,ess,nx+ny,pr);} Cudd_RecursiveDeref(dd, ess); /* Test functions for shortest paths. */ shortP = Cudd_ShortestPath(dd, M, NULL, NULL, &length); if (shortP == NULL) exit(2); Cudd_Ref(shortP); if (pr>0) { (void) printf(":5: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr); } /* Test functions for largest cubes. */ largest = Cudd_LargestCube(dd, Cudd_Not(C), &length); if (largest == NULL) exit(2); Cudd_Ref(largest); if (pr>0) { (void) printf(":5b: largest"); Cudd_PrintDebug(dd,largest,nx+ny,pr); } Cudd_RecursiveDeref(dd, largest); /* Test Cudd_addEvalConst and Cudd_addIteConstant. */ shortA = Cudd_BddToAdd(dd,shortP); if (shortA == NULL) exit(2); Cudd_Ref(shortA); Cudd_RecursiveDeref(dd, shortP); constN = Cudd_addEvalConst(dd,shortA,M); if (constN == DD_NON_CONSTANT) exit(2); if (Cudd_addIteConstant(dd,shortA,M,constN) != constN) exit(2); if (pr>0) {(void) printf("The value of M along the chosen shortest path is %g\n", cuddV(constN));} Cudd_RecursiveDeref(dd, shortA); shortP = Cudd_ShortestPath(dd, C, NULL, NULL, &length); if (shortP == NULL) exit(2); Cudd_Ref(shortP); if (pr>0) { (void) printf(":6: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr); } /* Test Cudd_bddIteConstant and Cudd_bddLeq. */ if (!Cudd_bddLeq(dd,shortP,C)) exit(2); if (Cudd_bddIteConstant(dd,Cudd_Not(shortP),_true,C) != _true) exit(2); Cudd_RecursiveDeref(dd, shortP); if (profile) { retval = cuddHeapProfile(dd); } size = dd->size; if (pr>0) { (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd)); } /* Reorder if so requested. */ if (approach != CUDD_REORDER_NONE) { #ifndef DD_STATS retval = Cudd_EnableReorderingReporting(dd); if (retval == 0) { (void) fprintf(stderr,"Error reported by Cudd_EnableReorderingReporting\n"); exit(3); } #endif #ifdef DD_DEBUG retval = Cudd_DebugCheck(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); exit(3); } retval = Cudd_CheckKeys(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); exit(3); } #endif retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5); if (retval == 0) { (void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n"); exit(3); } #ifndef DD_STATS retval = Cudd_DisableReorderingReporting(dd); if (retval == 0) { (void) fprintf(stderr,"Error reported by Cudd_DisableReorderingReporting\n"); exit(3); } #endif #ifdef DD_DEBUG retval = Cudd_DebugCheck(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); exit(3); } retval = Cudd_CheckKeys(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); exit(3); } #endif if (approach == CUDD_REORDER_SYMM_SIFT || approach == CUDD_REORDER_SYMM_SIFT_CONV) { Cudd_SymmProfile(dd,0,dd->size-1); } if (pr>0) { (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd)); } if (keepperm) { /* Print variable permutation. */ (void) printf("Variable Permutation:"); for (i=0; i<size; i++) { if (i%20 == 0) (void) printf("\n"); (void) printf("%d ", dd->invperm[i]); } (void) printf("\n"); (void) printf("Inverse Permutation:"); for (i=0; i<size; i++) { if (i%20 == 0) (void) printf("\n"); (void) printf("%d ", dd->perm[i]); } (void) printf("\n"); } if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,nx+ny,pr);} if (profile) { retval = cuddHeapProfile(dd); } } /* Dump DDs of C and M if so requested. */ if (dfile != NULL) { dfunc[0] = C; dfunc[1] = M; if (blifOrDot == 1) { /* Only dump C because blif cannot handle ADDs */ retval = Cudd_DumpBlif(dd,1,dfunc,NULL,(char **)onames, NULL,dfp); } else { retval = Cudd_DumpDot(dd,2,dfunc,NULL,(char **)onames,dfp); } if (retval != 1) { (void) fprintf(stderr,"abnormal termination\n"); exit(2); } } Cudd_RecursiveDeref(dd, C); Cudd_RecursiveDeref(dd, M); if (clearcache) { if (pr>0) {(void) printf("Clearing the cache... ");} for (i = dd->cacheSlots - 1; i>=0; i--) { dd->cache[i].data = NIL(DdNode); } if (pr>0) {(void) printf("done\n");} } if (pr>0) { (void) printf("Number of variables = %6d\t",dd->size); (void) printf("Number of slots = %6d\n",dd->slots); (void) printf("Number of keys = %6d\t",dd->keys); (void) printf("Number of min dead = %6d\n",dd->minDead); } } while (multiple && !feof(fp)); fclose(fp); if (dfile != NULL) { fclose(dfp); } /* Second phase: experiment with Walsh matrices. */ if (!testWalsh(dd,N,cmu,approach,pr)) { exit(2); } /* Check variable destruction. */ assert(cuddDestroySubtables(dd,3)); assert(Cudd_DebugCheck(dd) == 0); assert(Cudd_CheckKeys(dd) == 0); retval = Cudd_CheckZeroRef(dd); ok = retval != 0; /* ok == 0 means O.K. */ if (retval != 0) { (void) fprintf(stderr, "%d non-zero DD reference counts after dereferencing\n", retval); } if (pr >= 0) { (void) Cudd_PrintInfo(dd,stdout); } Cudd_Quit(dd); #ifdef MNEMOSYNE mnem_writestats(); #endif if (pr>0) (void) printf("total time = %s\n", util_print_time(util_cpu_time() - startTime)); if (pr >= 0) util_print_cpu_stats(stdout); exit(ok); /* NOTREACHED */ } /* end of main */
/**Function******************************************************************** Synopsis [Repeated squaring algorithm for all-pairs shortest paths.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static DdNode * ntrSquare( DdManager *dd /* manager */, DdNode *D /* D(z,y): distance matrix */, DdNode **x /* array of x variables */, DdNode **y /* array of y variables */, DdNode **z /* array of z variables */, int vars /* number of variables in each of the three arrays */, int pr /* verbosity level */, int st /* use the selective trace algorithm */) { DdNode *zero; DdNode *I; /* identity matirix */ DdNode *w, *V, *P, *M, *R, *RT; DdNode *diff, *min, *minDiag; int n; int neg; long start_time; zero = Cudd_ReadZero(dd); /* Make a working copy of the original matrix. */ R = D; Cudd_Ref(R); I = Cudd_addXeqy(dd,vars,z,y); /* identity matrix */ Cudd_Ref(I); /* Make a copy of the matrix for the selective trace algorithm. */ diff = R; Cudd_Ref(diff); start_time = util_cpu_time(); for (n = vars; n >= 0; n--) { printf("Starting iteration %d at time %s\n",vars-n, util_print_time(util_cpu_time() - start_time)); /* Check for negative cycles: They are identified by negative ** elements on the diagonal. */ /* Extract values from the diagonal. */ Cudd_Ref(w = Cudd_addIte(dd,I,R,zero)); minDiag = Cudd_addFindMin(dd,w); /* no need to ref */ neg = Cudd_V(minDiag) < 0; Cudd_RecursiveDeref(dd,w); if (neg) { Cudd_RecursiveDeref(dd,diff); (void) printf("Negative cycle after %d iterations!\n",vars-n); break; } /* Prepare the first operand of matrix multiplication: ** diff(z,y) -> RT(x,y) -> V(x,z) */ /* RT(x,y) */ Cudd_Ref(RT = Cudd_addSwapVariables(dd,diff,x,z,vars)); Cudd_RecursiveDeref(dd,diff); /* V(x,z) */ Cudd_Ref(V = Cudd_addSwapVariables(dd,RT,y,z,vars)); Cudd_RecursiveDeref(dd,RT); if (pr > 0) { double pathcount; (void) printf("V"); Cudd_PrintDebug(dd,V,2*vars,pr); pathcount = Cudd_CountPath(V); (void) printf("Path count = %g\n", pathcount); } /* V(x,z) * R(z,y) -> P(x,y) */ Cudd_Ref(P = Cudd_addTriangle(dd,V,R,z,vars)); Cudd_RecursiveDeref(dd,V); /* P(x,y) => M(z,y) */ Cudd_Ref(M = Cudd_addSwapVariables(dd,P,x,z,vars)); Cudd_RecursiveDeref(dd,P); if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,2*vars,pr);} /* min(z,y) */ Cudd_Ref(min = Cudd_addApply(dd,Cudd_addMinimum,R,M)); Cudd_RecursiveDeref(dd,M); if (R == min) { Cudd_RecursiveDeref(dd,min); if (pr>0) {printf("Done after %d iterations\n",vars-n+1); } break; } /* diff(z,y) */ if (st) { Cudd_Ref(diff = Cudd_addApply(dd,Cudd_addDiff,min,R)); } else { Cudd_Ref(diff = min); } Cudd_RecursiveDeref(dd,R); R = min; /* keep a copy of matrix at current iter. */ if (pr > 0) { double pathcount; (void) printf("R"); Cudd_PrintDebug(dd,R,2*vars,pr); pathcount = Cudd_CountPath(R); (void) printf("Path count = %g\n", pathcount); } if (n == 0) { (void) printf("Negative cycle!\n"); break; } } Cudd_RecursiveDeref(dd,I); Cudd_Deref(R); return(R); } /* end of ntrSquare */
/**Function******************************************************************** Synopsis [Floyd-Warshall algorithm for all-pair shortest paths.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static DdNode * ntrWarshall( DdManager *dd, DdNode *D, DdNode **x, DdNode **y, int vars, int pr) { DdNode *one, *zero; DdNode *xminterm, *w, *V, *V2; DdNode *P, *R; int i; int nodes; int k,u; long start_time; if (vars > 30) nodes = 1000000000; else nodes = 1 << vars; one = DD_ONE(dd); zero = DD_ZERO(dd); Cudd_Ref(R = D); /* make copy of original matrix */ /* Extract pivot row and column from D */ start_time = util_cpu_time(); for (k = 0; k < nodes; k++) { if (k % 10000 == 0) { (void) printf("Starting iteration %d at time %s\n", k,util_print_time(util_cpu_time() - start_time)); } Cudd_Ref(xminterm = one); u = k; for (i = vars-1; i >= 0; i--) { if (u&1) { Cudd_Ref(w = Cudd_addIte(dd,x[i],xminterm,zero)); } else { Cudd_Ref(w = Cudd_addIte(dd,x[i],zero,xminterm)); } Cudd_RecursiveDeref(dd,xminterm); xminterm = w; u >>= 1; } Cudd_Ref(V = Cudd_Cofactor(dd,R,xminterm)); Cudd_RecursiveDeref(dd,xminterm); if (pr>2) {(void) printf("V"); Cudd_PrintDebug(dd,V,vars,pr);} Cudd_Ref(xminterm = one); u = k; for (i = vars-1; i >= 0; i--) { if (u&1) { Cudd_Ref(w = Cudd_addIte(dd,y[i],xminterm,zero)); } else { Cudd_Ref(w = Cudd_addIte(dd,y[i],zero,xminterm)); } Cudd_RecursiveDeref(dd,xminterm); xminterm = w; u >>= 1; } Cudd_Ref(V2 = Cudd_Cofactor(dd,R,xminterm)); Cudd_RecursiveDeref(dd,xminterm); if (pr>2) {(void) printf("V2"); Cudd_PrintDebug(dd,V2,vars,pr);} Cudd_Ref(P = Cudd_addOuterSum(dd,R,V,V2)); Cudd_RecursiveDeref(dd,V); Cudd_RecursiveDeref(dd,V2); Cudd_RecursiveDeref(dd,R); R = P; if (pr>2) {(void) printf("R"); Cudd_PrintDebug(dd,R,vars,pr);} } Cudd_Deref(R); return(R); } /* end of ntrWarshall */
/* expire any stale mac addresses from the mac_list. * add mac_address to the list, or if it's already there refresh its * time to "now". * * include name, signal_strength, and desc in the record for this mac address. */ void mac_list_add(mac_list_t *mac_list, mac_address_t mac_addr, mac_address_t name, int signal_strength, char *desc, bool_t write_um) { int i, this_beacon; struct timeval tv; struct timezone tz; if (gettimeofday(&tv, &tz)) { fprintf(stderr, "mac_list_add; gettimeofday failed\n"); return; } if (mac_list_expire_timed_macs(mac_list)) { fprintf(stderr, "mac_list_add; mac_list_expire_timed_macs failed\n"); return; } this_beacon = -1; for (i = 0; i < mac_list->next_beacon; i++) { if (mac_equal(mac_addr, mac_list->beacons[i].mac_addr)) { this_beacon = i; break; } } if (this_beacon == -1) { if (mac_list->next_beacon == MAX_CLOUD) { fprintf(stderr, "mac_list_add; too many mac addresses\n"); return; } mac_copy(mac_list->beacons[mac_list->next_beacon].mac_addr, mac_addr); this_beacon = mac_list->next_beacon; mac_list->next_beacon++; } mac_copy(mac_list->names[this_beacon], name); if (desc != NULL) { strncpy(mac_list->desc[this_beacon], desc, MAX_DESC); } if (signal_strength != NO_SIGNAL_STRENGTH) { mac_list->signal_strength[this_beacon] = signal_strength; } mac_list->beacons[this_beacon].tv_sec = tv.tv_sec; mac_list->beacons[this_beacon].tv_usec = tv.tv_usec; #ifdef DEBUG if (debug_file_inited) { fprintf(debug_file, "%s; time update ", mac_list->fname); mac_print_no_eoln(debug_file, mac_list->beacons[this_beacon].mac_addr); fprintf(debug_file, " at "); util_print_time(debug_file, &tv); fprintf(debug_file, "\n"); fflush(debug_file); } #endif if (write_um) { if (mac_list_write(mac_list)) { fprintf(stderr, "mac_list_add; write_beacons failed\n"); } } }
/**Function******************************************************************** Synopsis [Main program for ntr.] Description [Main program for ntr. Performs initialization. Reads command line options and network(s). Builds BDDs with reordering, and optionally does reachability analysis. Prints stats.] SideEffects [None] SeeAlso [] ******************************************************************************/ int main( int argc, char ** argv) { NtrOptions *option; /* options */ FILE *fp1; /* first network file pointer */ BnetNetwork *net1 = NULL; /* first network */ FILE *fp2; /* second network file pointer */ BnetNetwork *net2 = NULL; /* second network */ DdManager *dd; /* pointer to DD manager */ int exitval; /* return value of Cudd_CheckZeroRef */ int ok; /* overall return value from main() */ int result; /* stores the return value of functions */ BnetNode *node; /* auxiliary pointer to network node */ int i; /* loop index */ int j; /* loop index */ double *signatures; /* array of signatures */ int pr; /* verbosity level */ int reencoded; /* linear transformations attempted */ /* Initialize. */ option = mainInit(); ntrReadOptions(argc,argv,option); pr = option->verb; reencoded = option->reordering == CUDD_REORDER_LINEAR || option->reordering == CUDD_REORDER_LINEAR_CONVERGE || option->autoMethod == CUDD_REORDER_LINEAR || option->autoMethod == CUDD_REORDER_LINEAR_CONVERGE; /* Currently traversal requires global BDDs. Override whatever ** was specified for locGlob. */ if (option->traverse == TRUE || option->envelope == TRUE || option->scc == TRUE) { option->locGlob = BNET_GLOBAL_DD; } /* Read the first network... */ fp1 = open_file(option->file1, "r"); net1 = Bnet_ReadNetwork(fp1,pr); (void) fclose(fp1); if (net1 == NULL) { (void) fprintf(stderr,"Syntax error in %s.\n",option->file1); exit(2); } /* ... and optionally echo it to the standard output. */ if (pr > 2) { Bnet_PrintNetwork(net1); } /* Read the second network... */ if (option->verify == TRUE || option->second == TRUE || option->clip > 0.0 || option->dontcares) { fp2 = open_file(option->file2, "r"); net2 = Bnet_ReadNetwork(fp2,pr); (void) fclose(fp2); if (net2 == NULL) { (void) fprintf(stderr,"Syntax error in %s.\n",option->file2); exit(2); } /* ... and optionally echo it to the standard output. */ if (pr > 2) { Bnet_PrintNetwork(net2); } } /* Initialize manager. We start with 0 variables, because ** Ntr_buildDDs will create new variables rather than using ** whatever already exists. */ dd = startCudd(option,net1->ninputs); if (dd == NULL) { exit(2); } /* Build the BDDs for the nodes of the first network. */ result = Ntr_buildDDs(net1,dd,option,NULL); if (result == 0) { exit(2); } /* Build the BDDs for the nodes of the second network if requested. */ if (option->verify == TRUE || option->second == TRUE || option->clip > 0.0 || option->dontcares == TRUE) { char *nodesave = option->node; option->node = NULL; result = Ntr_buildDDs(net2,dd,option,net1); option->node = nodesave; if (result == 0) { exit(2); } } if (option->noBuild == TRUE) { Bnet_FreeNetwork(net1); if (option->verify == TRUE || option->second == TRUE || option->clip > 0.0) { Bnet_FreeNetwork(net2); } freeOption(option); exit(0); } if (option->locGlob != BNET_LOCAL_DD) { /* Print the order before the final reordering. */ (void) printf("Order before final reordering\n"); result = Bnet_PrintOrder(net1,dd); if (result == 0) exit(2); } /* Perform final reordering */ if (option->zddtest == FALSE) { result = reorder(net1,dd,option); if (result == 0) exit(2); /* Print final order. */ if ((option->reordering != CUDD_REORDER_NONE || option->gaOnOff) && option->locGlob != BNET_LOCAL_DD) { (void) printf("New order\n"); result = Bnet_PrintOrder(net1,dd); if (result == 0) exit(2); } /* Print the re-encoded inputs. */ if (pr >= 1 && reencoded == 1) { for (i = 0; i < net1->npis; i++) { if (!st_lookup(net1->hash,net1->inputs[i],&node)) { exit(2); } (void) fprintf(stdout,"%s:",node->name); Cudd_PrintDebug(dd,node->dd,Cudd_ReadSize(dd),pr); } for (i = 0; i < net1->nlatches; i++) { if (!st_lookup(net1->hash,net1->latches[i][1],&node)) { exit(2); } (void) fprintf(stdout,"%s:",node->name); Cudd_PrintDebug(dd,node->dd,Cudd_ReadSize(dd),pr); } if (pr >= 3) { result = Cudd_PrintLinear(dd); if (result == 0) exit(2); } } } /* Verify (combinational) equivalence. */ if (option->verify == TRUE) { result = Ntr_VerifyEquivalence(dd,net1,net2,option); if (result == 0) { (void) printf("Verification abnormally terminated\n"); exit(2); } else if (result == -1) { (void) printf("Combinational verification failed\n"); } else { (void) printf("Verification succeeded\n"); } } /* Traverse if requested and if the circuit is sequential. */ result = Ntr_Trav(dd,net1,option); if (result == 0) exit(2); /* Traverse with trasitive closure. */ result = Ntr_ClosureTrav(dd,net1,option); if (result == 0) exit(2); /* Compute outer envelope if requested and if the circuit is sequential. */ if (option->envelope == TRUE && net1->nlatches > 0) { NtrPartTR *T; T = Ntr_buildTR(dd,net1,option,option->image); result = Ntr_Envelope(dd,T,NULL,option); Ntr_freeTR(dd,T); } /* Compute SCCs if requested and if the circuit is sequential. */ result = Ntr_SCC(dd,net1,option); if (result == 0) exit(2); /* Test Constrain Decomposition. */ if (option->partition == TRUE && net1->nlatches > 0) { NtrPartTR *T; DdNode *product; DdNode **decomp; int sharingSize; T = Ntr_buildTR(dd,net1,option,NTR_IMAGE_MONO); decomp = Cudd_bddConstrainDecomp(dd,T->part[0]); if (decomp == NULL) exit(2); sharingSize = Cudd_SharingSize(decomp, Cudd_ReadSize(dd)); (void) fprintf(stdout, "Decomposition Size: %d components %d nodes\n", Cudd_ReadSize(dd), sharingSize); product = Cudd_ReadOne(dd); Cudd_Ref(product); for (i = 0; i < Cudd_ReadSize(dd); i++) { DdNode *intermediate = Cudd_bddAnd(dd, product, decomp[i]); if (intermediate == NULL) { exit(2); } Cudd_Ref(intermediate); Cudd_IterDerefBdd(dd, product); product = intermediate; } if (product != T->part[0]) exit(2); Cudd_IterDerefBdd(dd, product); for (i = 0; i < Cudd_ReadSize(dd); i++) { Cudd_IterDerefBdd(dd, decomp[i]); } FREE(decomp); Ntr_freeTR(dd,T); } /* Test char-to-vect conversion. */ result = Ntr_TestCharToVect(dd,net1,option); if (result == 0) exit(2); /* Test extraction of two-literal clauses. */ result = Ntr_TestTwoLiteralClauses(dd,net1,option); if (result == 0) exit(2); /* Test BDD minimization functions. */ result = Ntr_TestMinimization(dd,net1,net2,option); if (result == 0) exit(2); /* Test density-related functions. */ result = Ntr_TestDensity(dd,net1,option); if (result == 0) exit(2); /* Test decomposition functions. */ result = Ntr_TestDecomp(dd,net1,option); if (result == 0) exit(2); /* Test cofactor estimation functions. */ result = Ntr_TestCofactorEstimate(dd,net1,option); if (result == 0) exit(2); /* Test BDD clipping functions. */ result = Ntr_TestClipping(dd,net1,net2,option); if (result == 0) exit(2); /* Test BDD equivalence and containment under DC functions. */ result = Ntr_TestEquivAndContain(dd,net1,net2,option); if (result == 0) exit(2); /* Test BDD Cudd_bddClosestCube. */ result = Ntr_TestClosestCube(dd,net1,option); if (result == 0) exit(2); /* Test ZDDs if requested. */ if (option->stateOnly == FALSE && option->zddtest == TRUE) { result = Ntr_testZDD(dd,net1,option); if (result == 0) (void) fprintf(stdout,"ZDD test failed.\n"); result = Ntr_testISOP(dd,net1,option); if (result == 0) (void) fprintf(stdout,"ISOP test failed.\n"); } /* Compute maximum flow if requested and if the circuit is sequential. */ if (option->maxflow == TRUE && net1->nlatches > 0) { result = Ntr_maxflow(dd,net1,option); if (result == 0) (void) fprintf(stdout,"Maxflow computation failed.\n"); } /* Compute shortest paths if requested and if the circuit is sequential. */ if (option->shortPath != NTR_SHORT_NONE && net1->nlatches > 0) { result = Ntr_ShortestPaths(dd,net1,option); if (result == 0) (void) fprintf(stdout,"Shortest paths computation failed.\n"); } /* Compute output signatures if so requested. */ if (option->signatures) { (void) printf("Positive cofactor measures\n"); for (i = 0; i < net1->noutputs; i++) { if (!st_lookup(net1->hash,net1->outputs[i],&node)) { exit(2); } signatures = Cudd_CofMinterm(dd, node->dd); if (signatures) { (void) printf("%s:\n", node->name); for (j = 0; j < Cudd_ReadSize(dd); j++) { if((j%5 == 0)&&i) (void) printf("\n"); (void) printf("%5d: %-#8.4g ", j, signatures[j]); } (void) printf("\n"); FREE(signatures); } else { (void) printf("Signature computation failed.\n"); } } } /* Dump BDDs if so requested. */ if (option->bdddump && option->second == FALSE && option->density == FALSE && option->decomp == FALSE && option->cofest == FALSE && option->clip < 0.0 && option->scc == FALSE) { (void) printf("Dumping BDDs to %s\n", option->dumpfile); if (option->node != NULL) { if (!st_lookup(net1->hash,option->node,&node)) { exit(2); } result = Bnet_bddArrayDump(dd,net1,option->dumpfile,&(node->dd), &(node->name),1,option->dumpFmt); } else { result = Bnet_bddDump(dd, net1, option->dumpfile, option->dumpFmt, reencoded); } if (result != 1) { (void) printf("BDD dump failed.\n"); } } /* Print stats and clean up. */ if (pr >= 0) { result = Cudd_PrintInfo(dd,stdout); if (result != 1) { (void) printf("Cudd_PrintInfo failed.\n"); } } #if defined(DD_DEBUG) && !defined(DD_NO_DEATH_ROW) (void) fprintf(dd->err,"%d empty slots in death row\n", cuddTimesInDeathRow(dd,NULL)); #endif (void) printf("Final size: %ld\n", Cudd_ReadNodeCount(dd)); /* Dispose of node BDDs. */ node = net1->nodes; while (node != NULL) { if (node->dd != NULL && node->type != BNET_INPUT_NODE && node->type != BNET_PRESENT_STATE_NODE) { Cudd_IterDerefBdd(dd,node->dd); } node = node->next; } /* Dispose of network. */ Bnet_FreeNetwork(net1); /* Do the same cleanup for the second network if it was created. */ if (option->verify == TRUE || option->second == TRUE || option->clip > 0.0 || option->dontcares == TRUE) { node = net2->nodes; while (node != NULL) { if (node->dd != NULL && node->type != BNET_INPUT_NODE && node->type != BNET_PRESENT_STATE_NODE) { Cudd_IterDerefBdd(dd,node->dd); } node = node->next; } Bnet_FreeNetwork(net2); } /* Check reference counts: At this point we should have dereferenced ** everything we had, except in the case of re-encoding. */ exitval = Cudd_CheckZeroRef(dd); ok = exitval != 0; /* ok == 0 means O.K. */ if (exitval != 0) { (void) fflush(stdout); (void) fprintf(stderr, "%d non-zero DD reference counts after dereferencing\n", exitval); } #ifdef DD_DEBUG Cudd_CheckKeys(dd); #endif Cudd_Quit(dd); if (pr >= 0) (void) printf("total time = %s\n", util_print_time(util_cpu_time() - option->initialTime)); freeOption(option); if (pr >= 0) util_print_cpu_stats(stdout); #ifdef MNEMOSYNE mnem_writestats(); #endif exit(ok); /* NOTREACHED */ } /* end of main */