/**CFile**************************************************************** FileName [mpmAbc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [Interface with ABC data structures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpmAbc.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig/gia/gia.h" #include "mpmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mig_ManCreateChoices( Mig_Man_t * pMig, Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; assert( Mig_ManObjNum(pMig) == Gia_ManObjNum(p) ); assert( Vec_IntSize(&pMig->vSibls) == 0 ); Vec_IntFill( &pMig->vSibls, Gia_ManObjNum(p), 0 ); Gia_ManMarkFanoutDrivers( p ); Gia_ManForEachObj( p, pObj, i ) { Gia_ObjSetPhase( p, pObj ); assert( Abc_Lit2Var(pObj->Value) == i ); Mig_ObjSetPhase( Mig_ManObj(pMig, i), pObj->fPhase ); if ( Gia_ObjSibl(p, i) && pObj->fMark0 ) { Gia_Obj_t * pSibl, * pPrev; for ( pPrev = pObj, pSibl = Gia_ObjSiblObj(p, i); pSibl; pPrev = pSibl, pSibl = Gia_ObjSiblObj(p, Gia_ObjId(p, pSibl)) ) Mig_ObjSetSiblId( Mig_ManObj(pMig, Abc_Lit2Var(pPrev->Value)), Abc_Lit2Var(pSibl->Value) ); pMig->nChoices++; } } Gia_ManCleanMark0( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mig_ObjFanin0Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); } static inline int Mig_ObjFanin1Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) ); } Mig_Man_t * Mig_ManCreate( void * pGia ) { Gia_Man_t * p = (Gia_Man_t *)pGia; Mig_Man_t * pNew; Gia_Obj_t * pObj; int i; pNew = Mig_ManStart(); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsMuxId(p, i) ) pObj->Value = Mig_ManAppendMux( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin2Copy(p, pObj) ); else if ( Gia_ObjIsXor(pObj) ) pObj->Value = Mig_ManAppendXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Mig_ManAppendAnd( pNew, Mig_ObjFanin0Copy(pObj), Mig_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCi(pObj) ) pObj->Value = Mig_ManAppendCi( pNew ); else if ( Gia_ObjIsCo(pObj) ) pObj->Value = Mig_ManAppendCo( pNew, Mig_ObjFanin0Copy(pObj) ); else assert( 0 ); } Mig_ManSetRegNum( pNew, Gia_ManRegNum(p) ); if ( Gia_ManHasChoices(p) ) Mig_ManCreateChoices( pNew, p ); return pNew; } /**Function************************************************************* Synopsis [Recursively derives the local AIG for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Mpm_CutDataInt( Mpm_Cut_t * pCut ) { return pCut->hNext; } static inline void Mpm_CutSetDataInt( Mpm_Cut_t * pCut, int Data ) { pCut->hNext = Data; } int Mpm_ManNodeIfToGia_rec( Gia_Man_t * pNew, Mpm_Man_t * pMan, Mig_Obj_t * pObj, Vec_Ptr_t * vVisited, int fHash ) { Mig_Obj_t * pTemp; Mpm_Cut_t * pCut; int iFunc, iFunc0, iFunc1, iFunc2 = 0; assert( fHash == 0 ); // get the best cut pCut = Mpm_ObjCutBestP( pMan, pObj ); // if the cut is visited, return the result if ( Mpm_CutDataInt(pCut) ) return Mpm_CutDataInt(pCut); // mark the node as visited Vec_PtrPush( vVisited, pCut ); // insert the worst case Mpm_CutSetDataInt( pCut, ~0 ); // skip in case of primary input if ( Mig_ObjIsCi(pObj) ) return Mpm_CutDataInt(pCut); // compute the functions of the children for ( pTemp = pObj; pTemp; pTemp = Mig_ObjSibl(pTemp) ) { iFunc0 = Mpm_ManNodeIfToGia_rec( pNew, pMan, Mig_ObjFanin0(pTemp), vVisited, fHash ); if ( iFunc0 == ~0 ) continue; iFunc1 = Mpm_ManNodeIfToGia_rec( pNew, pMan, Mig_ObjFanin1(pTemp), vVisited, fHash ); if ( iFunc1 == ~0 ) continue; if ( Mig_ObjIsNode3(pTemp) ) { iFunc2 = Mpm_ManNodeIfToGia_rec( pNew, pMan, Mig_ObjFanin2(pTemp), vVisited, fHash ); if ( iFunc2 == ~0 ) continue; iFunc2 = Abc_LitNotCond(iFunc2, Mig_ObjFaninC2(pTemp)); } iFunc0 = Abc_LitNotCond(iFunc0, Mig_ObjFaninC0(pTemp)); iFunc1 = Abc_LitNotCond(iFunc1, Mig_ObjFaninC1(pTemp)); // both branches are solved if ( fHash ) { if ( Mig_ObjIsMux(pTemp) ) iFunc = Gia_ManHashMux( pNew, iFunc2, iFunc1, iFunc0 ); else if ( Mig_ObjIsXor(pTemp) ) iFunc = Gia_ManHashXor( pNew, iFunc0, iFunc1 ); else iFunc = Gia_ManHashAnd( pNew, iFunc0, iFunc1 ); } else { if ( Mig_ObjIsMux(pTemp) ) iFunc = Gia_ManAppendMux( pNew, iFunc2, iFunc1, iFunc0 ); else if ( Mig_ObjIsXor(pTemp) ) iFunc = Gia_ManAppendXor( pNew, iFunc0, iFunc1 ); else iFunc = Gia_ManAppendAnd( pNew, iFunc0, iFunc1 ); } if ( Mig_ObjPhase(pTemp) != Mig_ObjPhase(pObj) ) iFunc = Abc_LitNot(iFunc); Mpm_CutSetDataInt( pCut, iFunc ); break; } return Mpm_CutDataInt(pCut); } int Mpm_ManNodeIfToGia( Gia_Man_t * pNew, Mpm_Man_t * pMan, Mig_Obj_t * pObj, Vec_Int_t * vLeaves, int fHash ) { Mpm_Cut_t * pCut; Mig_Obj_t * pFanin; int i, iRes; // get the best cut pCut = Mpm_ObjCutBestP( pMan, pObj ); assert( pCut->nLeaves > 1 ); // set the leaf variables Mpm_CutForEachLeaf( pMan->pMig, pCut, pFanin, i ) Mpm_CutSetDataInt( Mpm_ObjCutBestP(pMan, pFanin), Vec_IntEntry(vLeaves, i) ); // recursively compute the function while collecting visited cuts Vec_PtrClear( pMan->vTemp ); iRes = Mpm_ManNodeIfToGia_rec( pNew, pMan, pObj, pMan->vTemp, fHash ); if ( iRes == ~0 ) { Abc_Print( -1, "Mpm_ManNodeIfToGia(): Computing local AIG has failed.\n" ); return ~0; } // clean the cuts Mpm_CutForEachLeaf( pMan->pMig, pCut, pFanin, i ) Mpm_CutSetDataInt( Mpm_ObjCutBestP(pMan, pFanin), 0 ); Vec_PtrForEachEntry( Mpm_Cut_t *, pMan->vTemp, pCut, i ) Mpm_CutSetDataInt( pCut, 0 ); return iRes; } void * Mpm_ManFromIfLogic( Mpm_Man_t * pMan ) { Gia_Man_t * pNew; Mpm_Cut_t * pCutBest; Mig_Obj_t * pObj, * pFanin; Vec_Int_t * vMapping, * vMapping2, * vPacking = NULL; Vec_Int_t * vLeaves, * vLeaves2, * vCover; word uTruth, * pTruth = &uTruth; int i, k, Entry, iLitNew; // assert( !pMan->pPars->fDeriveLuts || pMan->pPars->fTruth ); // start mapping and packing vMapping = Vec_IntStart( Mig_ManObjNum(pMan->pMig) ); vMapping2 = Vec_IntStart( 1 ); if ( 0 ) // pMan->pPars->fDeriveLuts && pMan->pPars->pLutStruct ) { vPacking = Vec_IntAlloc( 1000 ); Vec_IntPush( vPacking, 0 ); } // create new manager pNew = Gia_ManStart( Mig_ManObjNum(pMan->pMig) ); // iterate through nodes used in the mapping vCover = Vec_IntAlloc( 1 << 16 ); vLeaves = Vec_IntAlloc( 16 ); vLeaves2 = Vec_IntAlloc( 16 ); Mig_ManCleanCopy( pMan->pMig ); Mig_ManForEachObj( pMan->pMig, pObj ) { if ( !Mpm_ObjMapRef(pMan, pObj) && !Mig_ObjIsTerm(pObj) ) continue; if ( Mig_ObjIsNode(pObj) ) { // collect leaves of the best cut Vec_IntClear( vLeaves ); pCutBest = Mpm_ObjCutBestP( pMan, pObj ); Mpm_CutForEachLeaf( pMan->pMig, pCutBest, pFanin, k ) Vec_IntPush( vLeaves, Mig_ObjCopy(pFanin) ); if ( pMan->pPars->fDeriveLuts && (pMan->pPars->fUseTruth || pMan->pPars->fUseDsd) ) { extern int Gia_ManFromIfLogicNode( void * p, Gia_Man_t * pNew, int iObj, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp, word * pRes, char * pStr, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking, int fCheck75, int fCheck44e ); if ( pMan->pPars->fUseTruth ) pTruth = Mpm_CutTruth(pMan, Abc_Lit2Var(pCutBest->iFunc)); else uTruth = Mpm_CutTruthFromDsd( pMan, pCutBest, Abc_Lit2Var(pCutBest->iFunc) ); // Kit_DsdPrintFromTruth( pTruth, Vec_IntSize(vLeaves) ); printf( "\n" ); // perform decomposition of the cut iLitNew = Gia_ManFromIfLogicNode( NULL, pNew, Mig_ObjId(pObj), vLeaves, vLeaves2, pTruth, NULL, vCover, vMapping, vMapping2, vPacking, 0, 0 ); iLitNew = Abc_LitNotCond( iLitNew, pCutBest->fCompl ^ Abc_LitIsCompl(pCutBest->iFunc) ); } else { // perform one of the two types of mapping: with and without structures iLitNew = Mpm_ManNodeIfToGia( pNew, pMan, pObj, vLeaves, 0 ); // write mapping Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLitNew), Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); Vec_IntForEachEntry( vLeaves, Entry, k ) assert( Abc_Lit2Var(Entry) < Abc_Lit2Var(iLitNew) ); Vec_IntForEachEntry( vLeaves, Entry, k ) Vec_IntPush( vMapping2, Abc_Lit2Var(Entry) ); Vec_IntPush( vMapping2, Abc_Lit2Var(iLitNew) ); } } else if ( Mig_ObjIsCi(pObj) ) iLitNew = Gia_ManAppendCi(pNew); else if ( Mig_ObjIsCo(pObj) ) iLitNew = Gia_ManAppendCo( pNew, Abc_LitNotCond(Mig_ObjCopy(Mig_ObjFanin0(pObj)), Mig_ObjFaninC0(pObj)) ); else if ( Mig_ObjIsConst0(pObj) ) { iLitNew = 0; // create const LUT Vec_IntWriteEntry( vMapping, 0, Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, 0 ); Vec_IntPush( vMapping2, 0 ); } else assert( 0 ); Mig_ObjSetCopy( pObj, iLitNew ); } Vec_IntFree( vCover ); Vec_IntFree( vLeaves ); Vec_IntFree( vLeaves2 ); // printf( "Mapping array size: IfMan = %d. Gia = %d. Increase = %.2f\n", // Mig_ManObjNum(pMan), Gia_ManObjNum(pNew), 1.0 * Gia_ManObjNum(pNew) / Mig_ManObjNum(pMan) ); // finish mapping if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) ) Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) ); else Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 ); assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) ); Vec_IntForEachEntry( vMapping, Entry, i ) if ( Entry > 0 ) Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) ); Vec_IntAppend( vMapping, vMapping2 ); Vec_IntFree( vMapping2 ); // attach mapping and packing assert( pNew->vMapping == NULL ); assert( pNew->vPacking == NULL ); pNew->vMapping = vMapping; pNew->vPacking = vPacking; // verify that COs have mapping { Gia_Obj_t * pObj; Gia_ManForEachCo( pNew, pObj, i ) assert( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) || Gia_ObjIsLut(pNew, Gia_ObjFaninId0p(pNew, pObj)) ); } return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* void Mig_ManTest2( Gia_Man_t * pGia ) { extern int Gia_ManSuppSizeTest( Gia_Man_t * p ); Mig_Man_t * p; Gia_ManSuppSizeTest( pGia ); p = Mig_ManCreate( pGia ); Mig_ManSuppSizeTest( p ); Mig_ManStop( p ); } */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END