/**CFile**************************************************************** FileName [giaShrink7.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Implementation of DAG-aware unmapping for 6-input cuts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaShrink6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/vec/vecHash.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // operation manager typedef struct Unm_Man_t_ Unm_Man_t; struct Unm_Man_t_ { Gia_Man_t * pGia; // user's AIG Gia_Man_t * pNew; // constructed AIG Hash_IntMan_t * pHash; // hash table int nNewSize; // expected size of new manager Vec_Int_t * vUsed; // used nodes Vec_Int_t * vId2Used; // mapping of obj IDs into used node IDs Vec_Wrd_t * vTruths; // truth tables Vec_Int_t * vLeaves; // temporary storage for leaves abctime clkStart; // starting the clock }; extern word Shr_ManComputeTruth6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Wrd_t * vTruths ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Unm_Man_t * Unm_ManAlloc( Gia_Man_t * pGia ) { Unm_Man_t * p; p = ABC_CALLOC( Unm_Man_t, 1 ); p->clkStart = Abc_Clock(); p->nNewSize = 3 * Gia_ManObjNum(pGia) / 2; p->pGia = pGia; p->pNew = Gia_ManStart( p->nNewSize ); p->pNew->pName = Abc_UtilStrsav( pGia->pName ); p->pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); Gia_ManHashAlloc( p->pNew ); Gia_ManCleanLevels( p->pNew, p->nNewSize ); // allocate traversal IDs p->pNew->nObjs = p->nNewSize; Gia_ManIncrementTravId( p->pNew ); p->pNew->nObjs = 1; // start hashing p->pHash = Hash_IntManStart( 1000 ); // truth tables p->vLeaves = Vec_IntStart( 10 ); return p; } Gia_Man_t * Unm_ManFree( Unm_Man_t * p ) { Gia_Man_t * pTemp = p->pNew; p->pNew = NULL; Gia_ManHashStop( pTemp ); Vec_IntFreeP( &pTemp->vLevels ); Gia_ManSetRegNum( pTemp, Gia_ManRegNum(p->pGia) ); // truth tables Vec_WrdFreeP( &p->vTruths ); Vec_IntFreeP( &p->vLeaves ); Vec_IntFreeP( &p->vUsed ); Vec_IntFreeP( &p->vId2Used ); // free data structures Hash_IntManStop( p->pHash ); ABC_FREE( p ); Gia_ManStop( pTemp ); pTemp = NULL; return pTemp; } /**Function************************************************************* Synopsis [Computes information about node pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Unm_ManPrintPairStats( Hash_IntMan_t * pHash, int nTotal0, int nPairs0, int nPairs1, int fUseLit ) { int i, Num, nRefs, nPairs = 0, nTotal = 0, Counter[21] = {0}; Num = Hash_IntManEntryNum( pHash ); for ( i = 1; i <= Num; i++ ) { nRefs = Abc_MinInt( 20, Hash_IntObjData2(pHash, i) ); nTotal += nRefs; Counter[nRefs]++; nPairs += (nRefs > 1); /* if ( fUseLit ) printf( "(%c%c, %c%c) %d\n", Abc_LitIsCompl(Hash_IntObjData0(pHash, i)-2) ? '!' : ' ', 'a' + Abc_Lit2Var(Hash_IntObjData0(pHash, i)-2), Abc_LitIsCompl(Hash_IntObjData1(pHash, i)-2) ? '!' : ' ', 'a' + Abc_Lit2Var(Hash_IntObjData1(pHash, i)-2), nRefs ); else printf( "( %c, %c) %d\n", 'a' + Hash_IntObjData0(pHash, i)-1, 'a' + Hash_IntObjData1(pHash, i)-1, nRefs ); */ // printf( "(%4d, %4d) %d\n", Hash_IntObjData0(pHash, i), Hash_IntObjData1(pHash, i), nRefs ); } printf( "Statistics for pairs appearing less than 20 times:\n" ); for ( i = 0; i < 21; i++ ) if ( Counter[i] > 0 ) printf( "%3d : %7d %7.2f %%\n", i, Counter[i], 100.0 * Counter[i] * i / Abc_MaxInt(nTotal, 1) ); printf( "Pairs: Total = %8d Init = %8d %7.2f %% Final = %8d %7.2f %% Real = %8d %7.2f %%\n", nTotal0, nPairs0, 100.0 * nPairs0 / Abc_MaxInt(nTotal0, 1), nPairs, 100.0 * nPairs / Abc_MaxInt(nTotal0, 1), nPairs1, 100.0 * nPairs1 / Abc_MaxInt(nTotal0, 1) ); return nPairs; } Vec_Int_t * Unm_ManComputePairs( Unm_Man_t * p, int fVerbose ) { Gia_Obj_t * pObj; Vec_Int_t * vPairs = Vec_IntAlloc( 1000 ); Vec_Int_t * vNum2Obj = Vec_IntStart( 1 ); Hash_IntMan_t * pHash = Hash_IntManStart( 1000 ); int nTotal = 0, nPairs0 = 0, nPairs = 0; int i, k, j, FanK, FanJ, Num, nRefs; Gia_ManSetRefsMapped( p->pGia ); Gia_ManForEachLut( p->pGia, i ) { nTotal += Gia_ObjLutSize(p->pGia, i) * (Gia_ObjLutSize(p->pGia, i) - 1) / 2; pObj = Gia_ManObj( p->pGia, i ); // collect leaves of this gate Vec_IntClear( p->vLeaves ); Gia_LutForEachFanin( p->pGia, i, Num, k ) if ( Gia_ObjRefNumId(p->pGia, Num) > 1 ) Vec_IntPush( p->vLeaves, Num ); if ( Vec_IntSize(p->vLeaves) < 2 ) continue; nPairs0 += Vec_IntSize(p->vLeaves) * (Vec_IntSize(p->vLeaves) - 1) / 2; // enumerate pairs Vec_IntForEachEntry( p->vLeaves, FanK, k ) Vec_IntForEachEntryStart( p->vLeaves, FanJ, j, k+1 ) { if ( FanK > FanJ ) ABC_SWAP( int, FanK, FanJ ); Num = Hash_Int2ManInsert( pHash, FanK, FanJ, 0 ); nRefs = Hash_Int2ObjInc(pHash, Num); if ( nRefs == 0 ) { assert( Num == Hash_IntManEntryNum(pHash) ); assert( Num == Vec_IntSize(vNum2Obj) ); Vec_IntPush( vNum2Obj, i ); continue; } if ( nRefs == 1 ) { assert( Num < Vec_IntSize(vNum2Obj) ); Vec_IntPush( vPairs, Vec_IntEntry(vNum2Obj, Num) ); Vec_IntPush( vPairs, FanK ); Vec_IntPush( vPairs, FanJ); } Vec_IntPush( vPairs, i ); Vec_IntPush( vPairs, FanK ); Vec_IntPush( vPairs, FanJ ); } } Vec_IntFree( vNum2Obj ); if ( fVerbose ) nPairs = Unm_ManPrintPairStats( pHash, nTotal, nPairs0, Vec_IntSize(vPairs) / 3, 0 ); Hash_IntManStop( pHash ); return vPairs; } // finds used nodes Vec_Int_t * Unm_ManFindUsedNodes( Vec_Int_t * vPairs, int nObjs ) { Vec_Int_t * vNodes = Vec_IntAlloc( 1000 ); Vec_Str_t * vMarks = Vec_StrStart( nObjs ); int i; for ( i = 0; i < Vec_IntSize(vPairs); i += 3 ) Vec_StrWriteEntry( vMarks, Vec_IntEntry(vPairs, i), 1 ); for ( i = 0; i < nObjs; i++ ) if ( Vec_StrEntry( vMarks, i ) ) Vec_IntPush( vNodes, i ); Vec_StrFree( vMarks ); printf( "The number of used nodes = %d\n", Vec_IntSize(vNodes) ); return vNodes; } // computes truth table for selected nodes Vec_Wrd_t * Unm_ManComputeTruths( Unm_Man_t * p ) { Vec_Wrd_t * vTruthsTemp, * vTruths; int i, k, iObj, iNode; word uTruth; vTruths = Vec_WrdAlloc( Vec_IntSize(p->vUsed) ); vTruthsTemp = Vec_WrdStart( Gia_ManObjNum(p->pGia) ); Vec_IntForEachEntry( p->vUsed, iObj, i ) { assert( Gia_ObjIsLut(p->pGia, iObj) ); // collect leaves of this gate Vec_IntClear( p->vLeaves ); Gia_LutForEachFanin( p->pGia, iObj, iNode, k ) Vec_IntPush( p->vLeaves, iNode ); assert( Vec_IntSize(p->vLeaves) <= 6 ); // compute truth table uTruth = Shr_ManComputeTruth6( p->pGia, Gia_ManObj(p->pGia, iObj), p->vLeaves, vTruthsTemp ); Vec_WrdPush( vTruths, uTruth ); // if ( i % 100 == 0 ) // Kit_DsdPrintFromTruth( (unsigned *)&uTruth, 6 ), printf( "\n" ); } Vec_WrdFreeP( &vTruthsTemp ); return vTruths; } /**Function************************************************************* Synopsis [Collects decomposable pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Unm_ManCollectDecomp( Unm_Man_t * p, Vec_Int_t * vPairs, int fVerbose ) { word uTruth; int nNonUnique = 0; int i, k, j, s, iObj, iNode, iUsed, FanK, FanJ, Res, Num, nRefs; Vec_Int_t * vNum2Obj = Vec_IntStart( 1 ); Vec_Int_t * vPairs2 = Vec_IntAlloc( 1000 ); assert( Hash_IntManEntryNum(p->pHash) == 0 ); for ( i = 0; i < Vec_IntSize(vPairs); i += 3 ) { iObj = Vec_IntEntry( vPairs, i ); assert( Gia_ObjIsLut(p->pGia, iObj) ); // collect leaves of this gate Vec_IntClear( p->vLeaves ); Gia_LutForEachFanin( p->pGia, iObj, iNode, s ) Vec_IntPush( p->vLeaves, iNode ); assert( Vec_IntSize(p->vLeaves) <= 6 ); FanK = Vec_IntEntry(vPairs, i+1); FanJ = Vec_IntEntry(vPairs, i+2); k = Vec_IntFind( p->vLeaves, FanK ); j = Vec_IntFind( p->vLeaves, FanJ ); assert( FanK < FanJ ); iUsed = Vec_IntEntry( p->vId2Used, iObj ); uTruth = Vec_WrdEntry( p->vTruths, iUsed ); Res = Abc_TtCheckDsdAnd( uTruth, k, j, NULL ); if ( Res == -1 ) continue; // derive literals FanK = Abc_Var2Lit( FanK, ((Res >> 0) & 1) ); FanJ = Abc_Var2Lit( FanJ, ((Res >> 1) & 1) ); if ( Res == 4 ) ABC_SWAP( int, FanK, FanJ ); Num = Hash_Int2ManInsert( p->pHash, FanK, FanJ, 0 ); nRefs = Hash_Int2ObjInc(p->pHash, Num); if ( nRefs == 0 ) { assert( Num == Hash_IntManEntryNum(p->pHash) ); assert( Num == Vec_IntSize(vNum2Obj) ); Vec_IntPush( vNum2Obj, iObj ); continue; } if ( nRefs == 1 ) { assert( Num < Vec_IntSize(vNum2Obj) ); Vec_IntPush( vPairs2, Vec_IntEntry(vNum2Obj, Num) ); Vec_IntPush( vPairs2, FanK ); Vec_IntPush( vPairs2, FanJ ); nNonUnique++; } Vec_IntPush( vPairs2, iObj ); Vec_IntPush( vPairs2, FanK ); Vec_IntPush( vPairs2, FanJ ); } Vec_IntFree( vNum2Obj ); if ( fVerbose ) Unm_ManPrintPairStats( p->pHash, Vec_IntSize(vPairs)/3, Hash_IntManEntryNum(p->pHash), Vec_IntSize(vPairs2)/3, 1 ); // Hash_IntManStop( pHash ); return vPairs2; } /**Function************************************************************* Synopsis [Compute truth tables for the selected nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Unm_ManWork( Unm_Man_t * p ) { Vec_Int_t * vPairs, * vPairs2; // find the duplicated pairs vPairs = Unm_ManComputePairs( p, 1 ); // find the used nodes p->vUsed = Unm_ManFindUsedNodes( vPairs, Gia_ManObjNum(p->pGia) ); p->vId2Used = Vec_IntInvert( p->vUsed, -1 ); Vec_IntFillExtra( p->vId2Used, Gia_ManObjNum(p->pGia), -1 ); // compute truth tables for used nodes p->vTruths = Unm_ManComputeTruths( p ); // derive new pairs vPairs2 = Unm_ManCollectDecomp( p, vPairs, 1 ); Vec_IntFreeP( &vPairs ); Vec_IntFreeP( &vPairs2 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Unm_ManTest( Gia_Man_t * pGia ) { Unm_Man_t * p; p = Unm_ManAlloc( pGia ); Unm_ManWork( p ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); return Unm_ManFree( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END