diff --git a/src/aig/gia/giaCut.c b/src/aig/gia/giaCut.c index 45f1de71d..222629d37 100644 --- a/src/aig/gia/giaCut.c +++ b/src/aig/gia/giaCut.c @@ -997,6 +997,81 @@ void Gia_ManExploreCutsTest( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int fV Vec_WecFree( vCutSel ); } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Sto_t * Gia_ManMatchCutsInt( Gia_Man_t * pGia, int nCutSize0, int nCutNum0, int fVerbose0 ) +{ + int nCutSize = nCutSize0; + int nCutNum = nCutNum0; + int fCutMin = 1; + int fTruthMin = 1; + int fVerbose = fVerbose0; + Gia_Sto_t * p = Gia_StoAlloc( pGia, nCutSize, nCutNum, fCutMin, fTruthMin, fVerbose ); + Gia_Obj_t * pObj; int i, iObj; + assert( nCutSize <= GIA_MAX_CUTSIZE ); + assert( nCutNum < GIA_MAX_CUTNUM ); + // prepare references + Gia_ManForEachObj( p->pGia, pObj, iObj ) + Gia_StoRefObj( p, iObj ); + // compute cuts + Gia_StoComputeCutsConst0( p, 0 ); + Gia_ManForEachCiId( p->pGia, iObj, i ) + Gia_StoComputeCutsCi( p, iObj ); + Gia_ManForEachAnd( p->pGia, pObj, iObj ) + Gia_StoComputeCutsNode( p, iObj ); + if ( p->fVerbose ) + { + printf( "Running cut computation with CutSize = %d CutNum = %d CutMin = %s TruthMin = %s\n", + p->nCutSize, p->nCutNum, p->fCutMin ? "yes":"no", p->fTruthMin ? "yes":"no" ); + printf( "CutPair = %.0f ", p->CutCount[0] ); + printf( "Merge = %.0f (%.2f %%) ", p->CutCount[1], 100.0*p->CutCount[1]/p->CutCount[0] ); + printf( "Eval = %.0f (%.2f %%) ", p->CutCount[2], 100.0*p->CutCount[2]/p->CutCount[0] ); + printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] ); + printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) ); + printf( "\n" ); + printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ", + p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) ); + Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart ); + } + return p; +} +void Gia_ManMatchCuts( Vec_Mem_t * vTtMem, 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, k, * pCut; + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + abctime clkStart = Abc_Clock(); + assert( Abc_Truth6WordNum(nCutSize) == Vec_MemEntrySize(vTtMem) ); + 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]) ); + int * pSpot = Vec_MemHashLookup( vTtMem, pTruth ); + if ( *pSpot == -1 ) + continue; + Vec_IntPush( vNodes, i ); + break; + } + } + printf( "Nodes with matching cuts: " ); + Vec_IntPrint( vNodes ); + Vec_IntFree( vNodes ); + Gia_StoFree( p ); + if ( fVerbose ) + Abc_PrintTime( 1, "Cut matching time", Abc_Clock() - clkStart ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 76ae22eb4..da6d06aa1 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -615,6 +615,7 @@ static int Abc_CommandAbc9GenMux ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Window ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9FunAbs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9DsdInfo ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9FunTrace ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1412,6 +1413,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&window", Abc_CommandAbc9Window, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&funabs", Abc_CommandAbc9FunAbs, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&dsdinfo", Abc_CommandAbc9DsdInfo, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&funtrace", Abc_CommandAbc9FunTrace, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); { @@ -53951,6 +53953,93 @@ usage: } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +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, fVerbose = 0; word * pTruth = NULL; + char * pStr = NULL; Vec_Mem_t * vTtMem = NULL; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Cvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCutNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutNum < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): There is no AIG.\n" ); + return 0; + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): Truth table in hex notation should be given on the command line.\n" ); + return 0; + } + pStr = argv[globalUtilOptind]; + if ( pStr[0] == '0' && pStr[1] == 'x' ) + pStr += 2; + nVars = Abc_Base2Log(strlen(pStr)*4); + if ( (1 << nVars) != strlen(pStr)*4 ) + { + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): String \"%s\" does not look like a truth table of a %d-var function.\n", pStr, nVars ); + return 0; + } + pTruth = ABC_CALLOC( word, Abc_Truth6WordNum(nVars+1) ); + nVars2 = Abc_TtReadHex( pTruth, pStr ); + if ( nVars != nVars2 ) + { + ABC_FREE( pTruth ); + Abc_Print( -1, "Abc_CommandAbc9FunTrace(): String \"%s\" does not look like a truth table of a %d-var function.\n", pStr, nVars ); + return 0; + } + //Abc_TtPrintHexRev( stdout, pTruth, nVars ); printf( "\n" ); + vTtMem = Dau_CollectNpnFunctions( pTruth, nVars, fVerbose ); + Gia_ManMatchCuts( vTtMem, pAbc->pGia, nVars, nCutNum, fVerbose ); + Vec_MemHashFree( vTtMem ); + Vec_MemFree( vTtMem ); + return 0; + +usage: + Abc_Print( -2, "usage: &funtrace [-C num] [-vh] \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-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\n"); + return 1; +} + + /**Function************************************************************* Synopsis [] diff --git a/src/opt/dau/dauNpn.c b/src/opt/dau/dauNpn.c index 2b9e1915d..71cc857b6 100644 --- a/src/opt/dau/dauNpn.c +++ b/src/opt/dau/dauNpn.c @@ -800,6 +800,65 @@ void Dau_FunctionEnum( int nInputs, int nVars, int nNodeMax, int fUseTwo, int fR fflush(stdout); } +/**Function************************************************************* + + Synopsis [Function enumeration.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Mem_t * Dau_CollectNpnFunctions( word * p, int nVars, int fVerbose ) +{ + abctime clkStart = Abc_Clock(); + Vec_Mem_t * vTtMem = Vec_MemAllocForTTSimple( nVars ); + int nWords = Abc_Truth6WordNum(nVars); + word * pCopy = ABC_ALLOC( word, nWords ); + Abc_TtCopy( pCopy, p, nWords, p[0] & 1 ); + Vec_MemHashInsert( vTtMem, pCopy ); + int nPerms = Extra_Factorial( nVars ); + int nMints = 1 << nVars; + int * pPerm = Extra_PermSchedule( nVars ); + int * pComp = Extra_GreyCodeSchedule( nVars ); + int m, i, k, nFuncs; + for ( m = 0; m < nMints; m++ ) { + Abc_TtFlip( pCopy, nWords, pComp[m] ); + if ( pCopy[0] & 1 ) { + Abc_TtNot( pCopy, nWords ); + assert( (pCopy[0] & 1) == 0 ); + Vec_MemHashInsert( vTtMem, pCopy ); + Abc_TtNot( pCopy, nWords ); + } + else + Vec_MemHashInsert( vTtMem, pCopy ); + } + assert( Abc_TtEqual(pCopy, Vec_MemReadEntry(vTtMem, 0), nWords) ); + nFuncs = Vec_MemEntryNum(vTtMem); + if ( fVerbose ) + printf( "Collected %d NN functions and ", nFuncs ), fflush(stdout); + for ( i = 0; i < nFuncs; i++ ) { + Abc_TtCopy( pCopy, Vec_MemReadEntry(vTtMem, i), nWords, 0 ); + for ( k = 0; k < nPerms; k++ ) { + Abc_TtSwapAdjacent( pCopy, nWords, pPerm[k] ); + assert( (pCopy[0] & 1) == 0 ); + Vec_MemHashInsert( vTtMem, pCopy ); + } + assert( Abc_TtEqual(pCopy, Vec_MemReadEntry(vTtMem, i), nWords) ); + } + ABC_FREE( pPerm ); + ABC_FREE( pComp ); + ABC_FREE( pCopy ); + nFuncs = Vec_MemEntryNum(vTtMem); + if ( fVerbose ) + printf( "%d NPN functions. ", nFuncs ), + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ), + fflush(stdout); + return vTtMem; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// ////////////////////////////////////////////////////////////////////////