From f5ac2d4bd3fc749825795f18c795513e2e85a3b1 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 19 Mar 2025 12:20:25 -0700 Subject: [PATCH] Updates to LUT cascade decomposition. --- src/base/abci/abc.c | 42 +++++++++++++-- src/base/abci/abcCas.c | 118 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 154 insertions(+), 6 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 8ceb65167..95518cea6 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -8925,10 +8925,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 ); - 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; + extern void Abc_NtkLutCascadeFile( char * pFileName, int nVarNum, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); + 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; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KMRSIgvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KMRSINFgvh" ) ) != EOF ) { switch ( c ) { @@ -8987,6 +8988,26 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nIters < 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; + } + nVarNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVarNum < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by a file name.\n" ); + goto usage; + } + pFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'g': fGen ^= 1; break; @@ -8999,6 +9020,16 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( pFileName ) + { + if ( nVarNum == -1 ) + { + 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 ); + return 1; + } if ( fGen ) { pNtkRes = Abc_NtkLutCascadeGen( nLutSize, nStages, nRails, nShared, fVerbose ); @@ -9010,7 +9041,6 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; } - if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); @@ -9044,13 +9074,15 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutcasdec [-KMRSI ] [-vh]\n" ); + Abc_Print( -2, "usage: lutcasdec [-KMRSIN ] [-F ] [-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-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-N : the number of support variables (for truth table files only) [default = unused]\n" ); + 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-h : print the command usage\n"); diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index 3a5a2b808..8bddc27f4 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -500,7 +500,7 @@ static inline int Abc_LutCascadeDecStage( char * pGuide, int Iter, Vec_Wrd_t * v 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 * 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) }; @@ -1079,6 +1079,122 @@ Abc_Ntk_t * Abc_NtkLutCascadeMap( Abc_Ntk_t * pNtk, int nLutsMax, int nIters, in } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Abc_NtkLutCasReadTruths( char * pFileName, int nVarNum ) +{ + Vec_Wrd_t * vTruths = NULL; + int nWords = Abc_TtWordNum(nVarNum); + int nFileSize = Gia_FileSize( pFileName ); + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) { printf("Cannot open file \"%s\" for reading.\n", pFileName); return NULL; } + word * pTruth = ABC_ALLOC( word, 2*nWords ); + char * pToken, * pLine = ABC_ALLOC( char, nFileSize ); + for ( int i = 0; fgets(pLine, nFileSize, pFile); i++ ) { + pToken = strtok(pLine, " ,\n\r\r"); + if ( pToken == NULL ) + continue; + if ( pToken[0] == '0' && pToken[1] == 'x' ) + pToken += 2; + if ( strlen(pToken) != (1 << (nVarNum-2)) ) { + printf( "Line %d has truth table of size %d while expected size is %d.\n", i, (int)strlen(pToken), 1 << (nVarNum-2) ); + Vec_WrdFreeP( &vTruths ); + break; + } + if ( !Abc_TtReadHex( pTruth, pToken ) ) { + printf( "Line %d has truth table that cannot be read correctly (%s).\n", i, pToken ); + Vec_WrdFreeP( &vTruths ); + break; + } + if ( vTruths == NULL ) + vTruths = Vec_WrdAlloc( 10000 ); + for ( int w = 0; w < nWords; w++ ) + Vec_WrdPush( vTruths, pTruth[w] ); + } + ABC_FREE( pTruth ); + ABC_FREE( pLine ); + fclose( pFile ); + return vTruths; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkLutCascadeFile( char * pFileName, int nVarNum, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) +{ + int nWords = Abc_TtWordNum(nVarNum); + Vec_Wrd_t * vTruths = Abc_NtkLutCasReadTruths( pFileName, nVarNum ); + if ( vTruths == NULL ) + return; + + word * pCopy = ABC_ALLOC( word, nWords ); + int nFuncs = Vec_WrdSize(vTruths)/nWords; + printf( "Considering %d functions having %d variables from file \"%s\".\n", nFuncs, nVarNum, pFileName ); + for ( int i = 0; i < nFuncs; i++ ) + { + word * pTruth = Vec_WrdEntryP( vTruths, i*nWords ); + Abc_TtCopy( pCopy, pTruth, nWords, 0 ); + + if ( fVerbose ) + printf( "\n" ); + printf( "Function %3d : ", i ); + if ( fVerbose ) + 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 ( 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 ); + Vec_IntFree( vVarIDs ); + if ( pLuts == NULL ) { + printf( "Not decomposable.\n" ); + continue; + } + int nWords2 = Abc_TtWordNum(nVars); + word * pTruth2 = Abc_LutCascadeTruth( pLuts, nVars ); + if ( fVerbose ) + Abc_LutCascadePrint( pLuts ); + else + printf( "Decomposition exists. " ); + if ( !Abc_TtEqual(pTruth, pTruth2, nWords2) ) { + printf( "Verification FAILED.\n" ); + Abc_TtPrintHexRev( stdout, pCopy, nVarNum ), printf( "\n" ); + } + else + 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 ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// ////////////////////////////////////////////////////////////////////////