ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Implements the function.] Description [Returns the node implementing this function.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Lpk_ImplementFun( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * p ) { extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); unsigned * pTruth; Abc_Obj_t * pObjNew; int i; if ( p->fMark ) pMan->nMuxes++; else pMan->nDsds++; // create the new node pObjNew = Abc_NtkCreateNode( pNtk ); for ( i = 0; i < (int)p->nVars; i++ ) Abc_ObjAddFanin( pObjNew, Abc_ObjRegular((Abc_Obj_t *)Vec_PtrEntry(vLeaves, p->pFanins[i])) ); Abc_ObjSetLevel( pObjNew, Abc_ObjLevelNew(pObjNew) ); // assign the node's function pTruth = Lpk_FunTruth(p, 0); if ( p->nVars == 0 ) { pObjNew->pData = Hop_NotCond( Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc), !(pTruth[0] & 1) ); return pObjNew; } if ( p->nVars == 1 ) { pObjNew->pData = Hop_NotCond( Hop_ManPi((Hop_Man_t *)pNtk->pManFunc, 0), (pTruth[0] & 1) ); return pObjNew; } // create the logic function pObjNew->pData = Kit_TruthToHop( (Hop_Man_t *)pNtk->pManFunc, pTruth, p->nVars, NULL ); return pObjNew; }
/**Function************************************************************* Synopsis [Cleans the data pointers for the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManCleanData( Hop_Man_t * p ) { Hop_Obj_t * pObj; int i; p->nTravIds = 1; Hop_ManConst1(p)->pData = NULL; Hop_ManForEachPi( p, pObj, i ) pObj->pData = NULL; Hop_ManForEachPo( p, pObj, i ) pObj->pData = NULL; Hop_ManForEachNode( p, pObj, i ) pObj->pData = NULL; }
/**Function************************************************************* Synopsis [Computes the max number of levels in the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_ManCountLevels( Hop_Man_t * p ) { Vec_Ptr_t * vNodes; Hop_Obj_t * pObj; int i, LevelsMax, Level0, Level1; // initialize the levels Hop_ManConst1(p)->pData = NULL; Hop_ManForEachPi( p, pObj, i ) pObj->pData = NULL; // compute levels in a DFS order vNodes = Hop_ManDfs( p ); Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) { Level0 = (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData; Level1 = (int)(ABC_PTRUINT_T)Hop_ObjFanin1(pObj)->pData; pObj->pData = (void *)(ABC_PTRUINT_T)(1 + Hop_ObjIsExor(pObj) + Abc_MaxInt(Level0, Level1)); }
/**Function************************************************************* Synopsis [Converts AIG from Aig_Man_t into Hop_Obj_t.] Description [Assumes that Aig_Man_t has exactly one primary outputs. Returns the pointer to the root node (Hop_Obj_t) in Hop_Man_t.] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_MfsConvertAigToHop( Aig_Man_t * pMan, Hop_Man_t * pHop ) { Aig_Obj_t * pRoot, * pObj; int i; assert( Aig_ManPoNum(pMan) == 1 ); pRoot = Aig_ManPo( pMan, 0 ); // check the case of a constant if ( Aig_ObjIsConst1( Aig_ObjFanin0(pRoot) ) ) return Hop_NotCond( Hop_ManConst1(pHop), Aig_ObjFaninC0(pRoot) ); // set the PI mapping Aig_ManCleanData( pMan ); Aig_ManForEachPi( pMan, pObj, i ) pObj->pData = Hop_IthVar( pHop, i ); // construct the AIG Abc_MfsConvertAigToHop_rec( Aig_ObjFanin0(pRoot), pHop ); return Hop_NotCond( (Hop_Obj_t *)Aig_ObjFanin0(pRoot)->pData, Aig_ObjFaninC0(pRoot) ); }
/**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Man_t * Abc_NtkToMini( Abc_Ntk_t * pNtk ) { Hop_Man_t * pMan; Abc_Obj_t * pObj; int i; // create the manager pMan = Hop_ManStart(); // transfer the pointers to the basic nodes Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Hop_ManConst1(pMan); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Hop_ObjCreatePi(pMan); // perform the conversion of the internal nodes (assumes DFS ordering) Abc_NtkForEachNode( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Hop_And( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj), (Hop_Obj_t *)Abc_ObjChild1Copy(pObj) ); // create the POs Abc_NtkForEachCo( pNtk, pObj, i ) Hop_ObjCreatePo( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj) ); Hop_ManCleanup( pMan ); return pMan; }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transforms the decomposition graph into the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Kit_GraphToHopInternal( Hop_Man_t * pMan, Kit_Graph_t * pGraph ) { Kit_Node_t * pNode = NULL; Hop_Obj_t * pAnd0, * pAnd1; int i; // check for constant function if ( Kit_GraphIsConst(pGraph) ) return Hop_NotCond( Hop_ManConst1(pMan), Kit_GraphIsComplement(pGraph) ); // check for a literal if ( Kit_GraphIsVar(pGraph) ) return Hop_NotCond( (Hop_Obj_t *)Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) ); // build the AIG nodes corresponding to the AND gates of the graph Kit_GraphForEachNode( pGraph, pNode, i ) { pAnd0 = Hop_NotCond( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); pAnd1 = Hop_NotCond( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 ); }
// pNtk->nLatches = Aig_ManRegNum(p); // pNtk->nTruePis = Nwk_ManCiNum(pNtk) - pNtk->nLatches; // pNtk->nTruePos = Nwk_ManCoNum(pNtk) - pNtk->nLatches; Aig_ManForEachObj( p, pObj, i ) { pIfObj = (If_Obj_t *)Vec_PtrEntry( vAigToIf, i ); if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) ) continue; if ( Aig_ObjIsNode(pObj) ) { pCutBest = If_ObjCutBest( pIfObj ); nLeaves = If_CutLeaveNum( pCutBest ); ppLeaves = If_CutLeaves( pCutBest ); // create node pObjNew = Nwk_ManCreateNode( pNtk, nLeaves, pIfObj->nRefs ); for ( k = 0; k < nLeaves; k++ ) { pObjRepr = (Aig_Obj_t *)Vec_PtrEntry( vIfToAig, ppLeaves[k] ); Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)pObjRepr->pData ); } // get the functionality pObjNew->pFunc = Nwk_NodeIfToHop( pNtk->pManHop, pIfMan, pIfObj ); } else if ( Aig_ObjIsCi(pObj) ) pObjNew = Nwk_ManCreateCi( pNtk, pIfObj->nRefs ); else if ( Aig_ObjIsCo(pObj) ) { pObjNew = Nwk_ManCreateCo( pNtk ); pObjNew->fInvert = Aig_ObjFaninC0(pObj); Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData ); //printf( "%d ", pObjNew->Id ); } else if ( Aig_ObjIsConst1(pObj) ) { pObjNew = Nwk_ManCreateNode( pNtk, 0, pIfObj->nRefs ); pObjNew->pFunc = Hop_ManConst1( pNtk->pManHop ); } else assert( 0 ); pObj->pData = pObjNew; }
int Abc_NtkTestTimNodeStrash( Gia_Man_t * pGia, Abc_Obj_t * pNode ) { Hop_Man_t * pMan; Hop_Obj_t * pRoot; Abc_Obj_t * pFanin; int i; assert( Abc_ObjIsNode(pNode) ); assert( Abc_NtkIsAigLogic(pNode->pNtk) ); // get the local AIG manager and the local root node pMan = (Hop_Man_t *)pNode->pNtk->pManFunc; pRoot = (Hop_Obj_t *)pNode->pData; // check the constant case if ( Abc_NodeIsConst(pNode) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) ) return !Hop_IsComplement(pRoot); // set elementary variables Abc_ObjForEachFanin( pNode, pFanin, i ) Hop_IthVar(pMan, i)->iData = pFanin->iTemp; // strash the AIG of this node Abc_NtkTestTimNodeStrash_rec( pGia, Hop_Regular(pRoot) ); Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); // return the final node with complement if needed return Abc_LitNotCond( Hop_Regular(pRoot)->iData, Hop_IsComplement(pRoot) ); }
/**Function************************************************************* Synopsis [Stops the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManStop( Hop_Man_t * p ) { Hop_Obj_t * pObj; int i; // make sure the nodes have clean marks pObj = Hop_ManConst1(p); assert( !pObj->fMarkA && !pObj->fMarkB ); Hop_ManForEachPi( p, pObj, i ) assert( !pObj->fMarkA && !pObj->fMarkB ); Hop_ManForEachPo( p, pObj, i ) assert( !pObj->fMarkA && !pObj->fMarkB ); Hop_ManForEachNode( p, pObj, i ) assert( !pObj->fMarkA && !pObj->fMarkB ); // print time if ( p->time1 ) { PRT( "time1", p->time1 ); } if ( p->time2 ) { PRT( "time2", p->time2 ); } // Hop_TableProfile( p ); if ( p->vChunks ) Hop_ManStopMemory( p ); if ( p->vPis ) Vec_PtrFree( p->vPis ); if ( p->vPos ) Vec_PtrFree( p->vPos ); if ( p->vObjs ) Vec_PtrFree( p->vObjs ); free( p->pTable ); free( p ); }
/**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromMini( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Hop_Obj_t * pObj; int i; // perform strashing pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // transfer the pointers to the basic nodes Hop_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); Hop_ManForEachPi( pMan, pObj, i ) pObj->pData = Abc_NtkCi(pNtkNew, i); // rebuild the AIG vNodes = Hop_ManDfs( pMan ); Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); Vec_PtrFree( vNodes ); // connect the PO nodes Hop_ManForEachPo( pMan, pObj, i ) Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Hop_ObjChild0Copy(pObj) ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkFromMini(): Network check has failed.\n" ); return pNtkNew; }
/**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; }