diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 165e1c02e..911f68245 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -8853,7 +8853,7 @@ int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pNtk == NULL ) { - Abc_Print( -1, "Empty network.\n" ); + Abc_Print( -1, "Empty neAtwork.\n" ); return 1; } @@ -8910,12 +8910,12 @@ usage: ***********************************************************************/ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); - extern Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); - Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; - int c, nLutSize = 6, nLuts = 8, nRails = 1, nIters = 1, fVerbose = 0; + extern Abc_Ntk_t * Abc_NtkLutCascadeGen( int nLutSize, int nStages, int nRails, int nShared, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, char * pGuide ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; char * pGuide = NULL; + int c, nLutSize = 6, nStages = 8, nRails = 1, nShared = 2, nIters = 1, fGen = 0, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KNRIvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KMRSIgvh" ) ) != EOF ) { switch ( c ) { @@ -8930,15 +8930,15 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nLutSize < 0 ) goto usage; break; - case 'N': + case 'M': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } - nLuts = atoi(argv[globalUtilOptind]); + nStages = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( nLuts < 0 ) + if ( nStages < 0 ) goto usage; break; case 'R': @@ -8952,6 +8952,17 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nRails < 0 ) goto usage; break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + nShared = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nShared < 0 ) + goto usage; + break; case 'I': if ( globalUtilOptind >= argc ) { @@ -8963,6 +8974,9 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nIters < 0 ) goto usage; break; + case 'g': + fGen ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -8972,6 +8986,17 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( fGen ) + { + pNtkRes = Abc_NtkLutCascadeGen( nLutSize, nStages, nRails, nShared, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "LUT cascade generation failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + } if ( pNtk == NULL ) { @@ -8988,13 +9013,15 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Run command \"strash\" to convert the network into an AIG.\n" ); return 1; } - if ( Abc_NtkCiNum(pNtk) > nLutSize + (nLutSize - nRails) * (nLuts - 1) ) + if ( Abc_NtkCiNum(pNtk) > nLutSize + (nLutSize - nRails) * (nStages - 1) ) { Abc_Print( -1, "Cannot decompose %d-input function into a %d-rail cascade of %d %d-LUTs (max suppose size = %d).\n", - Abc_NtkCiNum(pNtk), nRails, nLuts, nLutSize, nLutSize + (nLutSize - nRails) * (nLuts - 1) ); + Abc_NtkCiNum(pNtk), nRails, nStages, nLutSize, nLutSize + (nLutSize - nRails) * (nStages - 1) ); return 1; } - pNtkRes = Abc_NtkLutCascade2( pNtk, nLutSize, nLuts, nRails, nIters, fVerbose ); + if ( argc == globalUtilOptind + 1 ) + pGuide = argv[globalUtilOptind]; + pNtkRes = Abc_NtkLutCascade2( pNtk, nLutSize, nStages, nRails, nIters, fVerbose, pGuide ); if ( pNtkRes == NULL ) { Abc_Print( -1, "LUT cascade mapping failed.\n" ); @@ -9004,12 +9031,14 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutcasdec [-KNRI ] [-vh]\n" ); + Abc_Print( -2, "usage: lutcasdec [-KMRSI ] [-vh]\n" ); Abc_Print( -2, "\t decomposes the primary output functions into LUT cascades\n" ); Abc_Print( -2, "\t-K : the number of LUT inputs [default = %d]\n", nLutSize ); - Abc_Print( -2, "\t-N : the number of LUTs in the cascade [default = %d]\n", nLuts ); + Abc_Print( -2, "\t-M : the maximum delay (the number of stages) [default = %d]\n", nStages ); Abc_Print( -2, "\t-R : the number of direct connections (rails) [default = %d]\n", nRails ); + Abc_Print( -2, "\t-S : the number of shared variables in each stage [default = %d]\n", nShared ); Abc_Print( -2, "\t-I : the number of iterations when looking for a solution [default = %d]\n", nIters ); + Abc_Print( -2, "\t-g : toggle generating random cascade with these parameters [default = %s]\n", fGen? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index c48e95c73..3a5a2b808 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -21,10 +21,11 @@ #include "base/abc/abc.h" #include "bool/kit/kit.h" #include "aig/miniaig/miniaig.h" +#include "misc/util/utilTruth.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" -#include "bdd/extrab/extraLutCas.h" +//#include "bdd/extrab/extraLutCas.h" #endif ABC_NAMESPACE_IMPL_START @@ -131,7 +132,7 @@ word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nLuts, int nRails, int - the number of words in this block - the number of fanins - the list of fanins - - the variable ID of the output (can be one of the fanin variables) + - the variable ID of the output (should be a LUT counter starting with the number of variables) - truth tables (one word for 6 vars or less; more words as needed for more than 6 vars) For a 6-input node, the LUT info block takes 10 words (block size, fanin count, 6 fanins, output ID, truth table). For a 4-input node, the LUT info block takes 8 words (block size, fanin count, 4 fanins, output ID, truth table). @@ -159,37 +160,157 @@ word * Abc_LutCascadeGenTest() pLuts[1+1] = 6; for ( i = 0; i < 6; i++ ) pLuts[1+2+i] = i; - pLuts[1+8] = 0; + pLuts[1+8] = 9; pLuts[1+9] = ABC_CONST(0x8000000000000000); // second node pLuts[11+0] = 8; pLuts[11+1] = 4; for ( i = 0; i < 4; i++ ) - pLuts[11+2+i] = i ? i + 5 : 0; - pLuts[11+6] = 1; + pLuts[11+2+i] = i ? i + 5 : 9; + pLuts[11+6] = 10; pLuts[11+7] = ABC_CONST(0xFFFEFFFEFFFEFFFE); return pLuts; } +void Abc_LutCascadePrintLut( word * pLuts, int n, int i ) +{ + word nIns = pLuts[i+1]; + word * pIns = pLuts+i+2; + word * pT = pLuts+i+2+nIns+1; + printf( "LUT%d : ", n ); + printf( "%c = F( ", 'a'+(int)pIns[nIns] ); + for ( int k = 0; k < nIns; k++ ) + printf( "%c ", 'a'+(int)pIns[k] ); + printf( ") " ); + Abc_TtPrintHexRev( stdout, pT, nIns ); + printf( "\n" ); +} void Abc_LutCascadePrint( word * pLuts ) { - int n, i, k; - printf( "Single-rail LUT cascade has %d nodes:\n", (int)pLuts[0] ); + int n, i; + printf( "The LUT cascade contains %d LUTs:\n", (int)pLuts[0] ); + for ( n = 0, i = 1; n < pLuts[0]; n++, i += pLuts[i] ) + Abc_LutCascadePrintLut( pLuts, n, i ); +} +void Abc_LutCascadeGenOne( Vec_Wrd_t * vRes, int nIns, int * pIns, int Out, word * p ) +{ + int w, nWords = Abc_TtWordNum(nIns); + //int iStart = Vec_WrdSize(vRes); + Vec_WrdAddToEntry(vRes, 0, 1); + Vec_WrdPush( vRes, 3+nIns+nWords ); + Vec_WrdPush( vRes, nIns ); + for ( w = 0; w < nIns; w++ ) + Vec_WrdPush( vRes, pIns[w] ); + Vec_WrdPush( vRes, Out ); + if ( nIns < 6 ) + Vec_WrdPush( vRes, p ? p[0] : Abc_Tt6Stretch(Abc_Random(0), nIns) ); + else + for ( w = 0; w < nWords; w++ ) + Vec_WrdPush( vRes, p ? p[w] : Abc_RandomW(0) ); + //printf("Adding LUT: "); Abc_LutCascadePrintLut( Vec_WrdArray(vRes), 0, iStart ); +} +word * Abc_LutCascadeGen( int nVars, int nLutSize, int nRails, int nShared ) +{ + assert( nLutSize - nRails - nShared > 0 ); + Vec_Wrd_t * vRes = Vec_WrdStart( 1 ); + Vec_Int_t * vFanins = Vec_IntAlloc( nLutSize ); + Vec_Int_t * vVars = Vec_IntStartNatural( nVars ); + Vec_Str_t * vGuide = Vec_StrAlloc( 100 ); + Abc_Random(1); + int i, c = 0, Obj, iVarNext = nVars, iVarPrev = -1; + while ( Vec_IntSize(vVars) > nLutSize ) { + if ( Vec_WrdSize(vRes) > 1 ) + for ( i = 0; i < nRails; i++ ) + Vec_IntPop( vVars ); + Vec_StrPush( vGuide, '0'+c++ ); + Vec_IntClear( vFanins ); + for ( i = 0; i < nShared; i++ ) { + int Index = -1; + do Index = Abc_Random(0) % Vec_IntSize(vVars); + while ( Vec_IntFind(vFanins, Vec_IntEntry(vVars, Index)) >= 0 ); + Vec_IntPush( vFanins, Vec_IntEntry(vVars, Index) ); + Vec_StrPush( vGuide, 'A'+Vec_IntEntry(vVars, Index) ); + } + for ( i = 0; i < nLutSize - nRails - nShared; i++ ) { + int Index = -1; + do Index = Abc_Random(0) % Vec_IntSize(vVars); + while ( Vec_IntFind(vFanins, Vec_IntEntry(vVars, Index)) >= 0 ); + Vec_IntPush( vFanins, Vec_IntEntry(vVars, Index) ); + Vec_StrPush( vGuide, 'a'+Vec_IntEntry(vVars, Index) ); + Vec_IntDrop( vVars, Index ); + } + if ( Vec_WrdSize(vRes) == 1 ) { + for ( i = 0; i < nRails; i++ ) { + int Index = -1; + do Index = Abc_Random(0) % Vec_IntSize(vVars); + while ( Vec_IntFind(vFanins, Vec_IntEntry(vVars, Index)) >= 0 ); + Vec_IntPush( vFanins, Vec_IntEntry(vVars, Index) ); + Vec_StrPush( vGuide, 'a'+Vec_IntEntry(vVars, Index) ); + Vec_IntDrop( vVars, Index ); + } + } + else { + assert( iVarPrev > 0 ); + for ( i = 0; i < nRails; i++ ) { + Vec_IntPush( vFanins, iVarPrev+i ); + Vec_StrPush( vGuide, 'a'+iVarPrev+i ); + } + } + iVarPrev = iVarNext; + assert( Vec_IntSize(vFanins) == nLutSize ); + for ( i = 0; i < nRails; i++ ) { + Abc_LutCascadeGenOne( vRes, Vec_IntSize(vFanins), Vec_IntArray(vFanins), iVarNext++, NULL ); + Vec_IntPush( vVars, iVarPrev+i ); + } + } + assert( Vec_IntSize(vVars) <= nLutSize ); + Abc_LutCascadeGenOne( vRes, Vec_IntSize(vVars), Vec_IntArray(vVars), iVarNext, NULL ); + Vec_StrPush( vGuide, '0'+c++ ); + Vec_IntForEachEntry( vVars, Obj, i ) + Vec_StrPush( vGuide, 'a'+Obj ); + Vec_StrPush( vGuide, '\0' ); + + printf( "Generated %d-LUT cascade for a %d-var function with %d rails and %d shared vars (node = %d, level = %d).\n", + nLutSize, nVars, nRails, nShared, (int)Vec_WrdEntry(vRes, 0), c ); + printf( "Structural info: %s\n", Vec_StrArray(vGuide) ); + Vec_StrFree( vGuide ); + + word * pRes = Vec_WrdReleaseArray(vRes); + Vec_WrdFree( vRes ); + return pRes; +} +word * Abc_LutCascadeTruth( word * pLuts, int nVars ) +{ + int nWords = Abc_TtWordNum(nVars); + Vec_Wrd_t * vFuncs = Vec_WrdStartTruthTables6( nVars ); + Vec_WrdFillExtra( vFuncs, nWords*(nVars+pLuts[0]+1), (word)0 ); + word * pCube = Vec_WrdEntryP( vFuncs, nWords*(nVars+pLuts[0]) ); + int n, i, m, v, iLastLut = -1; for ( n = 0, i = 1; n < pLuts[0]; n++, i += pLuts[i] ) { - word nIns = pLuts[i+1]; + word nIns = pLuts[i+1]; word * pIns = pLuts+i+2; word * pT = pLuts+i+2+nIns+1; - printf( "LUT%d : ", n ); - printf( "%02d = F( ", (int)pIns[nIns] ); - for ( k = 0; k < nIns; k++ ) - printf( "%02d ", (int)pIns[k] ); - for ( ; k < 8; k++ ) - printf( " " ); - printf( ") " ); - Extra_PrintHex2( stdout, (unsigned *)pT, nIns ); - printf( "\n" ); - } + assert( pLuts[i] == 3+nIns+Abc_TtWordNum(nIns) ); + assert( pIns[nIns] < nVars+pLuts[0] ); + word * pIn[30], * pOut = Vec_WrdEntryP( vFuncs, nWords*pIns[nIns] ); + for ( v = 0; v < nIns; v++ ) + pIn[v] = Vec_WrdEntryP( vFuncs, nWords*pIns[v] ); + for ( m = 0; m < (1<>v)&1), nWords); + Abc_TtOr(pOut, pOut, pCube, nWords); + } + iLastLut = pIns[nIns]; + } + word * pRes = Vec_WrdReleaseArray(vFuncs); + Abc_TtCopy( pRes, pRes + nWords*iLastLut, nWords, 0 ); + Vec_WrdFree( vFuncs ); + return pRes; } + word * Abc_LutCascadeTest( Mini_Aig_t * p, int nLutSize, int fVerbose ) { word * pLuts = Abc_LutCascadeGenTest(); @@ -198,6 +319,207 @@ word * Abc_LutCascadeTest( Mini_Aig_t * p, int nLutSize, int fVerbose ) } +/**Function************************************************************* + + Synopsis [LUT cascade decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +// computes permutation masks for the current stage +int Abc_TtGetGuide( char * pGuide, int Iter, Vec_Int_t * vVarIDs, int fShared ) +{ + int i, Res = 0, Count = 0; + for ( i = 0; pGuide[i]; i++ ) + if ( pGuide[i] >= '0' && pGuide[i] <= '9' ) { + if ( Count++ == Iter ) + break; + } + assert( i < strlen(pGuide) ); + assert( pGuide[i] == '0'+Iter ); + for ( i++; pGuide[i]; i++ ) + { + char Char = pGuide[i]; + if ( Char >= '0' && Char <= '9' ) + break; + if ( fShared && Char >= 'a' && Char <= 'z' ) + continue; + int Value = -1; + if ( Char >= 'a' && Char <= 'z' ) + Value = Char - 'a'; + else if ( Char >= 'A' && Char <= 'Z' ) + Value = Char - 'A'; + else assert( 0 ); + int iPlace = Vec_IntFind(vVarIDs, Value); + assert( iPlace >= 0 ); + assert( ((Res >> iPlace) & 1) == 0 ); + Res |= 1 << iPlace; + } + return Res; +} + +// moves variables in the mask to be the last ones in the order +void Abc_TtPermuteMask( word * p, int nVars, int Mask, Vec_Int_t * vPerm ) +{ + assert( !vPerm || nVars == Vec_IntSize(vPerm) ); + int v, i, iLast = nVars-1, nWords = Abc_TtWordNum(nVars); + int * pPerm = vPerm ? Vec_IntArray(vPerm) : NULL; + if ( 0 && vPerm ) { + printf( "Beg: " ); + for ( v = 0; v < nVars; v++ ) + printf( "%c ", 'a'+Vec_IntEntry(vPerm, v) ); + printf( "\n" ); + printf( "Bit: " ); + for ( v = 0; v < nVars; v++ ) + printf( "%c ", (Mask >> v) & 1 ? '1' : '-' ); + printf( "\n" ); + } + for ( v = nVars-1; v >= 0; v-- ) { + if ( ((Mask >> v) & 1) == 0 ) + continue; + if ( v == iLast ) { + iLast--; + continue; + } + assert( v < iLast ); + for ( i = v; i < iLast; i++ ) { + Abc_TtSwapAdjacent( p, nWords, i ); + if ( pPerm ) ABC_SWAP( int, pPerm[i], pPerm[i+1] ) + } + iLast--; + } + if ( 0 && vPerm ) { + printf( "End: " ); + for ( v = 0; v < nVars; v++ ) + printf( "%c ", 'a'+Vec_IntEntry(vPerm, v) ); + printf( "\n" ); + } +} + + +// checks if the given function exists in storage +// if the function does not exist, adds it to storage +// returns the number of the function in storage +int Abc_LutCascadeLookup( word * pStore, int nFuncs, word * pFunc, int nWords ) +{ + int i; + for ( i = 0; i < nFuncs; i++ ) + if ( Abc_TtEqual( pStore+i*nWords, pFunc, nWords ) ) + return i; + Abc_TtCopy( pStore+i*nWords, pFunc, nWords, 0 ); + assert( i == nFuncs ); + return i; +} +void Abc_LutCascadeDerive( word * p, int nVars, int nBVars, int Myu, word * pRem, word * pDec, int nStep ) +{ + int nFVars = nVars-nBVars; assert( nFVars >= 6 ); + int nEVars = Abc_Base2Log(Myu); + int nFWords = Abc_TtWordNum(nFVars); + int m, e, iFunc, nFuncs = 0; + //printf( "Decomposition pattern with %d BS vars and %d FS vars: ", nBVars, nFVars ); + for ( m = 0; m < (1 << nBVars); m++ ) { + iFunc = Abc_LutCascadeLookup( pRem, nFuncs, p+m*nFWords, nFWords ); + //printf( "%x", iFunc ); + nFuncs = Abc_MaxInt( nFuncs, iFunc+1 ); + for ( e = 0; e < nEVars; e++ ) + if ( (iFunc >> e) & 1 ) + Abc_TtSetBit(pDec+e*nStep, m); + } + //printf( "\n" ); + assert( nFuncs <= Myu ); + iFunc = nFuncs-1; + for ( m = nFuncs; m < (1 << nEVars); m++ ) + Abc_TtCopy( pRem+m*nFWords, pRem+iFunc*nFWords, nFWords, 0 ); + if ( nBVars < 6 ) + for ( e = 0; e < nEVars; e++ ) + pDec[e*nStep] = Abc_Tt6Stretch( pDec[e*nStep], nBVars ); +} + +// performs decomposition of one stage +static inline int Abc_LutCascadeDecStage( char * pGuide, int Iter, Vec_Wrd_t * vFuncs[3], Vec_Int_t * vVarIDs, int nRVars, int nRails, int nLutSize, int fVerbose, Vec_Wrd_t * vCas ) +{ + extern word Abc_TtFindBVarsSVars( word * p, int nVars, int nRVars, int nRails, int nLutSize, int fVerbose ); + assert( Vec_IntSize(vVarIDs) > nLutSize ); + assert( Vec_IntSize(vVarIDs) <= 24 ); + word Guide = pGuide ? 0 : Abc_TtFindBVarsSVars( Vec_WrdArray(vFuncs[0]), Vec_IntSize(vVarIDs), nRVars, nRails, nLutSize, fVerbose ); + int m, Myu = pGuide ? 1 << nRails : (Guide >> 48) & 0xFF; + int nEVars = Abc_Base2Log(Myu); + if ( nEVars > nRails ) { + printf( "Best Myu (%d) requires %d rails that is more than available (%d).\n", Myu, nEVars, nRails ); + Vec_IntClear( vVarIDs ); + return 0; + } + int nVars = Vec_IntSize(vVarIDs); + int mBVars = pGuide ? Abc_TtGetGuide(pGuide, Iter, vVarIDs, 0) : Guide & 0xFFFFFF; + int nBVars = __builtin_popcount(mBVars); + assert( nBVars <= nLutSize ); + Abc_TtPermuteMask( Vec_WrdArray(vFuncs[0]), nVars, mBVars, vVarIDs ); + int mSVars = pGuide ? Abc_TtGetGuide(pGuide, Iter, vVarIDs, 1) : (Guide >> 24) & 0xFFFFFF; + int nSVars = __builtin_popcount(mSVars); + Abc_TtPermuteMask( Vec_WrdArray(vFuncs[0]), nVars, mSVars, vVarIDs ); + // prepare function (nVars -> nAVars+nVars) + int nFVars = nVars - nBVars; + int nAVars = nFVars >= 6 ? 0 : 6-nFVars; + int nWordsNew = Abc_TtWordNum(nVars+nAVars); + Vec_WrdFillExtra( vFuncs[0], nWordsNew, 0 ); + word * pFunc = Vec_WrdArray(vFuncs[0]); + Abc_TtStretch6( pFunc, nVars, nVars+nAVars ); + Abc_TtPermuteMask( pFunc, nVars+nAVars, (1 << nVars)-1, NULL ); + // prepare remainder function (nAVars+nFVars+nEVars+nSVars) + int nWordsRem = Abc_TtWordNum(nAVars+nFVars+nEVars+nSVars); + Vec_WrdFill( vFuncs[1], nWordsRem, 0 ); + word * pRem = Vec_WrdArray(vFuncs[1]); + // prepare decomposed functions (nBVars+nZVars) * nEVars + int nUVars = nBVars - nSVars; + int nZVars = nUVars >= 6 ? 0 : 6-nUVars; + int nWordsDec = Abc_TtWordNum(nBVars+nZVars); + int nWordsStep = Abc_TtWordNum(nUVars+nZVars); + Vec_WrdFill( vFuncs[2], nWordsDec*nEVars, 0 ); + word * pDec = Vec_WrdArray(vFuncs[2]); + int nSMints = 1 << nSVars; + for ( m = 0; m < nSMints; m++ ) + Abc_LutCascadeDerive(pFunc+m*nWordsNew/nSMints, nVars+nAVars-nSVars, nBVars-nSVars, Myu, + pRem+m*nWordsRem/nSMints, pDec+m*nWordsStep, nWordsDec ); + Abc_TtPermuteMask( pRem, nAVars+nFVars+nEVars+nSVars, (1 << nAVars)-1, NULL ); + Abc_TtPermuteMask( pRem, nFVars+nEVars+nSVars, ((1 << nEVars)-1) << nFVars, NULL ); + for ( m = 0; m < nEVars; m++ ) + Abc_TtPermuteMask( pDec+m*nWordsDec, nUVars+nZVars+nSVars, ((1 << nZVars)-1) << nUVars, NULL ); + for ( m = 0; m < nEVars; m++ ) + Abc_LutCascadeGenOne( vCas, nBVars, Vec_IntArray(vVarIDs)+nVars-nBVars, Vec_WrdEntry(vCas,0), pDec+m*nWordsDec ); + Abc_TtCopy( pFunc, pRem, Abc_TtWordNum(nFVars+nSVars+nEVars), 0 ); + assert( nEVars < nUVars ); + for ( m = 0; m < nSVars; m++ ) + Vec_IntWriteEntry(vVarIDs, nFVars+m, Vec_IntEntry(vVarIDs, nVars-nSVars+m) ); + for ( m = 0; m < nEVars; m++ ) + Vec_IntWriteEntry(vVarIDs, nFVars+nSVars+m, Vec_WrdEntry(vCas,0)-nEVars+m ); + Vec_IntShrink( vVarIDs, nFVars+nSVars+nEVars ); + return nEVars; +} +static inline word * Abc_LutCascadeDec( char * pGuide, word * pTruth, Vec_Int_t * vVarIDs, int nRails, int nLutSize, int fVerbose ) +{ + word * pRes = NULL; int i, nRVars = 0, nVars = Vec_IntSize(vVarIDs); + Vec_Wrd_t * vFuncs[3] = { Vec_WrdStart(Abc_TtWordNum(nVars)), Vec_WrdAlloc(0), Vec_WrdAlloc(0) }; + Abc_TtCopy( Vec_WrdArray(vFuncs[0]), pTruth, Abc_TtWordNum(nVars), 0 ); + Vec_Wrd_t * vCas = Vec_WrdAlloc( 100 ); Vec_WrdPush( vCas, nVars ); + for ( i = 0; Vec_IntSize(vVarIDs) > nLutSize; i++ ) + nRVars = Abc_LutCascadeDecStage( pGuide, i, vFuncs, vVarIDs, nRVars, nRails, nLutSize, fVerbose, vCas ); + if ( Vec_IntSize(vVarIDs) > 0 ) { + Abc_LutCascadeGenOne( vCas, Vec_IntSize(vVarIDs), Vec_IntArray(vVarIDs), Vec_WrdEntry(vCas, 0), Vec_WrdArray(vFuncs[0]) ); + Vec_WrdAddToEntry( vCas, 0, -nVars ); + pRes = Vec_WrdReleaseArray(vCas); + } + Vec_WrdFree( vCas ); + for ( i = 0; i < 3; i++ ) + Vec_WrdFree( vFuncs[i] ); + return pRes; +} + + /**Function************************************************************* Synopsis [] @@ -225,11 +547,30 @@ Abc_Obj_t * Abc_NtkLutCascadeDeriveSop( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeNe return pNodeNew; } } -Abc_Ntk_t * Abc_NtkLutCascadeFromLuts( word * pLuts, Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ) +Abc_Ntk_t * Abc_NtkLutCascadeFromLuts( word * pLuts, int nVars, Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ) { - Abc_Ntk_t * pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); - Vec_Int_t * vCover = Vec_IntAlloc( 1000 ); word n, i, k, iLastLut = -1; - assert( Abc_NtkCoNum(pNtk) == 1 ); + Abc_Ntk_t * pNtkNew = NULL; + Abc_Obj_t * pObj; int Id; char pName[2] = {0}; + Vec_Ptr_t * vCopy = Vec_PtrStart( nVars + pLuts[0] + 1000 ); + if ( pNtk ) { + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + } + else { + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP , 0 ); + pNtkNew->pName = Extra_UtilStrsav("cas"); + //pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + for ( Id = 0; Id < nVars; Id++ ) { + pObj = Abc_NtkCreatePi(pNtkNew); + pName[0] = 'a' + Id; + Abc_ObjAssignName( pObj, pName, NULL ); + } + pObj = Abc_NtkCreatePo(pNtkNew); + Abc_ObjAssignName( pObj, "Out", NULL ); + } + Abc_NtkForEachCi( pNtkNew, pObj, Id ) + Vec_PtrWriteEntry( vCopy, Id, pObj ); + Vec_Int_t * vCover = Vec_IntAlloc( 1000 ); + word n, i, k, iLastLut = -1; for ( n = 0, i = 1; n < pLuts[0]; n++, i += pLuts[i] ) { word nIns = pLuts[i+1]; @@ -237,12 +578,15 @@ Abc_Ntk_t * Abc_NtkLutCascadeFromLuts( word * pLuts, Abc_Ntk_t * pNtk, int nLutS word * pT = pLuts+i+2+nIns+1; Abc_Obj_t * pNodeNew = Abc_NtkCreateNode( pNtkNew ); for ( k = 0; k < nIns; k++ ) - Abc_ObjAddFanin( pNodeNew, Abc_NtkCi(pNtk, pIns[k])->pCopy ); - Abc_NtkCi(pNtk, pIns[nIns])->pCopy = Abc_NtkLutCascadeDeriveSop( pNtkNew, pNodeNew, pT, nIns, vCover ); + Abc_ObjAddFanin( pNodeNew, (Abc_Obj_t *)Vec_PtrEntry(vCopy, pIns[k]) ); + Abc_Obj_t * pObjNew = Abc_NtkLutCascadeDeriveSop( pNtkNew, pNodeNew, pT, nIns, vCover ); + Vec_PtrWriteEntry( vCopy, pIns[nIns], pObjNew ); iLastLut = pIns[nIns]; } Vec_IntFree( vCover ); - Abc_ObjAddFanin( Abc_NtkCo(pNtk, 0)->pCopy, Abc_NtkCi(pNtk, iLastLut)->pCopy ); + assert( Abc_NtkCoNum(pNtkNew) == 1 ); + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, 0), (Abc_Obj_t *)Vec_PtrEntry(vCopy, iLastLut) ); + Vec_PtrFree( vCopy ); if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkLutCascadeFromLuts: The network check has failed.\n" ); @@ -260,22 +604,65 @@ Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nR Mini_Aig_t * pM = Gia_ManToMiniAig( pGia ); //word * pLuts = Abc_LutCascade( pM, nLutSize, nLuts, nRails, nIters, fVerbose ); word * pLuts = Abc_LutCascadeTest( pM, nLutSize, 0 ); - Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, pNtk, nLutSize, fVerbose ) : NULL; + Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, Abc_NtkCiNum(pNtk), pNtk, nLutSize, fVerbose ) : NULL; ABC_FREE( pLuts ); Mini_AigStop( pM ); Gia_ManStop( pGia ); return pNew; } -Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) +Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, char * pGuide ) { extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk ); - extern word * Abc_LutCascade2( word * p, int nVars, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); + extern word * Abc_LutCascade2( word * p, int nVars, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk ); - word * pTruth = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, 0) ); - word * pLuts = Abc_LutCascade2( pTruth, Gia_ManCiNum(pGia), nLutSize, nLuts, nRails, nIters, fVerbose ); - Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, pNtk, nLutSize, fVerbose ) : NULL; - ABC_FREE( pLuts ); + word * pTruth1 = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, 0) ); + + int nVars = Abc_NtkCiNum(pNtk); + Vec_Int_t * vVarIDs = Vec_IntStartNatural( nVars ); + Abc_TtMinimumBase( pTruth1, Vec_IntArray(vVarIDs), nVars, &nVars ); + if ( fVerbose ) { + if ( Vec_IntSize(vVarIDs) != nVars ) + printf( "The support of the function is reduced from %d to %d variables.\n", Vec_IntSize(vVarIDs), nVars ); + printf( "Decomposing %d-var function into %d-rail cascade of %d-LUTs", nVars, nRails, nLutSize ); + if ( pGuide ) + printf( " using structural info: %s", pGuide ); + printf( ".\n" ); + } + Vec_IntShrink( vVarIDs, nVars ); + + //word * pLuts = Abc_LutCascade2( pTruth1, nVars, nLutSize, nLuts, nRails, nIters, fVerbose ); + word * pLuts = Abc_LutCascadeDec( pGuide, pTruth1, vVarIDs, nRails, nLutSize, fVerbose ); + Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, nVars, pNtk, nLutSize, fVerbose ) : NULL; + Vec_IntFree( vVarIDs ); + + if ( pLuts && fVerbose ) { + word * pTruth2 = Abc_LutCascadeTruth( pLuts, Abc_NtkCiNum(pNtk) ); + if ( nVars < 9 ) { + printf("Function before: "); Abc_TtPrintHexRev( stdout, pTruth1, nVars ); printf( "\n" ); + printf("Function after: "); Abc_TtPrintHexRev( stdout, pTruth2, nVars ); printf( "\n" ); + } + Abc_LutCascadePrint( pLuts ); + ABC_FREE( pLuts ); + ABC_FREE( pTruth2 ); + } Gia_ManStop( pGia ); + //ABC_FREE( pTruth1 ); + return pNew; +} +Abc_Ntk_t * Abc_NtkLutCascadeGen( int nLutSize, int nStages, int nRails, int nShared, int fVerbose ) +{ + int nVars = nStages * nLutSize - (nStages-1) * (nRails + nShared); + word * pLuts = Abc_LutCascadeGen( nVars, nLutSize, nRails, nShared ); + Abc_Ntk_t * pNew = Abc_NtkLutCascadeFromLuts( pLuts, nVars, NULL, nLutSize, fVerbose ); + Abc_LutCascadePrint( pLuts ); + if ( fVerbose ) { + word * pTruth = Abc_LutCascadeTruth( pLuts, nVars ); + if ( nVars <= 10 ) { + printf( "Function: "); Abc_TtPrintHexRev( stdout, pTruth, nVars ); printf( "\n" ); + } + ABC_FREE( pTruth ); + } + ABC_FREE( pLuts ); return pNew; } diff --git a/src/misc/util/utilBSet.c b/src/misc/util/utilBSet.c index e9b5e8912..8cee38e1b 100644 --- a/src/misc/util/utilBSet.c +++ b/src/misc/util/utilBSet.c @@ -773,39 +773,6 @@ void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryA SeeAlso [] ***********************************************************************/ -static inline Vec_Wrd_t * Vec_WrdStartTruthTables6( int nVars ) -{ - Vec_Wrd_t * p; - word Masks[6] = { - ABC_CONST(0xAAAAAAAAAAAAAAAA), - ABC_CONST(0xCCCCCCCCCCCCCCCC), - ABC_CONST(0xF0F0F0F0F0F0F0F0), - ABC_CONST(0xFF00FF00FF00FF00), - ABC_CONST(0xFFFF0000FFFF0000), - ABC_CONST(0xFFFFFFFF00000000) - }; - int i, k, nWords = nVars <= 6 ? 1 : (1 << (nVars - 6)); - p = Vec_WrdStart( nWords * nVars ); - for ( i = 0; i < nVars; i++ ) - { - word * pTruth = p->pArray + nWords * i; - if ( i < 6 ) - { - for ( k = 0; k < nWords; k++ ) - pTruth[k] = Masks[i]; - } - else - { - for ( k = 0; k < nWords; k++ ) - if ( k & (1 << (i-6)) ) - pTruth[k] = ~(word)0; - else - pTruth[k] = 0; - } - } - return p; -} - void Abc_BSEvalCreateCofs( int iSet, int nVars, Vec_Wrd_t * vCofs, Vec_Wrd_t * vElems ) { int nWords = Abc_Truth6WordNum(nVars); @@ -990,6 +957,76 @@ word * Abc_LutCascade2( word * pFunc, int nVars, int nLutSize, int nLuts, int nR return pRes; } +/**Function************************************************************* + + Synopsis [Computes bound set and shared set of the next stage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int nLutSize, int fVerbose ) +{ + Abc_BSEval_t * p = Abc_BSEvalAlloc(); + int nPermVars = nVars-nRVars; + if ( p->nVars != nPermVars || p->nBVars != nLutSize ) { + if ( p->nBVars != nLutSize ) { + Vec_WecFreeP( &p->vSets ); + Vec_WrdFreeP( &p->vCofs ); + p->vCofs = Abc_BSEvalCreateCofactorSets( nLutSize, &p->vSets ); + } + Vec_IntFreeP( &p->vPairs ); + p->vPairs = Abc_GenChasePairs( nPermVars, nLutSize ); + p->nVars = nPermVars; + p->nBVars = nLutSize; + } + + int v, nWords = Abc_TtWordNum(nVars); + word * pCopy = ABC_ALLOC( word, nWords ); + Abc_TtCopy( pCopy, pTruth, nWords, 0 ); + word pPat[1024]; + + + int pPermBest[32] = {0}; + word * pBest = ABC_ALLOC( word, nWords ); + //printf("Function before: "); Abc_TtPrintHexRev( stdout, pCopy, nVars ); printf( "\n" ); + int MyuMin = Abc_BSEvalBest( p, pCopy, pBest, nVars, nRVars, nVars-nLutSize, 0, pPermBest, 0 ); + //printf("Function before: "); Abc_TtPrintHexRev( stdout, pCopy, nVars ); printf( "\n" ); + + if ( fVerbose ) { + printf( "Best perm: " ); + for ( v = 0; v < nVars; v++ ) + printf( "%d ", pPermBest[v] ); + printf( " Myu = %d. ", MyuMin ); + } + + int Shared = 0, nRailsMin = Abc_Base2Log( MyuMin ); + if ( nRailsMin > nRails ) { + nRailsMin = Abc_SharedEvalBest( p, pBest, nVars, nRVars, nVars-nLutSize, MyuMin, nRails, 0, &Shared, pPat ); + MyuMin = 1 << nRailsMin; + } + + if ( fVerbose ) + printf( "Myu min = %d. Rail min = %d. Shared = %x.\n", MyuMin, nRailsMin, Shared ); + + word mBVars = 0; + for ( v = 0; v < nLutSize; v++ ) + mBVars |= (word)1 << pPermBest[nVars-nLutSize+v]; + + word mSVars = 0; + for ( v = 0; v < nLutSize; v++ ) + if ( (Shared >> v) & 1 ) + mSVars |= (word)1 << (nVars-nLutSize+v); + + ABC_FREE( pCopy ); + ABC_FREE( pBest ); + Abc_BSEvalFree(p); + return ((word)MyuMin << 48) | (mSVars << 24) | mBVars; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/util/utilTruth.h b/src/misc/util/utilTruth.h index 6f96e8d47..cf3d6cedf 100644 --- a/src/misc/util/utilTruth.h +++ b/src/misc/util/utilTruth.h @@ -2007,6 +2007,27 @@ static inline word Abc_Tt6RemoveVar( word t, int iVar ) t = Abc_Tt6SwapAdjacent( t, iVar++ ); return t; } +// permutes two variables while keeping track of their places +static inline void Abc_TtPermuteTwo( word * p, int nTTVars, int * Var2Pla, int * Pla2Var, int Var0, int Var1 ) +{ + int iPlace0 = Var2Pla[Var0]; + int iPlace1 = Var2Pla[Var1]; + if ( iPlace0 == iPlace1 ) + return; + Abc_TtSwapVars( p, nTTVars, iPlace0, iPlace1 ); + Var2Pla[Pla2Var[iPlace0]] = iPlace1; + Var2Pla[Pla2Var[iPlace1]] = iPlace0; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; + Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; +} +// restores natural variable order +static inline void Abc_TtRestoreOrder( word * p, int nTTVars, int * Var2Pla, int * Pla2Var, int nPermVars ) +{ + int i; + for ( i = 0; i < nPermVars; i++ ) + Abc_TtPermuteTwo( p, nTTVars, Var2Pla, Pla2Var, i, Var2Pla[i] ); +} /**Function************************************************************* diff --git a/src/misc/vec/vecWrd.h b/src/misc/vec/vecWrd.h index 9971ff484..88a08a576 100644 --- a/src/misc/vec/vecWrd.h +++ b/src/misc/vec/vecWrd.h @@ -221,6 +221,37 @@ static inline Vec_Wrd_t * Vec_WrdStartTruthTablesRev( int nVars ) } return p; } +static inline Vec_Wrd_t * Vec_WrdStartTruthTables6( int nVars ) +{ + word Masks[6] = { + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00), + ABC_CONST(0xFFFF0000FFFF0000), + ABC_CONST(0xFFFFFFFF00000000) + }; + int i, k, nWords = nVars <= 6 ? 1 : (1 << (nVars - 6)); + Vec_Wrd_t * p = Vec_WrdStart( nWords * nVars ); + for ( i = 0; i < nVars; i++ ) + { + word * pTruth = p->pArray + nWords * i; + if ( i < 6 ) + { + for ( k = 0; k < nWords; k++ ) + pTruth[k] = Masks[i]; + } + else + { + for ( k = 0; k < nWords; k++ ) + if ( k & (1 << (i-6)) ) + pTruth[k] = ~(word)0; + else + pTruth[k] = 0; + } + } + return p; +} static inline int Vec_WrdShiftOne( Vec_Wrd_t * p, int nWords ) { int i, nObjs = p->nSize/nWords;