Adding a way to dump sets of resub problems.

This commit is contained in:
Alan Mishchenko 2025-08-11 22:44:46 -07:00
parent e7d360811f
commit e29dcd9f32
2 changed files with 111 additions and 6 deletions

View File

@ -8619,7 +8619,9 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv )
int fUseZeros;
int fVerbose;
int fVeryVerbose;
extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nMinSaved, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose );
int Log2Probs;
int Log2Divs;
extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nMinSaved, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose, int Log2Probs, int Log2Divs );
// set defaults
nCutsMax = 8;
@ -8630,8 +8632,10 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv )
fUseZeros = 0;
fVerbose = 0;
fVeryVerbose = 0;
Log2Probs = 0;
Log2Divs = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "KNMFlzvwh" ) ) != EOF )
while ( ( c = Extra_UtilGetopt( argc, argv, "KNMFlzvwhPDV" ) ) != EOF )
{
switch ( c )
{
@ -8679,6 +8683,41 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( nLevelsOdc < 0 )
goto usage;
break;
case 'P':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
goto usage;
}
Log2Probs = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( Log2Probs < 0 )
goto usage;
break;
case 'D':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
goto usage;
}
Log2Divs = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( Log2Divs < 0 )
goto usage;
break;
case 'V':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" );
goto usage;
}
nCutsMax = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( nCutsMax < 0 )
goto usage;
break;
case 'l':
fUpdateLevel ^= 1;
break;
@ -8729,7 +8768,7 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// modify the current network
if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nMinSaved, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) )
if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nMinSaved, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose, Log2Probs, Log2Divs ) )
{
Abc_Print( -1, "Refactoring has failed.\n" );
return 1;
@ -8737,7 +8776,7 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
Abc_Print( -2, "usage: resub [-KNMF <num>] [-lzvwh]\n" );
Abc_Print( -2, "usage: resub [-KNMF <num>] [-lzvwh] [-PDV <num>]\n" );
Abc_Print( -2, "\t performs technology-independent restructuring of the AIG\n" );
Abc_Print( -2, "\t-K <num> : the max cut size (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax );
Abc_Print( -2, "\t-N <num> : the max number of nodes to add (0 <= num <= 3) [default = %d]\n", nNodesMax );
@ -8747,7 +8786,16 @@ usage:
Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-w : toggle verbose printout of ODC computation [default = %s]\n", fVeryVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
Abc_Print( -2, "\t-h : print the command usage\n\n");
Abc_Print( -2, "\t When command line options '-P num', '-D num', and '-V num' are used,\n");
Abc_Print( -2, "\t this command does not perform resubstitution; instead, it dumps a binary file\n");
Abc_Print( -2, "\t containing 2^P resub problems, each containing 2^D-2 divs with support size V,\n");
Abc_Print( -2, "\t while the last two divisors are the offset and the onset of the function\n");
Abc_Print( -2, "\t (by default, the functions are completely specified; to get functions with don't-cares,\n");
Abc_Print( -2, "\t the user has to use command-line option '-F num' to enable the limited ODC computation)\n");
Abc_Print( -2, "\t-P <num> : the log2 of the number of problems to be dumped [default = %d]\n", Log2Probs );
Abc_Print( -2, "\t-D <num> : the log2 of the number of divisors to be collected (4 <= num <= 7) [default = %d]\n", Log2Divs );
Abc_Print( -2, "\t-V <num> : the support size of the function (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax );
return 1;
}

View File

@ -37,6 +37,11 @@ struct Abc_ManRes_t_
// paramers
int nLeavesMax; // the max number of leaves in the cone
int nDivsMax; // the max number of divisors in the cone
// resub problem dumping
int Log2Probs;
int Log2Divs;
int nProbs;
FILE * pFile;
// representation of the cone
Abc_Obj_t * pRoot; // the root of the cone
int nLeaves; // the number of leaves
@ -51,6 +56,7 @@ struct Abc_ManRes_t_
unsigned * pInfo; // pointer to simulation info
// observability don't-cares
unsigned * pCareSet;
unsigned * pTempSim;
// internal divisor storage
Vec_Ptr_t * vDivs1UP; // the single-node unate divisors
Vec_Ptr_t * vDivs1UN; // the single-node unate divisors
@ -134,7 +140,7 @@ static int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves
SeeAlso []
***********************************************************************/
int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, int nMinSaved, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose )
int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, int nMinSaved, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose, int Log2Probs, int Log2Divs )
{
extern int Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain );
ProgressBar * pProgress;
@ -154,6 +160,19 @@ int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, int nMinS
// start the managers
pManCut = Abc_NtkManCutStart( nCutMax, 100000, 100000, 100000 );
pManRes = Abc_ManResubStart( nCutMax, ABC_RS_DIV1_MAX );
if ( Log2Probs && Log2Divs )
{
pManRes->Log2Probs = Log2Probs;
pManRes->Log2Divs = Log2Divs;
pManRes->nProbs = 0;
char pFileName[100]; sprintf( pFileName, "p%02dd%02dv%02d.bin", Log2Probs, nCutMax, Log2Divs );
pManRes->pFile = fopen( pFileName, "wb" );
if ( pManRes->pFile == NULL ) {
printf( "Cannot open output file \"%s\".\n", pFileName );
return 1;
}
printf( "Collecting resub problems into binary file \"%s\" expected to take %.3f MB...\n", pFileName, 1.0*(1 << Log2Probs)*(1 << Log2Divs)*(1 << (nCutMax-3)) / (1 << 20) );
}
if ( nLevelsOdc > 0 )
pManOdc = Abc_NtkDontCareAlloc( nCutMax, nLevelsOdc, fVerbose, fVeryVerbose );
@ -245,6 +264,16 @@ pManRes->timeTotal = Abc_Clock() - clkStart;
if ( fVerbose )
Abc_ManResubPrint( pManRes );
if ( Log2Probs && Log2Divs )
{
fclose( pManRes->pFile );
pManRes->pFile = NULL;
char pFileName[100]; sprintf( pFileName, "p%02dd%02dv%02d.bin", Log2Probs, nCutMax, Log2Divs );
printf( "Finished writing file \"%s\" containing %d (out of requested %d) resub problems,\n", pFileName, pManRes->nProbs, 1<<Log2Probs );
printf( "each having %d divisors with support size %d (including the on-set and the off-set). ", 1<<Log2Divs, nCutMax );
Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart );
}
// delete the managers
Abc_ManResubStop( pManRes );
Abc_NtkManCutStop( pManCut );
@ -321,6 +350,7 @@ Abc_ManRes_t * Abc_ManResubStart( int nLeavesMax, int nDivsMax )
if ( i & (1 << k) )
pData[i>>5] |= (1 << (i&31));
}
p->pTempSim = ABC_CALLOC( unsigned, p->nWords );
// create the remaining divisors
p->vDivs1UP = Vec_PtrAlloc( p->nDivsMax );
p->vDivs1UN = Vec_PtrAlloc( p->nDivsMax );
@ -356,6 +386,7 @@ void Abc_ManResubStop( Abc_ManRes_t * p )
Vec_PtrFree( p->vDivs2UN0 );
Vec_PtrFree( p->vDivs2UN1 );
Vec_PtrFree( p->vTemp );
ABC_FREE( p->pTempSim );
ABC_FREE( p->pInfo );
ABC_FREE( p );
}
@ -1943,6 +1974,32 @@ clk = Abc_Clock();
Abc_ManResubSimulate( p->vDivs, p->nLeaves, p->vSims, p->nLeavesMax, p->nWords );
p->timeSim += Abc_Clock() - clk;
if ( p->pFile && Vec_PtrSize(vLeaves) != p->nLeavesMax && p->nProbs < (1 << p->Log2Probs) )
{
Abc_Obj_t * pObj; int i, w, Count = 0;
unsigned * pFunc = (unsigned *)pRoot->pData;
int Limit = Abc_MinInt( Vec_PtrSize(p->vDivs), (1 << p->Log2Divs) - 2 );
Vec_PtrForEachEntryStop( Abc_Obj_t *, p->vDivs, pObj, i, Limit )
Count += fwrite( (unsigned *)pObj->pData, 1, sizeof(unsigned) * p->nWords, p->pFile );
// write constant zeros
memset( p->pTempSim, 0, sizeof(unsigned) * p->nWords );
for ( ; i < (1 << p->Log2Divs) - 2; i++ )
Count += fwrite( p->pTempSim, 1, sizeof(unsigned) * p->nWords, p->pFile );
// write offset
for ( w = 0; w < p->nWords; w++ )
p->pTempSim[w] = p->pCareSet[w] & ~pFunc[w];
Count += fwrite( p->pTempSim, 1, sizeof(unsigned) * p->nWords, p->pFile );
// write onset
for ( w = 0; w < p->nWords; w++ )
p->pTempSim[w] = p->pCareSet[w] & pFunc[w];
Count += fwrite( p->pTempSim, 1, sizeof(unsigned) * p->nWords, p->pFile );
assert( Count == (1 << p->Log2Divs) * (1 << (p->nLeavesMax-3)) );
p->nProbs++;
//printf( "Finished dumping node %d. Written %d bytes of data (expected %d bytes).\n", pRoot->Id, Count, (1 << p->Log2Divs) * (1 << (p->nLeavesMax-3)) );
//printf( "%d ", Vec_PtrSize(p->vDivs) );
return NULL;
}
clk = Abc_Clock();
// consider constants
if ( (pGraph = Abc_ManResubQuit( p )) )