diff --git a/src/aig/gia/giaCut.c b/src/aig/gia/giaCut.c index 3051fb13b..8788614f5 100644 --- a/src/aig/gia/giaCut.c +++ b/src/aig/gia/giaCut.c @@ -30,7 +30,7 @@ ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// #define GIA_MAX_CUTSIZE 8 -#define GIA_MAX_CUTNUM 65 +#define GIA_MAX_CUTNUM 257 #define GIA_MAX_TT_WORDS ((GIA_MAX_CUTSIZE > 6) ? 1 << (GIA_MAX_CUTSIZE-6) : 1) #define GIA_CUT_NO_LEAF 0xF @@ -1116,6 +1116,39 @@ Vec_Ptr_t * Gia_ManMatchCutsArray( Vec_Ptr_t * vTtMems, Gia_Man_t * pGia, int nC } return vRes; } +Vec_Ptr_t * Gia_ManMatchCutsMany( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, int nFuncs, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ) +{ + Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, fVerbose ); + Vec_Int_t * vLevel; int i, j, k, * pCut; + abctime clkStart = Abc_Clock(); + assert( Abc_Truth6WordNum(nCutSize) == Vec_MemEntrySize(vTtMem) ); + Vec_Ptr_t * vRes = Vec_PtrAlloc( nFuncs ); + for ( i = 0; i < nFuncs; i++ ) + Vec_PtrPush( vRes, Vec_WecAlloc(10) ); + Vec_WecForEachLevel( p->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) + { + Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] > 1 ) + { + word * pTruth = Vec_MemReadEntry( p->vTtMem, Abc_Lit2Var(pCut[pCut[0]+1]) ); + assert( (pTruth[0] & 1) == 0 ); + int * pSpot = Vec_MemHashLookup( vTtMem, pTruth ); + if ( *pSpot == -1 ) + continue; + int iFunc = vMap ? Vec_IntEntry( vMap, *pSpot ) : 0; + assert( iFunc < nFuncs ); + Vec_Wec_t * vCuts = (Vec_Wec_t *)Vec_PtrEntry( vRes, iFunc ); + vLevel = Vec_WecPushLevel( vCuts ); + Vec_IntPush( vLevel, i ); + for ( j = 1; j <= pCut[0]; j++ ) + Vec_IntPush( vLevel, pCut[j] ); + break; + } + } + Gia_StoFree( p ); + if ( fVerbose ) + Abc_PrintTime( 1, "Cut matching time", Abc_Clock() - clkStart ); + return vRes; +} /**Function************************************************************* @@ -1239,6 +1272,96 @@ void Gia_ManMatchCones( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutSize, int Abc_PrintTime( 1, "Total computation time", Abc_Clock() - clkStart ); } +/**Function************************************************************* + + Synopsis [Function enumeration.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManMatchConesMinimizeTts( Vec_Wrd_t * vSims, int nVarsMax ) +{ + int nVars = 0; + int nWordsMax = Abc_Truth6WordNum( nVarsMax ), nWords; + int i, k = 0, nTruths = Vec_WrdSize(vSims) / nWordsMax; + assert( nTruths * nWordsMax == Vec_WrdSize(vSims) ); + // support-minimize and find the largest supp size + for ( i = 0; i < nTruths; i++ ) { + word * pTruth = Vec_WrdEntryP( vSims, i * nWordsMax ); + int nVarsCur = Abc_TtMinBase( pTruth, NULL, nVarsMax, nVarsMax ); + nVars = Abc_MaxInt( nVars, nVarsCur ); + } + // remap truth tables + nWords = Abc_Truth6WordNum( nVars ); + for ( i = 0; i < nTruths; i++ ) { + word * pTruth = Vec_WrdEntryP( vSims, i * nWordsMax ); + word * pTruth2 = Vec_WrdEntryP( vSims, k * nWords ); + if ( Abc_TtSupportSize(pTruth, nVars) < 3 ) + continue; + memmove( pTruth2, pTruth, nWords * sizeof(word) ); + k++; + if ( 0 ) { + extern void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ); + printf( "Type%d : ", i ); + Extra_PrintHexadecimal( stdout, (unsigned *)pTruth2, nVars ); + printf( "\n" ); + } + } + Vec_WrdShrink ( vSims, k * nWords ); + return nVars; +} +void Gia_ManMatchConesOutputPrint( Vec_Ptr_t * p, int fVerbose ) +{ + Vec_Wec_t * vCuts; int i; + printf( "Nodes with matching cuts:\n" ); + Vec_PtrForEachEntry( Vec_Wec_t *, p, vCuts, i ) { + if ( fVerbose ) { + printf( "Type %d:\n", i ); + Vec_WecPrint( vCuts, 0 ); + } + else + printf( "Type %d present in %d cuts\n", i, Vec_WecSize(vCuts) ); + } +} +void Gia_ManMatchConesOutputFree( Vec_Ptr_t * p ) +{ + Vec_Wec_t * vCuts; int i; + Vec_PtrForEachEntry( Vec_Wec_t *, p, vCuts, i ) + Vec_WecFree( vCuts ); + Vec_PtrFree( p ); +} +void Gia_ManMatchConesOutput( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutNum, int fVerbose ) +{ + abctime clkStart = Abc_Clock(); + extern Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int_t ** pvMap, int fVerbose ); + Vec_Wrd_t * vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(pSmall) ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( pSmall, vSimsPi, 1 ); + int nVars = Gia_ManMatchConesMinimizeTts( vSims, Gia_ManCiNum(pSmall) ); + Vec_WrdFree( vSimsPi ); + if ( nVars > 10 ) { + printf( "Some output functions have support size more than 10.\n" ); + Vec_WrdFree( vSims ); + return; + } + Vec_Int_t * vMap = NULL; + Vec_Mem_t * vTtMem = Dau_CollectNpnFunctionsArray( vSims, nVars, &vMap, fVerbose ); + int nFuncs = Vec_WrdSize(vSims) / Abc_Truth6WordNum(nVars); + assert( Vec_WrdSize(vSims) == nFuncs * Abc_Truth6WordNum(nVars) ); + Vec_WrdFree( vSims ); + printf( "Using %d output functions with the support size between 3 and %d.\n", nFuncs, nVars ); + Vec_Ptr_t * vRes = Gia_ManMatchCutsMany( vTtMem, vMap, nFuncs, pBig, nVars, nCutNum, fVerbose ); + Vec_MemHashFree( vTtMem ); + Vec_MemFree( vTtMem ); + Vec_IntFree( vMap ); + Gia_ManMatchConesOutputPrint( vRes, fVerbose ); + Gia_ManMatchConesOutputFree( vRes ); + Abc_PrintTime( 1, "Total computation time", Abc_Clock() - clkStart ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index cdf8531e3..8324c67d9 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -54369,10 +54369,10 @@ int Abc_CommandAbc9FunTrace( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Vec_Mem_t * Dau_CollectNpnFunctions( word * p, int nVars, int fVerbose ); extern void Gia_ManMatchCuts( Vec_Mem_t * vTtMem, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ); - int c, nVars, nVars2, nCutNum = 8, nCutSize = 0, nNumFuncs = 5, nNumCones = 3, fVerbose = 0; word * pTruth = NULL; + int c, nVars, nVars2, nCutNum = 8, nCutSize = 0, nNumFuncs = 5, nNumCones = 3, fOutputs = 0, fVerbose = 0; word * pTruth = NULL; char * pStr = NULL; Vec_Mem_t * vTtMem = NULL; Gia_Man_t * pTemp; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CKNMvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "CKNMovh" ) ) != EOF ) { switch ( c ) { @@ -54420,6 +54420,9 @@ int Abc_CommandAbc9FunTrace( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nNumCones < 0 ) goto usage; break; + case 'o': + fOutputs ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -54442,16 +54445,27 @@ int Abc_CommandAbc9FunTrace( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( strstr(argv[globalUtilOptind], ".aig") ) { // the entry on the command line is an AIGER file extern void Gia_ManMatchCones( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutSize, int nCutNum, int nNumFuncs, int nNumCones, int fVerbose ); - if ( nCutSize == 0 ) { - Abc_Print( -1, "Abc_CommandAbc9FunTrace(): The LUT size for profiling should be given on the command line.\n" ); - return 0; - } + extern void Gia_ManMatchConesOutput( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutNum, int fVerbose ); pTemp = Gia_AigerRead( argv[globalUtilOptind], 0, 0, 0 ); if ( pTemp == NULL ) { Abc_Print( -1, "Abc_CommandAbc9FunTrace(): Cannot read input AIG \"%s\".\n", argv[globalUtilOptind] ); return 0; } - Gia_ManMatchCones( pAbc->pGia, pTemp, nCutSize, nCutNum, nNumFuncs, nNumCones, fVerbose ); + if ( fOutputs ) { + if ( Gia_ManCiNum(pTemp) > 16 ) { + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): The AIG \"%s\" has more than 16 primary inputs.\n", argv[globalUtilOptind] ); + Gia_ManStop( pTemp ); + return 0; + } + Gia_ManMatchConesOutput( pAbc->pGia, pTemp, nCutNum, fVerbose ); + } + else { + if ( nCutSize == 0 ) { + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): The LUT size for profiling should be given on the command line.\n" ); + return 0; + } + Gia_ManMatchCones( pAbc->pGia, pTemp, nCutSize, nCutNum, nNumFuncs, nNumCones, fVerbose ); + } Gia_ManStop( pTemp ); return 0; } @@ -54480,12 +54494,13 @@ int Abc_CommandAbc9FunTrace( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &funtrace [-CKNM num] [-vh] { or }\n" ); + Abc_Print( -2, "usage: &funtrace [-CKNM num] [-ovh] { or }\n" ); Abc_Print( -2, "\t traces the presence of the function in the current AIG\n" ); Abc_Print( -2, "\t-C num : the number of cuts to compute at each node [default = %d]\n", nCutNum ); Abc_Print( -2, "\t-K num : the LUT size to use when is given [default = %d]\n", nCutSize ); Abc_Print( -2, "\t-N num : the number of functions to use when is given [default = %d]\n", nNumFuncs ); Abc_Print( -2, "\t-M num : the number of logic cones to use when is given [default = %d]\n", nNumCones ); + Abc_Print( -2, "\t-o : toggles using AIG output functions instead of frequent cut functions [default = %s]\n", fOutputs ? "yes": "no" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose ? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : truth table in the hexadecimal notation used for tracing\n"); diff --git a/src/opt/dau/dauNpn.c b/src/opt/dau/dauNpn.c index 8f0f4fb73..a654695c5 100644 --- a/src/opt/dau/dauNpn.c +++ b/src/opt/dau/dauNpn.c @@ -872,6 +872,7 @@ Vec_Mem_t * Dau_CollectNpnFunctions( word * p, int nVars, int fVerbose ) ***********************************************************************/ Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int_t ** pvMap, int fVerbose ) { + assert( nVars <= 10 ); abctime clkStart = Abc_Clock(); Vec_Int_t * vMap = Vec_IntAlloc( 100 ); Vec_Int_t * vCnts = Vec_IntAlloc( Vec_WrdSize(vFuncs) ); @@ -881,13 +882,15 @@ Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int int nMints = 1 << nVars; int * pPerm = Extra_PermSchedule( nVars ); int * pComp = Extra_GreyCodeSchedule( nVars ); - int m, i, k, t, Entry; word Truth; - assert( nWords == 1 ); - Vec_WrdForEachEntry( vFuncs, Truth, t ) + int m, i, k, t, Entry; + word * pCopy = ABC_ALLOC( word, nWords ); + int nClasses = Vec_WrdSize(vFuncs) / nWords; + assert( nClasses * nWords == Vec_WrdSize(vFuncs) ); + for ( t = 0; t < nClasses; t++ ) { + word * pTruth = Vec_WrdEntryP( vFuncs, nWords * t ); int nFuncs = Vec_MemEntryNum(vTtMem); - Truth = (Truth & 1) ? ~Truth : Truth; - word pCopy[1] = {Truth}; + Abc_TtCopy( pCopy, pTruth, nWords, pTruth[0] & 1 ); Vec_MemHashInsert( vTtMem, pCopy ); for ( m = 0; m < nMints; m++ ) { Abc_TtFlip( pCopy, nWords, pComp[m] ); @@ -900,8 +903,12 @@ Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int else Vec_MemHashInsert( vTtMem, pCopy ); } - assert( Abc_TtEqual(pCopy, &Truth, nWords) ); - for ( i = 0; i < nFuncs; i++ ) { + if ( pTruth[0] & 1 ) + assert( Abc_TtOpposite(pCopy, pTruth, nWords) ); + else + assert( Abc_TtEqual(pCopy, pTruth, nWords) ); + int nFuncs2 = Vec_MemEntryNum(vTtMem); + for ( i = nFuncs; i < nFuncs2; i++ ) { Abc_TtCopy( pCopy, Vec_MemReadEntry(vTtMem, i), nWords, 0 ); for ( k = 0; k < nPerms; k++ ) { Abc_TtSwapAdjacent( pCopy, nWords, pPerm[k] ); @@ -914,13 +921,15 @@ Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int Vec_IntPush( vMap, t ); Vec_IntPush( vCnts, Vec_MemEntryNum(vTtMem) - nFuncs ); } + ABC_FREE( pCopy ); ABC_FREE( pPerm ); ABC_FREE( pComp ); if ( fVerbose ) { + int Lim = Abc_MinInt( Vec_IntSize(vCnts), 7 ); printf( "Collected %d", Vec_MemEntryNum(vTtMem) ); - Vec_IntForEachEntryStop( vCnts, Entry, i, 7 ) + Vec_IntForEachEntryStop( vCnts, Entry, i, Lim ) printf( " %c %d", i ? '+' : '=', Entry ); - if ( Vec_IntSize(vCnts) > 7 ) + if ( Vec_IntSize(vCnts) > Lim ) printf( " + ..." ); printf( " NPN class members. " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart );