static YAP_Bool ret_prob(void) { YAP_Term arg1, arg2, out; DdNode *node; arg1 = YAP_ARG1; arg2 = YAP_ARG2; node = (DdNode *)YAP_IntOfTerm(arg1); if (!Cudd_IsConstant(node)) { table = init_table(boolVars_ex[ex]); out = YAP_MkFloatTerm(Prob(node, 0)); destroy_table(table, boolVars_ex[ex]); } else { if (node == Cudd_ReadOne(mgr_ex[ex])) out = YAP_MkFloatTerm(1.0); else out = YAP_MkFloatTerm(0.0); } return (YAP_Unify(out, arg2)); }
BddBuilder::BddBuilder(){ __pddWireHead = __pddWireTail = NULL; __pddOutputWireHead = __pddOutputWireTail = NULL; __pddOutputNodes = NULL; __pddGateHead = __pddGateTail = NULL; __pddInputNodes = NULL; __pddManager = Cudd_Init(0, 0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS , 0); Cudd_ReduceHeap(__pddManager,CUDD_REORDER_RANDOM_PIVOT,0); Cudd_AutodynEnable(__pddManager,CUDD_REORDER_RANDOM_PIVOT); __Vcc = Cudd_ReadOne(__pddManager); __GND = Cudd_ReadLogicZero(__pddManager); char * name_vcc = new char[4]; char * name_gnd = new char[4]; sprintf(name_vcc, "Vcc"); sprintf(name_gnd, "GND"); __VccWire = new DdWire(__pddManager, name_vcc, 0, 0); __GNDWire = new DdWire(__pddManager, name_gnd, 0, 0); __VccWire->setDdNode(__Vcc); __GNDWire->setDdNode(__GND); Cudd_Ref(__Vcc); Cudd_Ref(__GND); if(__pddManager == NULL){ perror("DdManager initializing error."); } //__inputWireCnt = 2; // Vcc & GND __inputWireCnt = -1; __outputWireCnt = -1; __pddInputWireHead = __VccWire; __VccWire->setInputListNext(__GNDWire); __pddInputWireTail = __GNDWire; }
/* encode the program counter in an array of boolean variables */ DdNode* bdd_encode_pc(DdManager* m, DdNode* node, int** pc_array, int pc_size, int proc, int pc) { int i; DdNode* tmp, *var; DdNode* ret = Cudd_ReadOne(m); Cudd_Ref(ret); for (i=0; i<pc_size; i++) { /* iterate for each bit in pc_size */ var = Cudd_bddIthVar(m, pc_array[proc][i]); if (pc % 2) /* encode true bit */ tmp = Cudd_bddAnd(m, var, ret); else /* encode false bit */ tmp = Cudd_bddAnd(m, Cudd_Not(var), ret); Cudd_Ref(tmp); Cudd_RecursiveDeref(m, ret); /* release the old bdd each time a new */ ret = tmp; /* one is made */ pc /= 2; } tmp = Cudd_bddAnd(m, ret, node); /* add encoding to existing edge */ Cudd_Ref(tmp); Cudd_RecursiveDeref(m, ret); Cudd_RecursiveDeref(m, node); return tmp; /* return updated edge */ }
/**Function************************************************************* Synopsis [Transforms the AIG into nodes.] Description [Threhold is the max number of nodes duplicated at a node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { ProgressBar * pProgress; Abc_Obj_t * pNode, * pConst1, * pNodeNew; int i; // set the constant node pConst1 = Abc_AigConst1(pNtk); if ( Abc_ObjFanoutNum(pConst1) > 0 ) { pNodeNew = Abc_NtkCreateNode( pNtkNew ); pNodeNew->pData = Cudd_ReadOne( pNtkNew->pManFunc ); Cudd_Ref( pNodeNew->pData ); pConst1->pCopy = pNodeNew; } // perform renoding for POs pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) continue; Abc_NtkMulti_rec( pNtkNew, Abc_ObjFanin0(pNode) ); }
DdNode* compute_EX(DdManager* m, pos* postab, DdNode* R, DdNode* p) { DdNode* tmp; /* rename variables */ int perm[2*(postab->num_procs*postab->pc_size+postab->num_vars)]; int i, j, k; for (i=0; i<postab->num_vars; i++) { perm[i] = i+postab->num_vars; perm[i+postab->num_vars] = i; } for (j=0; j<postab->num_procs; j++) { for (k=0; k<postab->pc_size; k++) { perm[postab->num_vars+i] = postab->pc_[j][k]; perm[postab->num_vars+postab->num_procs*postab->pc_size+i++] = postab->pc[j][k]; } } p = Cudd_bddPermute(m, p, perm); /* construct cube of next state variables */ DdNode* cube = Cudd_ReadOne(m); for (i=0; i<postab->num_vars; i++) { tmp = Cudd_bddAnd(m, cube, Cudd_bddIthVar(m, postab->num_vars+i)); Cudd_Ref(tmp); Cudd_RecursiveDeref(m, cube); cube = tmp; } for (i=0; i<postab->num_procs*postab->pc_size; i++) { tmp = Cudd_bddAnd(m, cube, Cudd_bddIthVar(m, 2*postab->num_vars+postab->num_procs*postab->pc_size+i)); Cudd_Ref(tmp); Cudd_RecursiveDeref(m, cube); cube = tmp; } DdNode* EX_p = Cudd_bddAndAbstract(m, R, p, cube); Cudd_Ref(EX_p); Cudd_RecursiveDeref(m, p); Cudd_RecursiveDeref(m, cube); return EX_p; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MvRead( Mv_Man_t * p ) { FILE * pFile; char Buffer[1000], * pLine; DdNode * bCube, * bTemp, * bProd, * bVar0, * bVar1, * bCubeSum; int i, v; // start the cube bCubeSum = Cudd_ReadLogicZero(p->dd); Cudd_Ref( bCubeSum ); // start the values for ( i = 0; i < 15; i++ ) for ( v = 0; v < 4; v++ ) { p->bValues[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValues[i][v] ); p->bValueDcs[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValueDcs[i][v] ); } // read the file pFile = fopen( "input.pla", "r" ); while ( fgets( Buffer, 1000, pFile ) ) { if ( Buffer[0] == '#' ) continue; if ( Buffer[0] == '.' ) { if ( Buffer[1] == 'e' ) break; continue; } // get the cube bCube = Abc_MvReadCube( p->dd, Buffer, 18 ); Cudd_Ref( bCube ); // add it to the values of the output functions pLine = Buffer + 19; for ( i = 0; i < 15; i++ ) { if ( pLine[2*i] == '-' && pLine[2*i+1] == '-' ) { for ( v = 0; v < 4; v++ ) { p->bValueDcs[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValueDcs[i][v], bCube ); Cudd_Ref( p->bValueDcs[i][v] ); Cudd_RecursiveDeref( p->dd, bTemp ); } continue; } else if ( pLine[2*i] == '0' && pLine[2*i+1] == '0' ) // 0 v = 0; else if ( pLine[2*i] == '1' && pLine[2*i+1] == '0' ) // 1 v = 1; else if ( pLine[2*i] == '0' && pLine[2*i+1] == '1' ) // 2 v = 2; else if ( pLine[2*i] == '1' && pLine[2*i+1] == '1' ) // 3 v = 3; else assert( 0 ); // add the value p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], bCube ); Cudd_Ref( p->bValues[i][v] ); Cudd_RecursiveDeref( p->dd, bTemp ); } // add the cube bCubeSum = Cudd_bddOr( p->dd, bTemp = bCubeSum, bCube ); Cudd_Ref( bCubeSum ); Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bCube ); } // add the complement of the domain to all values for ( i = 0; i < 15; i++ ) for ( v = 0; v < 4; v++ ) { if ( p->bValues[i][v] == Cudd_Not(Cudd_ReadOne(p->dd)) ) continue; p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], p->bValueDcs[i][v] ); Cudd_Ref( p->bValues[i][v] ); Cudd_RecursiveDeref( p->dd, bTemp ); p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], Cudd_Not(bCubeSum) ); Cudd_Ref( p->bValues[i][v] ); Cudd_RecursiveDeref( p->dd, bTemp ); } printf( "Domain = %5.2f %%.\n", 100.0*Cudd_CountMinterm(p->dd, bCubeSum, 32)/Cudd_CountMinterm(p->dd, Cudd_ReadOne(p->dd), 32) ); Cudd_RecursiveDeref( p->dd, bCubeSum ); // create each output function for ( i = 0; i < 15; i++ ) { p->bFuncs[i] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bFuncs[i] ); for ( v = 0; v < 4; v++ ) { bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 30), ((v & 1) == 0) ); bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 31), ((v & 2) == 0) ); bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube ); bProd = Cudd_bddAnd( p->dd, p->bValues[i][v], bCube ); Cudd_Ref( bProd ); Cudd_RecursiveDeref( p->dd, bCube ); // add the value p->bFuncs[i] = Cudd_bddOr( p->dd, bTemp = p->bFuncs[i], bProd ); Cudd_Ref( p->bFuncs[i] ); Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bProd ); } } }
/**Function******************************************************************** Synopsis [Computes shortest paths in a state graph.] Description [Computes shortest paths in the state transition graph of a network. Three methods are availabe: <ul> <li> Bellman-Ford algorithm for single-source shortest paths; the algorithm computes the distance (number of transitions) from the initial states to all states. <li> Floyd-Warshall algorithm for all-pair shortest paths. <li> Repeated squaring algorithm for all-pair shortest paths. </ul> The function returns 1 in case of success; 0 otherwise. ] SideEffects [ADD variables are created in the manager.] SeeAlso [] ******************************************************************************/ int Ntr_ShortestPaths( DdManager * dd, BnetNetwork * net, NtrOptions * option) { NtrPartTR *TR; DdNode *edges, *source, *res, *r, *q, *bddSource; DdNode **xadd, **yadd, **zadd; int i; int pr = option->verb; int algorithm = option->shortPath; int selectiveTrace = option->selectiveTrace; int nvars = net->nlatches; /* Set background to infinity for shortest paths. */ Cudd_SetBackground(dd,Cudd_ReadPlusInfinity(dd)); /* Build the monolithic TR. */ TR = Ntr_buildTR(dd,net,option,NTR_IMAGE_MONO); /* Build the ADD variable vectors for x and y. */ xadd = ALLOC(DdNode *, nvars); yadd = ALLOC(DdNode *, nvars); for(i = 0; i < nvars; i++) { q = Cudd_addIthVar(dd,TR->x[i]->index); Cudd_Ref(q); xadd[i] = q; q = Cudd_addIthVar(dd,TR->y[i]->index); Cudd_Ref(q); yadd[i] = q; } /* Convert the transition relation BDD into an ADD... */ q = Cudd_BddToAdd(dd,TR->part[0]); Cudd_Ref(q); /* ...replacing zeroes with infinities... */ r = Cudd_addIte(dd,q,Cudd_ReadOne(dd),Cudd_ReadPlusInfinity(dd)); Cudd_Ref(r); Cudd_RecursiveDeref(dd,q); /* ...and zeroing the diagonal. */ q = Cudd_addXeqy(dd,nvars,xadd,yadd); Cudd_Ref(q); edges = Cudd_addIte(dd,q,Cudd_ReadZero(dd),r); Cudd_Ref(edges); Cudd_RecursiveDeref(dd,r); Cudd_RecursiveDeref(dd,q); switch(algorithm) { case NTR_SHORT_BELLMAN: bddSource = Ntr_initState(dd,net,option); source = Cudd_BddToAdd(dd,bddSource); Cudd_Ref(source); res = ntrBellman(dd,edges,source,xadd,yadd,nvars,pr); if (res == NULL) return(0); Cudd_Ref(res); Cudd_RecursiveDeref(dd,source); Cudd_RecursiveDeref(dd,bddSource); if (pr >= 0) { (void) fprintf(stdout,"Distance Matrix"); Cudd_PrintDebug(dd,res,nvars,pr); } break; case NTR_SHORT_FLOYD: res = ntrWarshall(dd,edges,xadd,yadd,nvars,pr); if (res == NULL) return(0); Cudd_Ref(res); if (pr >= 0) { (void) fprintf(stdout,"Distance Matrix"); Cudd_PrintDebug(dd,res,2*nvars,pr); } break; case NTR_SHORT_SQUARE: /* Create a third set of ADD variables. */ zadd = ALLOC(DdNode *, nvars); for(i = 0; i < nvars; i++) { int level; level = Cudd_ReadIndex(dd,TR->x[i]->index); q = Cudd_addNewVarAtLevel(dd,level); Cudd_Ref(q); zadd[i] = q; } /* Compute the shortest paths. */ res = ntrSquare(dd,edges,zadd,yadd,xadd,nvars,pr,selectiveTrace); if (res == NULL) return(0); Cudd_Ref(res); /* Dispose of the extra variables. */ for(i = 0; i < nvars; i++) { Cudd_RecursiveDeref(dd,zadd[i]); } FREE(zadd); if (pr >= 0) { (void) fprintf(stdout,"Distance Matrix"); Cudd_PrintDebug(dd,res,2*nvars,pr); } break; default: (void) printf("Unrecognized method. Try again.\n"); return(0); } /* Here we should compute the paths. */ /* Clean up. */ Ntr_freeTR(dd,TR); Cudd_RecursiveDeref(dd,edges); Cudd_RecursiveDeref(dd,res); for(i = 0; i < nvars; i++) { Cudd_RecursiveDeref(dd,xadd[i]); Cudd_RecursiveDeref(dd,yadd[i]); } FREE(xadd); FREE(yadd); if (option->autoDyn & 1) { (void) printf("Order after short path computation\n"); if (!Bnet_PrintOrder(net,dd)) return(0); } return(1); } /* end of Ntr_ShortestPaths */
anode_t *synthesize( DdManager *manager, unsigned char init_flags, unsigned char verbose ) { anode_t *strategy = NULL; anode_t *this_node_stack = NULL; anode_t *node, *new_node; bool initial; vartype *state; vartype **env_moves; int emoves_len; ptree_t *var_separator; DdNode *W; DdNode *strans_into_W; DdNode *einit, *sinit, *etrans, *strans, **egoals, **sgoals; DdNode *ddval; /* Store result of evaluating a BDD */ DdNode ***Y = NULL; DdNode *Y_i_primed; int *num_sublevels; DdNode ****X_ijr = NULL; DdNode *tmp, *tmp2; int i, j, r, k; /* Generic counters */ int offset; bool env_nogoal_flag = False; /* Indicate environment has no goals */ int loop_mode; int next_mode; int num_env, num_sys; int *cube; /* length will be twice total number of variables (to account for both variables and their primes). */ /* Variables used during CUDD generation (state enumeration). */ DdGen *gen; CUDD_VALUE_TYPE gvalue; int *gcube; /* Set environment goal to True (i.e., any state) if none was given. This simplifies the implementation below. */ if (spc.num_egoals == 0) { env_nogoal_flag = True; spc.num_egoals = 1; spc.env_goals = malloc( sizeof(ptree_t *) ); *spc.env_goals = init_ptree( PT_CONSTANT, NULL, 1 ); } num_env = tree_size( spc.evar_list ); num_sys = tree_size( spc.svar_list ); /* State vector (i.e., valuation of the variables) */ state = malloc( sizeof(vartype)*(num_env+num_sys) ); if (state == NULL) { perror( __FILE__ ", malloc" ); exit(-1); } /* Allocate cube array, used later for quantifying over variables. */ cube = (int *)malloc( sizeof(int)*2*(num_env+num_sys) ); if (cube == NULL) { perror( __FILE__ ", malloc" ); exit(-1); } /* Chain together environment and system variable lists for working with BDD library. */ if (spc.evar_list == NULL) { var_separator = NULL; spc.evar_list = spc.svar_list; /* that this is the deterministic case is indicated by var_separator = NULL. */ } else { var_separator = get_list_item( spc.evar_list, -1 ); if (var_separator == NULL) { fprintf( stderr, "Error: get_list_item failed on environment variables" " list.\n" ); free( state ); free( cube ); return NULL; } var_separator->left = spc.svar_list; } /* Generate BDDs for the various parse trees from the problem spec. */ if (spc.env_init != NULL) { einit = ptree_BDD( spc.env_init, spc.evar_list, manager ); } else { einit = Cudd_ReadOne( manager ); Cudd_Ref( einit ); } if (spc.sys_init != NULL) { sinit = ptree_BDD( spc.sys_init, spc.evar_list, manager ); } else { sinit = Cudd_ReadOne( manager ); Cudd_Ref( sinit ); } if (verbose > 1) logprint( "Building environment transition BDD..." ); etrans = ptree_BDD( spc.env_trans, spc.evar_list, manager ); if (verbose > 1) { logprint( "Done." ); logprint( "Building system transition BDD..." ); } strans = ptree_BDD( spc.sys_trans, spc.evar_list, manager ); if (verbose > 1) logprint( "Done." ); /* Build goal BDDs, if present. */ if (spc.num_egoals > 0) { egoals = malloc( spc.num_egoals*sizeof(DdNode *) ); for (i = 0; i < spc.num_egoals; i++) *(egoals+i) = ptree_BDD( *(spc.env_goals+i), spc.evar_list, manager ); } else { egoals = NULL; } if (spc.num_sgoals > 0) { sgoals = malloc( spc.num_sgoals*sizeof(DdNode *) ); for (i = 0; i < spc.num_sgoals; i++) *(sgoals+i) = ptree_BDD( *(spc.sys_goals+i), spc.evar_list, manager ); } else { sgoals = NULL; } if (var_separator == NULL) { spc.evar_list = NULL; } else { var_separator->left = NULL; } W = compute_winning_set_BDD( manager, etrans, strans, egoals, sgoals, verbose ); if (W == NULL) { fprintf( stderr, "Error synthesize: failed to construct winning set.\n" ); free( state ); free( cube ); return NULL; } Y = compute_sublevel_sets( manager, W, etrans, strans, egoals, spc.num_egoals, sgoals, spc.num_sgoals, &num_sublevels, &X_ijr, verbose ); if (Y == NULL) { fprintf( stderr, "Error synthesize: failed to construct sublevel sets.\n" ); free( state ); free( cube ); return NULL; } /* The sublevel sets are exactly as resulting from the vanilla fixed point formula. Thus for each system goal i, Y_0 = \emptyset, and Y_1 is a union of i-goal states and environment-blocking states. For the purpose of synthesis, it is enough to delete Y_0 and replace Y_1 with the intersection of i-goal states and the winning set, and then shift the indices down (so that Y_1 is now called Y_0, Y_2 is now called Y_1, etc.) */ for (i = 0; i < spc.num_sgoals; i++) { Cudd_RecursiveDeref( manager, *(*(Y+i)) ); Cudd_RecursiveDeref( manager, *(*(Y+i)+1) ); for (r = 0; r < spc.num_egoals; r++) Cudd_RecursiveDeref( manager, *(*(*(X_ijr+i))+r) ); free( *(*(X_ijr+i)) ); *(*(Y+i)+1) = Cudd_bddAnd( manager, *(sgoals+i), W ); Cudd_Ref( *(*(Y+i)+1) ); (*(num_sublevels+i))--; for (j = 0; j < *(num_sublevels+i); j++) { *(*(Y+i)+j) = *(*(Y+i)+j+1); *(*(X_ijr+i)+j) = *(*(X_ijr+i)+j+1); } assert( *(num_sublevels+i) > 0 ); *(Y+i) = realloc( *(Y+i), (*(num_sublevels+i))*sizeof(DdNode *) ); *(X_ijr+i) = realloc( *(X_ijr+i), (*(num_sublevels+i))*sizeof(DdNode **) ); if (*(Y+i) == NULL || *(X_ijr+i) == NULL) { perror( __FILE__ ", realloc" ); exit(-1); } } /* Make primed form of W and take conjunction with system transition (safety) formula, for use while stepping down Y_i sets. Note that we assume the variable map has been appropriately defined in the CUDD manager, after the call to compute_winning_set_BDD above. */ tmp = Cudd_bddVarMap( manager, W ); if (tmp == NULL) { fprintf( stderr, "Error synthesize: Error in swapping variables with primed" " forms.\n" ); free( state ); free( cube ); return NULL; } Cudd_Ref( tmp ); strans_into_W = Cudd_bddAnd( manager, strans, tmp ); Cudd_Ref( strans_into_W ); Cudd_RecursiveDeref( manager, tmp ); /* From each initial state, build strategy by propagating forward toward the next goal (current target goal specified by "mode" of a state), and iterating until every reached state and mode combination has already been encountered (whence the strategy already built). */ if (init_flags == ALL_INIT || (init_flags == ONE_SIDE_INIT && spc.sys_init == NULL)) { if (init_flags == ALL_INIT) { if (verbose > 1) logprint( "Enumerating initial states, given init_flags =" " ALL_INIT" ); tmp = Cudd_bddAnd( manager, einit, sinit ); } else { if (verbose > 1) logprint( "Enumerating initial states, given init_flags =" " ONE_SIDE_INIT and empty SYSINIT" ); tmp = einit; Cudd_Ref( tmp ); } Cudd_Ref( tmp ); Cudd_AutodynDisable( manager ); Cudd_ForeachCube( manager, tmp, gen, gcube, gvalue ) { initialize_cube( state, gcube, num_env+num_sys ); while (!saturated_cube( state, gcube, num_env+num_sys )) { this_node_stack = insert_anode( this_node_stack, 0, -1, False, state, num_env+num_sys ); if (this_node_stack == NULL) { fprintf( stderr, "Error synthesize: building list of initial" " states.\n" ); return NULL; } increment_cube( state, gcube, num_env+num_sys ); } this_node_stack = insert_anode( this_node_stack, 0, -1, False, state, num_env+num_sys ); if (this_node_stack == NULL) { fprintf( stderr, "Error synthesize: building list of initial" " states.\n" ); return NULL; } } Cudd_AutodynEnable( manager, CUDD_REORDER_SAME ); Cudd_RecursiveDeref( manager, tmp ); } else if (init_flags == ALL_ENV_EXIST_SYS_INIT) {
/** * @brief Basic test of timeout handler. * * @details Sets a short timeout and then tries to build a function * with a large BDD. Strives to avoid leaking nodes. * * @return 0 if successful; -1 otherwise. */ static int testTimeout(int verbosity) { DdManager *dd; /* Declare these "volatile" to prevent clobbering by longjmp. */ DdNode * volatile f; DdNode * volatile clause = NULL; DdNode * var1, * var2; int i, ret, count; int const N = 20; /* half the number of variables in f */ unsigned long timeout = 100UL; /* in milliseconds */ jmp_buf timeoutEnv; dd = Cudd_Init(0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); if (!dd) { if (verbosity) { printf("initialization failed\n"); } return -1; } /* Set up timeout handling. */ if (setjmp(timeoutEnv) > 0) { if (verbosity) { printf("caught timeout\n"); } /* The nodes of clause may be leaked if the timeout was * detected while conjoining the clause to f. We set * clause to NULL when it's not in use to be able to * detect this case. */ if (clause) Cudd_RecursiveDeref(dd, clause); goto finally; } (void) Cudd_RegisterTimeoutHandler(dd, timeoutHandler, (void *) &timeoutEnv); (void) Cudd_SetTimeLimit(dd, timeout); /* Try to build function. This is expected to run out of time. */ f = Cudd_ReadOne(dd); Cudd_Ref(f); for (i = 0; i < N; i++) { DdNode * tmp; var1 = Cudd_bddIthVar(dd, i); if (!var1) { if (verbosity) { printf("computation failed\n"); return -1; } } var2 = Cudd_bddIthVar(dd, i+N); if (!var2) { if (verbosity) { printf("computation failed\n"); return -1; } } clause = Cudd_bddOr(dd, var1, var2); if (!clause) { if (verbosity) { printf("computation failed\n"); } return -1; } Cudd_Ref(clause); tmp = Cudd_bddAnd(dd, f, clause); if (!tmp) { if (verbosity) { printf("computation failed\n"); } return -1; } Cudd_Ref(tmp); Cudd_RecursiveDeref(dd, clause); clause = NULL; Cudd_RecursiveDeref(dd, f); f = tmp; } if (verbosity > 1) { Cudd_bddPrintCover(dd, f, f); } finally: if (verbosity) { printf("so far"); Cudd_PrintSummary(dd, f, 2*N, 0); } count = 0; for (i = 0; i < N-1; i += 2) { var1 = Cudd_bddIthVar(dd, i); if (!var1) { printf("computation failed\n"); return -1; } var2 = Cudd_bddIthVar(dd, i+1); if (!var2) { printf("computation failed\n"); return -1; } clause = Cudd_bddOr(dd, var1, var2); if (!clause) { printf("computation failed\n"); return -1; } Cudd_Ref(clause); if (Cudd_bddLeq(dd, f, clause)) { count++; } Cudd_RecursiveDeref(dd, clause); } if (verbosity) { printf("f implies %d clauses\n", count); } Cudd_RecursiveDeref(dd, f); ret = Cudd_CheckZeroRef(dd); if (verbosity) { Cudd_PrintInfo(dd, stdout); if (ret != 0) { printf("%d non-zero references\n", ret); } } Cudd_Quit(dd); return 0; }
/** * @brief Basic test of long double and EPD minterm computation. * @return 0 if successful; -1 otherwise. */ static int testLdbl(int verbosity) { DdManager *dd; DdNode *f, *g; int i, ret; int const N = 12; /* half the number of variables */ long double cnt; dd = Cudd_Init(2*N, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); if (!dd) { if (verbosity) { printf("initialization failed\n"); } return -1; } f = g = Cudd_ReadOne(dd); Cudd_Ref(f); Cudd_Ref(g); for (i = 0; i < N; i++) { DdNode *var1, *var2, *clause, *tmp; var1 = Cudd_bddIthVar(dd, i); var2 = Cudd_bddIthVar(dd, i+N); clause = Cudd_bddOr(dd, var1, var2); if (!clause) { Cudd_Quit(dd); return -1; } Cudd_Ref(clause); tmp = Cudd_bddAnd(dd, f, clause); if (!tmp) { Cudd_Quit(dd); return -1; } Cudd_Ref(tmp); Cudd_RecursiveDeref(dd, clause); Cudd_RecursiveDeref(dd, f); f = tmp; clause = Cudd_bddOr(dd, Cudd_Not(var1), Cudd_Not(var2)); if (!clause) { Cudd_Quit(dd); return -1; } Cudd_Ref(clause); tmp = Cudd_bddAnd(dd, g, clause); if (!tmp) { Cudd_Quit(dd); return -1; } Cudd_Ref(tmp); Cudd_RecursiveDeref(dd, clause); Cudd_RecursiveDeref(dd, g); g = tmp; } if (verbosity) { printf("f"); Cudd_PrintSummary(dd, f, 2*N, 0); } cnt = Cudd_LdblCountMinterm(dd, f, 2*N); if (verbosity) { printf("f has %Lg minterms\n", cnt); } if (verbosity) { printf("EPD count for f = "); ret = Cudd_EpdPrintMinterm(dd, f, 2*N); printf("\n"); if (!ret) { printf("problem with EPD\n"); } } Cudd_RecursiveDeref(dd, f); if (verbosity) { printf("g"); Cudd_PrintSummary(dd, g, 2*N, 0); } cnt = Cudd_LdblCountMinterm(dd, g, 2*N); if (verbosity) { printf("g has %Lg minterms\n", cnt); } if (verbosity) { printf("EPD count for g = "); ret = Cudd_EpdPrintMinterm(dd, g, 2*N); printf("\n"); if (!ret) { printf("problem with EPD\n"); } } Cudd_RecursiveDeref(dd, g); ret = Cudd_CheckZeroRef(dd); if (verbosity && ret != 0) { printf("%d non-zero references\n", ret); } Cudd_Quit(dd); return 0; }
void I_BDD_new_mutex_domain (DdManager *dd, DdNode *node[], unsigned int size) { unsigned int shbuf, vars, ctr; DdNode **ddVar, *one, *newnode, *oldnode, *bitnode; int i,j, extra; /* base cases */ if (size == 0) { return; } one = Cudd_ReadOne(dd); if (size == 1) { node[0] = one; Cudd_Ref (node[0]); return; } for(shbuf = size - 1, vars = 0; shbuf != 0; shbuf >>= 1, vars++); extra = (1 << vars) - size; ddVar = malloc(vars * sizeof(DdNode *)); for (j = 0; j < vars; j++) { ddVar[j] = bitnode = Cudd_bddNewVar (dd); Cudd_Ref (bitnode); } ctr = 0; for (i = 0; i < size; i++, ctr++) { newnode = one; Cudd_Ref (newnode); #ifdef I_BDD_MUTEX_DEBUG printf("i%d:", i); #endif for (j = (extra > 0); j < vars; j++) { bitnode = (ctr & (1 << j)) ? ddVar[j] : Cudd_Not(ddVar[j]); newnode = Cudd_bddAnd (dd, bitnode, oldnode = newnode); Cudd_Ref (newnode); Cudd_RecursiveDeref (dd, oldnode); #ifdef I_BDD_MUTEX_DEBUG if (ctr & (1 << j)) printf("+ v%d ", j); else printf("+ !v%d ", j); #endif } #ifdef I_BDD_MUTEX_DEBUG printf ("\n"); #endif node[i] = newnode; if (extra > 0) { extra--; ctr++; } } #ifdef I_BDD_MUTEX_TEST { DdNode *test, *old_test; int i; test = Cudd_ReadLogicZero(dd); Cudd_Ref (test); for (i = 0; i < size; i++) { if (Cudd_bddIte (dd, test, node[i], zero) != zero) I_punt("I_BDD_new_mutex_complex: not mutex!"); test = Cudd_bddIte(dd, node[i], one, old_test = test); Cudd_Ref (test); Cudd_RecursiveDeref (dd, old_test); } if (test != one) I_punt("I_BDD_new_mutex_complex: not exhaustive!"); Cudd_RecursiveDeref (dd, test); } #endif for (j = 0; j < vars; j++) Cudd_RecursiveDeref (dd, ddVar[j]); free (ddVar); return; }
DdNode *compute_winning_set_BDD( DdManager *manager, DdNode *etrans, DdNode *strans, DdNode **egoals, DdNode **sgoals, unsigned char verbose ) { DdNode *X = NULL, *X_prev = NULL; DdNode *Y = NULL, *Y_exmod = NULL, *Y_prev = NULL; DdNode **Z = NULL, **Z_prev = NULL; bool Z_changed; /* Use to detect occurrence of fixpoint for all Z_i */ /* Fixpoint iteration counters */ int num_it_Z, num_it_Y, num_it_X; DdNode *tmp, *tmp2; int i, j; /* Generic counters */ DdNode **vars, **pvars; int num_env, num_sys; int *cube; /* length will be twice total number of variables (to account for both variables and their primes). */ num_env = tree_size( spc.evar_list ); num_sys = tree_size( spc.svar_list ); /* Allocate cube array, used later for quantifying over variables. */ cube = (int *)malloc( sizeof(int)*2*(num_env+num_sys) ); if (cube == NULL) { perror( __FILE__ ", malloc" ); exit(-1); } /* Define a map in the manager to easily swap variables with their primed selves. */ vars = malloc( (num_env+num_sys)*sizeof(DdNode *) ); pvars = malloc( (num_env+num_sys)*sizeof(DdNode *) ); for (i = 0; i < num_env+num_sys; i++) { *(vars+i) = Cudd_bddIthVar( manager, i ); *(pvars+i) = Cudd_bddIthVar( manager, i+num_env+num_sys ); } if (!Cudd_SetVarMap( manager, vars, pvars, num_env+num_sys )) { fprintf( stderr, "Error: failed to define variable map in CUDD manager.\n" ); free( cube ); return NULL; } free( vars ); free( pvars ); if (spc.num_sgoals > 0) { Z = malloc( spc.num_sgoals*sizeof(DdNode *) ); Z_prev = malloc( spc.num_sgoals*sizeof(DdNode *) ); for (i = 0; i < spc.num_sgoals; i++) { *(Z+i) = NULL; *(Z_prev+i) = NULL; } } /* Initialize */ for (i = 0; i < spc.num_sgoals; i++) { *(Z+i) = Cudd_ReadOne( manager ); Cudd_Ref( *(Z+i) ); } num_it_Z = 0; do { num_it_Z++; if (verbose > 1) { logprint( "Z iteration %d", num_it_Z ); logprint( "Cudd_ReadMemoryInUse (bytes): %d", Cudd_ReadMemoryInUse( manager ) ); } for (i = 0; i < spc.num_sgoals; i++) { if (*(Z_prev+i) != NULL) Cudd_RecursiveDeref( manager, *(Z_prev+i) ); *(Z_prev+i) = *(Z+i); } for (i = 0; i < spc.num_sgoals; i++) { if (i == spc.num_sgoals-1) { *(Z+i) = compute_existsmodal( manager, *Z_prev, etrans, strans, num_env, num_sys, cube ); } else { *(Z+i) = compute_existsmodal( manager, *(Z_prev+i+1), etrans, strans, num_env, num_sys, cube ); } if (*(Z+i) == NULL) { /* fatal error */ return NULL; } /* (Re)initialize Y */ if (Y != NULL) Cudd_RecursiveDeref( manager, Y ); Y = Cudd_Not( Cudd_ReadOne( manager ) ); Cudd_Ref( Y ); num_it_Y = 0; do { num_it_Y++; if (verbose > 1) { logprint( "\tY iteration %d", num_it_Y ); logprint( "\tCudd_ReadMemoryInUse (bytes): %d", Cudd_ReadMemoryInUse( manager ) ); } if (Y_prev != NULL) Cudd_RecursiveDeref( manager, Y_prev ); Y_prev = Y; if (Y_exmod != NULL) Cudd_RecursiveDeref( manager, Y_exmod ); Y_exmod = compute_existsmodal( manager, Y_prev, etrans, strans, num_env, num_sys, cube ); if (Y_exmod == NULL) { /* fatal error */ return NULL; } Y = Cudd_Not( Cudd_ReadOne( manager ) ); Cudd_Ref( Y ); for (j = 0; j < spc.num_egoals; j++) { /* (Re)initialize X */ if (X != NULL) Cudd_RecursiveDeref( manager, X ); X = Cudd_ReadOne( manager ); Cudd_Ref( X ); /* Greatest fixpoint for X, for this env goal */ num_it_X = 0; do { num_it_X++; if (verbose > 1) { logprint( "\t\tX iteration %d", num_it_X ); logprint( "\t\tCudd_ReadMemoryInUse (bytes): %d", Cudd_ReadMemoryInUse( manager ) ); } if (X_prev != NULL) Cudd_RecursiveDeref( manager, X_prev ); X_prev = X; X = compute_existsmodal( manager, X_prev, etrans, strans, num_env, num_sys, cube ); if (X == NULL) { /* fatal error */ return NULL; } tmp = Cudd_bddAnd( manager, *(sgoals+i), *(Z+i) ); Cudd_Ref( tmp ); tmp2 = Cudd_bddOr( manager, tmp, Y_exmod ); Cudd_Ref( tmp2 ); Cudd_RecursiveDeref( manager, tmp ); tmp = Cudd_bddAnd( manager, X, Cudd_Not( *(egoals+j) ) ); Cudd_Ref( tmp ); Cudd_RecursiveDeref( manager, X ); X = Cudd_bddOr( manager, tmp2, tmp ); Cudd_Ref( X ); Cudd_RecursiveDeref( manager, tmp ); Cudd_RecursiveDeref( manager, tmp2 ); tmp = X; X = Cudd_bddAnd( manager, X, X_prev ); Cudd_Ref( X ); Cudd_RecursiveDeref( manager, tmp ); } while (!Cudd_bddLeq( manager, X, X_prev ) || !Cudd_bddLeq( manager, X_prev, X )); tmp = Y; Y = Cudd_bddOr( manager, Y, X ); Cudd_Ref( Y ); Cudd_RecursiveDeref( manager, tmp ); Cudd_RecursiveDeref( manager, X ); X = NULL; Cudd_RecursiveDeref( manager, X_prev ); X_prev = NULL; } tmp2 = Y; Y = Cudd_bddOr( manager, Y, Y_prev ); Cudd_Ref( Y ); Cudd_RecursiveDeref( manager, tmp2 ); } while (!Cudd_bddLeq( manager, Y, Y_prev ) || !Cudd_bddLeq( manager, Y_prev, Y )); Cudd_RecursiveDeref( manager, *(Z+i) ); *(Z+i) = Cudd_bddAnd( manager, Y, *(Z_prev+i) ); Cudd_Ref( *(Z+i) ); Cudd_RecursiveDeref( manager, Y ); Y = NULL; Cudd_RecursiveDeref( manager, Y_prev ); Y_prev = NULL; Cudd_RecursiveDeref( manager, Y_exmod ); Y_exmod = NULL; } Z_changed = False; for (i = 0; i < spc.num_sgoals; i++) { if (!Cudd_bddLeq( manager, *(Z+i), *(Z_prev+i) ) || !Cudd_bddLeq( manager, *(Z_prev+i), *(Z+i) )) { Z_changed = True; break; } } } while (Z_changed); /* Pre-exit clean-up */ tmp = *Z; Cudd_RecursiveDeref( manager, *Z_prev ); for (i = 1; i < spc.num_sgoals; i++) { Cudd_RecursiveDeref( manager, *(Z+i) ); Cudd_RecursiveDeref( manager, *(Z_prev+i) ); } free( Z ); free( Z_prev ); free( cube ); return tmp; }
static DdNode *tree2BDD(DdManager *mgr, ACCExpr *expr, VarMap &varMap) { std::string op = expr->value; DdNode *ret = nullptr; if (op == "&&") op = "&"; else if (op == "||") op = "|"; if (checkInteger(expr, "1")) ret = Cudd_ReadOne(mgr); else if (checkInteger(expr, "0")) ret = Cudd_ReadLogicZero(mgr); else if (op == "!") return Cudd_Not(tree2BDD(mgr, expr->operands.front(), varMap)); // Not passes through ref count else if (op != "&" && op != "|" && op != "^") { if ((op == "!=" || op == "==")) { ACCExpr *lhs = getRHS(expr, 0); if (boolPossible(lhs) && boolPossible(getRHS(expr,1))) goto next; // we can analyze relops on booleans if (trace_bool) printf("[%s:%d] boolnot %d %d = %s\n", __FUNCTION__, __LINE__, boolPossible(getRHS(expr,0)), boolPossible(getRHS(expr,1)), tree2str(expr).c_str()); if (isIdChar(lhs->value[0])) { if (trace_bool) printf("[%s:%d] name %s type %s\n", __FUNCTION__, __LINE__, lhs->value.c_str(), refList[lhs->value].type.c_str()); } } if (op == "!=") // normalize comparison strings expr->value = "=="; std::string name = "( " + tree2str(expr) + " )"; if (!varMap[name]) { varMap[name] = new MapItem; varMap[name]->index = varMap.size(); varMap[name]->node = Cudd_bddIthVar(mgr, varMap[name]->index); } ret = varMap[name]->node; if (op == "!=") { // normalize comparison strings expr->value = op; // restore ret = Cudd_Not(ret); } } if (ret) { Cudd_Ref(ret); return ret; } next:; for (auto item: expr->operands) { DdNode *operand = tree2BDD(mgr, item, varMap), *next; if (!ret) ret = operand; else { if (op == "&") next = Cudd_bddAnd(mgr, ret, operand); else if (op == "|") next = Cudd_bddOr(mgr, ret, operand); else if (op == "^" || op == "!=") next = Cudd_bddXor(mgr, ret, operand); else if (op == "==") next = Cudd_bddXnor(mgr, ret, operand); else { printf("[%s:%d] unknown operator\n", __FUNCTION__, __LINE__); exit(-1); } Cudd_Ref(next); Cudd_RecursiveDeref(mgr, operand); Cudd_RecursiveDeref(mgr, ret); ret = next; } } return ret; }
/**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 */