diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index c0da2150f..8f63005c3 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -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 ] [-lzvwh]\n" ); + Abc_Print( -2, "usage: resub [-KNMF ] [-lzvwh] [-PDV ]\n" ); Abc_Print( -2, "\t performs technology-independent restructuring of the AIG\n" ); Abc_Print( -2, "\t-K : the max cut size (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax ); Abc_Print( -2, "\t-N : 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 : the log2 of the number of problems to be dumped [default = %d]\n", Log2Probs ); + Abc_Print( -2, "\t-D : the log2 of the number of divisors to be collected (4 <= num <= 7) [default = %d]\n", Log2Divs ); + Abc_Print( -2, "\t-V : the support size of the function (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax ); return 1; } diff --git a/src/base/abci/abcResub.c b/src/base/abci/abcResub.c index cb22e8a60..c2ce56d18 100644 --- a/src/base/abci/abcResub.c +++ b/src/base/abci/abcResub.c @@ -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<>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 )) )