/**CFile**************************************************************** FileName [amapGraph.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [Internal AIG manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapGraph.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManSetupObj( Amap_Man_t * p ) { Amap_Obj_t * pObj; pObj = (Amap_Obj_t *)Aig_MmFixedEntryFetch( p->pMemObj ); memset( pObj, 0, sizeof(Amap_Obj_t) ); pObj->nFouts[0] = 1; // needed for flow to work in the first pass pObj->Id = Vec_PtrSize(p->vObjs); Vec_PtrPush( p->vObjs, pObj ); return pObj; } /**Function************************************************************* Synopsis [Creates constant 1 node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManCreateConst1( Amap_Man_t * p ) { Amap_Obj_t * pObj; pObj = Amap_ManSetupObj( p ); pObj->Type = AMAP_OBJ_CONST1; pObj->fPhase = 1; p->nObjs[AMAP_OBJ_CONST1]++; return pObj; } /**Function************************************************************* Synopsis [Creates primary input.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManCreatePi( Amap_Man_t * p ) { Amap_Obj_t * pObj; pObj = Amap_ManSetupObj( p ); pObj->Type = AMAP_OBJ_PI; pObj->IdPio = Vec_PtrSize( p->vPis ); Vec_PtrPush( p->vPis, pObj ); p->nObjs[AMAP_OBJ_PI]++; return pObj; } /**Function************************************************************* Synopsis [Creates primary output with the given driver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManCreatePo( Amap_Man_t * p, Amap_Obj_t * pFan0 ) { Amap_Obj_t * pObj; pObj = Amap_ManSetupObj( p ); pObj->IdPio = Vec_PtrSize( p->vPos ); Vec_PtrPush( p->vPos, pObj ); pObj->Type = AMAP_OBJ_PO; pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; pObj->Level = Amap_Regular(pFan0)->Level; if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; assert( p->nLevelMax < 4094 ); // 2^12-2 p->nObjs[AMAP_OBJ_PO]++; return pObj; } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManCreateAnd( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 ) { Amap_Obj_t * pObj; pObj = Amap_ManSetupObj( p ); pObj->Type = AMAP_OBJ_AND; pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++; assert( Abc_Lit2Var(pObj->Fan[0]) != Abc_Lit2Var(pObj->Fan[1]) ); pObj->fPhase = Amap_ObjPhaseReal(pFan0) & Amap_ObjPhaseReal(pFan1); pObj->Level = 1 + Abc_MaxInt( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; assert( p->nLevelMax < 4094 ); // 2^12-2 p->nObjs[AMAP_OBJ_AND]++; return pObj; } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManCreateXor( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 ) { Amap_Obj_t * pObj; pObj = Amap_ManSetupObj( p ); pObj->Type = AMAP_OBJ_XOR; pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++; pObj->fPhase = Amap_ObjPhaseReal(pFan0) ^ Amap_ObjPhaseReal(pFan1); pObj->Level = 2 + Abc_MaxInt( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; assert( p->nLevelMax < 4094 ); // 2^12-2 p->nObjs[AMAP_OBJ_XOR]++; return pObj; } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManCreateMux( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pFanC ) { Amap_Obj_t * pObj; pObj = Amap_ManSetupObj( p ); pObj->Type = AMAP_OBJ_MUX; pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++; pObj->Fan[2] = Amap_ObjToLit(pFanC); Amap_Regular(pFanC)->nRefs++; pObj->fPhase = (Amap_ObjPhaseReal(pFan1) & Amap_ObjPhaseReal(pFanC)) | (Amap_ObjPhaseReal(pFan0) & ~Amap_ObjPhaseReal(pFanC)); pObj->Level = Abc_MaxInt( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); pObj->Level = 2 + Abc_MaxInt( pObj->Level, Amap_Regular(pFanC)->Level ); if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; assert( p->nLevelMax < 4094 ); // 2^12-2 p->nObjs[AMAP_OBJ_MUX]++; return pObj; } /**Function************************************************************* Synopsis [Creates the choice node.] Description [Should be called after the equivalence class nodes are linked.] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManCreateChoice( Amap_Man_t * p, Amap_Obj_t * pObj ) { Amap_Obj_t * pTemp; // mark the node as a representative if its class // assert( pObj->fRepr == 0 ); pObj->fRepr = 1; // update the level of this node (needed for correct required time computation) for ( pTemp = pObj; pTemp; pTemp = Amap_ObjChoice(p, pTemp) ) { pObj->Level = Abc_MaxInt( pObj->Level, pTemp->Level ); // pTemp->nVisits++; pTemp->nVisitsCopy++; } // mark the largest level if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; assert( p->nLevelMax < 4094 ); // 2^12-2 } /**Function************************************************************* Synopsis [Creates XOR/MUX choices for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManCreateXorChoices( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pChoices[] ) { pChoices[0] = Amap_ManCreateXor( p, pFan0, pFan1 ); pChoices[1] = Amap_ManCreateXor( p, Amap_Not(pFan0), pFan1 ); pChoices[2] = Amap_ManCreateXor( p, pFan0, Amap_Not(pFan1) ); pChoices[3] = Amap_ManCreateXor( p, Amap_Not(pFan0), Amap_Not(pFan1) ); } /**Function************************************************************* Synopsis [Creates XOR/MUX choices for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManCreateMuxChoices( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pFanC, Amap_Obj_t * pChoices[] ) { pChoices[0] = Amap_ManCreateMux( p, pFan0, pFan1, pFanC ); pChoices[1] = Amap_ManCreateMux( p, Amap_Not(pFan0), Amap_Not(pFan1), pFanC ); pChoices[2] = Amap_ManCreateMux( p, pFan1, pFan0, Amap_Not(pFanC) ); pChoices[3] = Amap_ManCreateMux( p, Amap_Not(pFan1), Amap_Not(pFan0), Amap_Not(pFanC) ); } /**Function************************************************************* Synopsis [Drags pointer out through the copy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Amap_Obj_t * Amap_AndToObj( Aig_Obj_t * pObj ) { return Amap_NotCond( (Amap_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj) ); } /**Function************************************************************* Synopsis [Starts the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManGetLast_rec( Amap_Man_t * p, Amap_Obj_t * pObj ) { if ( pObj->Equiv == 0 ) return pObj; return Amap_ManGetLast_rec( p, Amap_ObjChoice(p, pObj) ); } /**Function************************************************************* Synopsis [Starts the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManCreate( Amap_Man_t * p, Aig_Man_t * pAig ) { Vec_Ptr_t * vNodes; Amap_Obj_t * pChoices[4]; Aig_Obj_t * pObj, * pFanin, * pPrev, * pFan0, * pFan1, * pFanC; int i, fChoices; if ( pAig->pEquivs ) vNodes = Aig_ManDfsChoices( pAig ); else vNodes = Aig_ManDfs( pAig, 1 ); p->pConst1 = Amap_ManCreateConst1( p ); // print warning about excessive memory usage if ( p->pPars->fVerbose ) { if ( 1.0 * Aig_ManObjNum(pAig) * sizeof(Amap_Obj_t) / (1<<30) > 0.1 ) printf( "Warning: Mapper allocates %.3f GB for subject graph with %d objects.\n", 1.0 * Aig_ManObjNum(pAig) * sizeof(Amap_Obj_t) / (1<<30), Aig_ManObjNum(pAig) ); } // create PIs and remember them in the old nodes Aig_ManCleanData(pAig); Aig_ManConst1(pAig)->pData = Amap_ManConst1( p ); Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Amap_ManCreatePi( p ); // load the AIG into the mapper Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { fChoices = 0; if ( p->fUseXor && Aig_ObjRecognizeExor(pObj, &pFan0, &pFan1 ) ) { Amap_ManCreateXorChoices( p, Amap_AndToObj(pFan0), Amap_AndToObj(pFan1), pChoices ); fChoices = 1; } else if ( p->fUseMux && Aig_ObjIsMuxType(pObj) ) { pFanC = Aig_ObjRecognizeMux( pObj, &pFan1, &pFan0 ); Amap_ManCreateMuxChoices( p, Amap_AndToObj(pFan0), Amap_AndToObj(pFan1), Amap_AndToObj(pFanC), pChoices ); fChoices = 1; } pObj->pData = Amap_ManCreateAnd( p, (Amap_Obj_t *)Aig_ObjChild0Copy(pObj), (Amap_Obj_t *)Aig_ObjChild1Copy(pObj) ); if ( fChoices ) { p->nChoicesAdded++; Amap_ObjSetChoice( (Amap_Obj_t *)pObj->pData, pChoices[0] ); Amap_ObjSetChoice( pChoices[0], pChoices[1] ); Amap_ObjSetChoice( pChoices[1], pChoices[2] ); Amap_ObjSetChoice( pChoices[2], pChoices[3] ); Amap_ManCreateChoice( p, (Amap_Obj_t *)pObj->pData ); } if ( Aig_ObjIsChoice( pAig, pObj ) ) { // assert( !fChoices ); p->nChoicesGiven++; for ( pPrev = pObj, pFanin = Aig_ObjEquiv(pAig, pObj); pFanin; pPrev = pFanin, pFanin = Aig_ObjEquiv(pAig, pFanin) ) { ((Amap_Obj_t *)pFanin->pData)->fRepr = 0; Amap_ObjSetChoice( Amap_ManGetLast_rec(p, (Amap_Obj_t *)pPrev->pData), (Amap_Obj_t *)pFanin->pData ); } Amap_ManCreateChoice( p, (Amap_Obj_t *)pObj->pData ); } } Vec_PtrFree( vNodes ); // set the primary outputs without copying the phase Aig_ManForEachCo( pAig, pObj, i ) pObj->pData = Amap_ManCreatePo( p, (Amap_Obj_t *)Aig_ObjChild0Copy(pObj) ); if ( p->pPars->fVerbose ) printf( "Performing mapping with %d given and %d created choices.\n", p->nChoicesGiven, p->nChoicesAdded ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END