Updates to LUT cascade decomposition.

This commit is contained in:
Alan Mishchenko 2025-03-19 12:20:25 -07:00
parent e320888191
commit f5ac2d4bd3
2 changed files with 154 additions and 6 deletions

View File

@ -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 <num>\".\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 <num>] [-vh]\n" );
Abc_Print( -2, "usage: lutcasdec [-KMRSIN <num>] [-F <file>] [-vh]\n" );
Abc_Print( -2, "\t decomposes the primary output functions into LUT cascades\n" );
Abc_Print( -2, "\t-K <num> : the number of LUT inputs [default = %d]\n", nLutSize );
Abc_Print( -2, "\t-M <num> : the maximum delay (the number of stages) [default = %d]\n", nStages );
Abc_Print( -2, "\t-R <num> : the number of direct connections (rails) [default = %d]\n", nRails );
Abc_Print( -2, "\t-S <num> : the number of shared variables in each stage [default = %d]\n", nShared );
Abc_Print( -2, "\t-I <num> : the number of iterations when looking for a solution [default = %d]\n", nIters );
Abc_Print( -2, "\t-N <num> : the number of support variables (for truth table files only) [default = unused]\n" );
Abc_Print( -2, "\t-F <file>: 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");

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////