From 6d6a5accb4a9c140484455a700f10d994ffdd8fb Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 30 Mar 2025 18:20:55 -0700 Subject: [PATCH] Experiments with LUT cascade mapping. --- src/base/abci/abc.c | 14 ++++--- src/base/abci/abcCas.c | 79 +++++++++++++++++++++++++++------------- src/misc/util/utilBSet.c | 55 +++++++++++++++++++--------- 3 files changed, 100 insertions(+), 48 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index aaa62c8cb..0ec80baeb 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -8927,11 +8927,11 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) { 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 ); - extern void Abc_NtkLutCascadeFile( char * pFileName, int nVarNum, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); + extern void Abc_NtkLutCascadeFile( char * pFileName, int nVarNum, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, int fVeryVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; char * pGuide = NULL, * pFileName = NULL; - int c, nVarNum = -1, nLutSize = 6, nStages = 8, nRails = 1, nShared = 2, nIters = 1, fGen = 0, fVerbose = 0; + int c, nVarNum = -1, nLutSize = 6, nStages = 8, nRails = 1, nShared = 2, nIters = 1, fGen = 0, fVerbose = 0, fVeryVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KMRSINFgvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KMRSINFgvwh" ) ) != EOF ) { switch ( c ) { @@ -9016,6 +9016,9 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'v': fVerbose ^= 1; break; + case 'w': + fVeryVerbose ^= 1; + break; case 'h': goto usage; default: @@ -9029,7 +9032,7 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "The number of variables should be given on the command line using switch \"-N \".\n" ); return 1; } - Abc_NtkLutCascadeFile( pFileName, nVarNum, nLutSize, nStages, nRails, nIters, fVerbose ); + Abc_NtkLutCascadeFile( pFileName, nVarNum, nLutSize, nStages, nRails, nIters, fVerbose, fVeryVerbose ); return 1; } if ( fGen ) @@ -9076,7 +9079,7 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutcasdec [-KMRSIN ] [-F ] [-vh]\n" ); + Abc_Print( -2, "usage: lutcasdec [-KMRSIN ] [-F ] [-vwh]\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-M : the maximum delay (the number of stages) [default = %d]\n", nStages ); @@ -9087,6 +9090,7 @@ usage: Abc_Print( -2, "\t-F : a text file with truth tables in hexadecimal listed one per line\n"); 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-w : toggle additional 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 8bddc27f4..471391964 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -310,7 +310,10 @@ word * Abc_LutCascadeTruth( word * pLuts, int nVars ) Vec_WrdFree( vFuncs ); return pRes; } - +int Abc_LutCascadeCount( word * pLuts ) +{ + return (int)pLuts[0]; +} word * Abc_LutCascadeTest( Mini_Aig_t * p, int nLutSize, int fVerbose ) { word * pLuts = Abc_LutCascadeGenTest(); @@ -447,13 +450,14 @@ static inline int Abc_LutCascadeDecStage( char * pGuide, int Iter, Vec_Wrd_t * v 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 ); + if ( !pGuide && !Guide ) { + if ( fVerbose ) + printf( "The function is not decomposable with %d rails.\n", nRails ); + Vec_IntClear( vVarIDs ); + return -1; + } 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); @@ -506,9 +510,12 @@ word * Abc_LutCascadeDec( char * pGuide, word * pTruth, Vec_Int_t * vVarIDs, int 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++ ) + 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 ) { + if ( nRVars == -1 ) + break; + } + if ( nRVars != -1 && 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); @@ -1137,62 +1144,84 @@ Vec_Wrd_t * Abc_NtkLutCasReadTruths( char * pFileName, int nVarNum ) SeeAlso [] ***********************************************************************/ -void Abc_NtkLutCascadeFile( char * pFileName, int nVarNum, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) +void Abc_NtkLutCascadeFile( char * pFileName, int nVarNum, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, int fVeryVerbose ) { - int nWords = Abc_TtWordNum(nVarNum); - Vec_Wrd_t * vTruths = Abc_NtkLutCasReadTruths( pFileName, nVarNum ); + abctime clkStart = Abc_Clock(); + int i, Sum = 0, nWords = Abc_TtWordNum(nVarNum); + Vec_Wrd_t * vTruths = NULL; + if ( strstr(pFileName, ".txt") ) + vTruths = Abc_NtkLutCasReadTruths( pFileName, nVarNum ); + else + vTruths = Vec_WrdReadBin( pFileName, 0 ); if ( vTruths == NULL ) return; - word * pCopy = ABC_ALLOC( word, nWords ); int nFuncs = Vec_WrdSize(vTruths)/nWords; + if ( Vec_WrdSize(vTruths) != nFuncs * nWords ) { + printf( "The files size (%d bytes) does not match the truth table size (%d) for the given number of functions (%d).\n", 8*Vec_WrdSize(vTruths), 8*nWords, nFuncs ); + Vec_WrdFree( vTruths ); + return; + } + printf( "Considering %d functions having %d variables from file \"%s\".\n", nFuncs, nVarNum, pFileName ); - for ( int i = 0; i < nFuncs; i++ ) + word * pCopy = ABC_ALLOC( word, nWords ); + int LutStats[100] = {0}; + for ( i = 0; i < nFuncs; i++ ) { word * pTruth = Vec_WrdEntryP( vTruths, i*nWords ); Abc_TtCopy( pCopy, pTruth, nWords, 0 ); - if ( fVerbose ) + if ( fVeryVerbose ) printf( "\n" ); - printf( "Function %3d : ", i ); - if ( fVerbose ) + if ( fVerbose || fVeryVerbose ) + printf( "Function %3d : ", i ); + if ( fVeryVerbose ) Abc_TtPrintHexRev( stdout, pTruth, nVarNum ), printf( "\n" ); //continue; int nVars = nVarNum; Vec_Int_t * vVarIDs = Vec_IntStartNatural( nVars ); Abc_TtMinimumBase( pTruth, Vec_IntArray(vVarIDs), nVars, &nVars ); - if ( fVerbose ) { + if ( fVeryVerbose ) { 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.\n", nVars, nRails, nLutSize ); } Vec_IntShrink( vVarIDs, nVars ); - word * pLuts = Abc_LutCascadeDec( NULL, pTruth, vVarIDs, nRails, nLutSize, fVerbose ); + word * pLuts = Abc_LutCascadeDec( NULL, pTruth, vVarIDs, nRails, nLutSize, fVeryVerbose ); Vec_IntFree( vVarIDs ); if ( pLuts == NULL ) { - printf( "Not decomposable.\n" ); + if ( fVerbose || fVeryVerbose ) + printf( "Not decomposable.\n" ); continue; } + Sum++; + LutStats[Abc_LutCascadeCount(pLuts)]++; int nWords2 = Abc_TtWordNum(nVars); word * pTruth2 = Abc_LutCascadeTruth( pLuts, nVars ); - if ( fVerbose ) + if ( fVeryVerbose ) Abc_LutCascadePrint( pLuts ); - else + if ( fVerbose || fVeryVerbose ) printf( "Decomposition exists. " ); if ( !Abc_TtEqual(pTruth, pTruth2, nWords2) ) { - printf( "Verification FAILED.\n" ); - Abc_TtPrintHexRev( stdout, pCopy, nVarNum ), printf( "\n" ); + printf( "Verification FAILED for function %d.\n", i ); + Abc_TtPrintHexRev( stdout, pTruth, nVarNum ), printf( "\n" ); } - else + else if ( fVerbose || fVeryVerbose ) printf( "Verification passed.\n" ); ABC_FREE( pTruth2 ); ABC_FREE( pLuts ); } ABC_FREE( pCopy ); Vec_WrdFree( vTruths ); - printf( "Finished decomposing functions from file \"%s\".\n", pFileName ); + printf( "Statistics for %d-rail LUT cascade:\n", nRails ); + for ( i = 0; i < 100; i++ ) + if ( LutStats[i] ) + printf( " %d LUT6 : Function count = %8d (%6.2f %%)\n", i, LutStats[i], 100.0*LutStats[i]/nFuncs ); + printf( "Non-decomp : Function count = %8d (%6.2f %%)\n", nFuncs-Sum, 100.0*(nFuncs-Sum)/Abc_MaxInt(1, nFuncs) ); + printf( "Finished %d functions (speed = %.2f functions / second). ", nFuncs, 1.0*nFuncs/(((double)(Abc_Clock() - clkStart))/((double)CLOCKS_PER_SEC)) ); + Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); } //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/util/utilBSet.c b/src/misc/util/utilBSet.c index 8cee38e1b..e6d8a6673 100644 --- a/src/misc/util/utilBSet.c +++ b/src/misc/util/utilBSet.c @@ -589,7 +589,7 @@ int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int n { int i, k, Var0, Var1, Pla2Var[32], Var2Pla[32]; int nPermVars = nVars-nCVars; - assert( p->nVars == nPermVars && p->nBVars == nPermVars-nFVars ); + assert( p->nVars == nPermVars && p->nBVars == nVars-nFVars ); for ( i = 0; i < nVars; i++ ) Pla2Var[i] = Var2Pla[i] = i; if ( pPermBest ) @@ -617,8 +617,20 @@ int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int n for ( k = nFVars-1; k >= 0; k-- ) printf( " %d", Pla2Var[k] ); printf( " : Myu = %3d", CostThis ); - printf( "\n" ); + //printf( "\n" ); } + if ( 0 ) { + word pPat[1024]; + int nRails = 1, Shared = 0; + if ( CostThis > (1 << nRails) ) { + extern int Abc_SharedEvalBest( Abc_BSEval_t * p, word * pTruth, int nVars, int nCVars, int nFVars, int MyuMin, int nRails, int fVerbose, int * pSetShared, word * pPat ); + int nRailsMin = Abc_SharedEvalBest( p, pIn, nVars, nCVars, nFVars, CostThis, nRails, 0, &Shared, pPat ); + printf( " RailMin = %d. Shared = %2d. ", nRailsMin, Shared ); + } + } + if ( fVerbose ) + printf( "\n" ); + int iPlace0 = Var2Pla[Var0]; int iPlace1 = Var2Pla[Var1]; if ( iPlace0 == iPlace1 ) @@ -859,17 +871,19 @@ int Abc_BSEvalFindShared( int nVars, word * pISets, int nISets, int nBSWords, Ve ***********************************************************************/ int Abc_SharedEvalBest( Abc_BSEval_t * p, word * pTruth, int nVars, int nCVars, int nFVars, int MyuMin, int nRails, int fVerbose, int * pSetShared, word * pPat ) { - int nBSWords = Abc_Truth6WordNum( nVars - nFVars ), CVarMask = Abc_InfoMask(nCVars) << (nVars - nFVars - nCVars); + int nBSWords = Abc_Truth6WordNum( nVars - nFVars ), CVarMask = nCVars ? Abc_InfoMask(nCVars) << (nVars - nCVars - nFVars) : 0; int MyuCur, Myu = Abc_TtGetCMInt( pTruth, nVars, nFVars, p->vCounts, p->vTable, p->vStore, p->vUsed, pPat ); int nRailsCur = Abc_Base2Log( Myu ); Vec_Int_t * vLevel; assert( Myu == MyuMin && nRailsCur > nRails ); - int i, k, iSet, iStart, nSharedMax = nVars - nFVars - 1, nRailsMin = 100; - Vec_WecForEachLevelStartStop( p->vSets, vLevel, i, 1, nSharedMax+1 ) { + int i, k, iSet, iStart, nSharedMax = nVars - nCVars - nFVars - 1, nRailsMin = 100; + Vec_WecForEachLevelStartStop( p->vSets, vLevel, i, 1, nSharedMax ) { Vec_IntForEachEntryDouble( vLevel, iSet, iStart, k ) { if ( iSet & CVarMask ) continue; + //printf( "\nTrying set " ); Extra_PrintBinary( stdout, &iSet, nVars-nFVars ); printf( "\n" ); MyuCur = Abc_BSEvalCountUniqueMax( pPat, Myu, nBSWords, Vec_WrdEntryP(p->vCofs, iStart), i, 1 << nRails ); - if ( MyuCur == 0 ) + //printf( " Res = %d", MyuCur ); + if ( MyuCur == 0 || MyuCur > (1 << nRails) ) continue; nRailsCur = Abc_Base2Log(MyuCur); if ( nRailsCur > nRails ) @@ -972,23 +986,24 @@ word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int { 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 ); - } + if ( p->nVars != nPermVars ) { Vec_IntFreeP( &p->vPairs ); - p->vPairs = Abc_GenChasePairs( nPermVars, nLutSize ); - p->nVars = nPermVars; - p->nBVars = nLutSize; + p->vPairs = Abc_GenChasePairs( nPermVars, nLutSize-nRVars ); + p->nVars = nPermVars; } + if ( p->nBVars != nLutSize ) { + Vec_WecFreeP( &p->vSets ); + Vec_WrdFreeP( &p->vCofs ); + p->vCofs = Abc_BSEvalCreateCofactorSets( nLutSize, &p->vSets ); + p->nBVars = nLutSize; + } int v, nWords = Abc_TtWordNum(nVars); word * pCopy = ABC_ALLOC( word, nWords ); Abc_TtCopy( pCopy, pTruth, nWords, 0 ); word pPat[1024]; + //Abc_TtPrintHexRev( stdout, pTruth, nVars ); printf( "\n" ); int pPermBest[32] = {0}; word * pBest = ABC_ALLOC( word, nWords ); @@ -1009,9 +1024,16 @@ word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int MyuMin = 1 << nRailsMin; } + ABC_FREE( pCopy ); + ABC_FREE( pBest ); + Abc_BSEvalFree(p); + if ( fVerbose ) printf( "Myu min = %d. Rail min = %d. Shared = %x.\n", MyuMin, nRailsMin, Shared ); + if ( nRailsMin > nRails ) + return 0; + word mBVars = 0; for ( v = 0; v < nLutSize; v++ ) mBVars |= (word)1 << pPermBest[nVars-nLutSize+v]; @@ -1021,9 +1043,6 @@ word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int 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; }