Skip to content

Commit

Permalink
Updates to LUT cascade synthesis.
Browse files Browse the repository at this point in the history
  • Loading branch information
alanminko committed Nov 11, 2024
1 parent c787e32 commit aeb9772
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 14 deletions.
52 changes: 47 additions & 5 deletions src/base/abci/abc.c
Original file line number Diff line number Diff line change
Expand Up @@ -8847,11 +8847,11 @@ int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv )
***********************************************************************/
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 )
{
Expand All @@ -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;
Expand All @@ -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" );
Expand All @@ -8901,9 +8940,12 @@ int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;

usage:
Abc_Print( -2, "usage: lutcas [-K <num>] [-vh]\n" );
Abc_Print( -2, "usage: lutcas [-KNRI <num>] [-vh]\n" );
Abc_Print( -2, "\t derives single-rail LUT cascade for the primary output function\n" );
Abc_Print( -2, "\t-K <num> : the number of LUT inputs [default = %d]\n", nLutSize );
Abc_Print( -2, "\t-N <num> : the number of LUTs in the cascade [default = %d]\n", nLuts );
Abc_Print( -2, "\t-R <num> : the number of direct connections (rails) [default = %d]\n", nRails );
Abc_Print( -2, "\t-I <num> : 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;
Expand Down
9 changes: 5 additions & 4 deletions src/base/abci/abcCas.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 );
Expand Down
176 changes: 171 additions & 5 deletions src/bdd/extrab/extraLutCas.h
Original file line number Diff line number Diff line change
Expand Up @@ -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*************************************************************
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down

0 comments on commit aeb9772

Please sign in to comment.