/* preserve the state of unaffected variables */ DdNode* bdd_same(DdManager* m, pos* postab, int var, int proc) { DdNode* ret = Cudd_ReadOne(m); DdNode* var1, *var2, *xnor, *tmp; /* XNOR gate simulates equality */ Cudd_Ref(ret); int i, j; for (i=0; i<postab->num_procs; i++) {/* iterate through all processes */ if (i == proc) continue; /* skip pc of current process */ for (j=0; j<postab->pc_size; j++) {/* iterate through all bits */ var1 = Cudd_bddIthVar(m, postab->pc[i][j]); var2 = Cudd_bddIthVar(m, postab->pc_[i][j]); xnor = Cudd_bddXnor(m, var1, var2); Cudd_Ref(xnor); tmp = Cudd_bddAnd(m, ret, xnor); Cudd_Ref(tmp); Cudd_RecursiveDeref(m, xnor); Cudd_RecursiveDeref(m, ret); ret = tmp; } } for (i=0; i<postab->num_vars; i++) { /* iterate through all globals */ if (i == var) continue; /* skip assignment variable */ var1 = Cudd_bddIthVar(m, i); var2 = Cudd_bddIthVar(m, i+postab->num_vars); xnor = Cudd_bddXnor(m, var1, var2); Cudd_Ref(xnor); tmp = Cudd_bddAnd(m, ret, xnor); Cudd_Ref(tmp); Cudd_RecursiveDeref(m, xnor); Cudd_RecursiveDeref(m, ret); ret = tmp; } return ret; }
/**Function************************************************************* Synopsis [Computes the transition relation of the network.] Description [Assumes that the global BDDs are computed.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ) { DdNode * bRel, * bTemp, * bProd, * bVar, * bInputs; Abc_Obj_t * pNode; int fReorder = 1; int i; // extand the BDD manager to represent NS variables assert( dd->size == Abc_NtkCiNum(pNtk) ); Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + Abc_NtkLatchNum(pNtk) - 1 ); // enable reordering if ( fReorder ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); else Cudd_AutodynDisable( dd ); // compute the transition relation bRel = b1; Cudd_Ref( bRel ); Abc_NtkForEachLatch( pNtk, pNode, i ) { bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i ); // bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd ); bProd = Cudd_bddXnor( dd, bVar, Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( bProd ); bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); }
/* formula for assignment: pc ^ var' <=> expr ^ pc' ^ same(pc, var) */ DdNode* bdd_mk_assign(DdManager *m, pos* postab, cfg_node* host, int proc) { DdNode* tmp1 = Cudd_bddIthVar(m, symtab_lookup(postab->vars_, host->node->name)); DdNode* tmp2 = bdd_expr(m, postab->vars, host->node->children[EXPR]); DdNode* ret = Cudd_bddXnor(m, tmp1, tmp2); Cudd_Ref(ret); /* encode assignment with XNOR */ Cudd_RecursiveDeref(m, tmp2); ret = bdd_encode_pc(m, ret, postab->pc, postab->pc_size, proc, host->node->id); /* encode program counter */ tmp1 = bdd_same(m, postab, symtab_lookup(postab->vars, host->node->name), proc); /* encode unchanging variables */ tmp2 = ret; ret = Cudd_bddAnd(m, tmp1, tmp2); Cudd_Ref(ret); Cudd_RecursiveDeref(m, tmp1); Cudd_RecursiveDeref(m, tmp2); return ret; }
DdNode * DdGate::gateFuncElem(DdManager * pDdManager, DdNode * pa, DdNode * pb){ switch(__gate){ case AND: return Cudd_bddAnd(pDdManager, pa, pb); case NAND: return Cudd_bddNand(pDdManager, pa, pb); case OR: return Cudd_bddOr(pDdManager, pa, pb); case NOR: return Cudd_bddNor(pDdManager, pa, pb); case XOR: return Cudd_bddXor(pDdManager, pa, pb); case XNOR: return Cudd_bddXnor(pDdManager, pa, pb); case NOT: return Cudd_bddNand(pDdManager, pa, pa); default: return NULL; } }
/**Function************************************************************* Synopsis [Derive BDD of the characteristic function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_ResBuildBdd( Abc_Ntk_t * pNtk, DdManager * dd ) { Vec_Ptr_t * vNodes, * vBdds, * vLocals; Abc_Obj_t * pObj, * pFanin; DdNode * bFunc, * bPart, * bTemp, * bVar; int i, k; assert( Abc_NtkIsSopLogic(pNtk) ); assert( Abc_NtkCoNum(pNtk) <= 3 ); vBdds = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachCi( pNtk, pObj, i ) Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), Cudd_bddIthVar(dd, i) ); // create internal node BDDs vNodes = Abc_NtkDfs( pNtk, 0 ); vLocals = Vec_PtrAlloc( 6 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { if ( Abc_ObjFaninNum(pObj) == 0 ) { bFunc = Cudd_NotCond( Cudd_ReadOne(dd), Abc_SopIsConst0((char *)pObj->pData) ); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), bFunc ); continue; } Vec_PtrClear( vLocals ); Abc_ObjForEachFanin( pObj, pFanin, k ) Vec_PtrPush( vLocals, Vec_PtrEntry(vBdds, Abc_ObjId(pFanin)) ); bFunc = Abc_ConvertSopToBdd( dd, (char *)pObj->pData, (DdNode **)Vec_PtrArray(vLocals) ); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), bFunc ); } Vec_PtrFree( vLocals ); // create char function bFunc = Cudd_ReadOne( dd ); Cudd_Ref( bFunc ); Abc_NtkForEachCo( pNtk, pObj, i ) { bVar = Cudd_bddIthVar( dd, i + Abc_NtkCiNum(pNtk) ); bTemp = (DdNode *)Vec_PtrEntry( vBdds, Abc_ObjFaninId0(pObj) ); bPart = Cudd_bddXnor( dd, bTemp, bVar ); Cudd_Ref( bPart ); bFunc = Cudd_bddAnd( dd, bTemp = bFunc, bPart ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bPart ); }
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; }