/**Function************************************************************* Synopsis [ Given a node, evaluate its cuts and save the best one ] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rewrite_NodeRewrite( Mig_Man_t * pMig, Rewrite_Man_t * p, Cut_Man_t * pManCut, Mig_Obj_t * pNode, Cut_Cut_t * pCut, int fUpdateLevel ) { Gra_Graph_t * pGraph; Mig_Obj_t * pFanin; unsigned uPhase; unsigned uTruthBest = 0; unsigned uTruth; char * pPerm; int Required, nNodesSaved, nNodesSaveCur = -1; int i, GainCur = -1, GainBest = -1; Required = fUpdateLevel ? Mig_ObjRequiredLevel(pMig, pNode) : ABC_INFINITY; // triv cut is omitted for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) { if ( pCut->nLeaves < 4 ) continue; // NPN conditions uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); pPerm = p->pPerms4[ (int)p->pPerms[uTruth] ]; uPhase = p->pPhases[uTruth]; // collect fanin nodes Vec_PtrClear( p->vFaninsCur ); Vec_PtrFill( p->vFaninsCur, (int)pCut->nLeaves, 0 ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { pFanin = Mig_ManObj( pMig, pCut->pLeaves[(int)pPerm[i]] ); if( pFanin == NULL ) break; //assert( pFanin ); // bad cut condition-> fanin may be removed pFanin = Mig_NotCond( pFanin, ((uPhase & (1<<i)) > 0) ); Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); } if ( i != (int)pCut->nLeaves ) continue; // bad cut: fanin is removed // 1. mark boundary 2. mark MFFC 3.recover boundary Vec_PtrForEachEntry( Mig_Obj_t *, p->vFaninsCur, pFanin, i ) Mig_Regular(pFanin)->vFanouts.nSize++; Mig_ManIncTravId( pMig ); nNodesSaved = Mig_NodeMffcLabelMig( pMig, pNode ); Vec_PtrForEachEntry( Mig_Obj_t *, p->vFaninsCur, pFanin, i ) Mig_Regular(pFanin)->vFanouts.nSize--; // evaluate the cut pGraph = Rewrite_CutEvaluate( pMig, p, pNode, pCut, nNodesSaved, &GainCur, Required, 0xFFFF ); if( pGraph != NULL && GainBest < GainCur ) { nNodesSaveCur = nNodesSaved; GainBest = GainCur; p->pGraph = pGraph; p->fCompl = ((uPhase & (1<<4)) > 0 ); uTruthBest = 0xFFFF & *Cut_CutReadTruth(pCut); Vec_PtrClear( p->vFanins ); Vec_PtrForEachEntry( Mig_Obj_t *, p->vFaninsCur, pFanin, i ) Vec_PtrPush( p->vFanins, pFanin ); } }
void Dar_BalanceUniqify( Aig_Obj_t * pObj, Vec_Ptr_t * vNodes, int fExor ) { Aig_Obj_t * pTemp, * pTempNext; int i, k; // sort the nodes by their literal Vec_PtrSort( vNodes, (int (*)())Dar_ObjCompareLits ); // remove duplicates k = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pTemp, i ) { if ( i + 1 == Vec_PtrSize(vNodes) ) { Vec_PtrWriteEntry( vNodes, k++, pTemp ); break; } pTempNext = (Aig_Obj_t *)Vec_PtrEntry( vNodes, i+1 ); if ( !fExor && pTemp == Aig_Not(pTempNext) ) // pos_lit & neg_lit = 0 { Vec_PtrClear( vNodes ); return; } if ( pTemp != pTempNext ) // save if different Vec_PtrWriteEntry( vNodes, k++, pTemp ); else if ( fExor ) // in case of XOR, remove identical i++; } Vec_PtrShrink( vNodes, k ); // check that there is no duplicates pTemp = (Aig_Obj_t *)Vec_PtrEntry( vNodes, 0 ); Vec_PtrForEachEntryStart( Aig_Obj_t *, vNodes, pTempNext, i, 1 ) { assert( pTemp != pTempNext ); pTemp = pTempNext; } }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects fanins of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ObjCollectFanins( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Nwk_Obj_t * pFanin; int i; Vec_PtrClear(vNodes); Nwk_ObjForEachFanin( pNode, pFanin, i ) Vec_PtrPush( vNodes, pFanin ); }
/**Function************************************************************* Synopsis [Derives the local AIG for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Nwk_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj ) { If_Cut_t * pCut; Hop_Obj_t * gFunc; If_Obj_t * pLeaf; int i; // get the best cut pCut = If_ObjCutBest(pIfObj); assert( pCut->nLeaves > 1 ); // set the leaf variables If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) If_CutSetData( If_ObjCutBest(pLeaf), Hop_IthVar(pHopMan, i) ); // recursively compute the function while collecting visited cuts Vec_PtrClear( pIfMan->vTemp ); gFunc = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp ); if ( gFunc == (void *)1 ) { printf( "Nwk_NodeIfToHop(): Computing local AIG has failed.\n" ); return NULL; } // printf( "%d ", Vec_PtrSize(p->vTemp) ); // clean the cuts If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) If_CutSetData( If_ObjCutBest(pLeaf), NULL ); Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i ) If_CutSetData( pCut, NULL ); return gFunc; }
/**Function************************************************************* Synopsis [Collects fanouts of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ObjCollectFanouts( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Nwk_Obj_t * pFanout; int i; Vec_PtrClear(vNodes); Nwk_ObjForEachFanout( pNode, pFanout, i ) Vec_PtrPush( vNodes, pFanout ); }
/**Function************************************************************* Synopsis [Prepares node mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManImproveNodePrepare( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited ) { If_Cut_t * pCut; If_Obj_t * pLeaf; int i; Vec_PtrClear( vFront ); Vec_PtrClear( vFrontOld ); Vec_PtrClear( vVisited ); // expand the cut downwards from the given place pCut = If_ObjCutBest(pObj); If_CutForEachLeaf( p, pCut, pLeaf, i ) { Vec_PtrPush( vFront, pLeaf ); Vec_PtrPush( vFrontOld, pLeaf ); Vec_PtrPush( vVisited, pLeaf ); pLeaf->fMark = 1; }
/**Function************************************************************* Synopsis [Sets up the SAT sat_solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMiterSatCreateInt( sat_solver * pSat, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode, * pFanin, * pNodeC, * pNodeT, * pNodeE; Vec_Ptr_t * vNodes, * vSuper; Vec_Int_t * vVars; int i, k, fUseMuxes = 1; // int fOrderCiVarsFirst = 0; int RetValue = 0; assert( Abc_NtkIsStrash(pNtk) ); // clean the CI node pointers Abc_NtkForEachCi( pNtk, pNode, i ) pNode->pCopy = NULL; // start the data structures vNodes = Vec_PtrAlloc( 1000 ); // the nodes corresponding to vars in the sat_solver vSuper = Vec_PtrAlloc( 100 ); // the nodes belonging to the given implication supergate vVars = Vec_IntAlloc( 100 ); // the temporary array for variables in the clause // add the clause for the constant node pNode = Abc_AigConst1(pNtk); pNode->fMarkA = 1; pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)vNodes->nSize; Vec_PtrPush( vNodes, pNode ); Abc_NtkClauseTriv( pSat, pNode, vVars ); /* // add the PI variables first Abc_NtkForEachCi( pNtk, pNode, i ) { pNode->fMarkA = 1; pNode->pCopy = (Abc_Obj_t *)vNodes->nSize; Vec_PtrPush( vNodes, pNode ); } */ // collect the nodes that need clauses and top-level assignments Vec_PtrClear( vSuper ); Abc_NtkForEachCo( pNtk, pNode, i ) { // get the fanin pFanin = Abc_ObjFanin0(pNode); // create the node's variable if ( pFanin->fMarkA == 0 ) { pFanin->fMarkA = 1; pFanin->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)vNodes->nSize; Vec_PtrPush( vNodes, pFanin ); } // add the trivial clause Vec_PtrPush( vSuper, Abc_ObjChild0(pNode) ); }
/**Function************************************************************* Synopsis [Collects the support of depth-limited MFFC.] Description [Returns the number of internal nodes in the MFFC.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeMffsSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp ) { int ConeSize1, ConeSize2; assert( !Aig_IsComplement(pNode) ); assert( Aig_ObjIsNode(pNode) ); if ( vSupp ) Vec_PtrClear( vSupp ); Aig_ManIncrementTravId( p ); ConeSize1 = Aig_NodeDeref_rec( pNode, LevelMin ); Aig_NodeMffsSupp_rec( p, pNode, LevelMin, vSupp, 1, NULL ); ConeSize2 = Aig_NodeRef_rec( pNode, LevelMin ); assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 > 0 ); return ConeSize1; }
/**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCollectSupergate( Abc_Obj_t * pNode, int fStopAtMux, Vec_Ptr_t * vNodes ) { int RetValue, i; assert( !Abc_ObjIsComplement(pNode) ); // collect the nodes in the implication supergate Vec_PtrClear( vNodes ); RetValue = Abc_NtkCollectSupergate_rec( pNode, vNodes, 1, fStopAtMux ); assert( vNodes->nSize > 1 ); // unmark the visited nodes for ( i = 0; i < vNodes->nSize; i++ ) Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0; // if we found the node and its complement in the same implication supergate, // return empty set of nodes (meaning that we should use constant-0 node) if ( RetValue == -1 ) vNodes->nSize = 0; }
void If_ObjConePrint( If_Man_t * pIfMan, If_Obj_t * pIfObj ) { If_Cut_t * pCut; If_Obj_t * pLeaf; int i; Vec_PtrClear( pIfMan->vTemp ); If_ObjConePrint_rec( pIfMan, pIfObj, pIfMan->vTemp ); Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i ) If_CutSetDataInt( pCut, 0 ); // print the leaf variables printf( "Cut " ); pCut = If_ObjCutBest(pIfObj); If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) printf( "%d ", pLeaf->Id ); printf( "\n" ); }
ABC_NAMESPACE_IMPL_START /* Implememented here is the algorithm for minimal-LUT decomposition described in the paper: T. Sasao et al. "On the number of LUTs to implement logic functions", To appear in Proc. IWLS'09. */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [Check if a LUT can absort a fanin.] Description [The fanins are (c, d0, d1).] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjCheckAbsorb( Abc_Obj_t * pObj, Abc_Obj_t * pPivot, int nLutSize, Vec_Ptr_t * vFanins ) { Abc_Obj_t * pFanin; int i; assert( Abc_ObjIsNode(pObj) && Abc_ObjIsNode(pPivot) ); // add fanins of the node Vec_PtrClear( vFanins ); Abc_ObjForEachFanin( pObj, pFanin, i ) if ( pFanin != pPivot ) Vec_PtrPush( vFanins, pFanin ); // add fanins of the fanin Abc_ObjForEachFanin( pPivot, pFanin, i ) { Vec_PtrPushUnique( vFanins, pFanin ); if ( Vec_PtrSize(vFanins) > nLutSize ) return 0; }
/**Function************************************************************* Synopsis [Collects nodes in the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) { Ivy_Obj_t * pTemp; int i; assert( !Ivy_IsComplement(pObj) ); assert( Ivy_ObjIsNode(pObj) ); // mark the nodes Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) Ivy_Regular(pTemp)->fMarkA = 1; assert( pObj->fMarkA == 0 ); // collect the cone Vec_PtrClear( vCone ); Ivy_ManCollectCone_rec( pObj, vCone ); // unmark the nodes Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) Ivy_Regular(pTemp)->fMarkA = 0; }
Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) { Vec_Ptr_t * vNodes; assert( !Aig_IsComplement(pObj) ); assert( Aig_ObjIsNode(pObj) ); // extend the storage if ( Vec_VecSize( vStore ) <= Level ) Vec_VecPush( vStore, Level, 0 ); // get the temporary array of nodes vNodes = Vec_VecEntry( vStore, Level ); Vec_PtrClear( vNodes ); // collect the nodes in the implication supergate Dar_BalanceCone_rec( pObj, pObj, vNodes ); // remove duplicates Dar_BalanceUniqify( pObj, vNodes, Aig_ObjIsExor(pObj) ); return vNodes; }
/**Fnction************************************************************* Synopsis [Constructs AIG in ABC from the manager.] Description [The ABC network is started, as well as the array vCopy, which will map the new ID of each object in the BBLIF manager into the ponter ot the corresponding AIG object in the ABC. For each internal node in a topological oder the AIG representation is created by factoring the SOP representation of the BBLIF object. Finally, the CO objects are created, and the dummy names are assigned because ABC requires each CI/CO to have a name.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Bbl_ManToAig( Bbl_Man_t * p ) { extern int Bbl_ManFncSize( Bbl_Man_t * p ); extern int Bbl_ObjFncHandle( Bbl_Obj_t * p ); extern Abc_Obj_t * Dec_GraphToAig( Abc_Ntk_t * pNtk, Dec_Graph_t * pFForm, Vec_Ptr_t * vFaninAigs ); int fVerbose = 0; Abc_Ntk_t * pNtk; Abc_Obj_t * pObjNew; Bbl_Obj_t * pObj, * pFanin; Vec_Ptr_t * vCopy, * vNodes, * vFaninAigs; Dec_Graph_t ** pFForms; int i; clock_t clk; clk = clock(); // map SOP handles into factored forms pFForms = ABC_CALLOC( Dec_Graph_t *, Bbl_ManFncSize(p) ); Bbl_ManForEachObj( p, pObj ) if ( pFForms[Bbl_ObjFncHandle(pObj)] == NULL ) pFForms[Bbl_ObjFncHandle(pObj)] = Dec_Factor( Bbl_ObjSop(p, pObj) ); if ( fVerbose ) ABC_PRT( "Fct", clock() - clk ); // start the network pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtk->pName = Extra_UtilStrsav( Bbl_ManName(p) ); vCopy = Vec_PtrStart( 1000 ); // create CIs Bbl_ManForEachObj( p, pObj ) { if ( !Bbl_ObjIsInput(pObj) ) continue; Vec_PtrSetEntry( vCopy, Bbl_ObjId(pObj), Abc_NtkCreatePi(pNtk) ); } clk = clock(); // create internal nodes vNodes = Bbl_ManDfs( p ); vFaninAigs = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Bbl_Obj_t *, vNodes, pObj, i ) { // collect fanin AIGs Vec_PtrClear( vFaninAigs ); Bbl_ObjForEachFanin( pObj, pFanin ) Vec_PtrPush( vFaninAigs, Vec_PtrEntry( vCopy, Bbl_ObjId(pFanin) ) ); // create the new node pObjNew = Dec_GraphToAig( pNtk, pFForms[Bbl_ObjFncHandle(pObj)], vFaninAigs ); Vec_PtrSetEntry( vCopy, Bbl_ObjId(pObj), pObjNew ); }
/**Function************************************************************* Synopsis [Expands the cut by adding the most closely related node.] Description [Returns 1 if the cut exists.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult ) { Aig_Obj_t * pObj, * pLeafBest; int i, LevelMax, ConeSize1, ConeSize2, ConeCur1, ConeCur2, ConeBest; // dereference the current cut LevelMax = 0; Vec_PtrForEachEntry( vLeaves, pObj, i ) LevelMax = AIG_MAX( LevelMax, (int)pObj->Level ); if ( LevelMax == 0 ) return 0; // dereference the cut ConeSize1 = Aig_NodeDeref_rec( pNode, 0 ); // try expanding each node in the boundary ConeBest = AIG_INFINITY; pLeafBest = NULL; Vec_PtrForEachEntry( vLeaves, pObj, i ) { if ( (int)pObj->Level != LevelMax ) continue; ConeCur1 = Aig_NodeDeref_rec( pObj, 0 ); if ( ConeBest > ConeCur1 ) { ConeBest = ConeCur1; pLeafBest = pObj; } ConeCur2 = Aig_NodeRef_rec( pObj, 0 ); assert( ConeCur1 == ConeCur2 ); } assert( pLeafBest != NULL ); assert( Aig_ObjIsNode(pLeafBest) ); // deref the best leaf ConeCur1 = Aig_NodeDeref_rec( pLeafBest, 0 ); // collect the cut nodes Vec_PtrClear( vResult ); Aig_ManIncrementTravId( p ); Aig_NodeMffsSupp_rec( p, pNode, 0, vResult, 1, pLeafBest ); // ref the nodes ConeCur2 = Aig_NodeRef_rec( pLeafBest, 0 ); assert( ConeCur1 == ConeCur2 ); // ref the original node ConeSize2 = Aig_NodeRef_rec( pNode, 0 ); assert( ConeSize1 == ConeSize2 ); return 1; }
/**Function************************************************************* Synopsis [Transforms the node to take fanout sharing into account.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Seq_NodeShareOne( Abc_Obj_t * pNode, Abc_InitType_t Init, Vec_Ptr_t * vNodes ) { Vec_Int_t * vNums = Seq_ObjLNums( pNode ); Vec_Ptr_t * vInits = Seq_NodeLats( pNode ); Abc_Obj_t * pFanout, * pBuffer; Abc_InitType_t Type, InitNew; int i; // collect the fanouts that satisfy the property (have initial value Init or DC) InitNew = ABC_INIT_DC; Vec_PtrClear( vNodes ); Abc_ObjForEachFanout( pNode, pFanout, i ) { if ( Seq_ObjFanoutL(pNode, pFanout) == 0 ) continue; Type = Seq_NodeGetInitLast( pFanout, Abc_ObjFanoutEdgeNum(pNode, pFanout) ); if ( Type == Init ) InitNew = Init; if ( Type == Init || Type == ABC_INIT_DC ) { Vec_PtrPush( vNodes, pFanout ); Seq_NodeDeleteLast( pFanout, Abc_ObjFanoutEdgeNum(pNode, pFanout) ); } } // create the new buffer pBuffer = Abc_NtkCreateNode( pNode->pNtk ); Abc_ObjAddFanin( pBuffer, pNode ); // grow storage for initial states Vec_PtrGrow( vInits, 2 * pBuffer->Id + 2 ); for ( i = Vec_PtrSize(vInits); i < 2 * (int)pBuffer->Id + 2; i++ ) Vec_PtrPush( vInits, NULL ); // grow storage for numbers of latches Vec_IntGrow( vNums, 2 * pBuffer->Id + 2 ); for ( i = Vec_IntSize(vNums); i < 2 * (int)pBuffer->Id + 2; i++ ) Vec_IntPush( vNums, 0 ); // insert the new latch Seq_NodeInsertFirst( pBuffer, 0, InitNew ); // redirect the fanouts Vec_PtrForEachEntry( vNodes, pFanout, i ) Abc_ObjPatchFanin( pFanout, pNode, pBuffer ); }
/**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 ); }
/**Function************************************************************* Synopsis [Adds a new target to the manager.] Description [The meaning of the parameters are: nog: number of gates that are in the targets, names: name array of gates, values: value array of the corresponding gates given in "names" to be solved. The relation of them is AND.] SideEffects [] SeeAlso [] ***********************************************************************/ int ABC_AddTarget( ABC_Manager mng, int nog, char ** names, int * values ) { Abc_Obj_t * pObj; int i; if ( nog < 1 ) { printf( "ABC_AddTarget: The target has no gates.\n" ); return 0; } // clear storage for the target mng->nog = 0; Vec_PtrClear( mng->vNodes ); Vec_IntClear( mng->vValues ); // save the target for ( i = 0; i < nog; i++ ) { if ( !stmm_lookup( mng->tName2Node, names[i], (char **)&pObj ) ) { printf( "ABC_AddTarget: The target gate \"%s\" is not in the network.\n", names[i] ); return 0; } Vec_PtrPush( mng->vNodes, pObj ); if ( values[i] < 0 || values[i] > 1 ) { printf( "ABC_AddTarget: The value of gate \"%s\" is not 0 or 1.\n", names[i] ); return 0; } Vec_IntPush( mng->vValues, values[i] ); } mng->nog = nog; return 1; }
/**Function************************************************************* Synopsis [Returns the AIG representation of the reduction formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage ) { Hop_Obj_t * pRes = NULL; int v, fCompl; char Symbol; // get the operation Symbol = *pFormula++; fCompl = ( Symbol == '~' ); if ( fCompl ) Symbol = *pFormula++; // check the operation if ( Symbol != '&' && Symbol != '|' && Symbol != '^' ) { sprintf( pErrorMessage, "Ver_FormulaReduction(): Unknown operation (%c)\n", Symbol ); return NULL; } // skip the brace while ( *pFormula++ != '{' ); // parse the names Vec_PtrClear( vNames ); while ( *pFormula != '}' ) { v = Ver_FormulaParserFindVar( pFormula, vNames ); pFormula += (int)(ABC_PTRUINT_T)Vec_PtrEntry( vNames, 2*v ); while ( *pFormula == ' ' || *pFormula == ',' ) pFormula++; } // compute the function if ( Symbol == '&' ) pRes = Hop_CreateAnd( (Hop_Man_t *)pMan, Vec_PtrSize(vNames)/2 ); else if ( Symbol == '|' ) pRes = Hop_CreateOr( (Hop_Man_t *)pMan, Vec_PtrSize(vNames)/2 ); else if ( Symbol == '^' ) pRes = Hop_CreateExor( (Hop_Man_t *)pMan, Vec_PtrSize(vNames)/2 ); return Hop_NotCond( pRes, fCompl ); }
/**Function************************************************************* Synopsis [Performs rewriting for one node.] Description [This procedure considers all the cuts computed for the node and tries to rewrite each of them using the "forest" of different AIG structures precomputed and stored in the RWR manager. Determines the best rewriting and computes the gain in the number of AIG nodes in the final network. In the end, p->vFanins contains information about the best cut that can be used for rewriting, while p->pGraph gives the decomposition dag (represented using decomposition graph data structure). Returns gain in the number of nodes or -1 if node cannot be rewritten.] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable ) { int fVeryVerbose = 0; Dec_Graph_t * pGraph; Cut_Cut_t * pCut;//, * pTemp; Abc_Obj_t * pFanin; unsigned uPhase; unsigned uTruthBest = 0; // Suppress "might be used uninitialized" unsigned uTruth; char * pPerm; int Required, nNodesSaved; int nNodesSaveCur = -1; // Suppress "might be used uninitialized" int i, GainCur, GainBest = -1; int clk, clk2;//, Counter; p->nNodesConsidered++; // get the required times Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY; // get the node's cuts clk = clock(); pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0, 0 ); assert( pCut != NULL ); p->timeCut += clock() - clk; //printf( " %d", Rwr_CutCountNumNodes(pNode, pCut) ); /* Counter = 0; for ( pTemp = pCut->pNext; pTemp; pTemp = pTemp->pNext ) Counter++; printf( "%d ", Counter ); */ // go through the cuts clk = clock(); for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) { // consider only 4-input cuts if ( pCut->nLeaves < 4 ) continue; // Cut_CutPrint( pCut, 0 ), printf( "\n" ); // get the fanin permutation uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); pPerm = p->pPerms4[ (int)p->pPerms[uTruth] ]; uPhase = p->pPhases[uTruth]; // collect fanins with the corresponding permutation/phase Vec_PtrClear( p->vFaninsCur ); Vec_PtrFill( p->vFaninsCur, (int)pCut->nLeaves, 0 ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { pFanin = Abc_NtkObj( pNode->pNtk, pCut->pLeaves[(int)pPerm[i]] ); if ( pFanin == NULL ) break; pFanin = Abc_ObjNotCond(pFanin, ((uPhase & (1<<i)) > 0) ); Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); } if ( i != (int)pCut->nLeaves ) { p->nCutsBad++; continue; } p->nCutsGood++; { int Counter = 0; Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) if ( Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) == 1 ) Counter++; if ( Counter > 2 ) continue; } clk2 = clock(); /* printf( "Considering: (" ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) printf( "%d ", Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) ); printf( ")\n" ); */ // mark the fanin boundary Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) Abc_ObjRegular(pFanin)->vFanouts.nSize++; // label MFFC with current ID Abc_NtkIncrementTravId( pNode->pNtk ); nNodesSaved = Abc_NodeMffcLabelAig( pNode ); // unmark the fanin boundary Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) Abc_ObjRegular(pFanin)->vFanouts.nSize--; p->timeMffc += clock() - clk2; // evaluate the cut clk2 = clock(); pGraph = Rwr_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur, fPlaceEnable ); p->timeEval += clock() - clk2; // check if the cut is better than the current best one if ( pGraph != NULL && GainBest < GainCur ) { // save this form nNodesSaveCur = nNodesSaved; GainBest = GainCur; p->pGraph = pGraph; p->fCompl = ((uPhase & (1<<4)) > 0); uTruthBest = 0xFFFF & *Cut_CutReadTruth(pCut); // collect fanins in the Vec_PtrClear( p->vFanins ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) Vec_PtrPush( p->vFanins, pFanin ); } }
/**Function************************************************************* Synopsis [Performs rewriting for one node.] Description [This procedure considers all the cuts computed for the node and tries to rewrite each of them using the "forest" of different AIG structures precomputed and stored in the RWR manager. Determines the best rewriting and computes the gain in the number of AIG nodes in the final network. In the end, p->vFanins contains information about the best cut that can be used for rewriting, while p->pGraph gives the decomposition dag (represented using decomposition graph data structure). Returns gain in the number of nodes or -1 if node cannot be rewritten.] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable ) { int fVeryVerbose = 0; Dec_Graph_t * pGraph; Cut_Cut_t * pCut;//, * pTemp; Abc_Obj_t * pFanin; unsigned uPhase, uTruthBest, uTruth; char * pPerm; int Required, nNodesSaved, nNodesSaveCur; int i, GainCur, GainBest = -1; int clk, clk2;//, Counter; p->nNodesConsidered++; // get the required times Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY; // get the node's cuts clk = clock(); pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0, 0 ); assert( pCut != NULL ); p->timeCut += clock() - clk; //printf( " %d", Rwr_CutCountNumNodes(pNode, pCut) ); /* Counter = 0; for ( pTemp = pCut->pNext; pTemp; pTemp = pTemp->pNext ) Counter++; printf( "%d ", Counter ); */ // go through the cuts clk = clock(); for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) { // consider only 4-input cuts if ( pCut->nLeaves < 4 ) continue; // Cut_CutPrint( pCut, 0 ), printf( "\n" ); // get the fanin permutation uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); pPerm = p->pPerms4[ p->pPerms[uTruth] ]; uPhase = p->pPhases[uTruth]; // collect fanins with the corresponding permutation/phase Vec_PtrClear( p->vFaninsCur ); Vec_PtrFill( p->vFaninsCur, (int)pCut->nLeaves, 0 ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { pFanin = Abc_NtkObj( pNode->pNtk, pCut->pLeaves[pPerm[i]] ); if ( pFanin == NULL ) break; pFanin = Abc_ObjNotCond(pFanin, ((uPhase & (1<<i)) > 0) ); Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); } if ( i != (int)pCut->nLeaves ) { p->nCutsBad++; continue; } p->nCutsGood++; { int Counter = 0; Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) if ( Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) == 1 ) Counter++; if ( Counter > 2 ) continue; } clk2 = clock(); /* printf( "Considering: (" ); Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) printf( "%d ", Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) ); printf( ")\n" ); */ // mark the fanin boundary Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) Abc_ObjRegular(pFanin)->vFanouts.nSize++; // label MFFC with current ID Abc_NtkIncrementTravId( pNode->pNtk ); nNodesSaved = Abc_NodeMffcLabelAig( pNode ); // unmark the fanin boundary Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) Abc_ObjRegular(pFanin)->vFanouts.nSize--; p->timeMffc += clock() - clk2; // evaluate the cut clk2 = clock(); pGraph = Rwr_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur, fPlaceEnable ); p->timeEval += clock() - clk2; // check if the cut is better than the current best one if ( pGraph != NULL && GainBest < GainCur ) { // save this form nNodesSaveCur = nNodesSaved; GainBest = GainCur; p->pGraph = pGraph; p->fCompl = ((uPhase & (1<<4)) > 0); uTruthBest = 0xFFFF & *Cut_CutReadTruth(pCut); // collect fanins in the Vec_PtrClear( p->vFanins ); Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) Vec_PtrPush( p->vFanins, pFanin ); } } p->timeRes += clock() - clk; if ( GainBest == -1 ) return -1; /* if ( GainBest > 0 ) { printf( "Class %d ", p->pMap[uTruthBest] ); printf( "Gain = %d. Node %d : ", GainBest, pNode->Id ); Vec_PtrForEachEntry( p->vFanins, pFanin, i ) printf( "%d ", Abc_ObjRegular(pFanin)->Id ); Dec_GraphPrint( stdout, p->pGraph, NULL, NULL ); printf( "\n" ); } */ // printf( "%d", nNodesSaveCur - GainBest ); /* if ( GainBest > 0 ) { if ( Rwr_CutIsBoolean( pNode, p->vFanins ) ) printf( "b" ); else { printf( "Node %d : ", pNode->Id ); Vec_PtrForEachEntry( p->vFanins, pFanin, i ) printf( "%d ", Abc_ObjRegular(pFanin)->Id ); printf( "a" ); } } */ /* if ( GainBest > 0 ) if ( p->fCompl ) printf( "c" ); else printf( "." ); */ // copy the leaves Vec_PtrForEachEntry( p->vFanins, pFanin, i ) Dec_GraphNode(p->pGraph, i)->pFunc = pFanin; /* printf( "(" ); Vec_PtrForEachEntry( p->vFanins, pFanin, i ) printf( " %d", Abc_ObjRegular(pFanin)->vFanouts.nSize - 1 ); printf( " ) " ); */ // printf( "%d ", Rwr_NodeGetDepth_rec( pNode, p->vFanins ) ); p->nScores[p->pMap[uTruthBest]]++; p->nNodesGained += GainBest; if ( fUseZeros || GainBest > 0 ) { p->nNodesRewritten++; } // report the progress if ( fVeryVerbose && GainBest > 0 ) { printf( "Node %6s : ", Abc_ObjName(pNode) ); printf( "Fanins = %d. ", p->vFanins->nSize ); printf( "Save = %d. ", nNodesSaveCur ); printf( "Add = %d. ", nNodesSaveCur-GainBest ); printf( "GAIN = %d. ", GainBest ); printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 ); printf( "Class = %d. ", p->pMap[uTruthBest] ); printf( "\n" ); } return GainBest; }
/**Function************************************************************* Synopsis [Performs induction by unrolling timeframes backward.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManInduction( Aig_Man_t * p, int nFramesMax, int nConfMax, int fUnique, int fUniqueAll, int fGetCex, int fVerbose, int fVeryVerbose ) { sat_solver * pSat; Aig_Man_t * pAigPart; Cnf_Dat_t * pCnfPart; Vec_Int_t * vTopVarNums, * vState, * vTopVarIds = NULL; Vec_Ptr_t * vTop, * vBot; Aig_Obj_t * pObjPi, * pObjPiCopy, * pObjPo; int i, k, f, clk, Lits[2], status, RetValue, nSatVarNum, nConfPrev; int nOldSize, iReg, iLast, fAdded, nConstrs = 0, nClauses = 0; assert( fUnique == 0 || fUniqueAll == 0 ); assert( Saig_ManPoNum(p) == 1 ); Aig_ManSetPioNumbers( p ); // start the top by including the PO vBot = Vec_PtrAlloc( 100 ); vTop = Vec_PtrAlloc( 100 ); vState = Vec_IntAlloc( 1000 ); Vec_PtrPush( vTop, Aig_ManPo(p, 0) ); // start the array of CNF variables vTopVarNums = Vec_IntAlloc( 100 ); // start the solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, 1000 ); // iterate backward unrolling RetValue = -1; nSatVarNum = 0; if ( fVerbose ) printf( "Induction parameters: FramesMax = %5d. ConflictMax = %6d.\n", nFramesMax, nConfMax ); for ( f = 0; ; f++ ) { if ( f > 0 ) { Aig_ManStop( pAigPart ); Cnf_DataFree( pCnfPart ); } clk = clock(); // get the bottom Aig_SupportNodes( p, (Aig_Obj_t **)Vec_PtrArray(vTop), Vec_PtrSize(vTop), vBot ); // derive AIG for the part between top and bottom pAigPart = Aig_ManDupSimpleDfsPart( p, vBot, vTop ); // convert it into CNF pCnfPart = Cnf_Derive( pAigPart, Aig_ManPoNum(pAigPart) ); Cnf_DataLift( pCnfPart, nSatVarNum ); nSatVarNum += pCnfPart->nVars; nClauses += pCnfPart->nClauses; // remember top frame var IDs if ( fGetCex && vTopVarIds == NULL ) { vTopVarIds = Vec_IntStartFull( Aig_ManPiNum(p) ); Aig_ManForEachPi( p, pObjPi, i ) { if ( pObjPi->pData == NULL ) continue; pObjPiCopy = (Aig_Obj_t *)pObjPi->pData; assert( Aig_ObjIsPi(pObjPiCopy) ); if ( Saig_ObjIsPi(p, pObjPi) ) Vec_IntWriteEntry( vTopVarIds, Aig_ObjPioNum(pObjPi) + Saig_ManRegNum(p), pCnfPart->pVarNums[Aig_ObjId(pObjPiCopy)] ); else if ( Saig_ObjIsLo(p, pObjPi) ) Vec_IntWriteEntry( vTopVarIds, Aig_ObjPioNum(pObjPi) - Saig_ManPiNum(p), pCnfPart->pVarNums[Aig_ObjId(pObjPiCopy)] ); else assert( 0 ); } } // stitch variables of top and bot assert( Aig_ManPoNum(pAigPart)-1 == Vec_IntSize(vTopVarNums) ); Aig_ManForEachPo( pAigPart, pObjPo, i ) { if ( i == 0 ) { // do not perform inductive strengthening // if ( f > 0 ) // continue; // add topmost literal Lits[0] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], f>0 ); if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) ) assert( 0 ); nClauses++; continue; } Lits[0] = toLitCond( Vec_IntEntry(vTopVarNums, i-1), 0 ); Lits[1] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); Lits[0] = toLitCond( Vec_IntEntry(vTopVarNums, i-1), 1 ); Lits[1] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); nClauses += 2; } // add CNF to the SAT solver for ( i = 0; i < pCnfPart->nClauses; i++ ) if ( !sat_solver_addclause( pSat, pCnfPart->pClauses[i], pCnfPart->pClauses[i+1] ) ) break; if ( i < pCnfPart->nClauses ) { // printf( "SAT solver became UNSAT after adding clauses.\n" ); RetValue = 1; break; } // create new set of POs to derive new top Vec_PtrClear( vTop ); Vec_PtrPush( vTop, Aig_ManPo(p, 0) ); Vec_IntClear( vTopVarNums ); nOldSize = Vec_IntSize(vState); Vec_IntFillExtra( vState, nOldSize + Aig_ManRegNum(p), -1 ); Vec_PtrForEachEntry( Aig_Obj_t *, vBot, pObjPi, i ) { assert( Aig_ObjIsPi(pObjPi) ); if ( Saig_ObjIsLo(p, pObjPi) ) { pObjPiCopy = (Aig_Obj_t *)pObjPi->pData; assert( pObjPiCopy != NULL ); Vec_PtrPush( vTop, Saig_ObjLoToLi(p, pObjPi) ); Vec_IntPush( vTopVarNums, pCnfPart->pVarNums[pObjPiCopy->Id] ); iReg = pObjPi->PioNum - Saig_ManPiNum(p); assert( iReg >= 0 && iReg < Aig_ManRegNum(p) ); Vec_IntWriteEntry( vState, nOldSize+iReg, pCnfPart->pVarNums[pObjPiCopy->Id] ); } }
/**Function************************************************************* Synopsis [Collects POs in the transitive fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ManCollectFanoutPos( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout ) { Vec_PtrClear( vFanout ); Aig_ManIncrementTravId( pAig ); Cgt_ManCollectFanoutPos_rec( pAig, pObj, vFanout ); }
/**Function************************************************************* Synopsis [Detects multi-input gate rooted at this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ObjCollectMulti( Hop_Obj_t * pRoot, Vec_Ptr_t * vSuper ) { assert( !Hop_IsComplement(pRoot) ); Vec_PtrClear( vSuper ); Hop_ObjCollectMulti_rec( pRoot, pRoot, vSuper ); }
/**Function************************************************************* Synopsis [Parser of the formula encountered in assign statements.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage ) { char * pTemp; Hop_Obj_t * bFunc, * bTemp; int nParans, Flag; int Oper, Oper1, Oper2; int v; // clear the stacks and the names Vec_PtrClear( vNames ); Vec_PtrClear( vStackFn ); Vec_IntClear( vStackOp ); if ( !strcmp(pFormula, "0") || !strcmp(pFormula, "1\'b0") ) return Hop_ManConst0((Hop_Man_t *)pMan); if ( !strcmp(pFormula, "1") || !strcmp(pFormula, "1\'b1") ) return Hop_ManConst1((Hop_Man_t *)pMan); // make sure that the number of opening and closing parantheses is the same nParans = 0; for ( pTemp = pFormula; *pTemp; pTemp++ ) if ( *pTemp == '(' ) nParans++; else if ( *pTemp == ')' ) nParans--; if ( nParans != 0 ) { sprintf( pErrorMessage, "Parse_FormulaParser(): Different number of opening and closing parantheses ()." ); return NULL; } // add parantheses pTemp = pFormula + strlen(pFormula) + 2; *pTemp-- = 0; *pTemp = ')'; while ( --pTemp != pFormula ) *pTemp = *(pTemp - 1); *pTemp = '('; // perform parsing Flag = VER_PARSE_FLAG_START; for ( pTemp = pFormula; *pTemp; pTemp++ ) { switch ( *pTemp ) { // skip all spaces, tabs, and end-of-lines case ' ': case '\t': case '\r': case '\n': continue; /* // treat Constant 0 as a variable case VER_PARSE_SYM_CONST0: Vec_PtrPush( vStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( Hop_ManConst0(pMan) ); if ( Flag == VER_PARSE_FLAG_VAR ) { sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 0." ); Flag = VER_PARSE_FLAG_ERROR; break; } Flag = VER_PARSE_FLAG_VAR; break; // the same for Constant 1 case VER_PARSE_SYM_CONST1: Vec_PtrPush( vStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( Hop_ManConst1(pMan) ); if ( Flag == VER_PARSE_FLAG_VAR ) { sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 1." ); Flag = VER_PARSE_FLAG_ERROR; break; } Flag = VER_PARSE_FLAG_VAR; break; */ case VER_PARSE_SYM_NEGBEF1: case VER_PARSE_SYM_NEGBEF2: if ( Flag == VER_PARSE_FLAG_VAR ) {// if NEGBEF follows a variable, AND is assumed sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before negation." ); Flag = VER_PARSE_FLAG_ERROR; break; } Vec_IntPush( vStackOp, VER_PARSE_OPER_NEG ); break; case VER_PARSE_SYM_AND: case VER_PARSE_SYM_OR: case VER_PARSE_SYM_XOR: case VER_PARSE_SYM_MUX1: case VER_PARSE_SYM_MUX2: if ( Flag != VER_PARSE_FLAG_VAR ) { sprintf( pErrorMessage, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR." ); Flag = VER_PARSE_FLAG_ERROR; break; } if ( *pTemp == VER_PARSE_SYM_AND ) Vec_IntPush( vStackOp, VER_PARSE_OPER_AND ); else if ( *pTemp == VER_PARSE_SYM_OR ) Vec_IntPush( vStackOp, VER_PARSE_OPER_OR ); else if ( *pTemp == VER_PARSE_SYM_XOR ) Vec_IntPush( vStackOp, VER_PARSE_OPER_XOR ); else if ( *pTemp == VER_PARSE_SYM_MUX1 ) Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); // else if ( *pTemp == VER_PARSE_SYM_MUX2 ) // Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); Flag = VER_PARSE_FLAG_OPER; break; case VER_PARSE_SYM_OPEN: if ( Flag == VER_PARSE_FLAG_VAR ) { sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before a paranthesis." ); Flag = VER_PARSE_FLAG_ERROR; break; } Vec_IntPush( vStackOp, VER_PARSE_OPER_MARK ); // after an opening bracket, it feels like starting over again Flag = VER_PARSE_FLAG_START; break; case VER_PARSE_SYM_CLOSE: if ( Vec_IntSize( vStackOp ) ) { while ( 1 ) { if ( !Vec_IntSize( vStackOp ) ) { sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" ); Flag = VER_PARSE_FLAG_ERROR; break; } Oper = Vec_IntPop( vStackOp ); if ( Oper == VER_PARSE_OPER_MARK ) break; // skip the second MUX operation // if ( Oper == VER_PARSE_OPER_MUX2 ) // { // Oper = Vec_IntPop( vStackOp ); // assert( Oper == VER_PARSE_OPER_MUX1 ); // } // perform the given operation if ( Ver_FormulaParserTopOper( (Hop_Man_t *)pMan, vStackFn, Oper ) == NULL ) { sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); return NULL; } } } else { sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" ); Flag = VER_PARSE_FLAG_ERROR; break; } if ( Flag != VER_PARSE_FLAG_ERROR ) Flag = VER_PARSE_FLAG_VAR; break; default: // scan the next name v = Ver_FormulaParserFindVar( pTemp, vNames ); if ( *pTemp == '\\' ) pTemp++; pTemp += (int)(ABC_PTRUINT_T)Vec_PtrEntry( vNames, 2*v ) - 1; // assume operation AND, if vars follow one another if ( Flag == VER_PARSE_FLAG_VAR ) { sprintf( pErrorMessage, "Parse_FormulaParser(): Incorrect state." ); return NULL; } bTemp = Hop_IthVar( (Hop_Man_t *)pMan, v ); Vec_PtrPush( vStackFn, bTemp ); // Cudd_Ref( bTemp ); Flag = VER_PARSE_FLAG_VAR; break; } if ( Flag == VER_PARSE_FLAG_ERROR ) break; // error exit else if ( Flag == VER_PARSE_FLAG_START ) continue; // go on parsing else if ( Flag == VER_PARSE_FLAG_VAR ) while ( 1 ) { // check if there are negations in the OpStack if ( !Vec_IntSize(vStackOp) ) break; Oper = Vec_IntPop( vStackOp ); if ( Oper != VER_PARSE_OPER_NEG ) { Vec_IntPush( vStackOp, Oper ); break; } else { // Vec_PtrPush( vStackFn, Cudd_Not(Vec_PtrPop(vStackFn)) ); Vec_PtrPush( vStackFn, Hop_Not((Hop_Obj_t *)Vec_PtrPop(vStackFn)) ); } } else // if ( Flag == VER_PARSE_FLAG_OPER ) while ( 1 ) { // execute all the operations in the OpStack // with precedence higher or equal than the last one Oper1 = Vec_IntPop( vStackOp ); // the last operation if ( !Vec_IntSize(vStackOp) ) { // if it is the only operation, push it back Vec_IntPush( vStackOp, Oper1 ); break; } Oper2 = Vec_IntPop( vStackOp ); // the operation before the last one if ( Oper2 >= Oper1 && !(Oper1 == Oper2 && Oper1 == VER_PARSE_OPER_MUX) ) { // if Oper2 precedence is higher or equal, execute it if ( Ver_FormulaParserTopOper( (Hop_Man_t *)pMan, vStackFn, Oper2 ) == NULL ) { sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); return NULL; } Vec_IntPush( vStackOp, Oper1 ); // push the last operation back } else { // if Oper2 precedence is lower, push them back and done Vec_IntPush( vStackOp, Oper2 ); Vec_IntPush( vStackOp, Oper1 ); break; } } } if ( Flag != VER_PARSE_FLAG_ERROR ) { if ( Vec_PtrSize(vStackFn) ) { bFunc = (Hop_Obj_t *)Vec_PtrPop(vStackFn); if ( !Vec_PtrSize(vStackFn) ) if ( !Vec_IntSize(vStackOp) ) { // Cudd_Deref( bFunc ); return bFunc; } else sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the operation stack\n" ); else sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the function stack\n" ); } else sprintf( pErrorMessage, "Parse_FormulaParser(): The input string is empty\n" ); } // Cudd_Ref( bFunc ); // Cudd_RecursiveDeref( dd, bFunc ); return NULL; }