diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 428ba2c37..8e87106b2 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -8847,11 +8847,11 @@ usage: ***********************************************************************/ int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkLutCascade( 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, fVerbose = 0; + int c, nLutSize = 6, nLuts = 8, nRails = 1, nIters = 1, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KNRIvh" ) ) != EOF ) { switch ( c ) { @@ -8866,6 +8866,39 @@ int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nLutSize < 0 ) goto usage; break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLuts < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nRails = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRails < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; case 'v': fVerbose ^= 1; break; @@ -8891,7 +8924,13 @@ int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Run command \"strash\" to convert the network into an AIG.\n" ); return 1; } - pNtkRes = Abc_NtkLutCascade( pNtk, nLutSize, fVerbose ); + if ( Abc_NtkCiNum(pNtk) > nLutSize + (nLutSize - nRails) * (nLuts - 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) ); + return 1; + } + pNtkRes = Abc_NtkLutCascade( pNtk, nLutSize, nLuts, nRails, nIters, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "LUT cascade mapping failed.\n" ); @@ -8901,9 +8940,12 @@ int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutcas [-K ] [-vh]\n" ); + Abc_Print( -2, "usage: lutcas [-KNRI ] [-vh]\n" ); Abc_Print( -2, "\t derives single-rail LUT cascade for the primary output function\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-R : the number of direct connections (rails) [default = %d]\n", nRails ); + Abc_Print( -2, "\t-I : the number of iterations when looking for a solution [default = %d]\n", nIters ); 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 b81d813d6..eddb2c1a1 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -119,7 +119,7 @@ Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVer #else Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ) { return NULL; } -word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int fVerbose ) { return NULL; } +word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) { return NULL; } #endif @@ -251,14 +251,15 @@ Abc_Ntk_t * Abc_NtkLutCascadeFromLuts( word * pLuts, Abc_Ntk_t * pNtk, int nLutS } return pNtkNew; } -Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ) +Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) { extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk ); extern Mini_Aig_t * Gia_ManToMiniAig( Gia_Man_t * pGia ); - extern word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int fVerbose ); + extern word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk ); Mini_Aig_t * pM = Gia_ManToMiniAig( pGia ); - word * pLuts = Abc_LutCascade( pM, nLutSize, fVerbose ); + 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_FREE( pLuts ); Mini_AigStop( pM ); diff --git a/src/bdd/extrab/extraLutCas.h b/src/bdd/extrab/extraLutCas.h index 1308c2bee..6723525d1 100644 --- a/src/bdd/extrab/extraLutCas.h +++ b/src/bdd/extrab/extraLutCas.h @@ -107,6 +107,159 @@ Vec_Ptr_t * Abc_LutCasCollapse( Mini_Aig_t * p, DdManager * dd, int nBddLimit, i return vFuncs; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_LutBddScan( DdManager * dd, DdNode * bFunc, int nVars ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( 1 << nVars ); + Vec_Ptr_t * vRes2 = Vec_PtrAlloc( 1 << nVars ); + Vec_PtrPush( vRes, bFunc ); + int v, Level = Cudd_ReadPerm( dd, Cudd_NodeReadIndex(bFunc) ); + for ( v = 0; v < dd->size; v++ ) + printf( "%2d : perm = %d invperm = %d\n", v, dd->perm[v], dd->invperm[v] ); + for ( v = 0; v < nVars; v++ ) + { + int i, LevelCur = Level + v; + Vec_PtrClear( vRes2 ); + DdNode * bTemp; + Vec_PtrForEachEntry( DdNode *, vRes, bTemp, i ) { + int LevelTemp = Cudd_ReadPerm( dd, Cudd_NodeReadIndex(bTemp) ); + if ( LevelTemp == LevelCur ) { + Vec_PtrPush( vRes2, Cudd_NotCond(Cudd_E(bTemp), Cudd_IsComplement(bTemp)) ); + Vec_PtrPush( vRes2, Cudd_NotCond(Cudd_T(bTemp), Cudd_IsComplement(bTemp)) ); + } + else if ( LevelTemp > LevelCur ) { + Vec_PtrPush( vRes2, bTemp ); + Vec_PtrPush( vRes2, bTemp ); + } + else assert( 0 ); + } + ABC_SWAP( Vec_Ptr_t *, vRes, vRes2 ); + //Vec_PtrForEachEntry( DdNode *, vRes, bTemp, i ) + // printf( "%p ", bTemp ); + //printf( "\n" ); + } + Vec_PtrFree( vRes2 ); + assert( Vec_PtrSize(vRes) == (1 << nVars) ); + return vRes; +} +char * Abc_LutBddToTruth( Vec_Ptr_t * vFuncs ) +{ + assert( Vec_PtrSize(vFuncs) <= 256 ); + char * pRes = ABC_CALLOC( char, Vec_PtrSize(vFuncs)+1 ); + void * pTemp, * pStore[256] = {Vec_PtrEntry(vFuncs, 0)}; + int i, k, nStore = 1; pRes[0] = 'a'; + Vec_PtrForEachEntryStart( void *, vFuncs, pTemp, i, 1 ) { + for ( k = 0; k < nStore; k++ ) + if ( pStore[k] == pTemp ) + break; + if ( k == nStore ) + pStore[nStore++] = pTemp; + pRes[i] = 'a' + (char)k; + } + return pRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_NtkPrecomputeData() +{ + char * pRes = ABC_CALLOC( char, 1 << 16 ); + int i, k, b; + for ( i = 0; i < 256; i++ ) { + int nOnes = __builtin_popcount(i); + char * pTemp = pRes + 256*i; + for ( k = 0; k < 256; k++ ) { + int iMask = 0, Counts[2] = {nOnes, 0}; + for ( b = 0; b < 8; Counts[(i >> b++)&1]++ ) + if ( (k >> b) & 1 ) + iMask |= 1 << Counts[(i >> b)&1]; + pTemp[iMask] = (char)k; + assert( Counts[1] == nOnes ); + } + } + for ( i = 0; i < 16; i++, printf("\n") ) + for ( printf("%x : ", i), k = 0; k < 16; k++ ) + printf( "%x=%x ", k, (int)pRes[i*256+k] ); + return pRes; +} + +int Abc_NtkDecPatCount( int iFirst, int nStep, int MyuMax, char * pDecPat, char * pPermInfo ) +{ + int s, k, nPats = 1; + char Pats[256] = { pDecPat[(int)pPermInfo[iFirst]] }; + assert( MyuMax <= 256 ); + for ( s = 1; s < nStep; s++ ) { + char Entry = pDecPat[(int)pPermInfo[iFirst+s]]; + for ( k = 0; k < nPats; k++ ) + if ( Pats[k] == Entry ) + break; + if ( k < nPats ) + continue; + if ( nPats == MyuMax ) + return MyuMax + 1; + assert( nPats < 256 ); + Pats[nPats++] = Entry; + } + return nPats; +} +int Abc_NtkDecPatDecompose_rec( int Mask, int nMaskVars, int iStart, int nVars, int nDiffs, int nRails, char * pDecPat, char * pPermInfo ) +{ + if ( nDiffs == 0 || iStart == nVars ) + return 0; + int v, m, nMints = 1 << nVars; + for ( v = iStart; v < nVars; v++ ) { + int MaskThis = Mask & ~(1 << v); + int nStep = 1 << (nMaskVars - 1); + int MyuMax = 0; + for ( m = 0; m < nMints; m += nStep ) { + int MyuCur = Abc_NtkDecPatCount( m, nStep, 1 << nDiffs, pDecPat, pPermInfo+256*MaskThis ); + MyuMax = Abc_MaxInt( MyuMax, MyuCur ); + } + if ( MyuMax > (1 << nDiffs) ) + continue; + if ( MyuMax <= (1 << nRails) ) + return MaskThis; + MaskThis = Abc_NtkDecPatDecompose_rec( MaskThis, nMaskVars-1, v+1, nVars, nDiffs-1, nRails, pDecPat, pPermInfo ); + if ( MaskThis ) + return MaskThis; + } + return 0; +} +int Abc_NtkDecPatDecompose( int nVars, int nRails, char * pDecPat, char * pPermInfo ) +{ + int BoundSet = ~(~0 << nVars); + int Myu = Abc_NtkDecPatCount( 0, 1 << nVars, 256, pDecPat, pPermInfo + 256*BoundSet ); + int Log2 = Abc_Base2Log( Myu ); + if ( Log2 <= nRails ) + return BoundSet; + return Abc_NtkDecPatDecompose_rec( BoundSet, nVars, 0, nVars, Log2 - nRails, nRails, pDecPat, pPermInfo ); +} + +int Abc_NtkCascadeDecompose( int nVars, int nRails, char * pDecPat, char * pPermInfo ) +{ + return 0; +} + + /**Function************************************************************* @@ -159,12 +312,12 @@ void Abc_LutCasPrintDsd( DdManager * dd, DdNode * bFunc, int fVerbose ) } Dsd_ManagerStop( pManDsd ); } -DdNode * Abc_LutCasBuildBdds( Mini_Aig_t * p, DdManager ** pdd ) +DdNode * Abc_LutCasBuildBdds( Mini_Aig_t * p, DdManager ** pdd, int fReorder ) { DdManager * dd = Cudd_Init( Mini_AigPiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + if ( fReorder ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); Vec_Ptr_t * vFuncs = Abc_LutCasCollapse( p, dd, 10000, 0 ); - Cudd_AutodynDisable( dd ); + if ( fReorder ) Cudd_AutodynDisable( dd ); if ( vFuncs == NULL ) { Extra_StopManager( dd ); return NULL; @@ -174,15 +327,28 @@ DdNode * Abc_LutCasBuildBdds( Mini_Aig_t * p, DdManager ** pdd ) *pdd = dd; return bNode; } -static inline word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int fVerbose ) +static inline word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) { DdManager * dd = NULL; - DdNode * bFunc = Abc_LutCasBuildBdds( p, &dd ); + DdNode * bFunc = Abc_LutCasBuildBdds( p, &dd, 0 ); if ( bFunc == NULL ) return NULL; + char * pPermInfo = Abc_NtkPrecomputeData(); Abc_LutCasPrintDsd( dd, bFunc, 1 ); + + Vec_Ptr_t * vTemp = Abc_LutBddScan( dd, bFunc, nLutSize ); + char * pTruth = Abc_LutBddToTruth( vTemp ); + + int BoundSet = Abc_NtkDecPatDecompose( nLutSize, nRails, pTruth, pPermInfo ); + printf( "Pattern %s : Bound set = %d\n", pTruth, BoundSet ); + + ABC_FREE( pTruth ); + Vec_PtrFree( vTemp ); + Cudd_RecursiveDeref( dd, bFunc ); Extra_StopManager( dd ); + ABC_FREE( pPermInfo ); + printf( "\n" ); word * pLuts = NULL; return pLuts; }