From 8db417597c8443c9de304334b7186531da213957 Mon Sep 17 00:00:00 2001 From: phyzhenli <48823046+phyzhenli@users.noreply.github.com> Date: Thu, 3 Apr 2025 16:40:28 +0800 Subject: [PATCH 01/72] Update Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 50cff2d17..2dfc1c691 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ endif ifdef ABC_USE_NAMESPACE CFLAGS += -DABC_NAMESPACE=$(ABC_USE_NAMESPACE) -fpermissive -x c++ CC := $(CXX) - $(info $(MSG_PREFIX)Compiling in namespace $(ABC_NAMESPACE)) + $(info $(MSG_PREFIX)Compiling in namespace $(ABC_USE_NAMESPACE)) endif # compile CUDD with ABC From 0b68f061729cb403d960343c40db7ccee0df0cb4 Mon Sep 17 00:00:00 2001 From: JingrenWang Date: Fri, 4 Apr 2025 10:25:55 +0800 Subject: [PATCH 02/72] Refactor(gtest): Remove duplicate libgtest.a Close #398 Signed-off-by: JingrenWang --- test/gia/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/test/gia/CMakeLists.txt b/test/gia/CMakeLists.txt index c9022dc8c..e4dffd475 100644 --- a/test/gia/CMakeLists.txt +++ b/test/gia/CMakeLists.txt @@ -1,7 +1,6 @@ add_executable(gia_test gia_test.cc) target_link_libraries(gia_test - gtest gtest_main libabc ) From 5700bff205d3827d98b0b021de136d3cddc81c57 Mon Sep 17 00:00:00 2001 From: jiunhaochen Date: Wed, 9 Apr 2025 19:27:32 +0800 Subject: [PATCH 03/72] command rewire add external care --- src/base/abci/abc.c | 69 ++++++++++++++++--- src/opt/rar/rewire_miaig.cpp | 130 +++++++++++++++++++++++------------ src/opt/rar/rewire_miaig.h | 43 ++++++++---- src/opt/rar/rewire_rar.c | 12 ++-- src/opt/rar/rewire_rar.h | 12 ++-- src/opt/rar/rewire_tt.h | 6 ++ 6 files changed, 193 insertions(+), 79 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index f0ac69548..00eb766b7 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -20664,15 +20664,17 @@ usage: ***********************************************************************/ int Abc_CommandRewire( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose); + extern Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose); Abc_Ntk_t *pNtk, *pTemp; - int c, nIters = 100000, nExpands = 128, nGrowth = 4, nDivs = -1, nFaninMax = 8, nSeed = 1, nTimeOut = 0, nVerbose = 1, nMode = 0, nMappedMode = 0, nDist = 0; + Gia_Man_t *pExc = NULL; + FILE *pFile = NULL; + int c, nIters = 100000, nExpands = 128, nGrowth = 4, nDivs = -1, nFaninMax = 8, nSeed = 1, nTimeOut = 0, nVerbose = 1, nMode = 0, nMappedMode = 0, nDist = 0, fCheck = 0; float nLevelGrowRatio = 0; Extra_UtilGetoptReset(); pNtk = Abc_FrameReadNtk(pAbc); - while ( ( c = Extra_UtilGetopt( argc, argv, "IEGDFSTMALRVh" ) ) != EOF ) { + while ( ( c = Extra_UtilGetopt( argc, argv, "IEGDFSTMALRCVch" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) @@ -20773,6 +20775,22 @@ int Abc_CommandRewire( Abc_Frame_t * pAbc, int argc, char ** argv ) nLevelGrowRatio = atof(argv[globalUtilOptind]); globalUtilOptind++; break; + case 'C': + pFile = fopen( argv[globalUtilOptind], "rb" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", argv[globalUtilOptind] ); + return 1; + } + fclose( pFile ); + pExc = Gia_AigerRead( argv[globalUtilOptind], 0, 0, 0 ); + if ( pExc == NULL ) + { + Abc_Print( -1, "Reading Exc AIGER has failed.\n" ); + return 1; + } + globalUtilOptind++; + break; case 'V': if ( globalUtilOptind >= argc ) { @@ -20782,6 +20800,9 @@ int Abc_CommandRewire( Abc_Frame_t * pAbc, int argc, char ** argv ) nVerbose = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; + case 'c': + fCheck ^= 1; + break; case 'h': default: goto usage; @@ -20803,7 +20824,9 @@ int Abc_CommandRewire( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - pTemp = Abc_ManRewire( pNtk, nIters, nLevelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, nVerbose ); + pTemp = Abc_ManRewire( pNtk, pExc, nIters, nLevelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fCheck, nVerbose ); + if ( pExc ) + Gia_ManStop( pExc ); Abc_FrameReplaceCurrentNetwork( pAbc, pTemp ); return 0; @@ -20818,9 +20841,11 @@ usage: Abc_Print( -2, "\t-R : level constraint (0: unlimited, 1: preserve level) [default = %g]\n", nLevelGrowRatio); Abc_Print( -2, "\t-M : optimization target [default = %s]\n", nMode ? "area" : "AIG node" ); Abc_Print( -2, "\t-A : mapper (0: amap, 1: &nf, 2: &simap) (experimental) [default = %d]\n", nMappedMode ); + Abc_Print( -2, "\t-C : AIGER specifying external cares\n"); Abc_Print( -2, "\t-S : the random seed (0: random, >= 1: user defined) [default = %d]\n", nSeed ); Abc_Print( -2, "\t-T : the timeout in seconds (0: unlimited) [default = %d]\n", nTimeOut ); Abc_Print( -2, "\t-V : the verbosity level [default = %d]\n", nVerbose ); + Abc_Print( -2, "\t-c : check the equivalence [default = %s]\n", fCheck ? "yes" : "no" ); Abc_Print( -2, "\t-h : prints the command usage\n" ); Abc_Print( -2, "\n\tThis command was contributed by Jiun-Hao Chen from National Taiwan University.\n" ); return 1; @@ -46326,13 +46351,14 @@ usage: ***********************************************************************/ int Abc_CommandAbc9Rewire( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose); - Gia_Man_t *pTemp; - int c, nIters = 100000, nExpands = 128, nGrowth = 4, nDivs = -1, nFaninMax = 8, nSeed = 1, nTimeOut = 0, nVerbose = 1, nMode = 0, nMappedMode = 0, nDist = 0; + extern Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose); + FILE *pFile = NULL; + Gia_Man_t *pTemp, *pExc = NULL; + int c, nIters = 100000, nExpands = 128, nGrowth = 4, nDivs = -1, nFaninMax = 8, nSeed = 1, nTimeOut = 0, nVerbose = 1, nMode = 0, nMappedMode = 0, nDist = 0, fCheck = 0; float nLevelGrowRatio = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "IEGDFSTMALRVh" ) ) != EOF ) { + while ( ( c = Extra_UtilGetopt( argc, argv, "IEGDFSTMALRCVch" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) @@ -46433,6 +46459,22 @@ int Abc_CommandAbc9Rewire( Abc_Frame_t * pAbc, int argc, char ** argv ) nLevelGrowRatio = atof(argv[globalUtilOptind]); globalUtilOptind++; break; + case 'C': + pFile = fopen( argv[globalUtilOptind], "rb" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", argv[globalUtilOptind] ); + return 1; + } + fclose( pFile ); + pExc = Gia_AigerRead( argv[globalUtilOptind], 0, 0, 0 ); + if ( pExc == NULL ) + { + Abc_Print( -1, "Reading Exc AIGER has failed.\n" ); + return 1; + } + globalUtilOptind++; + break; case 'V': if ( globalUtilOptind >= argc ) { @@ -46442,6 +46484,9 @@ int Abc_CommandAbc9Rewire( Abc_Frame_t * pAbc, int argc, char ** argv ) nVerbose = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; + case 'c': + fCheck ^= 1; + break; case 'h': default: goto usage; @@ -46463,9 +46508,9 @@ int Abc_CommandAbc9Rewire( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - pTemp = Gia_ManRewire( pAbc->pGia, nIters, nLevelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, nVerbose ); - if ( pTemp->pName == NULL ) - pTemp->pName = Abc_UtilStrsav(Extra_FileNameWithoutPath(pAbc->pGia->pName)); + pTemp = Gia_ManRewire( pAbc->pGia, pExc, nIters, nLevelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fCheck, nVerbose ); + if ( pExc ) + Gia_ManStop( pExc ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; @@ -46481,9 +46526,11 @@ usage: Abc_Print( -2, "\t-R : level constraint (0: unlimited, 1: preserve level) [default = %g]\n", nLevelGrowRatio); Abc_Print( -2, "\t-M : optimization target [default = %s]\n", nMode ? "area" : "AIG node" ); Abc_Print( -2, "\t-A : mapper (0: amap, 1: &nf, 2: &simap) (experimental) [default = %d]\n", nMappedMode ); + Abc_Print( -2, "\t-C : AIGER specifying external cares\n"); Abc_Print( -2, "\t-S : the random seed (0: random, >= 1: user defined) [default = %d]\n", nSeed ); Abc_Print( -2, "\t-T : the timeout in seconds (0: unlimited) [default = %d]\n", nTimeOut ); Abc_Print( -2, "\t-V : the verbosity level [default = %d]\n", nVerbose ); + Abc_Print( -2, "\t-c : check the equivalence [default = %s]\n", fCheck ? "yes" : "no" ); Abc_Print( -2, "\t-h : prints the command usage\n" ); Abc_Print( -2, "\n\tThis command was contributed by Jiun-Hao Chen from National Taiwan University.\n" ); return 1; diff --git a/src/opt/rar/rewire_miaig.cpp b/src/opt/rar/rewire_miaig.cpp index 59070349f..dffb29fa7 100644 --- a/src/opt/rar/rewire_miaig.cpp +++ b/src/opt/rar/rewire_miaig.cpp @@ -26,22 +26,28 @@ ABC_NAMESPACE_IMPL_START #endif // RW_ABC #ifdef RW_ABC -Gia_Man_t *Gia_ManRewireInt(Gia_Man_t *pGia, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose) { +Gia_Man_t *Gia_ManRewireInt(Gia_Man_t *pGia, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose) { Random_Num(nSeed == 0 ? Abc_Random(0) % 10 : nSeed); + assert(Gia_ManCiNum(pGia) <= 58); Rewire::Miaig pNtkMiaig(pGia); - Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, fVerbose); + if (pExc) + pNtkMiaig.setExc(pExc); + Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, fCheck, fVerbose); pNew.setName(Gia_ManName(pGia)); return pNew.toGia(); } -Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose) { +Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose) { Random_Num(nSeed == 0 ? Abc_Random(0) % 10 : nSeed); + assert(Abc_NtkCiNum(pNtk) <= 58); int fMapped = nMode == 1; Rewire::Miaig pNtkMiaig(pNtk); - Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, fMapped, nMappedMode, nDist, fVerbose); + if (pExc) + pNtkMiaig.setExc(pExc); + Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, fMapped, nMappedMode, nDist, fCheck, fVerbose); pNew.setName(Abc_NtkName(pNtk)); if (nMode == 2) { pNew.countTransistors(1, nMappedMode); @@ -50,11 +56,14 @@ Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, int nIters, float levelGrowRatio, i return pNew.toNtk(nMode >= 1); } -Mini_Aig_t *MiniAig_ManRewireInt(Mini_Aig_t *pAig, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose) { +Mini_Aig_t *MiniAig_ManRewireInt(Mini_Aig_t *pAig, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose) { Random_Num(nSeed == 0 ? Abc_Random(0) % 10 : nSeed); + assert(Mini_AigPiNum(pAig) <= 58); Rewire::Miaig pNtkMiaig(pAig); - Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, fVerbose); + if (pExc) + pNtkMiaig.setExc(pExc); + Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, fCheck, fVerbose); return pNew.toMiniAig(); } @@ -234,6 +243,21 @@ vi *moveVecToVi(Vec_Int_t *v) { free(v); return p; } + +void Miaig::setExc(Gia_Man_t *pExc) { + int i; + assert(Gia_ManCiNum(pExc) == nIns()); + assert(Gia_ManCoNum(pExc) == nOuts()); + if (!_data->pExc) { + _data->pExc = (word *)malloc(sizeof(word) * nWords() * nOuts()); + } + Miaig Exc(pExc); + Exc.initializeTruth(); + for (i = 0; i < nOuts(); ++i) { + word *pExc = Exc.objTruth(Exc.nObjs() - Exc.nOuts() + i, 0); + Tt_Dup(_data->pExc + nWords() * i, pExc, nWords()); + } +} #endif // RW_ABC // technology mapping @@ -753,15 +777,24 @@ void Miaig::initializeTruth(void) { Tt_Dup(objTruth(i, 2), objTruth(i, 0), nWords()); } -void Miaig::truthUpdate(vi *vTfo) { +void Miaig::truthUpdate(vi *vTfo, word *pExc, int fCheck) { int i, iTemp, nFails = 0; nTravIds()++; - Vi_ForEachEntry(vTfo, iTemp, i) { - truthSimNode(iTemp); - if (objIsPo(iTemp) && !Tt_Equal(objTruth(iTemp, 2), objTruth(iTemp, 0), nWords())) - printf("Verification failed at output %d.\n", iTemp - (nObjs() - nOuts())), nFails++; + if (!pExc) { + Vi_ForEachEntry(vTfo, iTemp, i) { + truthSimNode(iTemp); + if (fCheck && objIsPo(iTemp) && !Tt_Equal(objTruth(iTemp, 2), objTruth(iTemp, 0), nWords())) + printf("Verification failed at output %d.\n", iTemp - (nObjs() - nOuts())), nFails++; + } + } else { + Vi_ForEachEntry(vTfo, iTemp, i) { + truthSimNode(iTemp); + if (fCheck && objIsPo(iTemp) && !Tt_EqualOnCare(pExc + objPoIdx(iTemp) * nWords(), objTruth(iTemp, 2), objTruth(iTemp, 0), nWords())) { + printf("Verification failed at output %d.\n", iTemp - (nObjs() - nOuts())), nFails++; + } + } } - if (nFails) + if (fCheck && nFails) printf("Verification failed for %d outputs after updating node %d.\n", nFails, Vi_Read(vTfo, 0)); } @@ -795,15 +828,23 @@ vi *Miaig::computeTfo(int iObj) { return _data->vTfo; } -word *Miaig::computeCareSet(int iObj) { +word *Miaig::computeCareSet(int iObj, word *pExc) { vi *vTfo = computeTfo(iObj); int i, iTemp; Tt_Not(objTruth(iObj, 1), objTruth(iObj, 0), nWords()); Tt_Clear(_data->pCare, nWords()); - Vi_ForEachEntryStart(vTfo, iTemp, i, 1) { - truthSimNode(iTemp); - if (objIsPo(iTemp)) - Tt_OrXor(_data->pCare, objTruth(iTemp, 0), objTruth(iTemp, 1), nWords()); + if (!pExc) { + Vi_ForEachEntryStart(vTfo, iTemp, i, 1) { + truthSimNode(iTemp); + if (objIsPo(iTemp)) + Tt_OrXor(_data->pCare, objTruth(iTemp, 0), objTruth(iTemp, 1), nWords()); + } + } else { + Vi_ForEachEntryStart(vTfo, iTemp, i, 1) { + truthSimNode(iTemp); + if (objIsPo(iTemp)) + Tt_OrXorAnd(_data->pCare, objTruth(iTemp, 0), objTruth(iTemp, 1), pExc + objPoIdx(iTemp) * nWords(), nWords()); + } } return _data->pCare; } @@ -916,13 +957,13 @@ int Miaig::findShared(int nNewNodesMax) { return i; } -int Miaig::checkConst(int iObj, word *pCare, int fVerbose) { +int Miaig::checkConst(int iObj, word *pCare, word *pExc, int fCheck, int fVerbose) { word *pFunc = objTruth(iObj, 0); if (!Tt_IntersectC(pCare, pFunc, 0, nWords())) { derefObj_rec(iObj, -1); Vi_Fill(_data->pvFans + iObj, 1, 0); // const0 refObj(iObj); - truthUpdate(_data->vTfo); + truthUpdate(_data->vTfo, pExc, fCheck); if (fVerbose) printf("Detected Const0 at node %d.\n", iObj); return 1; } @@ -930,16 +971,16 @@ int Miaig::checkConst(int iObj, word *pCare, int fVerbose) { derefObj_rec(iObj, -1); Vi_Fill(_data->pvFans + iObj, 1, 1); // const1 refObj(iObj); - truthUpdate(_data->vTfo); + truthUpdate(_data->vTfo, pExc, fCheck); if (fVerbose) printf("Detected Const1 at node %d.\n", iObj); return 1; } return 0; } -int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, int fVerbose) { +int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose) { int i, k, n, iLit, nAdded = 0; - word *pCare = computeCareSet(iObj); + word *pCare = computeCareSet(iObj, pExc); assert(nAddedMax > 0); assert(nAddedMax <= Vi_Space(_data->pvFans + iObj)); // mark node's fanins @@ -986,15 +1027,15 @@ int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, i break; } //printf( "Updating TFO of node %d: ", iObj ); Vi_Print(_data->vTfo); - truthUpdate(_data->vTfo); + truthUpdate(_data->vTfo, pExc, fCheck); //assert( objFaninNum(iObj) <= nFaninMax ); return nAdded; } -int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, int fVerbose) { +int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, word *pExc, int fCheck, int fVerbose) { int n, k, iLit, nFans = objFaninNum(iObj); - word *pCare = computeCareSet(iObj); - if (checkConst(iObj, pCare, fVerbose)) + word *pCare = computeCareSet(iObj, pExc); + if (checkConst(iObj, pCare, pExc, fCheck, fVerbose)) return nFans; if (fOnlyConst) return 0; @@ -1008,7 +1049,7 @@ int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, derefObj(iObj); Vi_Fill(_data->pvFans + iObj, 1, iLit); refObj(iObj); - truthUpdate(_data->vTfo); + truthUpdate(_data->vTfo, pExc, fCheck); if (fVerbose) printf("Reducing node %d fanin count from %d to %d.\n", iObj, nFans, objFaninNum(iObj)); return nFans - 1; } @@ -1049,16 +1090,16 @@ int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, Vi_ForEachEntry(_data->vOrderF, iLit, k) Vi_PushOrder(_data->pvFans + iObj, iLit); refObj(iObj); - truthUpdate(_data->vTfo); + truthUpdate(_data->vTfo, pExc, fCheck); if (fVerbose) printf("Reducing node %d fanin count from %d to %d.\n", iObj, nFans, objFaninNum(iObj)); return nFans - Vi_Size(_data->vOrderF); } return 0; } -int Miaig::expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int nExpandableLevel, int fVerbose) { - expandOne(iNode, Abc_MinInt(Vi_Space(_data->pvFans + iNode), nFaninAddLimit), nDist, nExpandableLevel, fVerbose); - reduceOne(iNode, 0, 0, 0, fVerbose); +int Miaig::expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose) { + expandOne(iNode, Abc_MinInt(Vi_Space(_data->pvFans + iNode), nFaninAddLimit), nDist, nExpandableLevel, pExc, fCheck, fVerbose); + reduceOne(iNode, 0, 0, 0, pExc, fCheck, fVerbose); return 0; } @@ -1071,7 +1112,7 @@ vi *Miaig::createRandomOrder(void) { return _data->vOrder; } -Miaig Miaig::expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, int fVerbose) { +Miaig Miaig::expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose) { int i, iNode, nAdded = 0; assert(nFaninAddLimitAll > 0); vi *vOrder = createRandomOrder(); @@ -1081,7 +1122,7 @@ Miaig Miaig::expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, int initializeLevels(); if (nDist) initializeDists(); Vi_ForEachEntry(vOrder, iNode, i) { - nAdded += expandOne(iNode, Abc_MinInt(Vi_Space(_data->pvFans + iNode), nFaninAddLimitAll - nAdded), nDist, nExpandableLevel, fVerbose); + nAdded += expandOne(iNode, Abc_MinInt(Vi_Space(_data->pvFans + iNode), nFaninAddLimitAll - nAdded), nDist, nExpandableLevel, pExc, fCheck, fVerbose); if (nAdded >= nFaninAddLimitAll) break; } @@ -1103,7 +1144,7 @@ Miaig Miaig::share(int nNewNodesMax) { return pNew; } -Miaig Miaig::reduce(int fVerbose) { +Miaig Miaig::reduce(word *pExc, int fCheck, int fVerbose) { int i, iNode; vi *vOrder = topoCollect(); @@ -1112,12 +1153,12 @@ Miaig Miaig::reduce(int fVerbose) { initializeLevels(); // works best for final Vi_ForEachEntry(vOrder, iNode, i) - reduceOne(iNode, 0, 0, 1, fVerbose); + reduceOne(iNode, 0, 0, 1, pExc, fCheck, fVerbose); verifyRefs(); return dupStrash(1, 1, 1); } -Miaig Miaig::expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLevel, int fVerbose) { +Miaig Miaig::expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose) { Miaig pTemp; int i, iNode; vi *vOrder = topoCollect(); @@ -1127,19 +1168,19 @@ Miaig Miaig::expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLeve initializeLevels(); if (nDist) initializeDists(); Vi_ForEachEntry(vOrder, iNode, i) { - expandThenReduceOne(iNode, nFaninAddLimit, nDist, nExpandableLevel, fVerbose); + expandThenReduceOne(iNode, nFaninAddLimit, nDist, nExpandableLevel, pExc, fCheck, fVerbose); } verifyRefs(); return dupDfs().dupStrash(1, 1, 1); } -Miaig Miaig::expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nExpandableLevel, int nVerbose) { +Miaig Miaig::expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nExpandableLevel, word *pExc, int fCheck, int nVerbose) { // expand - Miaig pNew = expand(nFaninAddLimitAll, nDist, nExpandableLevel, nVerbose); + Miaig pNew = expand(nFaninAddLimitAll, nDist, nExpandableLevel, pExc, fCheck, nVerbose); // share pNew = pNew.share(nDivs == -1 ? pNew.nObjs() : nDivs); // reduce - pNew = pNew.reduce(nVerbose); + pNew = pNew.reduce(pExc, fCheck, nVerbose); return pNew; } @@ -1156,7 +1197,7 @@ Miaig randomRead(std::vector &pBests) { return pBests[Random_Num(0) % pBests.size()]; } -Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nVerbose) { +Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int fCheck, int nVerbose) { const int nRootSave = 8; const int nBestSave = 4; int nRestart = 5000; @@ -1169,6 +1210,7 @@ Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, float (Miaig::*Miaig_ObjectiveFunction)(int, int) = (nMode == 0) ? &Miaig::countAnd2 : &Miaig::countTransistors; int maxLevel = levelGrowRatio != 0 ? this->countLevel() * levelGrowRatio : 0; int nExpandableLevel = maxLevel ? maxLevel - this->countLevel() : 0; + word *pExc = _data->pExc; float PrevBest = ((&pBest)->*Miaig_ObjectiveFunction)(1, nMappedMode); int iterNotImproveAfterRestart = 0; @@ -1180,9 +1222,9 @@ Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, pNew = pRoot.dupMulti(nFaninMax, nGrowth); if (i % 2 == 0) { - pNew = pNew.expandThenReduce(nGrowth, nDist, nExpandableLevel, nVerbose > 1); + pNew = pNew.expandThenReduce(nGrowth, nDist, nExpandableLevel, pExc, fCheck, nVerbose > 1); } - pNew = pNew.expandShareReduce(nExpands, nDivs, nDist, nExpandableLevel, nVerbose > 1); + pNew = pNew.expandShareReduce(nExpands, nDivs, nDist, nExpandableLevel, pExc, fCheck, nVerbose > 1); ++iterNotImproveAfterRestart; // report @@ -1204,7 +1246,7 @@ Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, } else if (rootTarget < newTarget) { if (iterNotImproveAfterRestart > nRestart) { pNew = randomRead(pBests).dupMulti(nFaninMax, nGrowth); - pNew = pNew.expand(nExpands, nDist, nExpandableLevel, nVerbose > 1); + pNew = pNew.expand(nExpands, nDist, nExpandableLevel, pExc, fCheck, nVerbose > 1); pNew = pNew.share(nDivs == -1 ? pNew.nObjs() : nDivs); pNew = pNew.dupStrash(1, 1, 0); pRoots = {pNew}; diff --git a/src/opt/rar/rewire_miaig.h b/src/opt/rar/rewire_miaig.h index 7cec02054..bdfd532fa 100644 --- a/src/opt/rar/rewire_miaig.h +++ b/src/opt/rar/rewire_miaig.h @@ -157,6 +157,7 @@ struct Miaig_Data { word *pTruths[3]; // truth tables word *pCare; // careset word *pProd; // product + word *pExc; // Exc vi *vOrder; // node order vi *vOrderF; // fanin order vi *vOrderF2; // fanin order @@ -181,6 +182,11 @@ public: Miaig(Mini_Aig_t *pMiniAig); #endif // RW_ABC +public: +#ifdef RW_ABC + void setExc(Gia_Man_t *pExc); +#endif // RW_ABC + public: void addref(void); void release(void); @@ -200,6 +206,8 @@ public: int objIsPi(int i); int objIsPo(int i); int objIsNode(int i); + int objPiIdx(int i); // No check isPi + int objPoIdx(int i); // No check isPo void print(void); int appendObj(void); void appendFanin(int i, int iLit); @@ -238,14 +246,14 @@ private: void reduceFanins(vi *v); int *createStops(void); void collectSuper_rec(int iLit, int *pStop, vi *vSuper); - int checkConst(int iObj, word *pCare, int fVerbose); + int checkConst(int iObj, word *pCare, word *pExc, int fCheck, int fVerbose); void truthSimNode(int i); word *truthSimNodeSubset(int i, int m); word *truthSimNodeSubset2(int i, vi *vFanins, int nFanins); - void truthUpdate(vi *vTfo); + void truthUpdate(vi *vTfo, word *pExc = NULL, int fCheck = 0); int computeTfo_rec(int iObj); vi *computeTfo(int iObj); - word *computeCareSet(int iObj); + word *computeCareSet(int iObj, word *pExc = NULL); vi *createRandomOrder(void); void addPair(vi *vPair, int iFan1, int iFan2); int findPair(vi *vPair); @@ -272,22 +280,22 @@ private: int buildNodeCascade(Miaig &pNew, vi *vFanins, int fCprop, int fStrash); private: - int expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, int fVerbose); - int reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, int fVerbose); - int expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int nExpandableLevel, int fVerbose); + int expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose); + int reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, word *pExc, int fCheck, int fVerbose); + int expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose); public: Miaig dup(int fRemDangle, int fMapped = 0); Miaig dupDfs(void); Miaig dupStrash(int fCprop, int fStrash, int fCascade); Miaig dupMulti(int nFaninMax_, int nGrowth); - Miaig expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, int nVerbose); + Miaig expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, word *pExc, int fCheck, int nVerbose); Miaig share(int nNewNodesMax); - Miaig reduce(int fVerbose); - Miaig expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLevel, int fVerbose); - Miaig expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nExpandableLevel, int nVerbose); - Miaig rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nVerbose); - #ifdef RW_ABC + Miaig reduce(word *pExc, int fCheck, int fVerbose); + Miaig expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose); + Miaig expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nExpandableLevel, word *pExc, int fCheck, int nVerbose); + Miaig rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int fCheck, int nVerbose); +#ifdef RW_ABC Gia_Man_t *toGia(void); Abc_Ntk_t *toNtk(int fMapped = 0); Mini_Aig_t *toMiniAig(void); @@ -373,6 +381,7 @@ inline void Miaig::release(void) { free(_data->pTruths[0]); if (_data->pCare) free(_data->pCare); if (_data->pProd) free(_data->pProd); + if (_data->pExc) free(_data->pExc); if (_data->pLevel) free(_data->pLevel); if (_data->pDist) free(_data->pDist); if (_data->pTable) free(_data->pTable); @@ -413,6 +422,16 @@ inline int Miaig::objIsNode(int i) { return i > _data->nIns && i < _data->nObjs - _data->nOuts; } +inline int Miaig::objPiIdx(int i) { + // assert(objIsPi(i)); + return i - 1; +} + +inline int Miaig::objPoIdx(int i) { + // assert(objIsPo(i)); + return i - (_data->nObjs - _data->nOuts); +} + inline int Miaig::appendObj(void) { assert(_data->nObjs < _data->nObjsAlloc); return _data->nObjs++; diff --git a/src/opt/rar/rewire_rar.c b/src/opt/rar/rewire_rar.c index c9c23f6d3..d0f51e746 100644 --- a/src/opt/rar/rewire_rar.c +++ b/src/opt/rar/rewire_rar.c @@ -22,16 +22,16 @@ ABC_NAMESPACE_IMPL_START -Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose) { - return Gia_ManRewireInt(pGia, nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fVerbose); +Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose) { + return Gia_ManRewireInt(pGia, pExc, nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fCheck, fVerbose); } -Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose) { - return Abc_ManRewireInt(pNtk, nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fVerbose); +Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose) { + return Abc_ManRewireInt(pNtk, pExc, nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fCheck, fVerbose); } -Mini_Aig_t *MiniAig_ManRewire(Mini_Aig_t *pAig, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose) { - return MiniAig_ManRewireInt(pAig, nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fVerbose); +Mini_Aig_t *MiniAig_ManRewire(Mini_Aig_t *pAig, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose) { + return MiniAig_ManRewireInt(pAig, pExc, nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fCheck, fVerbose); } ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/opt/rar/rewire_rar.h b/src/opt/rar/rewire_rar.h index dfe47712f..15a19d8c6 100644 --- a/src/opt/rar/rewire_rar.h +++ b/src/opt/rar/rewire_rar.h @@ -35,12 +35,12 @@ ABC_NAMESPACE_HEADER_START -Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose); -Gia_Man_t *Gia_ManRewireInt(Gia_Man_t *pGia, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose); -Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose); -Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose); -Mini_Aig_t *MiniAig_ManRewire(Mini_Aig_t *pAig, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose); -Mini_Aig_t *MiniAig_ManRewireInt(Mini_Aig_t *pAig, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose); +Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose); +Gia_Man_t *Gia_ManRewireInt(Gia_Man_t *pGia, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose); +Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose); +Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose); +Mini_Aig_t *MiniAig_ManRewire(Mini_Aig_t *pAig, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose); +Mini_Aig_t *MiniAig_ManRewireInt(Mini_Aig_t *pAig, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose); ABC_NAMESPACE_HEADER_END diff --git a/src/opt/rar/rewire_tt.h b/src/opt/rar/rewire_tt.h index 49fb9a0cd..ea8cc578c 100644 --- a/src/opt/rar/rewire_tt.h +++ b/src/opt/rar/rewire_tt.h @@ -152,6 +152,12 @@ static inline void Tt_OrXor(word *pOut, word *pIn1, word *pIn2, int nWords) { pOut[w] |= pIn1[w] ^ pIn2[w]; } +static inline void Tt_OrXorAnd(word *pOut, word *pIn1, word *pIn2, word *pIn3, int nWords) { + int w; + for (w = 0; w < nWords; w++) + pOut[w] |= (pIn1[w] ^ pIn2[w]) & pIn3[w]; +} + static inline int Tt_WordNum(int n) { return n > 6 ? (1 << (n - 6)) : 1; } From 83150e65494b352c92770a05274f526f5418ff76 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 9 Apr 2025 08:46:38 -0700 Subject: [PATCH 04/72] Enable overlapping partitions in "stochmap". --- src/base/abci/abcPart.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/base/abci/abcPart.c b/src/base/abci/abcPart.c index 81a051c2b..88f3d8c94 100644 --- a/src/base/abci/abcPart.c +++ b/src/base/abci/abcPart.c @@ -1467,7 +1467,7 @@ void Abc_NtkInsertPartitions_rec( Abc_Ntk_t * pNew, Abc_Obj_t * pObj, Vec_Int_t pNode->pCopy = Abc_ObjFanin0(Abc_NtkPo(pWin, i))->pCopy; assert( pObj->pCopy ); } -Abc_Ntk_t * Abc_NtkInsertPartitions( Abc_Ntk_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins, int fOverlap, Vec_Int_t * vGains ) +Abc_Ntk_t * Abc_NtkInsertPartitions( Abc_Ntk_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvNodes, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins, int fOverlap, Vec_Int_t * vGains ) { if ( vvIns == NULL ) { assert( vvOuts == NULL ); @@ -1493,16 +1493,12 @@ Abc_Ntk_t * Abc_NtkInsertPartitions( Abc_Ntk_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t Vec_IntForEachEntry( vGains, Gain, i ) { if ( Gain <= 0 ) continue; - Vec_Int_t * vIns = (Vec_Int_t *)Vec_PtrEntry(vvIns, i); - Vec_Int_t * vOuts = (Vec_Int_t *)Vec_PtrEntry(vvOuts, i); - Abc_Obj_t * pNode; int j, k; - Abc_NtkForEachObjVec( vIns, p, pNode, j ) + Vec_Int_t * vNodes = (Vec_Int_t *)Vec_PtrEntry(vvNodes, i); + Abc_Obj_t * pNode; int j; + Abc_NtkForEachObjVec( vNodes, p, pNode, j ) if ( Abc_NodeIsTravIdCurrent(pNode) ) break; - Abc_NtkForEachObjVec( vOuts, p, pNode, k ) - if ( Abc_NodeIsTravIdCurrent(pNode) ) - break; - if ( j < Vec_IntSize(vIns) || k < Vec_IntSize(vOuts) ) + if ( j < Vec_IntSize(vNodes) ) Vec_IntWriteEntry( vGains, i, -1 ); } } @@ -1764,8 +1760,8 @@ void Abc_NtKMarkTfiTfo( Vec_Int_t * vOne, Abc_Ntk_t * pNtk ) { int i; Abc_Obj_t * pObj; Abc_NtkForEachObjVec( vOne, pNtk, pObj, i ) { - Abc_NodeSetTravIdPrevious(pObj); - Abc_ObjDfsMark_rec( pObj ); + //Abc_NodeSetTravIdPrevious(pObj); + //Abc_ObjDfsMark_rec( pObj ); Abc_NodeSetTravIdPrevious(pObj); Abc_ObjDfsMark2_rec( pObj ); } @@ -1939,7 +1935,7 @@ void Abc_NtkStochMap( int nSuppMax, int nIters, int TimeOut, int Seed, int fOver Abc_Ntk_t * pNtk = Abc_NtkDupDfs(Abc_FrameReadNtk(Abc_FrameGetGlobalFrame())); Vec_Ptr_t * vWins = Abc_NtkExtractPartitions( pNtk, i, nSuppMax, &vIns, &vOuts, &vNodes, fOverlap ); Vec_Int_t * vGains = Abc_NtkStochProcess( vWins, pScript, nProcs, 0, 0 ); int nPartsInit = Vec_PtrSize(vWins); - Abc_Ntk_t * pNew = Abc_NtkInsertPartitions( pNtk, vIns, vOuts, vWins, fOverlap, vGains ); + Abc_Ntk_t * pNew = Abc_NtkInsertPartitions( pNtk, vIns, vNodes, vOuts, vWins, fOverlap, vGains ); Abc_FrameReplaceCurrentNetwork( Abc_FrameGetGlobalFrame(), pNew ); if ( fVerbose ) printf( "Iteration %3d : Using %3d -> %3d partitions. Reducing area from %.2f to %.2f. ", From c5fdfb38356c0e2c08aa9e938695a5824827fd9e Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 9 Apr 2025 18:16:24 -0700 Subject: [PATCH 05/72] New command "runscript". --- src/base/abci/abc.c | 109 ++++++++++++++++++++++++++++++++++++++ src/base/main/mainUtils.c | 6 +-- 2 files changed, 112 insertions(+), 3 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index f0ac69548..b91e9e560 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -146,6 +146,7 @@ static int Abc_CommandTestRand ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandRunSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRunScript ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -962,6 +963,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "runsat", Abc_CommandRunSat, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "runeco", Abc_CommandRunEco, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "rungen", Abc_CommandRunGen, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "runscript", Abc_CommandRunScript, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "xec", Abc_CommandRunTest, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 ); @@ -7681,6 +7683,113 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRunScript( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c, nIters = 10, nBeg = 0, nAdd = 1, fVerbose = 0; char * pScript = NULL, * pSpot = NULL; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IBASvh" ) ) != EOF ) + { + switch ( c ) + { + 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++; + break; + case 'B': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + nBeg = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); + goto usage; + } + nAdd = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by a script.\n" ); + goto usage; + } + pScript = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pScript == NULL ) + { + Abc_Print( -1, "Command line switch \"-S\" should be specified and followed by a string.\n" ); + goto usage; + } + pSpot = strstr( pScript, "*" ); + if ( pSpot == NULL ) + { + Abc_Print( -1, "Script should contain symbol \'*\'.\n" ); + goto usage; + } + assert( *pSpot == '*' ); + for ( c = 0; c < nIters; c++ ) + { + char pCommLine[1000] = {0}; + char pNumber[10] = {0}; + sprintf( pNumber, "%d", nBeg + c*nAdd ); + strcpy( pCommLine, pScript ); + pCommLine[(int)(pSpot - pScript)] = 0; + strcat( pCommLine, pNumber ); + strcat( pCommLine, pSpot+1 ); + if ( fVerbose ) + printf( "Iteration %3d : %s\n", c, pCommLine ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pCommLine) ) { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pCommLine ); + goto usage; + } + } + printf( "Finished iterating script %d times.\n", nIters ); + return 0; + +usage: + Abc_Print( -2, "usage: runscript [-IBA num] [-S str] [-vh]\n" ); + Abc_Print( -2, "\t running the script with different values\n" ); + Abc_Print( -2, "\t-I : the number of iterations [default = %d]\n", nIters ); + Abc_Print( -2, "\t-B : the starting number [default = %d]\n", nBeg ); + Abc_Print( -2, "\t-A : the increment added in each iteration [default = %d]\n", nAdd ); + Abc_Print( -2, "\t-S : the script to iterate [default = none]\n" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/base/main/mainUtils.c b/src/base/main/mainUtils.c index 22d0e8774..654d246f0 100644 --- a/src/base/main/mainUtils.c +++ b/src/base/main/mainUtils.c @@ -337,15 +337,15 @@ void Abc_FrameStorePrint( Abc_Frame_t * pAbc ) { if ( pAbc->pHash == NULL ) Abc_FrameStoreStart( pAbc ); - int i, Entry, Max = Vec_IntFindMax( pAbc->pHash->vValue ); + int i, Entry, nAll = 0, Max = Vec_IntFindMax( pAbc->pHash->vValue ); Vec_Int_t * vCounts = Vec_IntStart( Max+1 ); Vec_IntForEachEntry( pAbc->pHash->vValue, Entry, i ) Vec_IntAddToEntry( vCounts, Entry, 1 ); printf( "Distribution of %d stored items by reference count (=): ", Hsh_VecSize(pAbc->pHash) ); Vec_IntForEachEntry( vCounts, Entry, i ) if ( Entry ) - printf( "%d=%d ", i, Entry ); - printf( "\n" ); + printf( "%d=%d ", i, Entry ), nAll += i * Entry; + printf( "ALL=%d\n", nAll ); Vec_IntFree( vCounts ); } From d2714035145bd237097c509c23fc9e24b0fa933b Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 9 Apr 2025 21:23:44 -0700 Subject: [PATCH 06/72] Fixing a typo. --- src/base/abci/abcCas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index 4d34cce68..8ee79bffc 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -1238,7 +1238,7 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n printf( "Statistics for %d-rail LUT cascade:\n", nRails ); for ( i = 0; i < 100; i++ ) if ( LutStats[i] ) - printf( " %d LUT6 : Function count = %8d (%6.2f %%)\n", i, LutStats[i], 100.0*LutStats[i]/nFuncs ); + printf( " %2d LUT%d : Function count = %8d (%6.2f %%)\n", i, nLutSize, LutStats[i], 100.0*LutStats[i]/nFuncs ); printf( "Non-decomp : Function count = %8d (%6.2f %%)\n", nFuncs-Sum, 100.0*(nFuncs-Sum)/Abc_MaxInt(1, nFuncs) ); printf( "Finished %d functions (%.2f LUTs / function; %.2f functions / sec). ", nFuncs, 1.0*nTotalLuts/Sum, 1.0*nFuncs/(((double)(Abc_Clock() - clkStart))/((double)CLOCKS_PER_SEC)) ); From 43d12f6c31bc48c5cfebfa9b01cbcfeb0f9697ec Mon Sep 17 00:00:00 2001 From: jiunhaochen Date: Thu, 10 Apr 2025 16:57:13 +0800 Subject: [PATCH 07/72] command rewire add external careset --- src/base/abci/abc.c | 13 +++++++++---- src/opt/rar/rewire_miaig.cpp | 10 +++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index dcb67140a..602c6846b 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -20888,14 +20888,14 @@ int Abc_CommandRewire( Abc_Frame_t * pAbc, int argc, char ** argv ) pFile = fopen( argv[globalUtilOptind], "rb" ); if ( pFile == NULL ) { - Abc_Print( -1, "Cannot open input file \"%s\". ", argv[globalUtilOptind] ); + Abc_Print( -1, "Cannot open input file \"%s\".\n", argv[globalUtilOptind] ); return 1; } fclose( pFile ); pExc = Gia_AigerRead( argv[globalUtilOptind], 0, 0, 0 ); if ( pExc == NULL ) { - Abc_Print( -1, "Reading Exc AIGER has failed.\n" ); + Abc_Print( -1, "Reading AIGER has failed.\n" ); return 1; } globalUtilOptind++; @@ -20927,6 +20927,11 @@ int Abc_CommandRewire( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Empty network.\n" ); return 1; } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Rewiring works only for the AIG representation (run \"strash\").\n" ); + return 1; + } if ( nMode >= 1 && Abc_FrameReadLibGen2() == NULL ) { Abc_Print( -1, "Library is not available.\n" ); @@ -46572,14 +46577,14 @@ int Abc_CommandAbc9Rewire( Abc_Frame_t * pAbc, int argc, char ** argv ) pFile = fopen( argv[globalUtilOptind], "rb" ); if ( pFile == NULL ) { - Abc_Print( -1, "Cannot open input file \"%s\". ", argv[globalUtilOptind] ); + Abc_Print( -1, "Cannot open input file \"%s\".\n", argv[globalUtilOptind] ); return 1; } fclose( pFile ); pExc = Gia_AigerRead( argv[globalUtilOptind], 0, 0, 0 ); if ( pExc == NULL ) { - Abc_Print( -1, "Reading Exc AIGER has failed.\n" ); + Abc_Print( -1, "Reading AIGER has failed.\n" ); return 1; } globalUtilOptind++; diff --git a/src/opt/rar/rewire_miaig.cpp b/src/opt/rar/rewire_miaig.cpp index dffb29fa7..813a8ef80 100644 --- a/src/opt/rar/rewire_miaig.cpp +++ b/src/opt/rar/rewire_miaig.cpp @@ -247,15 +247,18 @@ vi *moveVecToVi(Vec_Int_t *v) { void Miaig::setExc(Gia_Man_t *pExc) { int i; assert(Gia_ManCiNum(pExc) == nIns()); - assert(Gia_ManCoNum(pExc) == nOuts()); + assert(Gia_ManCoNum(pExc) == nOuts() || Gia_ManCoNum(pExc) == 1); + if (Gia_ManCoNum(pExc) != nOuts() && Gia_ManCoNum(pExc) == 1) { + printf("[Warning] The external careset has only a single output that will be applied to all other outputs.\n"); + } if (!_data->pExc) { _data->pExc = (word *)malloc(sizeof(word) * nWords() * nOuts()); } Miaig Exc(pExc); Exc.initializeTruth(); for (i = 0; i < nOuts(); ++i) { - word *pExc = Exc.objTruth(Exc.nObjs() - Exc.nOuts() + i, 0); - Tt_Dup(_data->pExc + nWords() * i, pExc, nWords()); + word *tExc = Exc.objTruth(Exc.nObjs() - Exc.nOuts() + std::min(i, Gia_ManCoNum(pExc)-1), 0); + Tt_Dup(_data->pExc + nWords() * i, tExc, nWords()); } } #endif // RW_ABC @@ -1219,6 +1222,7 @@ Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, for (int i = 0; nIters ? i < nIters : 1; i++) { if (nVerbose) printf("\rIteration %7d : %5g -> ", i + 1, ((&pRoot)->*Miaig_ObjectiveFunction)(0, nMappedMode)); if (nTimeOut && nTimeOut < 1.0 * (Time_Clock() - clkStart) / CLOCKS_PER_SEC) break; + if (PrevBest == 0) break; pNew = pRoot.dupMulti(nFaninMax, nGrowth); if (i % 2 == 0) { From 2179034f232aff75f9596ce0c01e39d527a8e45e Mon Sep 17 00:00:00 2001 From: jiunhaochen Date: Thu, 10 Apr 2025 17:24:27 +0800 Subject: [PATCH 08/72] command rewire fix condition --- src/base/abci/abc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 602c6846b..83e5d2231 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -20927,7 +20927,7 @@ int Abc_CommandRewire( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Empty network.\n" ); return 1; } - if ( !Abc_NtkIsStrash(pNtk) ) + if ( nMode == 0 && !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Rewiring works only for the AIG representation (run \"strash\").\n" ); return 1; From 1a1bdbe4c8e5a58fcf24d4a28f020ffeb9f2792b Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 10 Apr 2025 07:03:19 -0700 Subject: [PATCH 09/72] Another typo. --- src/base/abci/abc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 83e5d2231..0be8b8e38 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -7696,7 +7696,7 @@ usage: ***********************************************************************/ int Abc_CommandRunScript( Abc_Frame_t * pAbc, int argc, char ** argv ) { - int c, nIters = 10, nBeg = 0, nAdd = 1, fVerbose = 0; char * pScript = NULL, * pSpot = NULL; + int c, nIters = 10, nBeg = 1, nAdd = 1, fVerbose = 0; char * pScript = NULL, * pSpot = NULL; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "IBASvh" ) ) != EOF ) { From 47ac9f75cad71a6c95ee17ec232522dfd565d2cc Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 15 Apr 2025 20:00:19 -0700 Subject: [PATCH 10/72] New command "&andcare" to AND the miter with the careset. --- src/aig/gia/giaDup.c | 44 +++++++++++++++++++++++++++++++ src/base/abci/abc.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 87f2bb74c..4468dfb52 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -3250,6 +3250,50 @@ Gia_Man_t * Gia_ManDupAndOr( Gia_Man_t * p, int nOuts, int fUseOr, int fCompl ) return pNew; } +/**Function************************************************************* + + Synopsis [Computes the AND of all POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupAndCare( Gia_Man_t * p, Gia_Man_t * pCare ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; int i; + assert( Gia_ManRegNum(p) == 0 ); + assert( Gia_ManRegNum(pCare) == 0 ); + assert( Gia_ManPiNum(p) == Gia_ManPiNum(pCare) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManConst0(p)->Value = 0; + Gia_ManConst0(pCare)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManPi(pCare, i)->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachAnd( pCare, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( Gia_ManPoNum(pCare) == 1 ) { + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(Gia_ManPo(pCare, 0)) ) ); + } + else if ( Gia_ManPoNum(p) == Gia_ManPoNum(pCare) ) { + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(Gia_ManPo(pCare, i)) ) ); + } + else assert( 0 ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + /**Function************************************************************* Synopsis [Transforms output names.] diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 0be8b8e38..f12c9db81 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -640,6 +640,7 @@ static int Abc_CommandAbc9FunAbs ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9DsdInfo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9FunTrace ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9MulFind ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9AndCare ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1462,6 +1463,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&dsdinfo", Abc_CommandAbc9DsdInfo, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&funtrace", Abc_CommandAbc9FunTrace, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&mulfind", Abc_CommandAbc9MulFind, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&andcare", Abc_CommandAbc9AndCare, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); @@ -56930,6 +56932,66 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9AndCare( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupAndCare( Gia_Man_t * p, Gia_Man_t * pCare ); + Gia_Man_t * pTemp = NULL, * pCare = NULL; int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9AndCare(): There is no AIG.\n" ); + return 0; + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( 1,"Abc_CommandAbc9AndCare(): There is no careset AIG.\n" ); + return 0; + } + pCare = Gia_AigerRead( argv[globalUtilOptind], 0, 0, 0 ); + if ( pCare == NULL ) + Abc_Print( -1, "Abc_CommandAbc9AndCare(): Reading careset from file has failed.\n" ); + else if ( Gia_ManPiNum(pAbc->pGia) != Gia_ManPiNum(pCare) ) + Abc_Print( -1, "Abc_CommandAbc9AndCare(): Careset should have the same number of primary inputs.\n" ); + else { + pTemp = Gia_ManDupAndCare( pAbc->pGia, pCare ); + Abc_FrameUpdateGia( pAbc, pTemp ); + } + Gia_ManStop( pCare ); + return 0; + +usage: + Abc_Print( -2, "usage: &andcare [-vh] \n" ); + Abc_Print( -2, "\t computes the conjunction of each primary output with the careset\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose ? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : input AIG file with the careset\n"); + return 1; +} + /**Function************************************************************* From dcf9079507f68107630246696b1a0dcac4767c9c Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 15 Apr 2025 21:56:24 -0700 Subject: [PATCH 11/72] Extending "stochmap" to work for AIGs. --- src/base/abci/abc.c | 29 ++++++++++++++++++++++++++++- src/base/abci/abcPart.c | 2 +- src/map/mio/mio.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index f12c9db81..17c857c1f 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -20309,7 +20309,8 @@ usage: ***********************************************************************/ int Abc_CommandStochMap( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Ntk_t * pNtkRes = NULL, * pNtk = Abc_FrameReadNtk(pAbc); + extern void Mio_IntallAndLibrary(); extern void Abc_NtkStochMap( int nSuppMax, int nIters, int TimeOut, int Seed, int fOverlap, int fVerbose, char * pScript, int nProcs ); int c, nMaxSize = 14, nIters = 1, TimeOut = 0, Seed = 0, nProcs = 1, fOverlap = 0, fVerbose = 0; char * pScript; Extra_UtilGetoptReset(); @@ -20389,6 +20390,21 @@ int Abc_CommandStochMap( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandStochMap(): There is no AIG.\n" ); return 0; } + if ( Abc_NtkIsStrash(pNtk) ) + { + extern Abc_Ntk_t * Abc_NtkDarAmap( Abc_Ntk_t * pNtk, Amap_Par_t * pPars ); + Amap_Par_t Pars, * pPars = &Pars; + Amap_ManSetDefaultParams( pPars ); + Mio_IntallAndLibrary(); + pNtkRes = Abc_NtkDarAmap( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Mapping has failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + pNtk = Abc_FrameReadNtk(pAbc); + } if ( !Abc_NtkIsMappedLogic(pNtk) ) { Abc_Print( -1, "Abc_CommandStochMap(): Expecting a mapped current newtork as input.\n" ); @@ -20402,6 +20418,17 @@ int Abc_CommandStochMap( Abc_Frame_t * pAbc, int argc, char ** argv ) pScript = Abc_UtilStrsav( argv[globalUtilOptind] ); Abc_NtkStochMap( nMaxSize, nIters, TimeOut, Seed, fOverlap, fVerbose, pScript, nProcs ); ABC_FREE( pScript ); + if ( pNtkRes ) + { + pNtk = Abc_FrameReadNtk(pAbc); + pNtkRes = Abc_NtkStrash( pNtk, 1, 1, 0 ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Strashing has failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } return 0; usage: diff --git a/src/base/abci/abcPart.c b/src/base/abci/abcPart.c index 88f3d8c94..19ac3aba8 100644 --- a/src/base/abci/abcPart.c +++ b/src/base/abci/abcPart.c @@ -1481,7 +1481,7 @@ Abc_Ntk_t * Abc_NtkInsertPartitions( Abc_Ntk_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t Abc_NtkIncrementTravId( p ); while ( 1 ) { int i, Gain, iEntry = Vec_IntArgMax(vGains); - if ( Vec_IntEntry(vGains, iEntry) <= 0 ) + if ( iEntry == -1 || Vec_IntEntry(vGains, iEntry) <= 0 ) break; //printf( "Selecting partition %d with gain %d.\n", iEntry, Vec_IntEntry(vGains, iEntry) ); Vec_IntWriteEntry( vGains, iEntry, -1 ); diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c index 8c5f38953..e06d3f6ea 100644 --- a/src/map/mio/mio.c +++ b/src/map/mio/mio.c @@ -73,6 +73,23 @@ static char * pMcncGenlib[] = { }; */ +// internal version of genlib library +static char * pAndGenlib[] = { + "GATE zero 0 O=CONST0;\n", + "GATE one 0 O=CONST1;\n", + "GATE buf 1 O=a; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n", + "GATE inv 1 O=!a; PIN * INV 1 999 1.0 0.0 1.0 0.0\n", + "GATE and00 1 O=a*b; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n", + "GATE and01 1 O=a*!b; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n", + "GATE and10 1 O=!a*b; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n", + "GATE and11 1 O=!a*!b; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n", + "GATE nand00 1 O=!(a*b); PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n", + "GATE nand01 1 O=!(a*!b); PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n", + "GATE nand10 1 O=!(!a*b); PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n", + "GATE nand11 1 O=!(!a*!b); PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n", + NULL +}; + // internal version of genlib library static char * pSimpleGenlib[] = { "GATE zero 0 O=CONST0;\n", @@ -126,6 +143,20 @@ static char * pSimpleGenlib2[] = { SeeAlso [] ***********************************************************************/ +void Mio_IntallAndLibrary() +{ + extern Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int nFaninLimit, int fVerbose ); + Vec_Str_t * vLibStr = Vec_StrAlloc( 1000 ); + for ( int i = 0; pAndGenlib[i]; i++ ) + Vec_StrAppend( vLibStr, pAndGenlib[i] ); + Vec_Str_t * vLibStr2 = Vec_StrDup( vLibStr ); + Vec_StrAppend( vLibStr2, ".end\n" ); + Vec_StrPush( vLibStr2, '\0' ); + Vec_StrPush( vLibStr, '\0' ); + Mio_UpdateGenlib2( vLibStr, vLibStr2, "and.genlib", 0 ); + Vec_StrFree( vLibStr ); + Vec_StrFree( vLibStr2 ); +} void Mio_IntallSimpleLibrary() { extern Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int nFaninLimit, int fVerbose ); From 6c37cc9ac3dbea013c5611eb1b97fcbcc8251f64 Mon Sep 17 00:00:00 2001 From: jiunhaochen Date: Thu, 17 Apr 2025 04:58:32 +0800 Subject: [PATCH 12/72] rewire restructured even if the cost is not improved --- src/opt/rar/rewire_miaig.cpp | 20 +++++++++++++------- src/opt/rar/rewire_miaig.h | 5 +++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/opt/rar/rewire_miaig.cpp b/src/opt/rar/rewire_miaig.cpp index 813a8ef80..7ff05cccc 100644 --- a/src/opt/rar/rewire_miaig.cpp +++ b/src/opt/rar/rewire_miaig.cpp @@ -1200,19 +1200,25 @@ Miaig randomRead(std::vector &pBests) { return pBests[Random_Num(0) % pBests.size()]; } +Miaig randomReadExcept(std::vector &pBests, Miaig &pExcept) { + int iNum = Random_Num(0) % pBests.size(); + return (pBests[iNum] == pExcept) ? pBests[(iNum + 1) % pBests.size()] : pBests[iNum]; +} + Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int fCheck, int nVerbose) { const int nRootSave = 8; const int nBestSave = 4; int nRestart = 5000; std::vector pRoots = {this->dup(0)}; - std::vector pBests = {this->dup(0)}; + std::vector pBests = {this->dup(0)}; Miaig pInit = pBests[0]; iword clkStart = Time_Clock(); Miaig pNew; Miaig pRoot = pRoots[0]; - Miaig pBest = this->dup(0); + Miaig pBest = this->dup(0); int improved = 0; float (Miaig::*Miaig_ObjectiveFunction)(int, int) = (nMode == 0) ? &Miaig::countAnd2 : &Miaig::countTransistors; int maxLevel = levelGrowRatio != 0 ? this->countLevel() * levelGrowRatio : 0; int nExpandableLevel = maxLevel ? maxLevel - this->countLevel() : 0; + int fMapped = nMode > 0; word *pExc = _data->pExc; float PrevBest = ((&pBest)->*Miaig_ObjectiveFunction)(1, nMappedMode); @@ -1220,7 +1226,7 @@ Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, if (nVerbose && maxLevel) printf("Max level : %5d\n", maxLevel); if (nVerbose) printf("Initial target : %5g (AND2 = %5g Level = %3d)\n", PrevBest, this->countAnd2(1), this->countLevel()); for (int i = 0; nIters ? i < nIters : 1; i++) { - if (nVerbose) printf("\rIteration %7d : %5g -> ", i + 1, ((&pRoot)->*Miaig_ObjectiveFunction)(0, nMappedMode)); + if (nVerbose) printf("\rIteration %7d(%zu) : %5g -> ", i + 1, pBests.size(), ((&pRoot)->*Miaig_ObjectiveFunction)(0, nMappedMode)); if (nTimeOut && nTimeOut < 1.0 * (Time_Clock() - clkStart) / CLOCKS_PER_SEC) break; if (PrevBest == 0) break; pNew = pRoot.dupMulti(nFaninMax, nGrowth); @@ -1239,11 +1245,11 @@ Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, if (nVerbose) printf("%5g (AND2 = %5g Level = %3d) ", newTarget, pNew.countAnd2(), pNew.countLevel()); if (nVerbose) Time_PrintEndl("Elapsed time", Time_Clock() - clkStart); PrevBest = newTarget; - pBests = {pNew.dup(0), pNew.dup(0)}; - pBest = pNew.dup(0, 1); + pBests = {pNew.dup(0, fMapped), pNew.dup(0, fMapped)}; + pBest = pNew.dup(0, fMapped), improved = 1; iterNotImproveAfterRestart = 0; } else if (PrevBest == newTarget) { - randomAddBest(pBests, pNew.dup(0), nBestSave); + randomAddBest(pBests, pNew.dup(0, fMapped), nBestSave); } // compare if (maxLevel ? pNew.countLevel() > maxLevel : 0) { @@ -1266,7 +1272,7 @@ Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, pRoot = randomRead(pRoots); } if (nVerbose) Time_PrintEndl("Total solving time", Time_Clock() - clkStart); - return pBest; + return improved ? pBest : randomReadExcept(pBests, pInit); } } // namespace Rewire diff --git a/src/opt/rar/rewire_miaig.h b/src/opt/rar/rewire_miaig.h index bdfd532fa..112332c2d 100644 --- a/src/opt/rar/rewire_miaig.h +++ b/src/opt/rar/rewire_miaig.h @@ -190,6 +190,7 @@ public: public: void addref(void); void release(void); + bool operator==(const Miaig &m) const; private: void create(int nIns, int nOuts, int nObjsAlloc); @@ -394,6 +395,10 @@ inline void Miaig::release(void) { _refcount = nullptr; } +inline bool Miaig::operator==(const Miaig &m) const { + return (_data == m._data); +} + inline int &Miaig::nIns(void) { return _data->nIns; } From 1626a337a1f4d78c8b6eea79096334f3014b1dcb Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 16 Apr 2025 16:35:23 -0700 Subject: [PATCH 13/72] Adding random seed to "lutcasdec". --- src/base/abci/abc.c | 32 ++++-- src/base/abci/abcCas.c | 223 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 242 insertions(+), 13 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 17c857c1f..3d47d11e1 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -9167,12 +9167,12 @@ usage: 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 ); - extern void Abc_NtkLutCascadeFile( char * pFileName, int nVarNum, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, int fVeryVerbose ); + extern Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int Seed, int fVerbose, char * pGuide ); + extern void Abc_NtkLutCascadeFile( char * pFileName, int nVarNum, int nLutSize, int nLuts, int nRails, int nIters, int Seed, int fVerbose, int fVeryVerbose ); 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 = 10, fGen = 0, fVerbose = 0, fVeryVerbose = 0; + int c, nVarNum = -1, nLutSize = 6, nStages = 8, nRails = 1, nShared = 2, Seed = 0, nIters = 10, fGen = 0, fVerbose = 0, fVeryVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KMRSINFgvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KMRSCINFgvwh" ) ) != EOF ) { switch ( c ) { @@ -9209,15 +9209,26 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nRails < 0 ) goto usage; break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nShared = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nShared < 0 ) + goto usage; + break; case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } - nShared = atoi(argv[globalUtilOptind]); + Seed = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( nShared < 0 ) + if ( Seed < 0 ) goto usage; break; case 'I': @@ -9273,7 +9284,7 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) 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, fVeryVerbose ); + Abc_NtkLutCascadeFile( pFileName, nVarNum, nLutSize, nStages, nRails, nIters, Seed, fVerbose, fVeryVerbose ); return 1; } if ( fGen ) @@ -9310,7 +9321,7 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( argc == globalUtilOptind + 1 ) pGuide = argv[globalUtilOptind]; - pNtkRes = Abc_NtkLutCascade2( pNtk, nLutSize, nStages, nRails, nIters, fVerbose, pGuide ); + pNtkRes = Abc_NtkLutCascade2( pNtk, nLutSize, nStages, nRails, nIters, Seed, fVerbose, pGuide ); if ( pNtkRes == NULL ) { Abc_Print( -1, "LUT cascade mapping failed.\n" ); @@ -9320,12 +9331,13 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutcasdec [-KMRSIN ] [-F ] [-vwh]\n" ); + Abc_Print( -2, "usage: lutcasdec [-KMRCSIN ] [-F ] [-vwh]\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-C : the number of shared variables in each stage [default = %d]\n", nShared ); + Abc_Print( -2, "\t-S : the random seed for randomized bound-set selection [default = %d]\n", Seed ); 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"); diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index 8ee79bffc..def9e34a8 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -117,6 +117,218 @@ Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVer return pNtkNew; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_LutBddTestPrint( DdManager * dd, Vec_Ptr_t * vNodes, Vec_Wrd_t * vMasks, char ** ppNames, int nNames ) +{ + DdNode * node; int i, k; + Vec_PtrForEachEntry( DdNode *, vNodes, node, i ) + { + if (Cudd_IsConstant(node)) + printf("ID = %2d value = %d ", (int)node->Id, (int)Cudd_V(node) ); + else + printf("ID = %2d level = %2d index = %2d (%s) cof0 = %2d Cof1 = %2d r = %u ", + (int)node->Id, Cudd_ReadPerm(dd, node->index), (int)node->index, ppNames[node->index], (int)Cudd_E(node)->Id, (int)Cudd_T(node)->Id, (int)node->ref); + if ( Cudd_ReadPerm(dd, node->index) == 0 ) { + printf( "\n" ); + continue; + } + word Mask = Vec_WrdEntry(vMasks, (int)node->Id); + for ( k = 0; k < nNames; k++ ) { + if ( Cudd_ReadPerm(dd, k) >= (int)node->index ) + continue; + int Val = (((Mask >> Abc_Var2Lit(k, 0)) & 1) << 1) | ((Mask >> Abc_Var2Lit(k, 1)) & 1); + if ( Val == 1 ) + printf( "%c%s", '-', ppNames[k] ); + else if ( Val == 2 ) + printf( "%c%s", '+', ppNames[k] ); + else if ( Val == 3 ) + printf( "**" ); + else if ( Val == 0 ) + printf( "??" ); + } + printf( "\n" ); + } +} + +DdManager * s_ddd = NULL; +int Abc_LutBddCompare( DdNode ** pp1, DdNode ** pp2 ) +{ + DdNode * pObj1 = *pp1; + DdNode * pObj2 = *pp2; + return Cudd_ReadPerm(s_ddd, pObj1->index) - Cudd_ReadPerm(s_ddd, pObj2->index); +} +void Abc_LutBddTest( DdManager * dd, DdNode * bFunc, char ** ppNames, int nNames, int nVars ) +{ + DdGen *gen; DdNode *node; + Vec_Ptr_t * vNodes = Vec_PtrAlloc( 100 ); + Cudd_ForeachNode(dd,bFunc,gen,node) + Vec_PtrPush( vNodes, node ); + + s_ddd = dd; + Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Abc_LutBddCompare ); + s_ddd = NULL; + + int i, k, f; + Vec_Int_t * vLevels = Vec_IntAlloc( Vec_PtrSize(vNodes) ); + Vec_PtrForEachEntry( DdNode *, vNodes, node, i ) { + node->Id = i; + Vec_IntPush( vLevels, Cudd_ReadPerm(dd, node->index) ); + } + assert( Vec_IntSize(vLevels) == Vec_PtrSize(vNodes) ); + + printf( "Size = %d. Fanins = %d. Vars = %d. Nodes = %d.\n", dd->size, nNames, nVars, Vec_PtrSize(vNodes) ); + Vec_PtrForEachEntry( DdNode *, vNodes, node, i ) + { + if (Cudd_IsConstant(node)) + printf("ID = %2d value = %d\n", (int)node->Id, (int)Cudd_V(node) ); + else + printf("ID = %2d level = %2d index = %2d (%s) cof0 = %2d Cof1 = %2d r = %u\n", + (int)node->Id, Cudd_ReadPerm(dd, node->index), (int)node->index, ppNames[node->index], (int)Cudd_E(node)->Id, (int)Cudd_T(node)->Id, (int)node->ref); + } + + Vec_Wec_t * vCofs = Vec_WecStart( nNames+1 ); + Vec_WecPush( vCofs, 0, 0 ); + Vec_PtrForEachEntry( DdNode *, vNodes, node, i ) { + if ( Cudd_IsConstant(node) ) + continue; + DdNode * pFans[2] = { Cudd_E(node), Cudd_T(node) }; + int LevelStart = Vec_IntEntry(vLevels, (int)node->Id); + for ( f = 0; f < 2; f++ ) { + int Level = Cudd_IsConstant(pFans[f]) ? nNames : Vec_IntEntry(vLevels, (int)pFans[f]->Id); + for ( k = LevelStart; k < Level; k++ ) + Vec_WecPushUnique( vCofs, k+1, pFans[f]->Id ); + } + } + Vec_WecPrint( vCofs, 0 ); + + assert( nNames < 32 ); + Vec_Wrd_t * vMasks = Vec_WrdStart( Vec_PtrSize(vNodes) ); + Vec_Int_t * vLevel; int n, Obj; + Vec_WecForEachLevel( vCofs, vLevel, i ) { + if ( i == Vec_WecSize(vCofs)-1 ) + break; + + //printf( "Level %2d : ", i ); + //Vec_IntPrint( vLevel ); + printf( "Level %2d : ", i ); + for ( k = 0; k < nNames; k++ ) { + if ( Cudd_ReadPerm(dd, k) >= i ) + continue; + int Counts[2] = {0}; + for ( f = 0; f < 2; f++ ) + Vec_IntForEachEntry(vLevel, Obj, n) + if ( (Vec_WrdEntry(vMasks, Obj) >> Abc_Var2Lit(k, !f)) & 1 ) + Counts[f]++; + printf( "%s(%d:%d) ", ppNames[k], Counts[0], Counts[1] ); + } + printf( "\n" ); + + Vec_IntForEachEntry( vLevel, Obj, n ) + { + DdNode * node = (DdNode *)Vec_PtrEntry( vNodes, Obj ); + if ( Cudd_IsConstant(node) ) + continue; + DdNode * pFans[2] = { Cudd_E(node), Cudd_T(node) }; + word * pMask = Vec_WrdEntryP( vMasks, (int)node->Id ); + int LevelStart = Vec_IntEntry(vLevels, (int)node->Id); + assert( LevelStart >= i ); + if ( LevelStart > i ) + continue; + for ( f = 0; f < 2; f++ ) { + int Level = Cudd_IsConstant(pFans[f]) ? nNames : Vec_IntEntry(vLevels, (int)pFans[f]->Id); + word * pMaskFan = Vec_WrdEntryP( vMasks, (int)pFans[f]->Id ); + *pMaskFan |= *pMask | ((word)1 << Abc_Var2Lit((int)node->index, !f)); + for ( k = LevelStart+1; k < Level; k++ ) { + *pMaskFan |= ((word)1 << Abc_Var2Lit(Cudd_ReadInvPerm(dd, k), 0)); + *pMaskFan |= ((word)1 << Abc_Var2Lit(Cudd_ReadInvPerm(dd, k), 1)); + } + } + } + + //Abc_LutBddTestPrint( dd, vNodes, vMasks, ppNames, nNames ); + } + +/* + assert( nNames < 32 ); + Vec_Wrd_t * vMasks = Vec_WrdStart( Count ); + Vec_PtrForEachEntry( DdNode *, vNodes, node, i ) { + if ( Cudd_IsConstant(node) ) + continue; + DdNode * pFans[2] = { Cudd_E(node), Cudd_T(node) }; + word * pMask = Vec_WrdEntryP( vMasks, (int)node->Id ); + int LevelStart = Vec_IntEntry(vLevels, (int)node->Id); + for ( f = 0; f < 2; f++ ) { + int Level = Cudd_IsConstant(pFans[f]) ? nNames : Vec_IntEntry(vLevels, (int)pFans[f]->Id); + word * pMaskFan = Vec_WrdEntryP( vMasks, (int)pFans[f]->Id ); + *pMaskFan |= *pMask | ((word)1 << Abc_Var2Lit((int)node->index, !f)); + for ( k = LevelStart+1; k < Level; k++ ) { + *pMaskFan |= ((word)1 << Abc_Var2Lit(Cudd_ReadInvPerm(dd, k), 0)); + *pMaskFan |= ((word)1 << Abc_Var2Lit(Cudd_ReadInvPerm(dd, k), 1)); + } + } + } + + Vec_PtrForEachEntry( DdNode *, vNodes, node, i ) + { + if (Cudd_IsConstant(node)) + printf("ID = %2d value = %d ", (int)node->Id, (int)Cudd_V(node) ); + else + printf("ID = %2d level = %2d index = %2d (%s) cof0 = %2d Cof1 = %2d r = %u ", + (int)node->Id, Cudd_ReadPerm(dd, node->index), (int)node->index, ppNames[node->index], (int)Cudd_E(node)->Id, (int)Cudd_T(node)->Id, (int)node->ref); + if ( Cudd_ReadPerm(dd, node->index) == 0 ) { + printf( "\n" ); + continue; + } + word Mask = Vec_WrdEntry(vMasks, (int)node->Id); + for ( k = 0; k < nNames; k++ ) { + if ( Cudd_ReadPerm(dd, k) >= (int)node->index ) + continue; + int Val = (((Mask >> Abc_Var2Lit(k, 0)) & 1) << 1) | ((Mask >> Abc_Var2Lit(k, 1)) & 1); + if ( Val == 1 ) + printf( "%c%s", '-', ppNames[k] ); + else if ( Val == 2 ) + printf( "%c%s", '+', ppNames[k] ); + else if ( Val == 3 ) + printf( "**" ); + else if ( Val == 0 ) + printf( "??" ); + } + printf( "\n" ); + } + + Vec_Int_t * vLevel; int n, Obj; + Vec_WecForEachLevelStart( vCofs, vLevel, i, 1 ) { + printf( "Level %2d : ", i ); + for ( k = 0; k < nNames; k++ ) { + if ( Cudd_ReadPerm(dd, k) >= i ) + continue; + int Counts[2] = {0}; + for ( f = 0; f < 2; f++ ) + Vec_IntForEachEntry(vLevel, Obj, n) + if ( (Vec_WrdEntry(vMasks, Obj) >> Abc_Var2Lit(k, !f)) & 1 ) + Counts[f]++; + printf( "%s(%d:%d) ", ppNames[k], Counts[0], Counts[1] ); + } + printf( "\n" ); + } +*/ + + Vec_IntFree( vLevels ); + Vec_WecFree( vCofs ); + Vec_PtrFree( vNodes ); + Vec_WrdFree( vMasks ); +} + #else Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ) { return NULL; } @@ -617,15 +829,17 @@ Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nR Gia_ManStop( pGia ); return pNew; } -Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, char * pGuide ) +Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int Seed, int fVerbose, char * pGuide ) { extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk ); extern word * Abc_LutCascade2( word * p, int nVars, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); - int nWords = Abc_TtWordNum(Abc_NtkCiNum(pNtk)); + int i, nWords = Abc_TtWordNum(Abc_NtkCiNum(pNtk)); word * pCopy = ABC_ALLOC( word, nWords ); Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk ); Abc_Ntk_t * pNew = NULL; Abc_Random(1); + for ( i = 0; i < Seed; i++ ) + Abc_Random(0); for ( int Iter = 0; Iter < nIters; Iter++ ) { word * pTruth1 = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, 0) ); Abc_TtCopy( pCopy, pTruth1, nWords, 0 ); @@ -635,6 +849,7 @@ Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int n Abc_TtMinimumBase( pTruth1, Vec_IntArray(vVarIDs), Abc_NtkCiNum(pNtk), &nVars ); Vec_IntShrink( vVarIDs, nVars ); if ( fVerbose ) { + printf( "Iter %2d : ", Iter ); if ( Abc_NtkCiNum(pNtk) != nVars ) printf( "The support of the function is reduced from %d to %d variables.\n", Abc_NtkCiNum(pNtk), nVars ); printf( "Decomposing %d-var function into %d-rail cascade of %d-LUTs", nVars, nRails, nLutSize ); @@ -1156,7 +1371,7 @@ Vec_Wrd_t * Abc_NtkLutCasReadTruths( char * pFileName, int nVarsOrig ) SeeAlso [] ***********************************************************************/ -void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, int fVeryVerbose ) +void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int nLuts, int nRails, int nIters, int Seed, int fVerbose, int fVeryVerbose ) { abctime clkStart = Abc_Clock(); int i, Sum = 0, nTotalLuts = 0, nWords = Abc_TtWordNum(nVarsOrig); @@ -1179,6 +1394,8 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n word * pCopy = ABC_ALLOC( word, nWords ); int Iter = 0, LutStats[100] = {0}; Abc_Random(1); + for ( i = 0; i < Seed; i++ ) + Abc_Random(0); for ( i = 0; i < nFuncs; i++ ) { word * pTruth = Vec_WrdEntryP( vTruths, i*nWords ); From 3a063c590124e995d1d9ea91cbb08439a785be34 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 16 Apr 2025 16:58:04 -0700 Subject: [PATCH 14/72] Allowing more aggressive restructuring in "stochmap". --- src/base/abci/abcPart.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/base/abci/abcPart.c b/src/base/abci/abcPart.c index 19ac3aba8..84c4b0221 100644 --- a/src/base/abci/abcPart.c +++ b/src/base/abci/abcPart.c @@ -1219,7 +1219,7 @@ void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams ) ***********************************************************************/ Vec_Int_t * Abc_NtkStochSynthesis( Vec_Ptr_t * vWins, char * pScript ) { - Vec_Int_t * vGains = Vec_IntStart( Vec_PtrSize(vWins) ); + Vec_Int_t * vGains = Vec_IntStartFull( Vec_PtrSize(vWins) ); Abc_Ntk_t * pNtk, * pNew; int i; Vec_PtrForEachEntry( Abc_Ntk_t *, vWins, pNtk, i ) { @@ -1248,7 +1248,7 @@ Vec_Int_t * Abc_NtkStochSynthesis( Vec_Ptr_t * vWins, char * pScript ) { double Before = Abc_NtkGetMappedArea(pNtk); double After = Abc_NtkGetMappedArea(pNew); - if ( After < Before ) + if ( Before >= After ) { Vec_IntWriteEntry( vGains, i, (int)(Before - After) ); Abc_NtkDelete( pNtk ); @@ -1257,7 +1257,7 @@ Vec_Int_t * Abc_NtkStochSynthesis( Vec_Ptr_t * vWins, char * pScript ) } else { - if ( Abc_NtkNodeNum(pNew) < Abc_NtkNodeNum(pNtk) ) + if ( Abc_NtkNodeNum(pNtk) >= Abc_NtkNodeNum(pNew) ) { Vec_IntWriteEntry( vGains, i, Abc_NtkNodeNum(pNtk) - Abc_NtkNodeNum(pNew) ); Abc_NtkDelete( pNtk ); @@ -1320,7 +1320,7 @@ Abc_Ntk_t * Abc_NtkStochProcessOne( Abc_Ntk_t * p, char * pScript0, int Rand, in ABC_FREE( pScript ); pNew = Abc_NtkReadFromFile( FileName ); unlink( FileName ); - if ( pNew && Abc_NtkGetMappedArea(pNew) < Abc_NtkGetMappedArea(p) ) { + if ( pNew && Abc_NtkGetMappedArea(pNew) <= Abc_NtkGetMappedArea(p) ) { pNew = Abc_NtkDupDfs( pTemp = pNew ); Abc_NtkDelete( pTemp ); return pNew; @@ -1343,7 +1343,7 @@ Vec_Int_t * Abc_NtkStochProcess( Vec_Ptr_t * vWins, char * pScript, int nProcs, if ( nProcs <= 2 ) { return Abc_NtkStochSynthesis( vWins, pScript ); } - Vec_Int_t * vGains = Vec_IntStart( Vec_PtrSize(vWins) ); + Vec_Int_t * vGains = Vec_IntStartFull( Vec_PtrSize(vWins) ); StochSynData_t * pData = ABC_CALLOC( StochSynData_t, Vec_PtrSize(vWins) ); Vec_Ptr_t * vData = Vec_PtrAlloc( Vec_PtrSize(vWins) ); Abc_Ntk_t * pNtk; int i; @@ -1481,7 +1481,7 @@ Abc_Ntk_t * Abc_NtkInsertPartitions( Abc_Ntk_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t Abc_NtkIncrementTravId( p ); while ( 1 ) { int i, Gain, iEntry = Vec_IntArgMax(vGains); - if ( iEntry == -1 || Vec_IntEntry(vGains, iEntry) <= 0 ) + if ( iEntry == -1 || Vec_IntEntry(vGains, iEntry) < 0 ) break; //printf( "Selecting partition %d with gain %d.\n", iEntry, Vec_IntEntry(vGains, iEntry) ); Vec_IntWriteEntry( vGains, iEntry, -1 ); @@ -1491,7 +1491,7 @@ Abc_Ntk_t * Abc_NtkInsertPartitions( Abc_Ntk_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t extern void Abc_NtKMarkTfiTfo( Vec_Int_t * vOne, Abc_Ntk_t * pNtk ); Abc_NtKMarkTfiTfo( (Vec_Int_t *)Vec_PtrEntryLast(vvInsNew), p ); Vec_IntForEachEntry( vGains, Gain, i ) { - if ( Gain <= 0 ) + if ( Gain < 0 ) continue; Vec_Int_t * vNodes = (Vec_Int_t *)Vec_PtrEntry(vvNodes, i); Abc_Obj_t * pNode; int j; From 01bfd8fbadcb631d9b958b9d2145adfbb8cb718f Mon Sep 17 00:00:00 2001 From: jiunhaochen Date: Thu, 17 Apr 2025 12:39:24 +0800 Subject: [PATCH 15/72] rewire fix not mapped --- src/opt/rar/rewire_miaig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opt/rar/rewire_miaig.cpp b/src/opt/rar/rewire_miaig.cpp index 7ff05cccc..9b7ce7a1f 100644 --- a/src/opt/rar/rewire_miaig.cpp +++ b/src/opt/rar/rewire_miaig.cpp @@ -49,7 +49,7 @@ Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, Gia_Man_t *pExc, int nIters, float pNtkMiaig.setExc(pExc); Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, fMapped, nMappedMode, nDist, fCheck, fVerbose); pNew.setName(Abc_NtkName(pNtk)); - if (nMode == 2) { + if (nMode > 0) { pNew.countTransistors(1, nMappedMode); } From 0ab176d7c979dc0262118d0cca1de5073fd24d1b Mon Sep 17 00:00:00 2001 From: jiunhaochen Date: Thu, 17 Apr 2025 16:14:49 +0800 Subject: [PATCH 16/72] rewire fix genlib change --- src/base/abci/abcMini.c | 2 +- src/opt/rar/rewire_miaig.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/base/abci/abcMini.c b/src/base/abci/abcMini.c index 40e28dad6..3b5640541 100644 --- a/src/base/abci/abcMini.c +++ b/src/base/abci/abcMini.c @@ -148,7 +148,7 @@ Mini_Aig_t * Abc_MiniAigFromNtk ( Abc_Ntk_t *pNtk ) { Abc_Ntk_t *pNtkRes = NULL; Mini_Aig_t *pAig; - if (Abc_NtkHasMapping(pNtk)) { + if (!Abc_NtkIsStrash(pNtk)) { pNtk = pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); if ( pNtkRes == NULL ) { diff --git a/src/opt/rar/rewire_miaig.cpp b/src/opt/rar/rewire_miaig.cpp index 9b7ce7a1f..f9490e1c2 100644 --- a/src/opt/rar/rewire_miaig.cpp +++ b/src/opt/rar/rewire_miaig.cpp @@ -1245,11 +1245,11 @@ Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, if (nVerbose) printf("%5g (AND2 = %5g Level = %3d) ", newTarget, pNew.countAnd2(), pNew.countLevel()); if (nVerbose) Time_PrintEndl("Elapsed time", Time_Clock() - clkStart); PrevBest = newTarget; - pBests = {pNew.dup(0, fMapped), pNew.dup(0, fMapped)}; + pBests = {pNew.dup(0), pNew.dup(0)}; pBest = pNew.dup(0, fMapped), improved = 1; iterNotImproveAfterRestart = 0; } else if (PrevBest == newTarget) { - randomAddBest(pBests, pNew.dup(0, fMapped), nBestSave); + randomAddBest(pBests, pNew.dup(0), nBestSave); } // compare if (maxLevel ? pNew.countLevel() > maxLevel : 0) { From b1b102328586795b8b3a439689bf48e84c5627e2 Mon Sep 17 00:00:00 2001 From: MyskYko Date: Thu, 17 Apr 2025 11:01:39 -0700 Subject: [PATCH 17/72] update rrr --- src/aig/gia/giaRrr.cpp | 2 +- src/base/abci/abc.c | 57 ++- src/opt/rrr/rrrAbc.h | 16 +- src/opt/rrr/rrrAnalyzer.h | 49 ++- src/opt/rrr/rrrAndNetwork.h | 36 +- src/opt/rrr/rrrBddAnalyzer.h | 448 ++++++++++++++-------- src/opt/rrr/rrrBddManager.h | 6 + src/opt/rrr/rrrBddMspfAnalyzer.h | 432 +++++++++++++-------- src/opt/rrr/rrrLevelBasePartitioner.h | 4 +- src/opt/rrr/rrrOptimizer.h | 533 +++++++++++++++++++------- src/opt/rrr/rrrParameter.h | 2 +- src/opt/rrr/rrrPartitioner.h | 4 +- src/opt/rrr/rrrSatSolver.h | 70 +++- src/opt/rrr/rrrScheduler.h | 234 +++++++---- src/opt/rrr/rrrSimulator.h | 245 +++++++++--- src/opt/rrr/rrrTypes.h | 5 + src/opt/rrr/rrrUtils.h | 84 ++-- 17 files changed, 1548 insertions(+), 679 deletions(-) diff --git a/src/aig/gia/giaRrr.cpp b/src/aig/gia/giaRrr.cpp index 1eccd4dc2..8483641b2 100644 --- a/src/aig/gia/giaRrr.cpp +++ b/src/aig/gia/giaRrr.cpp @@ -35,7 +35,7 @@ Gia_Man_t *Gia_ManRrr(Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int Par.fOptOnInsert = fOptOnInsert; Par.fGreedy = fGreedy; rrr::Perform(&ntk, &Par); - Gia_Man_t *pNew = rrr::CreateGia(&ntk); + Gia_Man_t *pNew = rrr::CreateGia(&ntk, false); return pNew; } diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 2875b3a1b..b4e47da0b 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -45457,7 +45457,7 @@ int Abc_CommandAbc9Rrr( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t *pNew; int c; - int iSeed = 0, nWords = 10, nTimeout = 0, nSchedulerVerbose = 1, nPartitionerVerbose = 0, nOptimizerVerbose = 0, nAnalyzerVerbose = 0, nSimulatorVerbose = 0, nSatSolverVerbose = 0, fUseBddCspf = 0, fUseBddMspf = 0, nConflictLimit = 0, nSortType = -1, nOptimizerFlow = 0, nSchedulerFlow = 0, nPartitionType = 0, nDistance = 0, nJobs = 1, nThreads = 1, nPartitionSize = 0, nPartitionSizeMin = 0, fDeterministic = 1, nParallelPartitions = 1, fOptOnInsert = 0, fGreedy = 1; + int iSeed = 0, nWords = 10, nTimeout = 0, nSchedulerVerbose = 0, nPartitionerVerbose = 0, nOptimizerVerbose = 0, nAnalyzerVerbose = 0, nSimulatorVerbose = 0, nSatSolverVerbose = 0, fUseBddCspf = 0, fUseBddMspf = 0, nConflictLimit = 0, nSortType = -1, nOptimizerFlow = 0, nSchedulerFlow = 0, nPartitionType = 0, nDistance = 0, nJobs = 1, nThreads = 1, nPartitionSize = 0, nPartitionSizeMin = 0, fDeterministic = 1, nParallelPartitions = 1, fOptOnInsert = 0, fGreedy = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "XYZNJKLBDRWTCGVPOAQSabdegh" ) ) != EOF ) { @@ -45576,6 +45576,51 @@ int Abc_CommandAbc9Rrr( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } + if ( nSchedulerVerbose ) + { + Abc_Print( 2, "Using the following parameters :\n" ); + Abc_Print( 2, "\t-X %3d : method ", nOptimizerFlow ); + switch( nOptimizerFlow ) + { + case 0: + Abc_Print( 2, "(0 = single-add resub)" ); + break; + case 1: + Abc_Print( 2, "(1 = multi-add resub)" ); + break; + case 2: + Abc_Print( 2, "(2 = repeat single-add and multi-add resubs)" ); + break; + case 3: + Abc_Print( 2, "(3 = random one meaningful resub)" ); + break; + } + Abc_Print( 2, "\n" ); + Abc_Print( 2, "\t-Y %3d : flow ", nSchedulerFlow ); + switch ( nSchedulerFlow ) + { + case 0: + Abc_Print( 2, "(0 = apply method once)" ); + break; + case 1: + Abc_Print( 2, "(1 = iterate like transtoch)" ); + break; + case 2: + Abc_Print( 2, "(2 = iterate like deepsyn)" ); + break; + } + Abc_Print( 2, "\n" ); + Abc_Print( 2, "\t-N %3d : number of jobs to create by restarting or partitioning\n", nJobs ); + Abc_Print( 2, "\t-J %3d : number of threads\n", nThreads ); + Abc_Print( 2, "\t-K %3d : maximum partition size (0 = no partitioning)\n", nPartitionSize ); + Abc_Print( 2, "\t-L %3d : minimum partition size\n", nPartitionSizeMin ); + Abc_Print( 2, "\t-B %3d : maximum number of partitions to optimize in parallel\n", nParallelPartitions ); + Abc_Print( 2, "\t-R %3d : random number generator seed\n", iSeed ); + Abc_Print( 2, "\t-T %3d : timeout in seconds (0 = no timeout)\n", nTimeout ); + Abc_Print( 2, "\t-C %3d : conflict limit (0 = no limit)\n", nConflictLimit ); + Abc_Print( 2, "Use command line switch \"-h\" to see more options\n\n" ); + } + pNew = Gia_ManRrr( pAbc->pGia, iSeed, nWords, nTimeout, nSchedulerVerbose, nPartitionerVerbose, nOptimizerVerbose, nAnalyzerVerbose, nSimulatorVerbose, nSatSolverVerbose, fUseBddCspf, fUseBddMspf, nConflictLimit, nSortType, nOptimizerFlow, nSchedulerFlow, nPartitionType, nDistance, nJobs, nThreads, nPartitionSize, nPartitionSizeMin, fDeterministic, nParallelPartitions, fOptOnInsert, fGreedy ); Abc_FrameUpdateGia( pAbc, pNew ); @@ -45599,10 +45644,10 @@ usage: Abc_Print( -2, "\t 1: level base\n" ); Abc_Print( -2, "\t-N num : number of jobs to create by restarting or partitioning [default = %d]\n", nJobs ); Abc_Print( -2, "\t-J num : number of threads [default = %d]\n", nThreads ); - Abc_Print( -2, "\t-K num : partition size (0 = no partitioning) [default = %d]\n", nPartitionSize ); - Abc_Print( -2, "\t-K num : minimum partition size [default = %d]\n", nPartitionSizeMin ); - Abc_Print( -2, "\t-B num : max number of partitions in parallel [default = %d]\n", nParallelPartitions ); - Abc_Print( -2, "\t-D num : distance between nodes (0 = no limit) [default = %d]\n", nDistance ); + Abc_Print( -2, "\t-K num : maximum partition size (0 = no partitioning) [default = %d]\n", nPartitionSize ); + Abc_Print( -2, "\t-L num : minimum partition size [default = %d]\n", nPartitionSizeMin ); + Abc_Print( -2, "\t-B num : maximum number of partitions in parallel [default = %d]\n", nParallelPartitions ); + Abc_Print( -2, "\t-D num : maximum distance between node and new fanin (0 = no limit) [default = %d]\n", nDistance ); Abc_Print( -2, "\t-R num : random number generator seed [default = %d]\n", iSeed ); Abc_Print( -2, "\t-W num : number of simulation words [default = %d]\n", nWords ); Abc_Print( -2, "\t-T num : timeout in seconds (0 = no timeout) [default = %d]\n", nTimeout ); @@ -45617,7 +45662,7 @@ usage: Abc_Print( -2, "\t-a : use BDD-based analyzer (CSPF) [default = %s]\n", fUseBddCspf? "yes": "no" ); Abc_Print( -2, "\t-b : use BDD-based analyzer (MSPF) [default = %s]\n", fUseBddMspf? "yes": "no" ); Abc_Print( -2, "\t-d : ensure deterministic execution [default = %s]\n", fDeterministic? "yes": "no" ); - Abc_Print( -2, "\t-e : apply c2rs; dc2 after importing changes of partitions [default = %s]\n", fOptOnInsert? "yes": "no" ); + Abc_Print( -2, "\t-e : apply \"c2rs; dc2\" after importing changes of partitions [default = %s]\n", fOptOnInsert? "yes": "no" ); Abc_Print( -2, "\t-g : discard changes that increased the cost [default = %s]\n", fGreedy? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; diff --git a/src/opt/rrr/rrrAbc.h b/src/opt/rrr/rrrAbc.h index 307d5e0d0..5df597a54 100644 --- a/src/opt/rrr/rrrAbc.h +++ b/src/opt/rrr/rrrAbc.h @@ -29,9 +29,11 @@ namespace rrr { } template - Gia_Man_t *CreateGia(Ntk *pNtk) { + Gia_Man_t *CreateGia(Ntk *pNtk, bool fHash = true) { Gia_Man_t *pGia = Gia_ManStart(pNtk->GetNumNodes()); - Gia_ManHashStart(pGia); + if(fHash) { + Gia_ManHashStart(pGia); + } std::vector v(pNtk->GetNumNodes()); v[0] = Gia_ManConst0Lit(); pNtk->ForEachPi([&](int id) { @@ -43,8 +45,10 @@ namespace rrr { pNtk->ForEachFanin(id, [&](int fi, bool c) { if(x == -1) { x = Abc_LitNotCond(v[fi], c); - } else { + } else if(fHash) { x = Gia_ManHashAnd(pGia, x, Abc_LitNotCond(v[fi], c)); + } else { + x = Gia_ManAppendAnd(pGia, x, Abc_LitNotCond(v[fi], c)); } }); if(x == -1) { @@ -55,7 +59,9 @@ namespace rrr { pNtk->ForEachPoDriver([&](int fi, bool c) { Gia_ManAppendCo(pGia, Abc_LitNotCond(v[fi], c)); }); - Gia_ManHashStop(pGia); + if(fHash) { + Gia_ManHashStop(pGia); + } return pGia; } @@ -72,7 +78,7 @@ namespace rrr { assert(r == 0); Abc_FrameSetBatchMode(0); } - pNtk->Read(Abc_FrameReadGia(pAbc), GiaReader); + pNtk->Read(Abc_FrameReadGia(pAbc), GiaReader, false); } } diff --git a/src/opt/rrr/rrrAnalyzer.h b/src/opt/rrr/rrrAnalyzer.h index 0689a3d11..75bc241ac 100644 --- a/src/opt/rrr/rrrAnalyzer.h +++ b/src/opt/rrr/rrrAnalyzer.h @@ -23,11 +23,16 @@ namespace rrr { public: // constructors Analyzer(Parameter const *pPar); - void UpdateNetwork(Ntk *pNtk_, bool fSame); + void AssignNetwork(Ntk *pNtk_, bool fReuse); // checks bool CheckRedundancy(int id, int idx); bool CheckFeasibility(int id, int fi, bool c); + + // summary + void ResetSummary(); + summary GetStatsSummary() const; + summary GetTimesSummary() const; }; /* {{{ Constructors */ @@ -39,12 +44,12 @@ namespace rrr { sim(pPar), sol(pPar) { } - + template - void Analyzer::UpdateNetwork(Ntk *pNtk_, bool fSame) { + void Analyzer::AssignNetwork(Ntk *pNtk_, bool fReuse) { pNtk = pNtk_; - sim.UpdateNetwork(pNtk, fSame); - sol.UpdateNetwork(pNtk, fSame); + sim.AssignNetwork(pNtk, fReuse); + sol.AssignNetwork(pNtk, fReuse); } /* }}} */ @@ -70,6 +75,10 @@ namespace rrr { } sim.AddCex(sol.GetCex()); } + } else { + // if(nVerbose) { + // std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is not redundant" << std::endl; + // } } return false; } @@ -93,11 +102,41 @@ namespace rrr { } sim.AddCex(sol.GetCex()); } + } else { + // if(nVerbose) { + // std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is not feasible" << std::endl; + // } } return false; } /* }}} */ + + /* {{{ Summary */ + + template + void Analyzer::ResetSummary() { + sim.ResetSummary(); + sol.ResetSummary(); + } + + template + summary Analyzer::GetStatsSummary() const { + summary v = sim.GetStatsSummary(); + summary v2 = sol.GetStatsSummary(); + v.insert(v.end(), v2.begin(), v2.end()); + return v; + } + + template + summary Analyzer::GetTimesSummary() const { + summary v = sim.GetTimesSummary(); + summary v2 = sol.GetTimesSummary(); + v.insert(v.end(), v2.begin(), v2.end()); + return v; + } + + /* }}} */ } diff --git a/src/opt/rrr/rrrAndNetwork.h b/src/opt/rrr/rrrAndNetwork.h index f39bbdc4d..036b8cd43 100644 --- a/src/opt/rrr/rrrAndNetwork.h +++ b/src/opt/rrr/rrrAndNetwork.h @@ -64,13 +64,13 @@ namespace rrr { AndNetwork &operator=(AndNetwork const &x); // initialization APIs (should not be called after optimization has started) - void Clear(); + void Clear(bool fClearCallbacks = true); void Reserve(int nReserve); int AddPi(); int AddAnd(int id0, int id1, bool c0, bool c1); int AddPo(int id, bool c); template - void Read(Ntk *pFrom, Reader &reader); + void Read(Ntk *pFrom, Reader &reader, bool fNew = true); // network properties bool UseComplementedEdges() const; @@ -78,6 +78,7 @@ namespace rrr { int GetNumPis() const; int GetNumInts() const; int GetNumPos() const; + int GetNumLevels() const; int GetConst0() const; int GetPi(int idx) const; int GetPo(int idx) const; @@ -272,7 +273,7 @@ namespace rrr { /* {{{ Initialization APIs */ - void AndNetwork::Clear() { + void AndNetwork::Clear(bool fClearCallbacks) { nNodes = 0; vPis.clear(); lInts.clear(); @@ -284,7 +285,9 @@ namespace rrr { iTrav = 0; vTrav.clear(); fPropagating = false; - vCallbacks.clear(); + if(fClearCallbacks) { + vCallbacks.clear(); + } vBackups.clear(); // add constant node vvFaninEdges.emplace_back(); @@ -330,9 +333,13 @@ namespace rrr { } template - void AndNetwork::Read(Ntk *pFrom, Reader &reader) { - Clear(); + void AndNetwork::Read(Ntk *pFrom, Reader &reader, bool fNew) { + Clear(false); reader(pFrom, this); + Action action; + action.type = READ; + action.fNew = fNew; + TakenAction(action); } /* }}} */ @@ -359,6 +366,23 @@ namespace rrr { return int_size(vPos); } + int AndNetwork::GetNumLevels() const { + int nMaxLevel = 0; + std::vector vLevels(nNodes); + ForEachInt([&](int id) { + ForEachFanin(id, [&](int fi) { + if(vLevels[id] < vLevels[fi]) { + vLevels[id] = vLevels[fi]; + } + }); + vLevels[id] += 1; + if(nMaxLevel < vLevels[id]) { + nMaxLevel = vLevels[id]; + } + }); + return nMaxLevel; + } + inline int AndNetwork::GetConst0() const { return 0; } diff --git a/src/opt/rrr/rrrBddAnalyzer.h b/src/opt/rrr/rrrBddAnalyzer.h index a9112a9ba..0f5d88d68 100644 --- a/src/opt/rrr/rrrBddAnalyzer.h +++ b/src/opt/rrr/rrrBddAnalyzer.h @@ -22,6 +22,7 @@ namespace rrr { int nVerbose; // data + bool fInitialized; NewBdd::Man *pBdd; int target; std::vector vFs; @@ -35,6 +36,14 @@ namespace rrr { // backups std::vector vBackups; + // stats + uint64_t nNodesOld; + uint64_t nNodesAccumulated; + double durationSimulation; + double durationPf; + double durationCheck; + double durationReorder; + // BDD utils void IncRef(lit x) const; void DecRef(lit x) const; @@ -61,6 +70,10 @@ namespace rrr { void CspfNode(int id); void Cspf(int id = -1, bool fC = true); + // preparation + void Reset(bool fReuse = false); + void Initialize(); + // save & load void Save(int slot); void Load(int slot); @@ -71,11 +84,16 @@ namespace rrr { BddAnalyzer(); BddAnalyzer(Parameter const *pPar); ~BddAnalyzer(); - void UpdateNetwork(Ntk *pNtk_, bool fSame); + void AssignNetwork(Ntk *pNtk_, bool fReuse); // checks bool CheckRedundancy(int id, int idx); bool CheckFeasibility(int id, int fi, bool c); + + // summary + void ResetSummary(); + summary GetStatsSummary() const; + summary GetTimesSummary() const; }; /* {{{ BDD utils */ @@ -163,103 +181,136 @@ namespace rrr { void BddAnalyzer::ActionCallback(Action const &action) { switch(action.type) { case REMOVE_FANIN: + assert(fInitialized); vUpdates[action.id] = true; vGUpdates[action.fi] = true; DecRef(vvCs[action.id][action.idx]); vvCs[action.id].erase(vvCs[action.id].begin() + action.idx); + if(target != action.id) { + // require resimulate before next fesibility check + // (this is not mandatory if no pending updates are in TFI of new fanin, but we would rather update than checking every time) + target = -1; + } break; case REMOVE_UNUSED: - if(vGUpdates[action.id] || vCUpdates[action.id]) { + if(fInitialized) { + if(vGUpdates[action.id] || vCUpdates[action.id]) { + for(int fi: action.vFanins) { + vGUpdates[fi] = true; + } + } + Assign(vFs[action.id], LitMax); + Assign(vGs[action.id], LitMax); + DelVec(vvCs[action.id]); + } + break; + case REMOVE_BUFFER: + if(fInitialized) { + if(vUpdates[action.id]) { + for(int fo: action.vFanouts) { + vUpdates[fo] = true; + vCUpdates[fo] = true; + } + } + if(vGUpdates[action.id] || vCUpdates[action.id]) { + vGUpdates[action.fi] = true; + } + Assign(vFs[action.id], LitMax); + Assign(vGs[action.id], LitMax); + DelVec(vvCs[action.id]); + } + break; + case REMOVE_CONST: + if(fInitialized) { + if(vUpdates[action.id]) { + for(int fo: action.vFanouts) { + vUpdates[fo] = true; + vCUpdates[fo] = true; + } + } for(int fi: action.vFanins) { vGUpdates[fi] = true; } + Assign(vFs[action.id], LitMax); + Assign(vGs[action.id], LitMax); + DelVec(vvCs[action.id]); } - Assign(vFs[action.id], LitMax); - Assign(vGs[action.id], LitMax); - DelVec(vvCs[action.id]); - break; - case REMOVE_BUFFER: - if(vUpdates[action.id]) { - for(int fo: action.vFanouts) { - vUpdates[fo] = true; - vCUpdates[fo] = true; - } - } - if(vGUpdates[action.id] || vCUpdates[action.id]) { - vGUpdates[action.fi] = true; - } - Assign(vFs[action.id], LitMax); - Assign(vGs[action.id], LitMax); - DelVec(vvCs[action.id]); - break; - case REMOVE_CONST: - if(vUpdates[action.id]) { - for(int fo: action.vFanouts) { - vUpdates[fo] = true; - vCUpdates[fo] = true; - } - } - for(int fi: action.vFanins) { - vGUpdates[fi] = true; - } - Assign(vFs[action.id], LitMax); - Assign(vGs[action.id], LitMax); - DelVec(vvCs[action.id]); break; case ADD_FANIN: + assert(action.id == target); + assert(fInitialized); vUpdates[action.id] = true; vCUpdates[action.id] = true; vvCs[action.id].insert(vvCs[action.id].begin() + action.idx, LitMax); break; - case TRIVIAL_COLLAPSE: { - if(vGUpdates[action.fi] || vCUpdates[action.fi]) { + case TRIVIAL_COLLAPSE: + if(fInitialized) { + if(vGUpdates[action.fi] || vCUpdates[action.fi]) { + vCUpdates[action.id] = true; + } + std::vector::iterator it = vvCs[action.id].begin() + action.idx; + DecRef(*it); + it = vvCs[action.id].erase(it); + vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end()); + vvCs[action.fi].clear(); + Assign(vFs[action.fi], LitMax); + Assign(vGs[action.fi], LitMax); + } + break; + case TRIVIAL_DECOMPOSE: + if(fInitialized) { + Allocate(); + SimulateNode(action.fi, vFs); + // time of this simulation is not measured for simplicity sake + assert(vGs[action.fi] == LitMax); + Assign(vGs[action.fi], vGs[action.id]); + std::vector::iterator it = vvCs[action.id].begin() + action.idx; + assert(vvCs[action.fi].empty()); + vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end()); + vvCs[action.id].erase(it, vvCs[action.id].end()); + assert(vvCs[action.id].size() == action.idx); + vvCs[action.id].resize(action.idx + 1, LitMax); + Assign(vvCs[action.id][action.idx], vGs[action.fi]); + vUpdates[action.fi] = false; + vGUpdates[action.fi] = false; + vCUpdates[action.fi] = vCUpdates[action.id]; + } + break; + case SORT_FANINS: + if(fInitialized) { + std::vector vCs = vvCs[action.id]; + vvCs[action.id].clear(); + for(int index: action.vIndices) { + vvCs[action.id].push_back(vCs[index]); + } + if(!fResim) { + fResim = true; + /* commenting out the following because it might not be worth checking + // if sorted node is in TFO of functionally updated nodes, resimulation is required + std::vector vFanouts; + pNtk->ForEachInt([&](int id) { + if(vUpdates[id]) { + pNtk->ForEachFanout(id, false, [&](int fo) { + vFanouts.push_back(fo); + }); + } + }); + pNtk->ForEachTfos(vFanouts, false, [&](int fo) { + if(fResim) { + return; + } + if(fo == action.id) { + fResim = true; + } + }); + */ + } vCUpdates[action.id] = true; } - std::vector::iterator it = vvCs[action.id].begin() + action.idx; - DecRef(*it); - it = vvCs[action.id].erase(it); - vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end()); - vvCs[action.fi].clear(); - Assign(vFs[action.fi], LitMax); - Assign(vGs[action.fi], LitMax); break; - } - case TRIVIAL_DECOMPOSE: { - Allocate(); - SimulateNode(action.fi, vFs); - assert(vGs[action.fi] == LitMax); - Assign(vGs[action.fi], vGs[action.id]); - std::vector::iterator it = vvCs[action.id].begin() + action.idx; - assert(vvCs[action.fi].empty()); - vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end()); - vvCs[action.id].erase(it, vvCs[action.id].end()); - assert(vvCs[action.id].size() == action.idx); - vvCs[action.id].resize(action.idx + 1, LitMax); - Assign(vvCs[action.id][action.idx], vGs[action.fi]); - vUpdates[action.fi] = false; - vGUpdates[action.fi] = false; - vCUpdates[action.fi] = vCUpdates[action.id]; + case READ: + Reset(!action.fNew); break; - } - case SORT_FANINS: { - std::vector vCs = vvCs[action.id]; - vvCs[action.id].clear(); - for(int index: action.vIndices) { - vvCs[action.id].push_back(vCs[index]); - } - if(!fResim && target != -1 && target != action.id) { - pNtk->ForEachTfo(target, false, [&](int fo) { - if(fResim) { - return; - } - if(fo == action.id) { - fResim = true; - } - }); - } - vCUpdates[action.id] = true; - break; - } case SAVE: Save(action.idx); break; @@ -306,6 +357,7 @@ namespace rrr { template void BddAnalyzer::Simulate() { + time_point timeStart = GetCurrentTime(); if(nVerbose) { std::cout << "symbolic simulation with BDD" << std::endl; } @@ -324,6 +376,7 @@ namespace rrr { vUpdates[id] = false; } }); + durationSimulation += Duration(timeStart, GetCurrentTime()); } /* }}} */ @@ -410,6 +463,7 @@ namespace rrr { template void BddAnalyzer::Cspf(int id, bool fC) { + time_point timeStart = GetCurrentTime(); if(id != -1) { pNtk->ForEachTfoReverse(id, false, [&](int fo) { CspfNode(fo); @@ -427,10 +481,82 @@ namespace rrr { CspfNode(id); }); } + durationPf += Duration(timeStart, GetCurrentTime()); } /* }}} */ + /* {{{ Preparation */ + + template + void BddAnalyzer::Reset(bool fReuse) { + while(!vBackups.empty()) { + PopBack(); + } + DelVec(vFs); + DelVec(vGs); + DelVecVec(vvCs); + fInitialized = false; + target = -1; + fResim = false; + vUpdates.clear(); + vGUpdates.clear(); + vCUpdates.clear(); + if(!fReuse) { + nNodesOld = 0; + if(pBdd) { + nNodesAccumulated += pBdd->GetNumTotalCreatedNodes(); + } + delete pBdd; + pBdd = NULL; + } + } + + template + void BddAnalyzer::Initialize() { + bool fUseReo = false; + if(!pBdd) { + NewBdd::Param Par; + Par.nObjsMaxLog = 25; + Par.nCacheMaxLog = 20; + Par.fCountOnes = false; + Par.nGbc = 1; + Par.nReo = 4000; + pBdd = new NewBdd::Man(pNtk->GetNumPis(), Par); + fUseReo = true; + } + assert(pBdd->GetNumVars() == pNtk->GetNumPis()); + Allocate(); + Assign(vFs[0], pBdd->Const0()); + int idx = 0; + pNtk->ForEachPi([&](int id) { + Assign(vFs[id], pBdd->IthVar(idx)); + idx++; + }); + pNtk->ForEachInt([&](int id) { + vUpdates[id] = true; + }); + Simulate(); + if(fUseReo) { + time_point timeStart = GetCurrentTime(); + pBdd->Reorder(); + pBdd->TurnOffReo(); + durationReorder += Duration(timeStart, GetCurrentTime()); + } + pNtk->ForEachInt([&](int id) { + vvCs[id].resize(pNtk->GetNumFanins(id), LitMax); + }); + pNtk->ForEachPo([&](int id) { + vvCs[id].resize(1, LitMax); + Assign(vvCs[id][0], pBdd->Const0()); + int fi = pNtk->GetFanin(id, 0); + vGUpdates[fi] = true; + }); + fInitialized = true; + } + + /* }}} */ + /* {{{ Save & load */ template @@ -468,7 +594,7 @@ namespace rrr { vBackups.pop_back(); } - /* }}} Save & load end */ + /* }}} */ /* {{{ Constructors */ @@ -476,93 +602,34 @@ namespace rrr { BddAnalyzer::BddAnalyzer() : pNtk(NULL), nVerbose(0), + fInitialized(false), pBdd(NULL), target(-1), fResim(false) { + ResetSummary(); } template BddAnalyzer::BddAnalyzer(Parameter const *pPar) : pNtk(NULL), nVerbose(pPar->nAnalyzerVerbose), + fInitialized(false), pBdd(NULL), target(-1), fResim(false) { - } - - template - void BddAnalyzer::UpdateNetwork(Ntk *pNtk_, bool fSame) { - // clear - while(!vBackups.empty()) { - PopBack(); - } - DelVec(vFs); - DelVec(vGs); - DelVecVec(vvCs); - pNtk = pNtk_; - target = -1; - fResim = false; - vUpdates.clear(); - vGUpdates.clear(); - vCUpdates.clear(); - // alloc - bool fUseReo = false; - if(!pBdd || pBdd->GetNumVars() != pNtk->GetNumPis()) { - // need to reset manager - delete pBdd; - NewBdd::Param Par; - Par.nObjsMaxLog = 25; - Par.nCacheMaxLog = 20; - Par.fCountOnes = true; - Par.nGbc = 1; - Par.nReo = 4000; - pBdd = new NewBdd::Man(pNtk->GetNumPis(), Par); - fUseReo = true; - } else if(!fSame) { - // turning on reordering if network function changed - pBdd->TurnOnReo(); - fUseReo = true; - } - Allocate(); - // prepare - Assign(vFs[0], pBdd->Const0()); - int idx = 0; - pNtk->ForEachPi([&](int id) { - Assign(vFs[id], pBdd->IthVar(idx)); - idx++; - }); - pNtk->ForEachInt([&](int id) { - vUpdates[id] = true; - }); - Simulate(); - if(fUseReo) { - pBdd->Reorder(); - pBdd->TurnOffReo(); - } - pNtk->ForEachInt([&](int id) { - vvCs[id].resize(pNtk->GetNumFanins(id), LitMax); - }); - pNtk->ForEachPo([&](int id) { - vvCs[id].resize(1, LitMax); - Assign(vvCs[id][0], pBdd->Const0()); - int fi = pNtk->GetFanin(id, 0); - vGUpdates[fi] = true; - }); - pNtk->AddCallback(std::bind(&BddAnalyzer::ActionCallback, this, std::placeholders::_1)); + ResetSummary(); } template BddAnalyzer::~BddAnalyzer() { - while(!vBackups.empty()) { - PopBack(); - } - DelVec(vFs); - DelVec(vGs); - DelVecVec(vvCs); - if(pBdd) { - pBdd->PrintStats(); - } - delete pBdd; + Reset(); + } + + template + void BddAnalyzer::AssignNetwork(Ntk *pNtk_, bool fReuse) { + Reset(fReuse); + pNtk = pNtk_; + pNtk->AddCallback(std::bind(&BddAnalyzer::ActionCallback, this, std::placeholders::_1)); } /* }}} */ @@ -571,20 +638,22 @@ namespace rrr { template bool BddAnalyzer::CheckRedundancy(int id, int idx) { - if(fResim) { + if(!fInitialized) { + Initialize(); + } else if(fResim) { Simulate(); + fResim = false; } Cspf(id); + time_point timeStart = GetCurrentTime(); + bool fRedundant = false; switch(pNtk->GetNodeType(id)) { case AND: { int fi = pNtk->GetFanin(id, idx); bool c = pNtk->GetCompl(id, idx); lit x = pBdd->Or(pBdd->LitNotCond(vFs[fi], c), vvCs[id][idx]); if(pBdd->IsConst1(x)) { - if(nVerbose) { - std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is redundant" << std::endl; - } - return true; + fRedundant = true; } break; } @@ -592,18 +661,30 @@ namespace rrr { assert(0); } if(nVerbose) { - std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is NOT redundant" << std::endl; + if(fRedundant) { + std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is redundant" << std::endl; + } else { + std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is NOT redundant" << std::endl; + } } - return false; + durationCheck += Duration(timeStart, GetCurrentTime()); + return fRedundant; } template bool BddAnalyzer::CheckFeasibility(int id, int fi, bool c) { - if(target != id) { // simualte if there has been update in non-tfo of this node + if(!fInitialized) { + Initialize(); + } else if(target != id && (target == -1 || vUpdates[target])) { + // resimulation is required if there are pending updates in TFI of new fanin + // but it seems not worthwhile to check that condition every time + // so we update if pending updates are not only at current target Simulate(); - target = id; } + target = id; Cspf(id, false); + time_point timeStart = GetCurrentTime(); + bool fFeasible = false; switch(pNtk->GetNodeType(id)) { case AND: { lit x = pBdd->Or(pBdd->LitNot(vFs[id]), vGs[id]); @@ -611,10 +692,7 @@ namespace rrr { lit y = pBdd->Or(x, pBdd->LitNotCond(vFs[fi], c)); DecRef(x); if(pBdd->IsConst1(y)) { - if(nVerbose) { - std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is feasible" << std::endl; - } - return true; + fFeasible = true; } break; } @@ -622,9 +700,49 @@ namespace rrr { assert(0); } if(nVerbose) { - std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is NOT feasible" << std::endl; + if(fFeasible) { + std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is feasible" << std::endl; + } else { + std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is NOT feasible" << std::endl; + } } - return false; + durationCheck += Duration(timeStart, GetCurrentTime()); + return fFeasible; + } + + /* }}} */ + + /* {{{ Summary */ + + template + void BddAnalyzer::ResetSummary() { + if(pBdd) { + nNodesOld = pBdd->GetNumTotalCreatedNodes(); + } else { + nNodesOld = 0; + } + nNodesAccumulated = 0; + durationSimulation = 0; + durationPf = 0; + durationCheck = 0; + durationReorder = 0; + } + + template + summary BddAnalyzer::GetStatsSummary() const { + summary v; + v.emplace_back("bdd node", pBdd->GetNumTotalCreatedNodes() - nNodesOld + nNodesAccumulated); + return v; + } + + template + summary BddAnalyzer::GetTimesSummary() const { + summary v; + v.emplace_back("bdd symbolic simulation", durationSimulation); + v.emplace_back("bdd care computation", durationPf); + v.emplace_back("bdd check", durationCheck); + v.emplace_back("bdd reorder", durationReorder); + return v; } /* }}} */ diff --git a/src/opt/rrr/rrrBddManager.h b/src/opt/rrr/rrrBddManager.h index 1227147c0..af0f8b10f 100644 --- a/src/opt/rrr/rrrBddManager.h +++ b/src/opt/rrr/rrrBddManager.h @@ -181,6 +181,7 @@ namespace NewBdd { bvar nObjs; bvar nObjsAlloc; bvar nObjsMax; + unsigned long long nCreatedTotal; bvar RemovedHead; int nGbc; bvar nReo; @@ -396,6 +397,7 @@ namespace NewBdd { for(; *q; q = vNexts.begin() + *q) if(VarOfBvar(*q) == v && ThenOfBvar(*q) == x1 && ElseOfBvar(*q) == x0) return Bvar2Lit(*q); + nCreatedTotal++; bvar next = *p; if(nObjs < nObjsAlloc) *p = nObjs++; @@ -642,6 +644,7 @@ namespace NewBdd { public: Man(int nVars_, Param p) { + nCreatedTotal = 0; nVerbose = p.nVerbose; // parameter sanity check if(p.nObjsMaxLog < p.nObjsAllocLog) @@ -840,6 +843,9 @@ namespace NewBdd { << "alloc: " << std::setw(10) << nObjsAlloc << std::endl; } + unsigned long long GetNumTotalCreatedNodes() { + return nCreatedTotal; + } }; } diff --git a/src/opt/rrr/rrrBddMspfAnalyzer.h b/src/opt/rrr/rrrBddMspfAnalyzer.h index 400fd9e6c..3119c4605 100644 --- a/src/opt/rrr/rrrBddMspfAnalyzer.h +++ b/src/opt/rrr/rrrBddMspfAnalyzer.h @@ -22,6 +22,7 @@ namespace rrr { int nVerbose; // data + bool fInitialized; NewBdd::Man *pBdd; std::vector vFs; std::vector vGs; @@ -35,6 +36,14 @@ namespace rrr { // backups std::vector vBackups; + // stats + uint64_t nNodesOld; + uint64_t nNodesAccumulated; + double durationSimulation; + double durationPf; + double durationCheck; + double durationReorder; + // BDD utils void IncRef(lit x) const; void DecRef(lit x) const; @@ -63,6 +72,10 @@ namespace rrr { void MspfNode(int id); void Mspf(int id = -1, bool fC = true); + // preparation + void Reset(bool fReuse = false); + void Initialize(); + // save & load void Save(int slot); void Load(int slot); @@ -73,11 +86,16 @@ namespace rrr { BddMspfAnalyzer(); BddMspfAnalyzer(Parameter const *pPar); ~BddMspfAnalyzer(); - void UpdateNetwork(Ntk *pNtk_, bool fSame); + void AssignNetwork(Ntk *pNtk_, bool fReuse); // checks bool CheckRedundancy(int id, int idx); bool CheckFeasibility(int id, int fi, bool c); + + // summary + void ResetSummary(); + summary GetStatsSummary() const; + summary GetTimesSummary() const; }; /* {{{ BDD utils */ @@ -165,6 +183,7 @@ namespace rrr { void BddMspfAnalyzer::ActionCallback(Action const &action) { switch(action.type) { case REMOVE_FANIN: + assert(fInitialized); fUpdate = true; std::fill(vVisits.begin(), vVisits.end(), false); vUpdates[action.id] = true; @@ -174,103 +193,117 @@ namespace rrr { vvCs[action.id].erase(vvCs[action.id].begin() + action.idx); break; case REMOVE_UNUSED: - if(vGUpdates[action.id] || vCUpdates[action.id]) { + if(fInitialized) { + if(vGUpdates[action.id] || vCUpdates[action.id]) { + for(int fi: action.vFanins) { + vGUpdates[fi] = true; + } + } + Assign(vGs[action.id], LitMax); + DelVec(vvCs[action.id]); + } + break; + case REMOVE_BUFFER: + if(fInitialized) { + if(vUpdates[action.id]) { + fUpdate = true; + for(int fo: action.vFanouts) { + vUpdates[fo] = true; + vCUpdates[fo] = true; + } + } + if(vGUpdates[action.id] || vCUpdates[action.id]) { + vGUpdates[action.fi] = true; + } + Assign(vGs[action.id], LitMax); + DelVec(vvCs[action.id]); + } + break; + case REMOVE_CONST: + if(fInitialized) { + if(vUpdates[action.id]) { + fUpdate = true; + for(int fo: action.vFanouts) { + vUpdates[fo] = true; + vCUpdates[fo] = true; + } + } for(int fi: action.vFanins) { vGUpdates[fi] = true; } } - Assign(vGs[action.id], LitMax); - DelVec(vvCs[action.id]); - break; - case REMOVE_BUFFER: - if(vUpdates[action.id]) { - fUpdate = true; - for(int fo: action.vFanouts) { - vUpdates[fo] = true; - vCUpdates[fo] = true; - } - } - if(vGUpdates[action.id] || vCUpdates[action.id]) { - vGUpdates[action.fi] = true; - } - Assign(vGs[action.id], LitMax); - DelVec(vvCs[action.id]); - break; - case REMOVE_CONST: - if(vUpdates[action.id]) { - fUpdate = true; - for(int fo: action.vFanouts) { - vUpdates[fo] = true; - vCUpdates[fo] = true; - } - } - for(int fi: action.vFanins) { - vGUpdates[fi] = true; - } break; case ADD_FANIN: + assert(fInitialized); fUpdate = true; std::fill(vVisits.begin(), vVisits.end(), false); vUpdates[action.id] = true; vCUpdates[action.id] = true; vvCs[action.id].insert(vvCs[action.id].begin() + action.idx, LitMax); break; - case TRIVIAL_COLLAPSE: { - if(vGUpdates[action.fi] || vCUpdates[action.fi]) { - vCUpdates[action.id] = true; - } - std::vector::iterator it = vvCs[action.id].begin() + action.idx; - DecRef(*it); - it = vvCs[action.id].erase(it); - vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end()); - vvCs[action.fi].clear(); - Assign(vFs[action.fi], LitMax); - Assign(vGs[action.fi], LitMax); - break; - } - case TRIVIAL_DECOMPOSE: { - Allocate(); - SimulateNode(action.fi, vFs); - assert(vGs[action.fi] == LitMax); - std::vector::iterator it = vvCs[action.id].begin() + action.idx; - assert(vvCs[action.fi].empty()); - vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end()); - vvCs[action.id].erase(it, vvCs[action.id].end()); - assert(vvCs[action.id].size() == action.idx); - if(!vGUpdates[action.id] && !vCUpdates[action.id]) { - // recompute here only when updates are unlikely to happen - if(pBdd->IsConst1(vGs[action.id])) { - Assign(vGs[action.fi], pBdd->Const1()); - } else { - lit x = pBdd->Const1(); - IncRef(x); - for(int idx2 = 0; idx2 < action.idx; idx2++) { - int fi = pNtk->GetFanin(action.id, idx2); - bool c = pNtk->GetCompl(action.id, idx2); - Assign(x, pBdd->And(x, pBdd->LitNotCond(vFs[fi], c))); - } - Assign(vGs[action.fi], pBdd->Or(pBdd->LitNot(x), vGs[action.id])); - DecRef(x); + case TRIVIAL_COLLAPSE: + if(fInitialized) { + if(vGUpdates[action.fi] || vCUpdates[action.fi]) { + vCUpdates[action.id] = true; } - } else { - // otherwise mark the node for future update - vCUpdates[action.id] = true; - } - vvCs[action.id].resize(action.idx + 1, LitMax); - Assign(vvCs[action.id][action.idx], vGs[action.fi]); - vUpdates[action.fi] = false; - vGUpdates[action.fi] = false; - vCUpdates[action.fi] = false; - break; - } - case SORT_FANINS: { - std::vector vCs = vvCs[action.id]; - vvCs[action.id].clear(); - for(int index: action.vIndices) { - vvCs[action.id].push_back(vCs[index]); + std::vector::iterator it = vvCs[action.id].begin() + action.idx; + DecRef(*it); + it = vvCs[action.id].erase(it); + vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end()); + vvCs[action.fi].clear(); + Assign(vFs[action.fi], LitMax); + Assign(vGs[action.fi], LitMax); } break; - } + case TRIVIAL_DECOMPOSE: + if(fInitialized) { + Allocate(); + SimulateNode(action.fi, vFs); + // time of this simulation is not measured for simplicity sake + assert(vGs[action.fi] == LitMax); + std::vector::iterator it = vvCs[action.id].begin() + action.idx; + assert(vvCs[action.fi].empty()); + vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end()); + vvCs[action.id].erase(it, vvCs[action.id].end()); + assert(vvCs[action.id].size() == action.idx); + if(!vGUpdates[action.id] && !vCUpdates[action.id]) { + // recompute here only when updates are unlikely to happen + if(pBdd->IsConst1(vGs[action.id])) { + Assign(vGs[action.fi], pBdd->Const1()); + } else { + lit x = pBdd->Const1(); + IncRef(x); + for(int idx2 = 0; idx2 < action.idx; idx2++) { + int fi = pNtk->GetFanin(action.id, idx2); + bool c = pNtk->GetCompl(action.id, idx2); + Assign(x, pBdd->And(x, pBdd->LitNotCond(vFs[fi], c))); + } + Assign(vGs[action.fi], pBdd->Or(pBdd->LitNot(x), vGs[action.id])); + DecRef(x); + } + } else { + // otherwise mark the node for future update + vCUpdates[action.id] = true; + } + vvCs[action.id].resize(action.idx + 1, LitMax); + Assign(vvCs[action.id][action.idx], vGs[action.fi]); + vUpdates[action.fi] = false; + vGUpdates[action.fi] = false; + vCUpdates[action.fi] = false; + } + break; + case SORT_FANINS: + if(fInitialized) { + std::vector vCs = vvCs[action.id]; + vvCs[action.id].clear(); + for(int index: action.vIndices) { + vvCs[action.id].push_back(vCs[index]); + } + } + break; + case READ: + Reset(!action.fNew); + break; case SAVE: Save(action.idx); break; @@ -326,6 +359,7 @@ namespace rrr { template void BddMspfAnalyzer::Simulate() { + time_point timeStart = GetCurrentTime(); if(nVerbose) { std::cout << "symbolic simulation with BDD" << std::endl; } @@ -340,6 +374,7 @@ namespace rrr { vUpdates[id] = false; } }); + durationSimulation += Duration(timeStart, GetCurrentTime()); } /* }}} */ @@ -507,6 +542,7 @@ namespace rrr { template void BddMspfAnalyzer::Mspf(int id, bool fC) { + time_point timeStart = GetCurrentTime(); if(id != -1) { pNtk->ForEachTfoReverse(id, false, [&](int fo) { MspfNode(fo); @@ -524,10 +560,82 @@ namespace rrr { MspfNode(id); }); } + durationPf += Duration(timeStart, GetCurrentTime()); } /* }}} */ + /* {{{ Preparation */ + + template + void BddMspfAnalyzer::Reset(bool fReuse) { + while(!vBackups.empty()) { + PopBack(); + } + DelVec(vFs); + DelVec(vGs); + DelVecVec(vvCs); + fInitialized = false; + fUpdate = false; + vUpdates.clear(); + vGUpdates.clear(); + vCUpdates.clear(); + vVisits.clear(); + if(!fReuse) { + nNodesOld = 0; + if(pBdd) { + nNodesAccumulated += pBdd->GetNumTotalCreatedNodes(); + } + delete pBdd; + pBdd = NULL; + } + } + + template + void BddMspfAnalyzer::Initialize() { + bool fUseReo = false; + if(!pBdd) { + NewBdd::Param Par; + Par.nObjsMaxLog = 25; + Par.nCacheMaxLog = 20; + Par.fCountOnes = false; + Par.nGbc = 1; + Par.nReo = 4000; + pBdd = new NewBdd::Man(pNtk->GetNumPis(), Par); + fUseReo = true; + } + assert(pBdd->GetNumVars() == pNtk->GetNumPis()); + Allocate(); + Assign(vFs[0], pBdd->Const0()); + int idx = 0; + pNtk->ForEachPi([&](int id) { + Assign(vFs[id], pBdd->IthVar(idx)); + idx++; + }); + pNtk->ForEachInt([&](int id) { + vUpdates[id] = true; + }); + Simulate(); + if(fUseReo) { + time_point timeStart = GetCurrentTime(); + pBdd->Reorder(); + pBdd->TurnOffReo(); + durationReorder += Duration(timeStart, GetCurrentTime()); + } + pNtk->ForEachInt([&](int id) { + vvCs[id].resize(pNtk->GetNumFanins(id), LitMax); + }); + pNtk->ForEachPo([&](int id) { + vvCs[id].resize(1, LitMax); + Assign(vvCs[id][0], pBdd->Const0()); + int fi = pNtk->GetFanin(id, 0); + vGUpdates[fi] = true; + }); + fInitialized = true; + } + + /* }}} */ + /* {{{ Save & load */ template @@ -575,113 +683,56 @@ namespace rrr { BddMspfAnalyzer::BddMspfAnalyzer() : pNtk(NULL), nVerbose(0), - pBdd(NULL) { + fInitialized(false), + pBdd(NULL), + fUpdate(false) { + ResetSummary(); } template BddMspfAnalyzer::BddMspfAnalyzer(Parameter const *pPar) : pNtk(NULL), nVerbose(pPar->nAnalyzerVerbose), + fInitialized(false), pBdd(NULL), fUpdate(false) { + ResetSummary(); } template - void BddMspfAnalyzer::UpdateNetwork(Ntk *pNtk_, bool fSame) { - // clear - while(!vBackups.empty()) { - PopBack(); - } - DelVec(vFs); - DelVec(vGs); - DelVecVec(vvCs); + BddMspfAnalyzer::~BddMspfAnalyzer() { + Reset(); + } + + template + void BddMspfAnalyzer::AssignNetwork(Ntk *pNtk_, bool fReuse) { + Reset(fReuse); pNtk = pNtk_; - fUpdate = false; - vUpdates.clear(); - vGUpdates.clear(); - vCUpdates.clear(); - vVisits.clear(); - // alloc - bool fUseReo = false; - if(!pBdd || pBdd->GetNumVars() != pNtk->GetNumPis()) { - // need to reset manager - delete pBdd; - NewBdd::Param Par; - Par.nObjsMaxLog = 25; - Par.nCacheMaxLog = 20; - Par.fCountOnes = false; - Par.nGbc = 1; - Par.nReo = 4000; - pBdd = new NewBdd::Man(pNtk->GetNumPis(), Par); - fUseReo = true; - } else if(!fSame) { - // turning on reordering if network function changed - pBdd->TurnOnReo(); - fUseReo = true; - } - Allocate(); - // prepare - Assign(vFs[0], pBdd->Const0()); - int idx = 0; - pNtk->ForEachPi([&](int id) { - Assign(vFs[id], pBdd->IthVar(idx)); - idx++; - }); - pNtk->ForEachInt([&](int id) { - vUpdates[id] = true; - }); - Simulate(); - if(fUseReo) { - pBdd->Reorder(); - pBdd->TurnOffReo(); - } - pNtk->ForEachInt([&](int id) { - vvCs[id].resize(pNtk->GetNumFanins(id), LitMax); - }); - pNtk->ForEachPo([&](int id) { - vvCs[id].resize(1, LitMax); - Assign(vvCs[id][0], pBdd->Const0()); - int fi = pNtk->GetFanin(id, 0); - vGUpdates[fi] = true; - }); pNtk->AddCallback(std::bind(&BddMspfAnalyzer::ActionCallback, this, std::placeholders::_1)); } - template - BddMspfAnalyzer::~BddMspfAnalyzer() { - while(!vBackups.empty()) { - PopBack(); - } - DelVec(vFs); - DelVec(vGs); - DelVecVec(vvCs); - if(pBdd) { - pBdd->PrintStats(); - } - delete pBdd; - } - /* }}} */ /* {{{ Checks */ template bool BddMspfAnalyzer::CheckRedundancy(int id, int idx) { - if(fUpdate) { + if(!fInitialized) { + Initialize(); + } else if(fUpdate) { Simulate(); fUpdate = false; } Mspf(id); + time_point timeStart = GetCurrentTime(); + bool fRedundant = false; switch(pNtk->GetNodeType(id)) { case AND: { int fi = pNtk->GetFanin(id, idx); bool c = pNtk->GetCompl(id, idx); lit x = pBdd->Or(pBdd->LitNotCond(vFs[fi], c), vvCs[id][idx]); if(pBdd->IsConst1(x)) { - if(nVerbose) { - std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is redundant" << std::endl; - } - return true; + fRedundant = true; } break; } @@ -689,18 +740,27 @@ namespace rrr { assert(0); } if(nVerbose) { - std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is NOT redundant" << std::endl; + if(fRedundant) { + std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is redundant" << std::endl; + } else { + std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is NOT redundant" << std::endl; + } } - return false; + durationCheck += Duration(timeStart, GetCurrentTime()); + return fRedundant; } template bool BddMspfAnalyzer::CheckFeasibility(int id, int fi, bool c) { - if(fUpdate) { + if(!fInitialized) { + Initialize(); + } else if(fUpdate) { Simulate(); fUpdate = false; } Mspf(id, false); + time_point timeStart = GetCurrentTime(); + bool fFeasible = false; switch(pNtk->GetNodeType(id)) { case AND: { lit x = pBdd->Or(pBdd->LitNot(vFs[id]), vGs[id]); @@ -708,9 +768,7 @@ namespace rrr { lit y = pBdd->Or(x, pBdd->LitNotCond(vFs[fi], c)); DecRef(x); if(pBdd->IsConst1(y)) { - if(nVerbose) { - std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is feasible" << std::endl; - } + fFeasible = true; return true; } break; @@ -719,9 +777,49 @@ namespace rrr { assert(0); } if(nVerbose) { - std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is NOT feasible" << std::endl; + if(fFeasible) { + std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is feasible" << std::endl; + } else { + std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is NOT feasible" << std::endl; + } } - return false; + durationCheck += Duration(timeStart, GetCurrentTime()); + return fFeasible; + } + + /* }}} */ + + /* {{{ Summary */ + + template + void BddMspfAnalyzer::ResetSummary() { + if(pBdd) { + nNodesOld = pBdd->GetNumTotalCreatedNodes(); + } else { + nNodesOld = 0; + } + nNodesAccumulated = 0; + durationSimulation = 0; + durationPf = 0; + durationCheck = 0; + durationReorder = 0; + } + + template + summary BddMspfAnalyzer::GetStatsSummary() const { + summary v; + v.emplace_back("bdd node", pBdd->GetNumTotalCreatedNodes() - nNodesOld + nNodesAccumulated); + return v; + } + + template + summary BddMspfAnalyzer::GetTimesSummary() const { + summary v; + v.emplace_back("bdd symbolic simulation", durationSimulation); + v.emplace_back("bdd care computation", durationPf); + v.emplace_back("bdd check", durationCheck); + v.emplace_back("bdd reorder", durationReorder); + return v; } /* }}} */ diff --git a/src/opt/rrr/rrrLevelBasePartitioner.h b/src/opt/rrr/rrrLevelBasePartitioner.h index 5225cc5a7..5693c38e5 100644 --- a/src/opt/rrr/rrrLevelBasePartitioner.h +++ b/src/opt/rrr/rrrLevelBasePartitioner.h @@ -43,7 +43,7 @@ namespace rrr { public: // constructors LevelBasePartitioner(Parameter const *pPar); - void UpdateNetwork(Ntk *pNtk); + void AssignNetwork(Ntk *pNtk); // APIs Ntk *Extract(int iSeed); @@ -214,7 +214,7 @@ namespace rrr { } template - void LevelBasePartitioner::UpdateNetwork(Ntk *pNtk_) { + void LevelBasePartitioner::AssignNetwork(Ntk *pNtk_) { pNtk = pNtk_; assert(mSubNtk2Io.empty()); assert(sBlocked.empty()); diff --git a/src/opt/rrr/rrrOptimizer.h b/src/opt/rrr/rrrOptimizer.h index 831456295..eacb0a0ad 100644 --- a/src/opt/rrr/rrrOptimizer.h +++ b/src/opt/rrr/rrrOptimizer.h @@ -21,7 +21,7 @@ namespace rrr { using citr = std::vector::const_iterator; using ritr = std::vector::reverse_iterator; using critr = std::vector::const_reverse_iterator; - + // pointer to network Ntk *pNtk; @@ -35,7 +35,7 @@ namespace rrr { bool fCompatible; bool fGreedy; seconds nTimeout; // assigned upon Run - std::string strVerbosePrefix; + std::function PrintLine; // data Ana ana; @@ -52,6 +52,11 @@ namespace rrr { int target; std::vector vTfoMarks; + // statistics + struct Stats; + std::map stats; + Stats statsLocal; + // print template void Print(int nVerboseLevel, Args... args); @@ -76,17 +81,18 @@ namespace rrr { bool ReduceFaninsOneRandom(int id, bool fRemoveUnused = false); // reduce - bool Reduce(); + bool Reduce(bool fSubRoutine = false); void ReduceRandom(); // remove redundancy - void RemoveRedundancy(); + bool RemoveRedundancy(); void RemoveRedundancyRandom(); // addition template T SingleAdd(int id, T begin, T end); int MultiAdd(int id, std::vector const &vCands, int nMax = 0); + void Undo(); // resub void SingleResub(int id, std::vector const &vCands); @@ -108,25 +114,81 @@ namespace rrr { public: // constructors Optimizer(Parameter const *pPar, std::function CostFunction); - void UpdateNetwork(Ntk *pNtk_, bool fSame = false); + void AssignNetwork(Ntk *pNtk_, bool fReuse = false); + void SetPrintLine(std::function const &PrintLine_); // run void Run(int iSeed = 0, seconds nTimeout_ = 0); - + + // summary + void ResetSummary(); + summary GetStatsSummary() const; + summary GetTimesSummary() const; }; - /* {{{ Print */ + /* {{{ Stats */ + template + struct Optimizer::Stats { + int nTriedFis = 0; + int nAddedFis = 0; + int nTried = 0; + int nAdded = 0; + int nChanged = 0; + int nUps = 0; + int nEqs = 0; + int nDowns = 0; + double durationAdd = 0; + double durationReduce = 0; + + void Reset() { + nTriedFis = 0; + nAddedFis = 0; + nTried = 0; + nAdded = 0; + nChanged = 0; + nUps = 0; + nEqs = 0; + nDowns = 0; + durationAdd = 0; + durationReduce = 0; + } + + Stats& operator+=(Stats const &other) { + this->nTriedFis += other.nTriedFis; + this->nAddedFis += other.nAddedFis; + this->nTried += other.nTried; + this->nAdded += other.nAdded; + this->nChanged += other.nChanged; + this->nUps += other.nUps; + this->nEqs += other.nEqs; + this->nDowns += other.nDowns; + this->durationAdd += other.durationAdd; + this->durationReduce += other.durationReduce; + return *this; + } + + std::string GetString() const { + std::stringstream ss; + PrintNext(ss, "tried node/fanin", "=", nTried, "/", nTriedFis, ",", "added node/fanin", "=", nAdded, "/", nAddedFis, ",", "changed", "=", nChanged, ",", "up/eq/dn", "=", nUps, "/", nEqs, "/", nDowns); + return ss.str(); + } + }; + + /* }}} */ + + /* {{{ Print */ + template template inline void Optimizer::Print(int nVerboseLevel, Args... args) { if(nVerbose > nVerboseLevel) { - std::cout << strVerbosePrefix; + std::stringstream ss; for(int i = 0; i < nVerboseLevel; i++) { - std::cout << "\t"; + ss << "\t"; } - PrintNext(std::cout, args...); - std::cout << std::endl; + PrintNext(ss, args...); + PrintLine(ss.str()); } } @@ -136,13 +198,13 @@ namespace rrr { template void Optimizer::ActionCallback(Action const &action) { - if(nVerbose > 2) { + if(nVerbose > 4) { std::stringstream ss = GetActionDescription(action); std::string str; std::getline(ss, str); - Print(2, str); + Print(4, str); while(std::getline(ss, str)) { - Print(3, str); + Print(5, str); } } switch(action.type) { @@ -171,6 +233,9 @@ namespace rrr { break; case SORT_FANINS: break; + case READ: + target = -1; + break; case SAVE: break; case LOAD: @@ -482,7 +547,7 @@ namespace rrr { template inline bool Optimizer::ReduceFanins(int id, bool fRemoveUnused) { assert(pNtk->GetNumFanouts(id) > 0); - bool fRemoved = false; + bool fReduced = false; for(int idx = 0; idx < pNtk->GetNumFanins(id); idx++) { // skip fanins that were just added if(mapNewFanins.count(id)) { @@ -495,14 +560,14 @@ namespace rrr { if(ana.CheckRedundancy(id, idx)) { int fi = pNtk->GetFanin(id, idx); pNtk->RemoveFanin(id, idx); - fRemoved = true; + fReduced = true; idx--; if(fRemoveUnused && pNtk->GetNumFanouts(fi) == 0) { pNtk->RemoveUnused(fi, true); } } } - return fRemoved; + return fReduced; } /* @@ -542,7 +607,8 @@ namespace rrr { /* {{{ Reduce */ template - bool Optimizer::Reduce() { + bool Optimizer::Reduce(bool fSubRoutine) { + time_point timeStart = GetCurrentTime(); bool fReduced = false; std::vector vInts = pNtk->GetInts(); for(critr it = vInts.rbegin(); it != vInts.rend(); it++) { @@ -558,6 +624,10 @@ namespace rrr { pNtk->Propagate(*it); } } + if(!fSubRoutine) { + time_point timeEnd = GetCurrentTime(); + statsLocal.durationReduce += Duration(timeStart, timeEnd); + } return fReduced; } @@ -588,35 +658,42 @@ namespace rrr { /* {{{ Redundancy removal */ template - void Optimizer::RemoveRedundancy() { + bool Optimizer::RemoveRedundancy() { + time_point timeStart = GetCurrentTime(); + bool fReduced = false; if(fCompatible) { - while(Reduce()) { + while(Reduce(true)) { + fReduced = true; SortFanins(); } - return; - } - std::vector vInts = pNtk->GetInts(); - for(critr it = vInts.rbegin(); it != vInts.rend();) { - if(!pNtk->IsInt(*it)) { - it++; - continue; - } - if(pNtk->GetNumFanouts(*it) == 0) { - pNtk->RemoveUnused(*it); - it++; - continue; - } - SortFanins(*it); - bool fReduced = ReduceFanins(*it); - if(pNtk->GetNumFanins(*it) <= 1) { - pNtk->Propagate(*it); - } - if(fReduced) { - it = vInts.rbegin(); - } else { - it++; + } else { + std::vector vInts = pNtk->GetInts(); + for(critr it = vInts.rbegin(); it != vInts.rend();) { + if(!pNtk->IsInt(*it)) { + it++; + continue; + } + if(pNtk->GetNumFanouts(*it) == 0) { + pNtk->RemoveUnused(*it); + it++; + continue; + } + SortFanins(*it); + bool fReduced_ = ReduceFanins(*it); + fReduced |= fReduced_; + if(pNtk->GetNumFanins(*it) <= 1) { + pNtk->Propagate(*it); + } + if(fReduced_) { + it = vInts.rbegin(); + } else { + it++; + } } } + time_point timeEnd = GetCurrentTime(); + statsLocal.durationReduce += Duration(timeStart, timeEnd); + return fReduced; } /* @@ -656,6 +733,7 @@ namespace rrr { template template T Optimizer::SingleAdd(int id, T begin, T end) { + time_point timeStart = GetCurrentTime(); MarkTfo(id); pNtk->ForEachFanin(id, [&](int fi) { vTfoMarks[fi] = true; @@ -668,10 +746,13 @@ namespace rrr { if(vTfoMarks[*it]) { continue; } + statsLocal.nTriedFis++; if(ana.CheckFeasibility(id, *it, false)) { pNtk->AddFanin(id, *it, false); + statsLocal.nAddedFis++; } else if(pNtk->UseComplementedEdges() && ana.CheckFeasibility(id, *it, true)) { pNtk->AddFanin(id, *it, true); + statsLocal.nAddedFis++; } else { continue; } @@ -681,16 +762,19 @@ namespace rrr { pNtk->ForEachFanin(id, [&](int fi) { vTfoMarks[fi] = false; }); + time_point timeEnd = GetCurrentTime(); + statsLocal.durationAdd += Duration(timeStart, timeEnd); return it; } template int Optimizer::MultiAdd(int id, std::vector const &vCands, int nMax) { + time_point timeStart = GetCurrentTime(); MarkTfo(id); pNtk->ForEachFanin(id, [&](int fi) { vTfoMarks[fi] = true; }); - int nAdded = 0; + int nAddedFis_ = 0; for(int cand: vCands) { if(!pNtk->IsInt(cand) && !pNtk->IsPi(cand)) { continue; @@ -698,23 +782,39 @@ namespace rrr { if(vTfoMarks[cand]) { continue; } + statsLocal.nTriedFis++; if(ana.CheckFeasibility(id, cand, false)) { pNtk->AddFanin(id, cand, false); + statsLocal.nAddedFis++; } else if(pNtk->UseComplementedEdges() && ana.CheckFeasibility(id, cand, true)) { pNtk->AddFanin(id, cand, true); + statsLocal.nAddedFis++; } else { continue; } mapNewFanins[id].insert(cand); - nAdded++; - if(nAdded == nMax) { + nAddedFis_++; + if(nAddedFis_ == nMax) { break; } } pNtk->ForEachFanin(id, [&](int fi) { vTfoMarks[fi] = false; }); - return nAdded; + time_point timeEnd = GetCurrentTime(); + statsLocal.durationAdd += Duration(timeStart, timeEnd); + return nAddedFis_; + } + + template + void Optimizer::Undo() { + for(auto const &entry: mapNewFanins) { + int id = entry.first; + for(int fi: entry.second) { + int idx = pNtk->FindFanin(id, fi); + pNtk->RemoveFanin(id, idx); + } + } } /* }}} */ @@ -731,11 +831,12 @@ namespace rrr { pNtk->TrivialCollapse(id); // save if wanted int slot = -2; - if(fGreedy) { + if(fGreedy || fCompatible) { slot = pNtk->Save(); } - double dCost = CostFunction(pNtk); // main loop + double cost = CostFunction(pNtk); + bool fTried = false, fAdded = false; for(citr it = vCands.begin(); it != vCands.end(); it++) { if(Timeout()) { break; @@ -743,25 +844,44 @@ namespace rrr { if(!pNtk->IsInt(id)) { break; } + fTried = true; it = SingleAdd(id, it, vCands.end()); if(it == vCands.end()) { break; } - Print(1, "cand", *it, "(", int_distance(vCands.begin(), it) + 1, "/", int_size(vCands), "):", "cost", "=", dCost); - RemoveRedundancy(); - mapNewFanins.clear(); - double dNewCost = CostFunction(pNtk); - Print(2, "cost:", dCost, "->", dNewCost); - if(fGreedy) { - if(dNewCost <= dCost) { - pNtk->Save(slot); - dCost = dNewCost; + fAdded = true; + Print(2, "cand", *it, "(", int_distance(vCands.begin(), it) + 1, "/", int_size(vCands), ")", ":", "cost", "=", cost); + if(RemoveRedundancy()) { + double costNew = CostFunction(pNtk); + // stats + statsLocal.nChanged++; + if(costNew < cost) { + statsLocal.nDowns++; + } else if (costNew == cost) { + statsLocal.nEqs++; } else { - pNtk->Load(slot); + statsLocal.nUps++; + } + // greedy + if(fGreedy) { + if(costNew <= cost) { + pNtk->Save(slot); + cost = costNew; + } else { + pNtk->Load(slot); + } + } else { + cost = costNew; } } else { - dCost = dNewCost; + // assuming addition only always increases cost + if(fCompatible) { + pNtk->Load(slot); + } else { + Undo(); + } } + mapNewFanins.clear(); } if(pNtk->IsInt(id)) { pNtk->TrivialDecompose(id); @@ -770,9 +890,15 @@ namespace rrr { RemoveRedundancy(); } } - if(fGreedy) { + if(fGreedy || fCompatible) { pNtk->PopBack(); } + if(fTried) { + statsLocal.nTried++; + } + if(fAdded) { + statsLocal.nAdded++; + } } template @@ -781,24 +907,43 @@ namespace rrr { // let us assume the node is not trivially redundant for now assert(pNtk->GetNumFanouts(id) != 0); assert(pNtk->GetNumFanins(id) > 1); + statsLocal.nTried++; // save if wanted int slot = -2; - if(fGreedy) { + if(fGreedy || fCompatible) { slot = pNtk->Save(); } - double dCost = CostFunction(pNtk); // collapse pNtk->TrivialCollapse(id); // resub - MultiAdd(id, vCands, nMax); - RemoveRedundancy(); - mapNewFanins.clear(); - // TODO: we could quit here if nothing has been removed - RemoveRedundancy(); - double dNewCost = CostFunction(pNtk); - Print(1, "cost:", dCost, "->", dNewCost); - if(fGreedy && dNewCost > dCost) { - pNtk->Load(slot); + double cost = CostFunction(pNtk); + if(MultiAdd(id, vCands, nMax)) { + statsLocal.nAdded++; + if(RemoveRedundancy()) { + mapNewFanins.clear(); + RemoveRedundancy(); + double costNew = CostFunction(pNtk); + // stats + statsLocal.nChanged++; + if(costNew < cost) { + statsLocal.nDowns++; + } else if (costNew == cost) { + statsLocal.nEqs++; + } else { + statsLocal.nUps++; + } + // greedy + if(fGreedy && costNew > cost) { + pNtk->Load(slot); + } + } else { + if(fCompatible) { + pNtk->Load(slot); + } else { + Undo(); + } + mapNewFanins.clear(); + } } if(pNtk->IsInt(id)) { pNtk->TrivialDecompose(id); @@ -807,7 +952,7 @@ namespace rrr { RemoveRedundancy(); } } - if(fGreedy) { + if(fGreedy || fCompatible) { pNtk->PopBack(); } } @@ -824,57 +969,77 @@ namespace rrr { // let us assume the node is not trivially redundant for now assert(pNtk->GetNumFanouts(id) != 0); assert(pNtk->GetNumFanins(id) > 1); - // save before trivial collapse - int slot0 = pNtk->Save(); + Print(2, "method", "=", "single"); // collapse pNtk->TrivialCollapse(id); - // save after trivial collapse + // save int slot = pNtk->Save(); - double dCost = CostFunction(pNtk); // remember fanins std::set sFanins = pNtk->GetExtendedFanins(id); - Print(2, "extended fanins:", sFanins); + Print(3, "extended fanins", ":", sFanins); // main loop + bool fChanged = false; + double cost = CostFunction(pNtk); + bool fTried = false, fAdded = false; for(citr it = vCands.begin(); it != vCands.end(); it++) { if(Timeout()) { break; } assert(pNtk->IsInt(id)); + fTried = true; it = SingleAdd(id, it, vCands.end()); if(it == vCands.end()) { break; } - Print(1, "cand", *it, "(", int_distance(vCands.begin(), it) + 1, "/", int_size(vCands), "):", "cost", "=", dCost); - RemoveRedundancy(); - mapNewFanins.clear(); - double dNewCost = CostFunction(pNtk); - Print(2, "cost:", dCost, "->", dNewCost); - if(dNewCost <= dCost) { - bool fChanged = false; - if(dNewCost < dCost || !pNtk->IsInt(id)) { - fChanged = true; - } else { - std::set sNewFanins = pNtk->GetExtendedFanins(id); - Print(2, "new extended fanins:", sNewFanins); - if(sFanins != sNewFanins) { + fAdded = true; + Print(3, "cand", *it, "(", int_distance(vCands.begin(), it) + 1, "/", int_size(vCands), ")", ":", "cost", "=", cost); + if(RemoveRedundancy()) { + mapNewFanins.clear(); + double costNew = CostFunction(pNtk); + if(costNew <= cost) { + fChanged = false; + if(costNew < cost || !pNtk->IsInt(id)) { fChanged = true; + } else { + std::set sNewFanins = pNtk->GetExtendedFanins(id); + Print(3, "new extended fanins", ":", sNewFanins); + if(sFanins != sNewFanins) { + fChanged = true; + } + } + if(fChanged) { + statsLocal.nChanged++; + if(costNew < cost) { + statsLocal.nDowns++; + } else if (costNew == cost) { + statsLocal.nEqs++; + } else { + statsLocal.nUps++; + } + break; } } - if(fChanged) { - if(pNtk->IsInt(id)) { - pNtk->TrivialDecompose(id); - } - pNtk->PopBack(); // slot - pNtk->PopBack(); // slot0 - return true; + pNtk->Load(slot); + } else { + if(fCompatible) { + pNtk->Load(slot); + } else { + Undo(); } + mapNewFanins.clear(); } - pNtk->Load(slot); } - pNtk->PopBack(); // slot - pNtk->Load(slot0); - pNtk->PopBack(); // slot0 - return false; + if(pNtk->IsInt(id)) { + pNtk->TrivialDecompose(id); + } + pNtk->PopBack(); + if(fTried) { + statsLocal.nTried++; + } + if(fAdded) { + statsLocal.nAdded++; + } + return fChanged; } template @@ -885,44 +1050,59 @@ namespace rrr { // let us assume the node is not trivially redundant for now assert(pNtk->GetNumFanouts(id) != 0); assert(pNtk->GetNumFanins(id) > 1); + Print(2, "method", "=", "multi"); + statsLocal.nTried++; // save int slot = pNtk->Save(); - double dCost = CostFunction(pNtk); // remember fanins std::set sFanins = pNtk->GetExtendedFanins(id); - Print(2, "extended fanins:", sFanins); + Print(3, "extended fanins", ":", sFanins); // collapse pNtk->TrivialCollapse(id); // resub - MultiAdd(id, vCands, nMax); - RemoveRedundancy(); - mapNewFanins.clear(); - // TODO: we could quit here if nothing has been removed - RemoveRedundancy(); - double dNewCost = CostFunction(pNtk); - Print(1, "cost:", dCost, "->", dNewCost); - if(!fGreedy || dNewCost <= dCost) { - bool fChanged = false; - if(dNewCost < dCost || !pNtk->IsInt(id)) { - fChanged = true; + bool fChanged = false; + double cost = CostFunction(pNtk); + if(MultiAdd(id, vCands, nMax)) { + statsLocal.nAdded++; + if(RemoveRedundancy()) { + mapNewFanins.clear(); + RemoveRedundancy(); + double costNew = CostFunction(pNtk); + if(!fGreedy || costNew <= cost) { + fChanged = false; + if(costNew < cost || !pNtk->IsInt(id)) { + fChanged = true; + } else { + std::set sNewFanins = pNtk->GetExtendedFanins(id); + Print(3, "new extended fanins", ":", sNewFanins); + if(sFanins != sNewFanins) { + fChanged = true; + } + } + if(fChanged) { + statsLocal.nChanged++; + if(costNew < cost) { + statsLocal.nDowns++; + } else if (costNew == cost) { + statsLocal.nEqs++; + } else { + statsLocal.nUps++; + } + } + } } else { - std::set sNewFanins = pNtk->GetExtendedFanins(id); - Print(2, "new extended fanins:", sNewFanins); - if(sFanins != sNewFanins) { - fChanged = true; - } - } - if(fChanged) { - if(pNtk->IsInt(id)) { - pNtk->TrivialDecompose(id); - } - pNtk->PopBack(); - return true; + mapNewFanins.clear(); } } - pNtk->Load(slot); + if(fChanged) { + if(pNtk->IsInt(id)) { + pNtk->TrivialDecompose(id); + } + } else { + pNtk->Load(slot); + } pNtk->PopBack(); - return false; + return fChanged; } /* }}} */ @@ -948,7 +1128,7 @@ namespace rrr { } } // add while remembering extended fanins - Print(1, "targets:", vTargets); + Print(2, "targets", ":", vTargets); std::vector> vsFanins; for(int id: vTargets) { // get candidates @@ -961,7 +1141,7 @@ namespace rrr { std::shuffle(vCands.begin(), vCands.end(), rng); // remember fanins std::set sFanins = pNtk->GetExtendedFanins(id); - Print(2, "extended fanins:", sFanins); + Print(3, "extended fanins", ":", sFanins); vsFanins.push_back(std::move(sFanins)); // add MultiAdd(id, vCands, nMax); @@ -972,7 +1152,7 @@ namespace rrr { // TODO: we could quit here if nothing has been removed RemoveRedundancy(); double dNewCost = CostFunction(pNtk); - Print(1, "cost:", dCost, "->", dNewCost); + Print(2, "cost =", dCost, "->", dNewCost); if(!fGreedy || dNewCost <= dCost) { bool fChanged = false; if(dNewCost < dCost) { @@ -986,7 +1166,7 @@ namespace rrr { } for(int i = 0; !fChanged && i < int_size(vTargets); i++) { std::set sNewFanins = pNtk->GetExtendedFanins(vTargets[i]); - Print(2, "new extended fanins:", sNewFanins); + Print(3, "new extended fanins", ":", sNewFanins); if(vsFanins[i] != sNewFanins) { fChanged = true; } @@ -1021,7 +1201,7 @@ namespace rrr { if(!pNtk->IsInt(*it)) { continue; } - Print(0, "node", *it, "(", int_distance(vInts.crbegin(), it) + 1, "/", int_size(vInts), "):", "cost", "=", CostFunction(pNtk)); + Print(1, "node", *it, "(", int_distance(vInts.crbegin(), it) + 1, "/", int_size(vInts), ")", ":", "cost", "=", CostFunction(pNtk)); func(*it); } } @@ -1037,7 +1217,7 @@ namespace rrr { if(!pNtk->IsInt(*it)) { continue; } - Print(0, "node", *it, "(", int_distance(vInts.cbegin(), it) + 1, "/", int_size(vInts), "):", "cost", "=", CostFunction(pNtk)); + Print(1, "node", *it, "(", int_distance(vInts.cbegin(), it) + 1, "/", int_size(vInts), ")", ":", "cost", "=", CostFunction(pNtk)); if(func(*it)) { break; } @@ -1048,10 +1228,10 @@ namespace rrr { void Optimizer::ApplyCombinationRandomlyStop(int k, std::function const &)> const &func) { std::vector vInts = pNtk->GetInts(); std::shuffle(vInts.begin(), vInts.end(), rng); // order is decided here, so it's not truely exhaustive - int nTried = 0; + int nTried_ = 0; int nCombs = k * (k - 1) / 2; ForEachCombinationStop(int_size(vInts), k, [&](std::vector const &vIdxs) { - Print(0, "comb", vIdxs, "(", ++nTried, "/", nCombs, ")"); + Print(1, "comb", vIdxs, "(", ++nTried_, "/", nCombs, ")"); assert(int_size(vIdxs) == k); if(Timeout()) { return true; @@ -1078,7 +1258,7 @@ namespace rrr { } std::vector vIdxs(sIdxs.begin(), sIdxs.end()); std::shuffle(vIdxs.begin(), vIdxs.end(), rng); - Print(0, "comb", vIdxs, "(", i + 1, "/", nSamples, ")"); + Print(1, "comb", vIdxs, "(", i + 1, "/", nSamples, ")"); std::vector vTargets(k); for(int i = 0; i < k; i++) { vTargets[i] = vInts[vIdxs[i]]; @@ -1109,11 +1289,16 @@ namespace rrr { } template - void Optimizer::UpdateNetwork(Ntk *pNtk_, bool fSame) { + void Optimizer::AssignNetwork(Ntk *pNtk_, bool fReuse) { pNtk = pNtk_; target = -1; pNtk->AddCallback(std::bind(&Optimizer::ActionCallback, this, std::placeholders::_1)); - ana.UpdateNetwork(pNtk, fSame); + ana.AssignNetwork(pNtk, fReuse); + } + + template + void Optimizer::SetPrintLine(std::function const &PrintLine_) { + PrintLine = PrintLine_; } /* }}} */ @@ -1127,13 +1312,14 @@ namespace rrr { vRandCosts.clear(); if(nSortTypeOriginal < 0) { nSortType = rng() % 18; - Print(0, "sorttype =", nSortType); + Print(0, "fanin cost function =", nSortType); } nTimeout = nTimeout_; start = GetCurrentTime(); switch(nFlow) { case 0: RemoveRedundancy(); + statsLocal.Reset(); ApplyReverseTopologically([&](int id) { std::vector vCands; if(nDistance) { @@ -1143,9 +1329,12 @@ namespace rrr { } SingleResub(id, vCands); }); + stats["single"] += statsLocal; + Print(0, statsLocal.GetString()); break; case 1: RemoveRedundancy(); + statsLocal.Reset(); ApplyReverseTopologically([&](int id) { std::vector vCands; if(nDistance) { @@ -1155,11 +1344,14 @@ namespace rrr { } MultiResub(id, vCands); }); + stats["multi"] += statsLocal; + Print(0, statsLocal.GetString()); break; case 2: { RemoveRedundancy(); double dCost = CostFunction(pNtk); while(true) { + statsLocal.Reset(); ApplyReverseTopologically([&](int id) { std::vector vCands; if(nDistance) { @@ -1169,6 +1361,9 @@ namespace rrr { } SingleResub(id, vCands); }); + stats["single"] += statsLocal; + Print(0, "single", ":", "cost", "=", CostFunction(pNtk), ",", statsLocal.GetString()); + statsLocal.Reset(); ApplyReverseTopologically([&](int id) { std::vector vCands; if(nDistance) { @@ -1179,6 +1374,8 @@ namespace rrr { } MultiResub(id, vCands); }); + stats["multi"] += statsLocal; + Print(0, "multi ", ":", "cost", "=", CostFunction(pNtk), ",", statsLocal.GetString()); double dNewCost = CostFunction(pNtk); if(dNewCost < dCost) { dCost = dNewCost; @@ -1195,17 +1392,27 @@ namespace rrr { vCands = pNtk->GetPisInts(); std::shuffle(vCands.begin(), vCands.end(), rng); } + Stats statsSingle, statsMulti; ApplyRandomlyStop([&](int id) { + statsLocal.Reset(); if(nDistance) { vCands = pNtk->GetNeighbors(id, true, nDistance); std::shuffle(vCands.begin(), vCands.end(), rng); } + bool fChanged; if(rng() & 1) { - return SingleResubStop(id, vCands); + fChanged = SingleResubStop(id, vCands); + statsSingle += statsLocal; } else { - return MultiResubStop(id, vCands); + fChanged = MultiResubStop(id, vCands); + statsMulti += statsLocal; } + return fChanged; }); + stats["single"] += statsSingle; + stats["multi"] += statsMulti; + Print(0, "single", ":", statsSingle.GetString()); + Print(0, "multi ", ":", statsMulti.GetString()); break; } case 4: { @@ -1221,6 +1428,46 @@ namespace rrr { } /* }}} */ + + /* {{{ Summary */ + + template + void Optimizer::ResetSummary() { + stats.clear(); + ana.ResetSummary(); + } + + template + summary Optimizer::GetStatsSummary() const { + summary v; + for(auto const &entry: stats) { + v.emplace_back("opt " + entry.first + " tried node", entry.second.nTried); + v.emplace_back("opt " + entry.first + " tried fanin", entry.second.nTriedFis); + v.emplace_back("opt " + entry.first + " added node", entry.second.nAdded); + v.emplace_back("opt " + entry.first + " added fanin", entry.second.nAddedFis); + v.emplace_back("opt " + entry.first + " changed", entry.second.nChanged); + v.emplace_back("opt " + entry.first + " up", entry.second.nUps); + v.emplace_back("opt " + entry.first + " eq", entry.second.nEqs); + v.emplace_back("opt " + entry.first + " dn", entry.second.nDowns); + } + summary v2 = ana.GetStatsSummary(); + v.insert(v.end(), v2.begin(), v2.end()); + return v; + } + + template + summary Optimizer::GetTimesSummary() const { + summary v; + for(auto const &entry: stats) { + v.emplace_back("opt " + entry.first + " add", entry.second.durationAdd); + v.emplace_back("opt " + entry.first + " reduce", entry.second.durationReduce); + } + summary v2 = ana.GetTimesSummary(); + v.insert(v.end(), v2.begin(), v2.end()); + return v; + } + + /* }}} */ } diff --git a/src/opt/rrr/rrrParameter.h b/src/opt/rrr/rrrParameter.h index e6b5ccb8c..c80171c43 100644 --- a/src/opt/rrr/rrrParameter.h +++ b/src/opt/rrr/rrrParameter.h @@ -8,7 +8,7 @@ namespace rrr { int iSeed = 0; int nWords = 10; int nTimeout = 0; - int nSchedulerVerbose = 1; + int nSchedulerVerbose = 0; int nPartitionerVerbose = 0; int nOptimizerVerbose = 0; int nAnalyzerVerbose = 0; diff --git a/src/opt/rrr/rrrPartitioner.h b/src/opt/rrr/rrrPartitioner.h index 16819f075..da14344fc 100644 --- a/src/opt/rrr/rrrPartitioner.h +++ b/src/opt/rrr/rrrPartitioner.h @@ -42,7 +42,7 @@ namespace rrr { public: // constructors Partitioner(Parameter const *pPar); - void UpdateNetwork(Ntk *pNtk); + void AssignNetwork(Ntk *pNtk); // APIs Ntk *Extract(int iSeed); @@ -270,7 +270,7 @@ namespace rrr { } template - void Partitioner::UpdateNetwork(Ntk *pNtk_) { + void Partitioner::AssignNetwork(Ntk *pNtk_) { pNtk = pNtk_; assert(mSubNtk2Io.empty()); assert(sBlocked.empty()); diff --git a/src/opt/rrr/rrrSatSolver.h b/src/opt/rrr/rrrSatSolver.h index b1bf01f35..1f5101753 100644 --- a/src/opt/rrr/rrrSatSolver.h +++ b/src/opt/rrr/rrrSatSolver.h @@ -28,10 +28,12 @@ namespace rrr { std::vector vValues; // values in satisfied problem bool fUpdate; - // statistics + // stats int nCalls; int nSats; int nUnsats; + double durationRedundancy; + double durationFeasibility; // callback void ActionCallback(Action const &action); @@ -45,7 +47,7 @@ namespace rrr { // constructors SatSolver(Parameter const *pPar); ~SatSolver(); - void UpdateNetwork(Ntk *pNtk_, bool fSame); + void AssignNetwork(Ntk *pNtk_, bool fReuse); // checks SatResult CheckRedundancy(int id, int idx); @@ -53,6 +55,11 @@ namespace rrr { // cex std::vector GetCex(); + + // stats + void ResetSummary(); + summary GetStatsSummary() const; + summary GetTimesSummary() const; }; /* {{{ Callback */ @@ -88,6 +95,11 @@ namespace rrr { break; case SORT_FANINS: break; + case READ: + status = false; + target = -1; + fUpdate = false; + break; case SAVE: break; case LOAD: @@ -259,25 +271,23 @@ namespace rrr { pSat(sat_solver_new()), status(false), target(-1), - fUpdate(false), - nCalls(0), - nSats(0), - nUnsats(0) { + fUpdate(false) { + ResetSummary(); } template SatSolver::~SatSolver() { sat_solver_delete(pSat); - std::cout << "SAT solver stats: calls = " << nCalls << " (SAT = " << nSats << ", UNSAT = " << nUnsats << ", UNDET = " << nCalls - nSats - nUnsats << ")" << std::endl; + //std::cout << "SAT solver stats: calls = " << nCalls << " (SAT = " << nSats << ", UNSAT = " << nUnsats << ", UNDET = " << nCalls - nSats - nUnsats << ")" << std::endl; } template - void SatSolver::UpdateNetwork(Ntk *pNtk_, bool fSame) { - (void)fSame; - pNtk = pNtk_; + void SatSolver::AssignNetwork(Ntk *pNtk_, bool fReuse) { + (void)fReuse; status = false; target = -1; fUpdate = false; + pNtk = pNtk_; pNtk->AddCallback(std::bind(&SatSolver::ActionCallback, this, std::placeholders::_1)); } @@ -287,11 +297,13 @@ namespace rrr { template SatResult SatSolver::CheckRedundancy(int id, int idx) { + time_point timeStart = GetCurrentTime(); SetTarget(id); if(!status) { if(nVerbose) { std::cout << "trivially UNSATISFIABLE" << std::endl; } + durationRedundancy += Duration(timeStart, GetCurrentTime()); return UNSAT; } vLits.clear(); @@ -319,12 +331,14 @@ namespace rrr { std::cout << "UNSATISFIABLE" << std::endl; } nUnsats++; + durationRedundancy += Duration(timeStart, GetCurrentTime()); return UNSAT; } if(res == l_Undef) { if(nVerbose) { std::cout << "UNDETERMINED" << std::endl; } + durationRedundancy += Duration(timeStart, GetCurrentTime()); return UNDET; } assert(res == l_True); @@ -353,16 +367,19 @@ namespace rrr { assert((vValues[fi] == TEMP_TRUE) ^ (idx == idx2) ^ c); vValues[fi] = DecideVarValue(vValues[fi]); }); + durationRedundancy += Duration(timeStart, GetCurrentTime()); return SAT; } template SatResult SatSolver::CheckFeasibility(int id, int fi, bool c) { + time_point timeStart = GetCurrentTime(); SetTarget(id); if(!status) { if(nVerbose) { std::cout << "trivially UNSATISFIABLE" << std::endl; } + durationFeasibility += Duration(timeStart, GetCurrentTime()); return UNSAT; } vLits.clear(); @@ -385,12 +402,14 @@ namespace rrr { std::cout << "UNSATISFIABLE" << std::endl; } nUnsats++; + durationFeasibility += Duration(timeStart, GetCurrentTime()); return UNSAT; } if(res == l_Undef) { if(nVerbose) { std::cout << "UNDETERMINED" << std::endl; } + durationFeasibility += Duration(timeStart, GetCurrentTime()); return UNDET; } assert(res == l_True); @@ -419,6 +438,7 @@ namespace rrr { vValues[id] = DecideVarValue(vValues[id]); assert((vValues[fi] == TEMP_TRUE) ^ !c); vValues[fi] = DecideVarValue(vValues[fi]); + durationFeasibility += Duration(timeStart, GetCurrentTime()); return SAT; } @@ -537,6 +557,36 @@ namespace rrr { /* }}} */ + /* {{{ Stats */ + + template + void SatSolver::ResetSummary() { + nCalls = 0; + nSats = 0; + nUnsats = 0; + durationRedundancy = 0; + durationFeasibility = 0; + } + + template + summary SatSolver::GetStatsSummary() const { + summary v; + v.emplace_back("sat call", nCalls); + v.emplace_back("sat satisfiable", nSats); + v.emplace_back("sat unsatisfiable", nUnsats); + return v; + } + + template + summary SatSolver::GetTimesSummary() const { + summary v; + v.emplace_back("sat redundancy", durationRedundancy); + v.emplace_back("sat feasibility", durationFeasibility); + return v; + } + + /* }}} */ + } ABC_NAMESPACE_CXX_HEADER_END diff --git a/src/opt/rrr/rrrScheduler.h b/src/opt/rrr/rrrScheduler.h index ced6da047..2db2fc4c4 100644 --- a/src/opt/rrr/rrrScheduler.h +++ b/src/opt/rrr/rrrScheduler.h @@ -46,10 +46,14 @@ namespace rrr { // data int nCreatedJobs; int nFinishedJobs; - time_point start; + time_point timeStart; Par par; std::queue qPendingJobs; Opt *pOpt; // used only in case of single thread execution + std::vector vStatsSummaryKeys; + std::map mStatsSummary; + std::vector vTimesSummaryKeys; + std::map mTimesSummary; #ifdef ABC_USE_PTHREADS bool fTerminate; std::vector vThreads; @@ -57,21 +61,27 @@ namespace rrr { std::mutex mutexAbc; std::mutex mutexPendingJobs; std::mutex mutexFinishedJobs; + std::mutex mutexPrint; std::condition_variable condPendingJobs; std::condition_variable condFinishedJobs; #endif + // print + template + void Print(int nVerboseLevel, std::string prefix, Args... args); + // time seconds GetRemainingTime() const; + double GetElapsedTime() const; // abc void CallAbc(Ntk *pNtk_, std::string Command); // run jobs - void RunJob(Opt &opt, Job const *pJob); + void RunJob(Opt &opt, Job *pJob); // manage jobs - void CreateJob(Ntk *pNtk_, int iSeed_); + Job *CreateJob(Ntk *pNtk_, int iSeed_, double cost); void OnJobEnd(std::function const &func); // thread @@ -79,6 +89,10 @@ namespace rrr { void Thread(Parameter const *pPar); #endif + // summary + template + void AddToSummary(std::vector &keys, std::map &m, summary const &result) const; + public: // constructors Scheduler(Ntk *pNtk, Parameter const *pPar); @@ -96,12 +110,21 @@ namespace rrr { int id; Ntk *pNtk; int iSeed; + double costInitial; + std::string prefix; + double duration; + summary stats; + summary times; // constructor - Job(int id, Ntk *pNtk, int iSeed) : + Job(int id, Ntk *pNtk, int iSeed, double cost) : id(id), pNtk(pNtk), - iSeed(iSeed) { + iSeed(iSeed), + costInitial(cost) { + std::stringstream ss; + PrintNext(ss, "job", id, ":"); + prefix = ss.str() + " "; } }; @@ -115,21 +138,53 @@ namespace rrr { /* }}} */ + /* {{{ Print */ + + template + template + inline void Scheduler::Print(int nVerboseLevel, std::string prefix, Args... args) { + if(nVerbose <= nVerboseLevel) { + return; + } +#ifdef ABC_USE_PTHREADS + if(fMultiThreading) { + { + std::unique_lock l(mutexPrint); + std::cout << prefix; + PrintNext(std::cout, args...); + std::cout << std::endl; + } + return; + } +#endif + std::cout << prefix; + PrintNext(std::cout, args...); + std::cout << std::endl; + } + + /* }}} */ + /* {{{ Time */ template - seconds Scheduler::GetRemainingTime() const { + inline seconds Scheduler::GetRemainingTime() const { if(nTimeout == 0) { return 0; } - time_point current = GetCurrentTime(); - seconds nRemainingTime = nTimeout - DurationInSeconds(start, current); + time_point timeCurrent = GetCurrentTime(); + seconds nRemainingTime = nTimeout - DurationInSeconds(timeStart, timeCurrent); if(nRemainingTime == 0) { // avoid glitch return -1; } return nRemainingTime; } + template + inline double Scheduler::GetElapsedTime() const { + time_point timeCurrent = GetCurrentTime(); + return Duration(timeStart, timeCurrent); + } + /* }}} */ /* {{{ Abc */ @@ -153,8 +208,12 @@ namespace rrr { /* {{{ Run jobs */ template - void Scheduler::RunJob(Opt &opt, Job const *pJob) { - opt.UpdateNetwork(pJob->pNtk); + void Scheduler::RunJob(Opt &opt, Job *pJob) { + time_point timeStartLocal = GetCurrentTime(); + opt.AssignNetwork(pJob->pNtk, !fPartitioning); // reuse backend if restarting + opt.SetPrintLine([&](std::string str) { + Print(-1, pJob->prefix, str); + }); // start flow switch(nFlow) { case 0: @@ -162,23 +221,17 @@ namespace rrr { break; case 1: { // transtoch std::mt19937 rng(pJob->iSeed); - double dCost = CostFunction(pJob->pNtk); - double dBestCost = dCost; + double cost = pJob->costInitial; + double costBest = cost; Ntk best(*(pJob->pNtk)); - if(nVerbose) { - std::cout << "start: cost = " << dCost << std::endl; - } for(int i = 0; i < 10; i++) { if(GetRemainingTime() < 0) { break; } if(i != 0) { CallAbc(pJob->pNtk, "&if -K 6; &mfs; &st"); - dCost = CostFunction(pJob->pNtk); - opt.UpdateNetwork(pJob->pNtk, true); - if(nVerbose) { - std::cout << "hop " << std::setw(3) << i << ": cost = " << dCost << std::endl; - } + cost = CostFunction(pJob->pNtk); + Print(1, pJob->prefix, "hop", i, ":", "cost", "=", cost); } for(int j = 0; true; j++) { if(GetRemainingTime() < 0) { @@ -186,37 +239,28 @@ namespace rrr { } opt.Run(rng(), GetRemainingTime()); CallAbc(pJob->pNtk, "&dc2"); - double dNewCost = CostFunction(pJob->pNtk); - if(nVerbose) { - std::cout << "\tite " << std::setw(3) << j << ": cost = " << dNewCost << std::endl; - } - if(dNewCost < dCost) { - dCost = dNewCost; - opt.UpdateNetwork(pJob->pNtk, true); + double costNew = CostFunction(pJob->pNtk); + Print(1, pJob->prefix, "ite", j, ":", "cost", "=", costNew); + if(costNew < cost) { + cost = costNew; } else { break; } } - if(dCost < dBestCost) { - dBestCost = dCost; + if(cost < costBest) { + costBest = cost; best = *(pJob->pNtk); i = 0; } } *(pJob->pNtk) = best; - if(nVerbose) { - std::cout << "end: cost = " << dBestCost << std::endl; - } break; } case 2: { // deep std::mt19937 rng(pJob->iSeed); int n = 0; - double dCost = CostFunction(pJob->pNtk); + double cost = pJob->costInitial; Ntk best(*(pJob->pNtk)); - if(nVerbose) { - std::cout << "start: cost = " << dCost << std::endl; - } for(int i = 0; i < 1000000; i++) { if(GetRemainingTime() < 0) { break; @@ -246,38 +290,30 @@ namespace rrr { Command += "; &fx; &st"; Command += pComp; CallAbc(pJob->pNtk, Command); - if(nVerbose) { - std::cout << "ite " << std::setw(6) << i << ": cost = " << CostFunction(pJob->pNtk) << std::endl; - } + Print(1, pJob->prefix, "ite", i, ":", "cost", "=", CostFunction(pJob->pNtk)); // rrr for(int j = 0; j < n; j++) { if(GetRemainingTime() < 0) { break; } - opt.UpdateNetwork(pJob->pNtk, true); opt.Run(rng(), GetRemainingTime()); if(rng() & 1) { CallAbc(pJob->pNtk, "&dc2"); } else { CallAbc(pJob->pNtk, std::string("&put; ") + pCompress2rs + "; &get"); } - if(nVerbose) { - std::cout << "\trrr " << std::setw(6) << j << ": cost = " << CostFunction(pJob->pNtk) << std::endl; - } + Print(1, pJob->prefix, "rrr", j, ":", "cost", "=", CostFunction(pJob->pNtk)); } // eval - double dNewCost = CostFunction(pJob->pNtk); - if(dNewCost < dCost) { - dCost = dNewCost; + double costNew = CostFunction(pJob->pNtk); + if(costNew < cost) { + cost = costNew; best = *(pJob->pNtk); } else { n++; } } *(pJob->pNtk) = best; - if(nVerbose) { - std::cout << "end: cost = " << dCost << std::endl; - } break; } case 3: @@ -287,6 +323,11 @@ namespace rrr { default: assert(0); } + time_point timeEndLocal = GetCurrentTime(); + pJob->duration = Duration(timeStartLocal, timeEndLocal); + pJob->stats = opt.GetStatsSummary(); + pJob->times = opt.GetTimesSummary(); + opt.ResetSummary(); } /* }}} */ @@ -294,8 +335,8 @@ namespace rrr { /* {{{ Manage jobs */ template - void Scheduler::CreateJob(Ntk *pNtk_, int iSeed_) { - Job *pJob = new Job(nCreatedJobs++, pNtk_, iSeed_); + typename Scheduler::Job *Scheduler::CreateJob(Ntk *pNtk_, int iSeed_, double cost) { + Job *pJob = new Job(nCreatedJobs++, pNtk_, iSeed_, cost); #ifdef ABC_USE_PTHREADS if(fMultiThreading) { { @@ -303,10 +344,11 @@ namespace rrr { qPendingJobs.push(pJob); condPendingJobs.notify_one(); } - return; + return pJob; } #endif qPendingJobs.push(pJob); + return pJob; } template @@ -324,6 +366,8 @@ namespace rrr { } assert(pJob != NULL); func(pJob); + AddToSummary(vStatsSummaryKeys, mStatsSummary, pJob->stats); + AddToSummary(vTimesSummaryKeys, mTimesSummary, pJob->times); delete pJob; nFinishedJobs++; return; @@ -335,6 +379,8 @@ namespace rrr { qPendingJobs.pop(); RunJob(*pOpt, pJob); func(pJob); + AddToSummary(vStatsSummaryKeys, mStatsSummary, pJob->stats); + AddToSummary(vTimesSummaryKeys, mTimesSummary, pJob->times); delete pJob; nFinishedJobs++; } @@ -374,6 +420,28 @@ namespace rrr { /* }}} */ + /* {{{ Summary */ + + template + template + void Scheduler::AddToSummary(std::vector &keys, std::map &m, summary const &result) const { + std::vector::iterator it = keys.begin(); + for(auto const &entry: result) { + if(m.count(entry.first)) { + m[entry.first] += entry.second; + it = std::find(it, keys.end(), entry.first); + assert(it != keys.end()); + it++; + } else { + m[entry.first] = entry.second; + it = keys.insert(it, entry.first); + it++; + } + } + } + + /* }}} */ + /* {{{ Constructors */ template @@ -439,74 +507,90 @@ namespace rrr { template void Scheduler::Run() { - start = GetCurrentTime(); + timeStart = GetCurrentTime(); + double costStart = CostFunction(pNtk); if(fPartitioning) { fDeterministic = false; // it is deterministic anyways as we wait until all jobs finish each round pNtk->Sweep(); - par.UpdateNetwork(pNtk); + par.AssignNetwork(pNtk); while(nCreatedJobs < nJobs) { assert(nParallelPartitions > 0); if(nCreatedJobs < nFinishedJobs + nParallelPartitions) { Ntk *pSubNtk = par.Extract(iSeed + nCreatedJobs); if(pSubNtk) { - CreateJob(pSubNtk, iSeed + nCreatedJobs); - std::cout << "job " << nCreatedJobs - 1 << " created (size = " << pSubNtk->GetNumInts() << ")" << std::endl; + Job *pJob = CreateJob(pSubNtk, iSeed + nCreatedJobs, CostFunction(pSubNtk)); + Print(1, pJob->prefix, "created ", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", pJob->costInitial); continue; } } if(nCreatedJobs == nFinishedJobs) { - std::cout << "failed to partition" << std::endl; + PrintWarning("failed to partition"); break; } while(nFinishedJobs < nCreatedJobs) { OnJobEnd([&](Job *pJob) { - std::cout << "job " << pJob->id << " finished (size = " << pJob->pNtk->GetNumInts() << ")" << std::endl; + double cost = CostFunction(pJob->pNtk); + Print(1, pJob->prefix, "finished", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost); + Print(0, "", "job", pJob->id, "(", nFinishedJobs + 1, "/", nJobs, ")", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - pJob->costInitial) / pJob->costInitial, "%", ")", ",", "duration", "=", pJob->duration, "s", ",", "elapsed", "=", GetElapsedTime(), "s"); par.Insert(pJob->pNtk); }); } if(fOptOnInsert) { + time_point timeStartLocal = GetCurrentTime(); CallAbc(pNtk, std::string("&put; ") + pCompress2rs + "; dc2; &get"); - par.UpdateNetwork(pNtk); + time_point timeEndLocal = GetCurrentTime(); + par.AssignNetwork(pNtk); + double cost = CostFunction(pNtk); + Print(0, "", "c2rs; dc2", ":", std::string(34, ' '), "node", "=", pNtk->GetNumInts(), ",", "level", "=", pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - costStart) / costStart, "%", ")", ",", "duration", "=", Duration(timeStartLocal, timeEndLocal), "s", ",", "elapsed", "=", GetElapsedTime(), "s"); } } while(nFinishedJobs < nCreatedJobs) { OnJobEnd([&](Job *pJob) { - std::cout << "job " << pJob->id << " finished (size = " << pJob->pNtk->GetNumInts() << ")" << std::endl; + double cost = CostFunction(pJob->pNtk); + Print(1, pJob->prefix, "finished", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", CostFunction(pJob->pNtk)); + Print(0, "", "job", pJob->id, "(", nFinishedJobs + 1, "/", nJobs, ")", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - pJob->costInitial) / pJob->costInitial, "%", ")", ",", "duration", "=", pJob->duration, "s", ",", "elapsed", "=", GetElapsedTime(), "s"); par.Insert(pJob->pNtk); }); } if(fOptOnInsert) { CallAbc(pNtk, std::string("&put; ") + pCompress2rs + "; dc2; &get"); - par.UpdateNetwork(pNtk); + par.AssignNetwork(pNtk); } } else if(nJobs > 1) { - double dCost = CostFunction(pNtk); + double costBest = costStart; for(int i = 0; i < nJobs; i++) { Ntk *pCopy = new Ntk(*pNtk); - CreateJob(pCopy, iSeed + i); + CreateJob(pCopy, iSeed + i, costBest); } for(int i = 0; i < nJobs; i++) { OnJobEnd([&](Job *pJob) { - double dNewCost = CostFunction(pJob->pNtk); - if(nVerbose) { - std::cout << "run " << pJob->id << ": cost = " << dNewCost << std::endl; - } - if(dNewCost < dCost) { - dCost = dNewCost; + double cost = CostFunction(pJob->pNtk); + Print(0, "", "job", pJob->id, "(", nFinishedJobs + 1, "/", nJobs, ")", ":", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - pJob->costInitial) / pJob->costInitial, "%", ")", ",", "duration", "=", pJob->duration, "s", ",", "elapsed", "=", GetElapsedTime(), "s"); + if(cost < costBest) { + costBest = cost; *pNtk = *(pJob->pNtk); } delete pJob->pNtk; }); } } else { - CreateJob(pNtk, iSeed); - OnJobEnd([&](Job *pJob) { (void)pJob; }); + CreateJob(pNtk, iSeed, costStart); + OnJobEnd([&](Job *pJob) { + double cost = CostFunction(pJob->pNtk); + Print(0, "", "job", pJob->id, "(", nFinishedJobs + 1, "/", nJobs, ")", ":", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - pJob->costInitial) / pJob->costInitial, "%", ")", ",", "duration", "=", pJob->duration, "s", ",", "elapsed", "=", GetElapsedTime(), "s"); + }); } - time_point end = GetCurrentTime(); - double elapsed_seconds = Duration(start, end); - if(nVerbose) { - std::cout << "elapsed: " << std::fixed << std::setprecision(3) << elapsed_seconds << "s" << std::endl; + double cost = CostFunction(pNtk); + double duration = GetElapsedTime(); + Print(0, "\n", "stats summary", ":"); + for(std::string key: vStatsSummaryKeys) { + Print(0, "\t", SW{30, true}, key, ":", SW{10}, mStatsSummary[key]); } + Print(0, "", "runtime summary", ":"); + for(std::string key: vTimesSummaryKeys) { + Print(0, "\t", SW{30, true}, key, ":", mTimesSummary[key], "s", "(", 100 * mTimesSummary[key] / duration, "%", ")"); + } + Print(0, "", "end", ":", "cost", "=", cost, "(", 100 * (cost - costStart) / costStart, "%", ")", ",", "time", "=", duration, "s"); } /* }}} */ diff --git a/src/opt/rrr/rrrSimulator.h b/src/opt/rrr/rrrSimulator.h index b1d7296e7..6bc3bb19d 100644 --- a/src/opt/rrr/rrrSimulator.h +++ b/src/opt/rrr/rrrSimulator.h @@ -29,6 +29,8 @@ namespace rrr { int nWords; // data + bool fGenerated; + bool fInitialized; int target; // node for which the careset has been computed std::vector vValues; std::vector vValues2; // simulation with an inverter @@ -46,9 +48,14 @@ namespace rrr { // backups std::vector vBackups; - // statistics - int nAdds; - int nResets; + // stats + int nCex; + int nDiscarded; + int nPackedCountOld; + std::vector vPackedCount; + std::vector vPackedCountEvicted; + double durationSimulation; + double durationCare; // vector computations void Clear(int n, itr x) const; @@ -77,6 +84,9 @@ namespace rrr { // careset computation void ComputeCare(int id); + // preparation + void Initialize(); + // save & load void Save(int slot); void Load(int slot); @@ -85,8 +95,7 @@ namespace rrr { // constructors Simulator(); Simulator(Parameter const *pPar); - ~Simulator(); - void UpdateNetwork(Ntk *pNtk_, bool fSame); + void AssignNetwork(Ntk *pNtk_, bool fReuse); // checks bool CheckRedundancy(int id, int idx); @@ -94,6 +103,11 @@ namespace rrr { // cex void AddCex(std::vector const &vCex); + + // summary + void ResetSummary(); + summary GetStatsSummary() const; + summary GetTimesSummary() const; }; @@ -195,53 +209,71 @@ namespace rrr { template void Simulator::ActionCallback(Action const &action) { - if(target == -1) { - return; - } switch(action.type) { case REMOVE_FANIN: - if(action.id == target) { - fUpdate = true; - } else { - sUpdates.insert(action.id); + assert(fInitialized); + if(target != -1) { + if(action.id == target) { + fUpdate = true; + } else { + sUpdates.insert(action.id); + } } break; case REMOVE_UNUSED: break; case REMOVE_BUFFER: case REMOVE_CONST: - if(action.id == target) { - if(fUpdate) { - for(int fo: action.vFanouts) { - sUpdates.insert(fo); - } - fUpdate = false; - } - target = -1; - } else { - if(sUpdates.count(action.id)) { - sUpdates.erase(action.id); - for(int fo: action.vFanouts) { - sUpdates.insert(fo); + if(fInitialized) { + if(target != -1) { + if(action.id == target) { + if(fUpdate) { + for(int fo: action.vFanouts) { + sUpdates.insert(fo); + } + fUpdate = false; + } + target = -1; + } else { + if(sUpdates.count(action.id)) { + sUpdates.erase(action.id); + for(int fo: action.vFanouts) { + sUpdates.insert(fo); + } + } } } } break; case ADD_FANIN: - if(action.id == target) { - fUpdate = true; - } else { - sUpdates.insert(action.id); + assert(fInitialized); + if(target != -1) { + if(action.id == target) { + fUpdate = true; + } else { + sUpdates.insert(action.id); + } } break; case TRIVIAL_COLLAPSE: break; case TRIVIAL_DECOMPOSE: - vValues.resize(nWords * pNtk->GetNumNodes()); - SimulateNode(vValues, action.fi); + if(fInitialized) { + if(target != -1) { + vValues.resize(nWords * pNtk->GetNumNodes()); + SimulateNode(vValues, action.fi); + // time of this simulation is not measured for simplicity sake + } + } break; case SORT_FANINS: break; + case READ: + fInitialized = false; + if(action.fNew) { + fGenerated = false; + } + break; case SAVE: Save(action.idx); break; @@ -345,6 +377,7 @@ namespace rrr { template void Simulator::Simulate() { + time_point timeStart = GetCurrentTime(); if(nVerbose) { std::cout << "simulating" << std::endl; } @@ -356,10 +389,12 @@ namespace rrr { std::cout << std::endl; } }); + durationSimulation += Duration(timeStart, GetCurrentTime()); } template void Simulator::Resimulate() { + time_point timeStart = GetCurrentTime(); if(nVerbose) { std::cout << "resimulating" << std::endl; } @@ -382,10 +417,12 @@ namespace rrr { } }); */ + durationSimulation += Duration(timeStart, GetCurrentTime()); } template void Simulator::SimulateOneWord(int offset) { + time_point timeStart = GetCurrentTime(); if(nVerbose) { std::cout << "simulating word " << offset << std::endl; } @@ -397,6 +434,7 @@ namespace rrr { std::cout << std::endl; } }); + durationSimulation += Duration(timeStart, GetCurrentTime()); } /* }}} */ @@ -440,6 +478,7 @@ namespace rrr { sUpdates.clear(); } target = id; + time_point timeStart = GetCurrentTime(); if(nVerbose) { std::cout << "computing careset of " << target << std::endl; } @@ -450,6 +489,7 @@ namespace rrr { Print(nWords, care.begin()); std::cout << std::endl; } + durationCare += Duration(timeStart, GetCurrentTime()); return; } vValues2 = vValues; @@ -484,10 +524,40 @@ namespace rrr { Print(nWords, care.begin()); std::cout << std::endl; } + durationCare += Duration(timeStart, GetCurrentTime()); } /* }}} */ + /* {{{ Preparation */ + + template + void Simulator::Initialize() { + if(!fGenerated) { + // TODO: reset nWords to default here maybe, if such a mechanism that changes nWords has been implemneted + vValues.resize(nWords * pNtk->GetNumNodes()); + iPivot = 0; + vAssignedStimuli.clear(); + vAssignedStimuli.resize(nWords * pNtk->GetNumPis()); + for(int count: vPackedCount) { + if(count) { + vPackedCountEvicted.push_back(count); + } + } + vPackedCount.clear(); + vPackedCount.resize(nWords * 64); + GenerateRandomStimuli(); + fGenerated = true; + } else { + // use same nWords as we are reusing patterns even if nWords has changed + vValues.resize(nWords * pNtk->GetNumNodes()); + } + Simulate(); + fInitialized = true; + } + + /* }}} */ + /* {{{ Save & load */ template @@ -517,6 +587,12 @@ namespace rrr { vBackups[slot].iPivot = iPivot; vBackups[slot].vAssignedStimuli = vAssignedStimuli; target = vBackups[slot].target; // assigned to -1 when careset needs updating + if(!fKeepStimula) { + vBackups[slot].nCex = nCex; + vBackups[slot].nPackedCountOld = nPackedCountOld; + vBackups[slot].vPackedCount = vPackedCount; + vBackups[slot].vPackedCountEvicted = vPackedCountEvicted; + } } template @@ -532,6 +608,11 @@ namespace rrr { care = vBackups[slot].care; iPivot = vBackups[slot].iPivot; vAssignedStimuli = vBackups[slot].vAssignedStimuli; + nDiscarded += nCex - vBackups[slot].nCex; + nCex = vBackups[slot].nCex; + nPackedCountOld = vBackups[slot].nPackedCountOld; + vPackedCount = vBackups[slot].vPackedCount; + vPackedCountEvicted = vBackups[slot].vPackedCountEvicted; tmp.resize(nWords); } else { std::vector vOffsets; @@ -567,7 +648,7 @@ namespace rrr { } } } else { - // when nWords has changed + // TODO: when nWords has changed assert(0); } } @@ -582,11 +663,12 @@ namespace rrr { pNtk(NULL), nVerbose(0), nWords(0), + fGenerated(false), + fInitialized(false), target(-1), iPivot(0), - fUpdate(false), - nAdds(0), - nResets(0) { + fUpdate(false) { + ResetSummary(); } template @@ -594,38 +676,27 @@ namespace rrr { pNtk(NULL), nVerbose(pPar->nSimulatorVerbose), nWords(pPar->nWords), + fGenerated(false), + fInitialized(false), target(-1), iPivot(0), - fUpdate(false), - nAdds(0), - nResets(0) { + fUpdate(false) { care.resize(nWords); tmp.resize(nWords); + ResetSummary(); } template - Simulator::~Simulator() { - if(pNtk) { - std::cout << "simulator stats: added CEXs = " << nAdds << ", resets = " << nResets << std::endl; + void Simulator::AssignNetwork(Ntk *pNtk_, bool fReuse) { + if(!fReuse) { + fGenerated = false; } - } - - template - void Simulator::UpdateNetwork(Ntk *pNtk_, bool fSame) { - pNtk = pNtk_; - pNtk->AddCallback(std::bind(&Simulator::ActionCallback, this, std::placeholders::_1)); - // TODO: what if nWords has changed? shall we reset it to default? - vValues.resize(nWords * pNtk->GetNumNodes()); + fInitialized = false; target = -1; fUpdate = false; sUpdates.clear(); - if(!fSame) { // reset stimuli if network function changed - iPivot = 0; - vAssignedStimuli.clear(); - vAssignedStimuli.resize(nWords * pNtk->GetNumPis()); - GenerateRandomStimuli(); - } - Simulate(); + pNtk = pNtk_; + pNtk->AddCallback(std::bind(&Simulator::ActionCallback, this, std::placeholders::_1)); } /* }}} */ @@ -634,6 +705,9 @@ namespace rrr { template bool Simulator::CheckRedundancy(int id, int idx) { + if(!fInitialized) { + Initialize(); + } ComputeCare(id); switch(pNtk->GetNodeType(id)) { case AND: { @@ -671,6 +745,9 @@ namespace rrr { template bool Simulator::CheckFeasibility(int id, int fi, bool c) { + if(!fInitialized) { + Initialize(); + } ComputeCare(id); switch(pNtk->GetNodeType(id)) { case AND: { @@ -768,6 +845,7 @@ namespace rrr { if(nVerbose) { std::cout << "fusing into stimulus word " << iWord << " bit " << iBit << std::endl; } + vPackedCount[iWord * 64 + iBit]++; } else { // no bits are compatible, so reset at pivot iWord = iPivot / 64; @@ -775,6 +853,11 @@ namespace rrr { if(nVerbose) { std::cout << "resetting stimulus word " << iWord << " bit " << iBit << std::endl; } + if(vPackedCount[iWord * 64 + iBit]) { + // this can be zero only when stats has been reset + vPackedCountEvicted.push_back(vPackedCount[iWord * 64 + iBit]); + } + vPackedCount[iWord * 64 + iBit] = 1; word mask = 1ull << iBit; for(int idx = 0; idx < pNtk->GetNumPis(); idx++) { vAssignedStimuli[idx * nWords + iWord] &= ~mask; @@ -783,7 +866,6 @@ namespace rrr { if(iPivot == 64 * nWords) { iPivot = 0; } - nResets++; } // update stimulus for(int idx: vCarePiIdxs) { @@ -808,6 +890,7 @@ namespace rrr { // simulate SimulateOneWord(iWord); // recompute care with new stimulus + time_point timeStart = GetCurrentTime(); if(target != -1 && !pNtk->IsPoDriver(target)) { if(nVerbose) { std::cout << "recomputing careset of " << target << std::endl; @@ -838,10 +921,56 @@ namespace rrr { std::cout << std::endl; } } - nAdds++; + durationCare += Duration(timeStart, GetCurrentTime()); + nCex++; } /* }}} */ + + /* {{{ Summary */ + + template + void Simulator::ResetSummary() { + nCex = 0; + nDiscarded = 0; + nPackedCountOld = 0; + for(int count: vPackedCount) { + if(count) { + nPackedCountOld++; + } + } + vPackedCountEvicted.clear(); + durationSimulation = 0; + durationCare = 0; + }; + + template + summary Simulator::GetStatsSummary() const { + summary v; + v.emplace_back("sim cex", nCex); + if(!fKeepStimula) { + v.emplace_back("sim discarded cex", nDiscarded); + } + int nPackedCount = vPackedCountEvicted.size() - nPackedCountOld; + for(int count: vPackedCount) { + if(count) { + nPackedCount++; + } + } + v.emplace_back("sim packed pattern", nPackedCount); + v.emplace_back("sim evicted pattern", vPackedCountEvicted.size()); + return v; + }; + + template + summary Simulator::GetTimesSummary() const { + summary v; + v.emplace_back("sim simulation", durationSimulation); + v.emplace_back("sim care computation", durationCare); + return v; + }; + + /* }}} */ } diff --git a/src/opt/rrr/rrrTypes.h b/src/opt/rrr/rrrTypes.h index 858b65a5f..66f50a6d5 100644 --- a/src/opt/rrr/rrrTypes.h +++ b/src/opt/rrr/rrrTypes.h @@ -39,6 +39,7 @@ namespace rrr { TRIVIAL_COLLAPSE, TRIVIAL_DECOMPOSE, SORT_FANINS, + READ, SAVE, LOAD, POP_BACK, @@ -51,6 +52,7 @@ namespace rrr { int idx = -1; int fi = -1; bool c = false; + bool fNew = false; std::vector vFanins; std::vector vIndices; std::vector vFanouts; @@ -60,6 +62,9 @@ namespace rrr { using clock_type = std::chrono::steady_clock; using time_point = std::chrono::time_point; + template + using summary = std::vector>; + } ABC_NAMESPACE_CXX_HEADER_END diff --git a/src/opt/rrr/rrrUtils.h b/src/opt/rrr/rrrUtils.h index b05a47625..85709f4ce 100644 --- a/src/opt/rrr/rrrUtils.h +++ b/src/opt/rrr/rrrUtils.h @@ -97,7 +97,8 @@ namespace rrr { /* {{{ Print next */ struct SW { - int width; + int width = 0; + bool left = false; }; struct NS {}; // no space @@ -107,6 +108,16 @@ namespace rrr { template void PrintNext(std::ostream &os, T t, Args... args); + static inline void PrintNext(std::ostream &os, int t) { + os << std::setw(4) << t; + } + + template + static inline void PrintNext(std::ostream &os, int t, Args... args) { + os << std::setw(4) << t << " "; + PrintNext(os, args...); + } + static inline void PrintNext(std::ostream &os, bool arg) { os << arg; } @@ -121,16 +132,6 @@ namespace rrr { PrintNext(os, args...); } - static inline void PrintNext(std::ostream &os, int t) { - os << std::setw(4) << t; - } - - template - static inline void PrintNext(std::ostream &os, int t, Args... args) { - os << std::setw(4) << t << " "; - PrintNext(os, args...); - } - static inline void PrintNext(std::ostream &os, double t) { os << std::fixed << std::setprecision(2) << std::setw(8) << t; } @@ -143,12 +144,24 @@ namespace rrr { template static inline void PrintNext(std::ostream &os, SW sw, T arg) { + if(sw.left) { + os << std::left; + } os << std::setw(sw.width) << arg; + if(sw.left) { + os << std::right; + } } template static inline void PrintNext(std::ostream &os, SW sw, T arg, Args... args) { + if(sw.left) { + os << std::left; + } os << std::setw(sw.width) << arg << " "; + if(sw.left) { + os << std::right; + } PrintNext(os, args...); } @@ -161,24 +174,20 @@ namespace rrr { template static inline void PrintNext(std::ostream& os, std::vector const &arg) { - std::string delim; - os << "["; + os << "[ "; for(T const &e: arg) { - os << delim; PrintNext(os, e); - delim = ", "; + os << " "; } os << "]"; } template static inline void PrintNext(std::ostream& os, std::vector const &arg, Args... args) { - std::string delim; - os << "["; + os << "[ "; for(T const &e: arg) { - os << delim; PrintNext(os, e); - delim = ", "; + os << " "; } os << "] "; PrintNext(os, args...); @@ -186,24 +195,20 @@ namespace rrr { template static inline void PrintNext(std::ostream& os, std::set const &arg) { - std::string delim; - os << "{"; + os << "{ "; for(T const &e: arg) { - os << delim; PrintNext(os, e); - delim = ", "; + os << " "; } os << "}"; } template static inline void PrintNext(std::ostream& os, std::set const &arg, Args... args) { - std::string delim; - os << "{"; + os << "{ "; for(T const &e: arg) { - os << delim; PrintNext(os, e); - delim = ", "; + os << " "; } os << "} "; PrintNext(os, args...); @@ -222,6 +227,14 @@ namespace rrr { /* }}} */ + /* {{{ Print others */ + + static inline void PrintWarning(std::string message) { + std::cerr << "[w] " << message << std::endl; + } + + /* }}} */ + /* {{{ Combination */ bool ForEachCombinationStopRec(std::vector &v, int n, int k, std::function const &)> const &func) { @@ -306,6 +319,8 @@ namespace rrr { return "trivial decompose"; case SORT_FANINS: return "sort fanins"; + case READ: + return "read"; case SAVE: return "save"; case LOAD: @@ -323,32 +338,35 @@ namespace rrr { static inline std::stringstream GetActionDescription(Action const &action) { std::stringstream ss; ss << GetActionTypeCstr(action); - std::string delim = ": "; + std::string delim = " : "; if(action.id != -1) { ss << delim; PrintNext(ss, "node", action.id); - delim = ", "; + delim = " , "; } if(action.fi != -1) { ss << delim; PrintNext(ss, "fanin", (bool)action.c, action.fi); - delim = ", "; + delim = " , "; } if(action.idx != -1) { ss << delim; PrintNext(ss, "index", action.idx); } + if(action.fNew) { + ss << " new"; + } ss << std::endl; if(!action.vFanins.empty()) { - ss << "fanins: "; + ss << "fanins : "; PrintNext(ss, action.vFanins); } if(!action.vIndices.empty()) { - ss << "indices: "; + ss << "indices : "; PrintNext(ss, action.vIndices); } if(!action.vFanouts.empty()) { - ss << "fanouts: "; + ss << "fanouts : "; PrintNext(ss, action.vFanouts); } return ss; From b1734ac297ac18e58f3c074f318a53b97e43d339 Mon Sep 17 00:00:00 2001 From: jiunhaochen Date: Sat, 19 Apr 2025 00:43:48 +0800 Subject: [PATCH 18/72] rewire clean up --- src/opt/rar/rewire_miaig.cpp | 171 ++++++++++++++++++++--------------- src/opt/rar/rewire_miaig.h | 59 ++++++++---- 2 files changed, 140 insertions(+), 90 deletions(-) diff --git a/src/opt/rar/rewire_miaig.cpp b/src/opt/rar/rewire_miaig.cpp index f9490e1c2..334264b5f 100644 --- a/src/opt/rar/rewire_miaig.cpp +++ b/src/opt/rar/rewire_miaig.cpp @@ -173,7 +173,7 @@ int Miaig::fromMiniAig(Mini_Aig_t *pMiniAig) { Gia_Man_t *Miaig::toGia(void) { int i, k, iLit, And2 = countAnd2(); Gia_Man_t *pGia = Gia_ManStart(1 + nIns() + And2 + nOuts()), *pTemp; - pGia->pName = Abc_UtilStrsav( _data->pName ); + pGia->pName = Abc_UtilStrsav(_data->pName); Gia_ManHashAlloc(pGia); memset(_data->pCopy, 0, sizeof(int) * nObjs()); Miaig_ForEachInput(i) @@ -310,7 +310,7 @@ void Miaig::topoCollect_rec(int iObj) { objTravId(iObj) = nTravIds(); Vi_PushOrder(_data->vOrder, iObj); Miaig_ForEachObjFanin(iObj, iLit, i) - topoCollect_rec(Abc_Lit2Var(iLit)); + topoCollect_rec(Rw_Lit2Var(iLit)); } vi *Miaig::topoCollect(void) { @@ -320,7 +320,7 @@ vi *Miaig::topoCollect(void) { Miaig_ForEachConstInput(i) objTravId(i) = nTravIds(); Miaig_ForEachOutput(i) - topoCollect_rec(Abc_Lit2Var(objFanin0(i))); + topoCollect_rec(Rw_Lit2Var(objFanin0(i))); return _data->vOrder; } @@ -331,7 +331,7 @@ int Miaig::initializeLevels_rec(int iObj) { return objLevel(iObj); int level = -1; Miaig_ForEachObjFanin(iObj, iLit, i) { - level = Abc_MaxInt(initializeLevels_rec(Abc_Lit2Var(iLit)), level); + level = Abc_MaxInt(initializeLevels_rec(Rw_Lit2Var(iLit)), level); } return objLevel(iObj) = level + 1; } @@ -348,7 +348,7 @@ void Miaig::initializeLevels(void) { objLevel(i) = 0; } Miaig_ForEachOutput(i) { - objLevel(i) = initializeLevels_rec(Abc_Lit2Var(objFanin0(i))); + objLevel(i) = initializeLevels_rec(Rw_Lit2Var(objFanin0(i))); } } @@ -366,7 +366,7 @@ void Miaig::markDistanceN_rec(int iObj, int n, int limit) { if (n == limit) return; Miaig_ForEachObjFanin(iObj, iLit, i) - markDistanceN_rec(Abc_Lit2Var(iLit), n + 1, limit); + markDistanceN_rec(Rw_Lit2Var(iLit), n + 1, limit); } void Miaig::markDistanceN(int iObj, int n) { @@ -378,8 +378,8 @@ void Miaig::markDistanceN(int iObj, int n) { if (objDist(j) >= 0) continue; int minDist = nObjs(); Miaig_ForEachObjFanin(j, iLit, k) { - if (objDist(Abc_Lit2Var(iLit)) == -1) continue; - minDist = Abc_MinInt(minDist, objDist(Abc_Lit2Var(iLit))); + if (objDist(Rw_Lit2Var(iLit)) == -1) continue; + minDist = Rw_MinInt(minDist, objDist(Rw_Lit2Var(iLit))); } if (minDist != nObjs()) { markDistanceN_rec(j, minDist + 1, n); @@ -388,26 +388,50 @@ void Miaig::markDistanceN(int iObj, int n) { } } +void Miaig::markCritical(void) { + int iObj; + int maxRequire = countLevel(0); + nTravIds()++; + Miaig_ForEachOutput(iObj) { + if (objLevel(iObj) != maxRequire) continue; + markCritical_rec(iObj); + } +} + +void Miaig::markCritical_rec(int iObj) { + objTravId(iObj) = nTravIds(); + if (objIsPi(iObj)) return; + int iLit, k; + int maxFaninLevel = objLevel(Rw_Lit2Var(objFanin0(iObj))); + Miaig_ForEachObjFaninStart(iObj, iLit, k, 1) { + maxFaninLevel = Rw_MaxInt(maxFaninLevel, objLevel(Rw_Lit2Var(iLit))); + } + Miaig_ForEachObjFanin(iObj, iLit, k) { + if (objLevel(Rw_Lit2Var(iLit)) != maxFaninLevel) continue; + markCritical_rec(Rw_Lit2Var(iLit)); + } +} + // reference counting void Miaig::refObj(int iObj) { int k, iLit; Miaig_ForEachObjFanin(iObj, iLit, k) - objRef(Abc_Lit2Var(iLit))++; + objRef(Rw_Lit2Var(iLit))++; } void Miaig::derefObj(int iObj) { int k, iLit; Miaig_ForEachObjFanin(iObj, iLit, k) - objRef(Abc_Lit2Var(iLit))--; + objRef(Rw_Lit2Var(iLit))--; } void Miaig::derefObj_rec(int iObj, int iLitSkip) { int k, iLit; Miaig_ForEachObjFanin(iObj, iLit, k) { - if (iLit != iLitSkip && --objRef(Abc_Lit2Var(iLit)) == 0 && objIsNode(Abc_Lit2Var(iLit))) { - derefObj_rec(Abc_Lit2Var(iLit), -1); - Vi_Fill(_data->pvFans + Abc_Lit2Var(iLit), 1, 0); - refObj(Abc_Lit2Var(iLit)); + if (iLit != iLitSkip && --objRef(Rw_Lit2Var(iLit)) == 0 && objIsNode(Rw_Lit2Var(iLit))) { + derefObj_rec(Rw_Lit2Var(iLit), -1); + Vi_Fill(objFanins(Rw_Lit2Var(iLit)), 1, 0); + refObj(Rw_Lit2Var(iLit)); } } } @@ -423,7 +447,7 @@ void Miaig::verifyRefs(void) { int i; Miaig_ForEachNodeOutput(i) derefObj(i); - for (i = 0; i < _data->nObjs; i++) + for (i = 0; i < nObjs(); i++) if (objRef(i)) printf("Ref count of node %d is incorrect (%d).\n", i, objRef(i)); initializeRefs(); @@ -436,7 +460,7 @@ void Miaig::markDfs_rec(int iObj) { return; objTravId(iObj) = nTravIds(); Miaig_ForEachObjFanin(iObj, iLit, i) - markDfs_rec(Abc_Lit2Var(iLit)); + markDfs_rec(Rw_Lit2Var(iLit)); } int Miaig::markDfs(void) { @@ -445,7 +469,7 @@ int Miaig::markDfs(void) { Miaig_ForEachConstInput(i) objTravId(i) = nTravIds(); Miaig_ForEachOutput(i) - markDfs_rec(Abc_Lit2Var(objFanin0(i))); + markDfs_rec(Rw_Lit2Var(objFanin0(i))); Miaig_ForEachOutput(i) objTravId(i) = nTravIds(); Miaig_ForEachNode(i) @@ -485,7 +509,7 @@ void Miaig::dupDfs_rec(Miaig &pNew, int iObj) { return; // 2. create fanins for a given node Miaig_ForEachObjFanin(iObj, iLit, i) - dupDfs_rec(pNew, Abc_Lit2Var(iLit)); + dupDfs_rec(pNew, Rw_Lit2Var(iLit)); assert(objCopy(iObj) < 0); // combinational loop catching assert(objFaninNum(iObj) > 0); // 3. create current node @@ -505,7 +529,7 @@ Miaig Miaig::dupDfs(void) { objCopy(i) = i; // 2. for each primary output we call recursive function for it's fanin Miaig_ForEachOutput(i) - dupDfs_rec(pNew, Abc_Lit2Var(objFanin0(i))); + dupDfs_rec(pNew, Rw_Lit2Var(objFanin0(i))); // 3. for each primary output append it's fanin Miaig_ForEachOutput(i) pNew.appendFanin(pNew.appendObj(), Rw_Lit2LitV(_data->pCopy, objFanin0(i))); @@ -544,10 +568,10 @@ void Miaig::reduceFanins(vi *v) { int Miaig::hashTwo(int l0, int l1, int TableSize) { unsigned Key = 0; - Key += Abc_Lit2Var(l0) * 7937; - Key += Abc_Lit2Var(l1) * 2971; - Key += Abc_LitIsCompl(l0) * 911; - Key += Abc_LitIsCompl(l1) * 353; + Key += Rw_Lit2Var(l0) * 7937; + Key += Rw_Lit2Var(l1) * 2971; + Key += Rw_LitIsCompl(l0) * 911; + Key += Rw_LitIsCompl(l1) * 353; return Key % TableSize; } @@ -573,14 +597,14 @@ int Miaig::buildNode(int l0, int l1, int fCprop, int fStrash) { } int *pPlace = NULL; if (fStrash) { - pPlace = hashLookup(_data->pTable, Abc_MinInt(l0, l1), Abc_MaxInt(l0, l1), _data->TableSize); + pPlace = hashLookup(_data->pTable, Rw_MinInt(l0, l1), Rw_MaxInt(l0, l1), _data->TableSize); if (*pPlace) return *pPlace; } int iObj = appendObj(); - appendFanin(iObj, Abc_MinInt(l0, l1)); - appendFanin(iObj, Abc_MaxInt(l0, l1)); - return pPlace ? (*pPlace = Abc_Var2Lit(iObj, 0)) : Abc_Var2Lit(iObj, 0); + appendFanin(iObj, Rw_MinInt(l0, l1)); + appendFanin(iObj, Rw_MaxInt(l0, l1)); + return pPlace ? (*pPlace = Rw_Var2Lit(iObj, 0)) : Rw_Var2Lit(iObj, 0); } int Miaig::buildNodeBalance_rec(Miaig &pNew, vi *vFanins, int begin, int end, int fCprop, int fStrash) { @@ -621,13 +645,13 @@ Miaig Miaig::dupStrash(int fCprop, int fStrash, int fCascade) { pNew._data->pTable = (int *)calloc(sizeof(int), 3 * pNew._data->TableSize); } Miaig_ForEachInput(i) - objCopy(i) = Abc_Var2Lit(i, 0); + objCopy(i) = Rw_Var2Lit(i, 0); Miaig_ForEachNode(i) { assert(objFaninNum(i) > 0); if (fCascade) - objCopy(i) = buildNodeCascade(pNew, _data->pvFans + i, fCprop, fStrash); + objCopy(i) = buildNodeCascade(pNew, objFanins(i), fCprop, fStrash); else - objCopy(i) = buildNodeBalance(pNew, _data->pvFans + i, fCprop, fStrash); + objCopy(i) = buildNodeBalance(pNew, objFanins(i), fCprop, fStrash); } Miaig_ForEachOutput(i) pNew.appendFanin(pNew.appendObj(), Rw_Lit2LitL(_data->pCopy, objFanin0(i))); @@ -643,21 +667,21 @@ int *Miaig::createStops(void) { assert(objFaninNum(i) == 2); int iLit0 = objFanin0(i); int iLit1 = objFanin1(i); - pStop[Abc_Lit2Var(iLit0)] += 1 + Abc_LitIsCompl(iLit0); - pStop[Abc_Lit2Var(iLit1)] += 1 + Abc_LitIsCompl(iLit1); + pStop[Rw_Lit2Var(iLit0)] += 1 + Rw_LitIsCompl(iLit0); + pStop[Rw_Lit2Var(iLit1)] += 1 + Rw_LitIsCompl(iLit1); } Miaig_ForEachOutput(i) - pStop[Abc_Lit2Var(objFanin0(i))] += 2; + pStop[Rw_Lit2Var(objFanin0(i))] += 2; return pStop; } void Miaig::collectSuper_rec(int iLit, int *pStop, vi *vSuper) { - if (pStop[Abc_Lit2Var(iLit)] > 1) + if (pStop[Rw_Lit2Var(iLit)] > 1) Vi_Push(vSuper, Rw_Lit2LitL(_data->pCopy, iLit)); else { - assert(Abc_LitIsCompl(iLit) == 0); - collectSuper_rec(objFanin0(Abc_Lit2Var(iLit)), pStop, vSuper); - collectSuper_rec(objFanin1(Abc_Lit2Var(iLit)), pStop, vSuper); + assert(Rw_LitIsCompl(iLit) == 0); + collectSuper_rec(objFanin0(Rw_Lit2Var(iLit)), pStop, vSuper); + collectSuper_rec(objFanin1(Rw_Lit2Var(iLit)), pStop, vSuper); } } @@ -669,7 +693,7 @@ Miaig Miaig::dupMulti(int nFaninMax_, int nGrowth) { assert(nFaninMax_ >= 2 && nGrowth >= 1); memset(_data->pCopy, 0, sizeof(int) * nObjs()); // obj2lit Miaig_ForEachConstInput(i) - objCopy(i) = Abc_Var2Lit(i, 0); + objCopy(i) = Rw_Var2Lit(i, 0); Miaig_ForEachNode(i) { if (pStop[i] == 1) continue; @@ -693,7 +717,7 @@ Miaig Miaig::dupMulti(int nFaninMax_, int nGrowth) { // create a cascade of nodes while (Vi_Size(vArray) > nFaninMaxLocal) { int iObj = pNew.appendObj(); - vi *vFanins = pNew._data->pvFans + iObj; + vi *vFanins = pNew.objFanins(iObj); assert(vFanins->ptr == NULL); vFanins->cap = nFaninMaxLocal + nGrowthLocal; vFanins->ptr = (int *)malloc(sizeof(int) * vFanins->cap); @@ -702,18 +726,18 @@ Miaig Miaig::dupMulti(int nFaninMax_, int nGrowth) { assert(Vi_Space(vFanins) == nGrowthLocal); for (k = 0; k < nFaninMaxLocal; k++) Vi_Drop(vArray, 0); - Vi_Push(vArray, Abc_Var2Lit(iObj, 0)); + Vi_Push(vArray, Rw_Var2Lit(iObj, 0)); } // create the last node int iObj = pNew.appendObj(); - vi *vFanins = pNew._data->pvFans + iObj; + vi *vFanins = pNew.objFanins(iObj); assert(vFanins->ptr == NULL); vFanins->cap = Vi_Size(vArray) + nGrowthLocal; vFanins->ptr = (int *)malloc(sizeof(int) * vFanins->cap); Vi_ForEachEntry(vArray, iLit, k) pNew.appendFanin(iObj, iLit); assert(Vi_Space(vFanins) == nGrowthLocal); - objCopy(i) = Abc_Var2Lit(iObj, 0); + objCopy(i) = Rw_Var2Lit(iObj, 0); } } Miaig_ForEachOutput(i) @@ -727,8 +751,8 @@ Miaig Miaig::dupMulti(int nFaninMax_, int nGrowth) { void Miaig::truthSimNode(int i) { int k, iLit; Miaig_ForEachObjFanin(i, iLit, k) { - if (k == 0) Tt_DupC(objTruth(i, objType(i)), objTruth(Abc_Lit2Var(iLit), objType(Abc_Lit2Var(iLit))), Abc_LitIsCompl(iLit), nWords()); - else Tt_Sharp(objTruth(i, objType(i)), objTruth(Abc_Lit2Var(iLit), objType(Abc_Lit2Var(iLit))), Abc_LitIsCompl(iLit), nWords()); + if (k == 0) Tt_DupC(objTruth(i, objType(i)), objTruth(Rw_Lit2Var(iLit), objType(Rw_Lit2Var(iLit))), Rw_LitIsCompl(iLit), nWords()); + else Tt_Sharp(objTruth(i, objType(i)), objTruth(Rw_Lit2Var(iLit), objType(Rw_Lit2Var(iLit))), Rw_LitIsCompl(iLit), nWords()); } } @@ -739,9 +763,9 @@ word *Miaig::truthSimNodeSubset(int i, int m) { Miaig_ForEachObjFanin(i, iLit, k) { if ((m >> k) & 1) { // fanin is included in the subset if (Counter++ == 0) - Tt_DupC(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords()); + Tt_DupC(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords()); else - Tt_Sharp(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords()); + Tt_Sharp(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords()); } } assert(Counter == Tt_BitCount16(m)); @@ -751,8 +775,8 @@ word *Miaig::truthSimNodeSubset(int i, int m) { word *Miaig::truthSimNodeSubset2(int i, vi *vFanins, int nFanins) { int k, iLit; Vi_ForEachEntryStop(vFanins, iLit, k, nFanins) { - if (k == 0) Tt_DupC(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords()); - else Tt_Sharp(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords()); + if (k == 0) Tt_DupC(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords()); + else Tt_Sharp(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords()); } return _data->pProd; } @@ -808,7 +832,7 @@ int Miaig::computeTfo_rec(int iObj) { if (objTravId(iObj) == nTravIds() - 1) return 0; Miaig_ForEachObjFanin(iObj, iLit, k) { - Value |= computeTfo_rec(Abc_Lit2Var(iLit)); + Value |= computeTfo_rec(Rw_Lit2Var(iLit)); } objTravId(iObj) = nTravIds() - 1 + Value; if (Value) Vi_Push(_data->vTfo, iObj); @@ -867,7 +891,6 @@ void Miaig::addPair(vi *vPair, int iFan1, int iFan2) { pArray = Vi_Array(vPair); } pArray[i + 2]++; - //printf( "Adding pair (%d, %d)\n", iFan1, iFan2 ); } // find fanin pair that appears most often @@ -905,11 +928,11 @@ void Miaig::extractBest(vi *vPairs) { int iBest = findPair(vPairs); assert(iBest >= 0); //printf( "Creating node %d with fanins (%d, %d).\n", iObj, pArray[iBest], pArray[iBest+1] ); - assert(Vi_Size(_data->pvFans + iObj) == 0); + assert(Vi_Size(objFanins(iObj)) == 0); appendFanin(iObj, pArray[iBest]); appendFanin(iObj, pArray[iBest + 1]); Miaig_ForEachNode(i) - Counter += updateFanins(_data->pvFans + i, pArray[iBest], pArray[iBest + 1], Abc_Var2Lit(iObj, 0)); + Counter += updateFanins(objFanins(i), pArray[iBest], pArray[iBest + 1], Rw_Var2Lit(iObj, 0)); assert(Counter == pArray[iBest + 2]); } @@ -918,7 +941,7 @@ vi *Miaig::findPairs(word *pSto, int nWords) { vi *vPairs = Vi_Alloc(30); int i, f1, f2, iFan1, iFan2; Miaig_ForEachNode(i) { - vi *vFans = _data->pvFans + i; + vi *vFans = objFanins(i); Vi_ForEachEntry(vFans, iFan1, f1) { word *pRowFan1 = pSto + iFan1 * nWords; Vi_ForEachEntryStart(vFans, iFan2, f2, f1 + 1) { @@ -964,7 +987,7 @@ int Miaig::checkConst(int iObj, word *pCare, word *pExc, int fCheck, int fVerbos word *pFunc = objTruth(iObj, 0); if (!Tt_IntersectC(pCare, pFunc, 0, nWords())) { derefObj_rec(iObj, -1); - Vi_Fill(_data->pvFans + iObj, 1, 0); // const0 + Vi_Fill(objFanins(iObj), 1, 0); // const0 refObj(iObj); truthUpdate(_data->vTfo, pExc, fCheck); if (fVerbose) printf("Detected Const0 at node %d.\n", iObj); @@ -972,7 +995,7 @@ int Miaig::checkConst(int iObj, word *pCare, word *pExc, int fCheck, int fVerbos } if (!Tt_IntersectC(pCare, pFunc, 1, nWords())) { derefObj_rec(iObj, -1); - Vi_Fill(_data->pvFans + iObj, 1, 1); // const1 + Vi_Fill(objFanins(iObj), 1, 1); // const1 refObj(iObj); truthUpdate(_data->vTfo, pExc, fCheck); if (fVerbose) printf("Detected Const1 at node %d.\n", iObj); @@ -985,10 +1008,10 @@ int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, w int i, k, n, iLit, nAdded = 0; word *pCare = computeCareSet(iObj, pExc); assert(nAddedMax > 0); - assert(nAddedMax <= Vi_Space(_data->pvFans + iObj)); + assert(nAddedMax <= Vi_Space(objFanins(iObj))); // mark node's fanins Miaig_ForEachObjFanin(iObj, iLit, k) - objTravId(Abc_Lit2Var(iLit)) = nTravIds(); + objTravId(Rw_Lit2Var(iLit)) = nTravIds(); // compute the onset word *pOnset = objTruth(iObj, 0); Tt_Sharp(pOnset, pCare, 0, nWords()); @@ -1005,13 +1028,13 @@ int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, w int *pOrderF = Vi_Array(_data->vOrderF); std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) { - return objLevel(Abc_Lit2Var(a)) > objLevel(Abc_Lit2Var(b)); + return objLevel(Rw_Lit2Var(a)) > objLevel(Rw_Lit2Var(b)); }); std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) { - if (objLevel(Abc_Lit2Var(a)) == 0 || objLevel(Abc_Lit2Var(b)) == 0) { + if (objLevel(Rw_Lit2Var(a)) == 0 || objLevel(Rw_Lit2Var(b)) == 0) { return false; } - return objRef(Abc_Lit2Var(a)) < objRef(Abc_Lit2Var(b)); + return objRef(Rw_Lit2Var(a)) < objRef(Rw_Lit2Var(b)); }); // iterate through candidate fanins (nodes that are not in the TFO of iObj) @@ -1020,8 +1043,8 @@ int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, w // new fanin can be added if its offset does not intersect with the node's onset for (n = 0; n < 2; n++) if (!Tt_IntersectC(pOnset, objTruth(i, 0), !n, nWords())) { - if (fVerbose) printf("Adding node %d fanin %d\n", iObj, Abc_Var2Lit(i, n)); - appendFanin(iObj, Abc_Var2Lit(i, n)); + if (fVerbose) printf("Adding node %d fanin %d\n", iObj, Rw_Var2Lit(i, n)); + appendFanin(iObj, Rw_Var2Lit(i, n)); objRef(i)++; nAdded++; break; @@ -1047,10 +1070,10 @@ int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, // if one fanin can be used, take it word *pFunc = objTruth(iObj, 0); Miaig_ForEachObjFanin(iObj, iLit, k) { - Tt_DupC(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords()); + Tt_DupC(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords()); if (Tt_EqualOnCare(pCare, pFunc, _data->pProd, nWords())) { derefObj(iObj); - Vi_Fill(_data->pvFans + iObj, 1, iLit); + Vi_Fill(objFanins(iObj), 1, iLit); refObj(iObj); truthUpdate(_data->vTfo, pExc, fCheck); if (fVerbose) printf("Reducing node %d fanin count from %d to %d.\n", iObj, nFans, objFaninNum(iObj)); @@ -1067,13 +1090,13 @@ int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, if (fHeuristic) { int *pOrderF = Vi_Array(_data->vOrderF); std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) { - return objLevel(Abc_Lit2Var(a)) < objLevel(Abc_Lit2Var(b)); + return objLevel(Rw_Lit2Var(a)) < objLevel(Rw_Lit2Var(b)); }); std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) { - if (objLevel(Abc_Lit2Var(a)) == 0 || objLevel(Abc_Lit2Var(b)) == 0) { + if (objLevel(Rw_Lit2Var(a)) == 0 || objLevel(Rw_Lit2Var(b)) == 0) { return false; } - return objRef(Abc_Lit2Var(a)) > objRef(Abc_Lit2Var(b)); + return objRef(Rw_Lit2Var(a)) > objRef(Rw_Lit2Var(b)); }); } @@ -1089,9 +1112,9 @@ int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, // update the node if it is reduced if (Vi_Size(_data->vOrderF) < nFans) { derefObj(iObj); - Vi_Shrink(_data->pvFans + iObj, 0); + Vi_Shrink(objFanins(iObj), 0); Vi_ForEachEntry(_data->vOrderF, iLit, k) - Vi_PushOrder(_data->pvFans + iObj, iLit); + Vi_PushOrder(objFanins(iObj), iLit); refObj(iObj); truthUpdate(_data->vTfo, pExc, fCheck); if (fVerbose) printf("Reducing node %d fanin count from %d to %d.\n", iObj, nFans, objFaninNum(iObj)); @@ -1101,7 +1124,7 @@ int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, } int Miaig::expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose) { - expandOne(iNode, Abc_MinInt(Vi_Space(_data->pvFans + iNode), nFaninAddLimit), nDist, nExpandableLevel, pExc, fCheck, fVerbose); + expandOne(iNode, std::min(Vi_Space(objFanins(iNode)), nFaninAddLimit), nDist, nExpandableLevel, pExc, fCheck, fVerbose); reduceOne(iNode, 0, 0, 0, pExc, fCheck, fVerbose); return 0; } @@ -1125,12 +1148,12 @@ Miaig Miaig::expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, word initializeLevels(); if (nDist) initializeDists(); Vi_ForEachEntry(vOrder, iNode, i) { - nAdded += expandOne(iNode, Abc_MinInt(Vi_Space(_data->pvFans + iNode), nFaninAddLimitAll - nAdded), nDist, nExpandableLevel, pExc, fCheck, fVerbose); + nAdded += expandOne(iNode, std::min(Vi_Space(objFanins(iNode)), nFaninAddLimitAll - nAdded), nDist, nExpandableLevel, pExc, fCheck, fVerbose); if (nAdded >= nFaninAddLimitAll) break; } assert(nAdded <= nFaninAddLimitAll); - verifyRefs(); + if (fCheck) verifyRefs(); return dupDfs(); } @@ -1157,7 +1180,7 @@ Miaig Miaig::reduce(word *pExc, int fCheck, int fVerbose) { // works best for final Vi_ForEachEntry(vOrder, iNode, i) reduceOne(iNode, 0, 0, 1, pExc, fCheck, fVerbose); - verifyRefs(); + if (fCheck) verifyRefs(); return dupStrash(1, 1, 1); } @@ -1173,7 +1196,7 @@ Miaig Miaig::expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLeve Vi_ForEachEntry(vOrder, iNode, i) { expandThenReduceOne(iNode, nFaninAddLimit, nDist, nExpandableLevel, pExc, fCheck, fVerbose); } - verifyRefs(); + if (fCheck) verifyRefs(); return dupDfs().dupStrash(1, 1, 1); } diff --git a/src/opt/rar/rewire_miaig.h b/src/opt/rar/rewire_miaig.h index 112332c2d..6690141ae 100644 --- a/src/opt/rar/rewire_miaig.h +++ b/src/opt/rar/rewire_miaig.h @@ -27,6 +27,15 @@ #include "base/abc/abc.h" #include "aig/miniaig/miniaig.h" #include "rewire_map.h" +#define RW_INT_MAX ABC_INT_MAX +#define Rw_MaxInt Abc_MaxInt +#define Rw_MinInt Abc_MinInt +#define Rw_Var2Lit Abc_Var2Lit +#define Rw_Lit2Var Abc_Lit2Var +#define Rw_LitIsCompl Abc_LitIsCompl +#define Rw_LitNot Abc_LitNot +#define Rw_LitNotCond Abc_LitNotCond +#define Rw_LitRegular Abc_LitRegular #else #ifdef _WIN32 typedef unsigned __int64 word; // 32-bit windows @@ -38,6 +47,15 @@ typedef __int64 iword; // 32-bit windows #else typedef long long iword; // other platforms #endif +#define RW_INT_MAX (2147483647) +static inline int Rw_MaxInt( int a, int b ) { return a > b ? a : b; } +static inline int Rw_MinInt( int a, int b ) { return a < b ? a : b; } +static inline int Rw_Var2Lit( int Var, int c ) { assert(Var >= 0 && !(c >> 1)); return Var + Var + c; } +static inline int Rw_Lit2Var( int Lit ) { assert(Lit >= 0); return Lit >> 1; } +static inline int Rw_LitIsCompl( int Lit ) { assert(Lit >= 0); return Lit & 1; } +static inline int Rw_LitNot( int Lit ) { assert(Lit >= 0); return Lit ^ 1; } +static inline int Rw_LitNotCond( int Lit, int c ) { assert(Lit >= 0); return Lit ^ (int)(c > 0); } +static inline int Rw_LitRegular( int Lit ) { assert(Lit >= 0); return Lit & ~01; } #endif // RW_ABC #include "rewire_vec.h" #include "rewire_tt.h" @@ -129,15 +147,16 @@ static inline int RW_XADD(int *addr, int delta) { #define Miaig_ForEachNodeOutputStart(i, s) for (i = s; i < _data->nObjs; i++) #define Miaig_ForEachObj(i) for (i = 0; i < _data->nObjs; i++) #define Miaig_ForEachObjFanin(i, iLit, k) Vi_ForEachEntry(&_data->pvFans[i], iLit, k) +#define Miaig_ForEachObjFaninStart(i, iLit, k, s) Vi_ForEachEntryStart(&_data->pvFans[i], iLit, k, s) static inline int Rw_Lit2LitV(int *pMapV2V, int Lit) { assert(Lit >= 0); - return Abc_Var2Lit(pMapV2V[Abc_Lit2Var(Lit)], Abc_LitIsCompl(Lit)); + return Rw_Var2Lit(pMapV2V[Rw_Lit2Var(Lit)], Rw_LitIsCompl(Lit)); } static inline int Rw_Lit2LitL(int *pMapV2L, int Lit) { assert(Lit >= 0); - return Abc_LitNotCond(pMapV2L[Abc_Lit2Var(Lit)], Abc_LitIsCompl(Lit)); + return Rw_LitNotCond(pMapV2L[Rw_Lit2Var(Lit)], Rw_LitIsCompl(Lit)); } struct Miaig_Data { @@ -222,6 +241,7 @@ public: int &objDist(int i); int &nTravIds(void); word *objTruth(int i, int n); + vi *objFanins(int i); int objType(int i); int nWords(void); void refObj(int iObj); @@ -242,6 +262,8 @@ private: int markDfs(void); void markDistanceN_rec(int iObj, int n, int limit); void markDistanceN(int Obj, int n); + void markCritical(void); + void markCritical_rec(int iObj); void topoCollect_rec(int iObj); vi *topoCollect(void); void reduceFanins(vi *v); @@ -269,7 +291,7 @@ public: float countAnd2(int reset = 0, int fDummy = 0); // 0: amap 1: &nf 2: &simap float countTransistors(int reset = 0, int nMode = 0); - int countLevel(void); + int countLevel(int min = 0); private: void dupDfs_rec(Miaig &pNew, int iObj); @@ -416,15 +438,15 @@ inline int &Miaig::nObjsAlloc(void) { } inline int Miaig::objIsPi(int i) { - return i > 0 && i <= _data->nIns; + return i > 0 && i <= nIns(); } inline int Miaig::objIsPo(int i) { - return i >= _data->nObjs - _data->nOuts; + return i >= nObjs() - nOuts(); } inline int Miaig::objIsNode(int i) { - return i > _data->nIns && i < _data->nObjs - _data->nOuts; + return i > nIns() && i < nObjs() - nOuts(); } inline int Miaig::objPiIdx(int i) { @@ -434,29 +456,29 @@ inline int Miaig::objPiIdx(int i) { inline int Miaig::objPoIdx(int i) { // assert(objIsPo(i)); - return i - (_data->nObjs - _data->nOuts); + return i - (nObjs() - nOuts()); } inline int Miaig::appendObj(void) { - assert(_data->nObjs < _data->nObjsAlloc); - return _data->nObjs++; + assert(nObjs() < nObjsAlloc()); + return nObjs()++; } inline void Miaig::appendFanin(int i, int iLit) { - Vi_PushOrder(_data->pvFans + i, iLit); + Vi_PushOrder(objFanins(i), iLit); } inline int Miaig::objFaninNum(int i) { - return Vi_Size(_data->pvFans + i); + return Vi_Size(objFanins(i)); } inline int Miaig::objFanin0(int i) { - return Vi_Read(_data->pvFans + i, 0); + return Vi_Read(objFanins(i), 0); } inline int Miaig::objFanin1(int i) { assert(objFaninNum(i) == 2); - return Vi_Read(_data->pvFans + i, 1); + return Vi_Read(objFanins(i), 1); } inline int &Miaig::objLevel(int i) { @@ -495,11 +517,12 @@ inline float Miaig::countAnd2(int reset, int fDummy) { return Counter; } -inline int Miaig::countLevel(void) { +inline int Miaig::countLevel(int min) { initializeLevels(); - int i, Level = -1; + int i, Level = (min) ? RW_INT_MAX : -1; + int (*compareFunc)(int, int) = (min) ? Rw_MinInt : Rw_MaxInt; Miaig_ForEachOutput(i) { - Level = Abc_MaxInt(Level, objLevel(i)); + Level = compareFunc(Level, objLevel(i)); } return Level; } @@ -508,6 +531,10 @@ inline word *Miaig::objTruth(int i, int n) { return _data->pTruths[n] + nWords() * i; } +inline vi *Miaig::objFanins(int i) { + return _data->pvFans + i; +} + inline int Miaig::objType(int i) { return objTravId(i) == nTravIds(); } From 59bb4de39f676fea1aa30676e33fc6c4935f89ec Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 30 Apr 2025 10:47:12 -0700 Subject: [PATCH 19/72] Misc changes. --- src/aig/gia/giaCut.c | 40 ++++++ src/aig/gia/giaSimBase.c | 15 +++ src/base/abci/abcDar.c | 273 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 328 insertions(+) diff --git a/src/aig/gia/giaCut.c b/src/aig/gia/giaCut.c index 19d98c3be..61ce665a7 100644 --- a/src/aig/gia/giaCut.c +++ b/src/aig/gia/giaCut.c @@ -1168,6 +1168,46 @@ Vec_Ptr_t * Gia_ManMatchCutsMany( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, int nFun return vRes; } +/**Function************************************************************* + + Synopsis [Function enumeration.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDumpCuts( Gia_Man_t * p, int nCutSize, int nCutNum, int fVerbose ) +{ + FILE * pFile = fopen( "input.txt", "wb" ); if ( !pFile ) return; + Gia_Sto_t * pSto = Gia_ManMatchCutsInt( p, nCutSize, nCutNum, 0 ); + Vec_Int_t * vLevel; int i, k, c, * pCut, nCuts = 0, nNodes = 0; + Vec_WecForEachLevel( pSto->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) { + if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) ) + continue; + Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) { + if ( pCut[0] == 1 ) + continue; + fprintf( pFile, "%d ", i ); + for ( c = 1; c <= pCut[0]; c++ ) + fprintf( pFile, "%d ", pCut[c] ); + fprintf( pFile, "1\n" ); + nCuts += pCut[0]; + nNodes++; + } + } + Gia_Obj_t * pObj; + Gia_ManForEachCo( p, pObj, i ) { + fprintf( pFile, "%d %d 0\n", Gia_ObjId(p, pObj), Gia_ObjFaninId0p(p, pObj) ); + } + fclose( pFile ); + Gia_StoFree( pSto ); + if ( fVerbose ) + printf( "Dumped %d cuts for %d nodes into file \"input.txt\".\n", nCuts, nNodes ); +} + /**Function************************************************************* Synopsis [Function enumeration.] diff --git a/src/aig/gia/giaSimBase.c b/src/aig/gia/giaSimBase.c index b5c3c0802..734d9359b 100644 --- a/src/aig/gia/giaSimBase.c +++ b/src/aig/gia/giaSimBase.c @@ -288,6 +288,21 @@ void Gia_ManSimPatWrite( char * pFileName, Vec_Wrd_t * vSimsIn, int nWords ) SeeAlso [] ***********************************************************************/ +Vec_Wrd_t * Gia_ManDeriveNodeFuncs( Gia_Man_t * p ) +{ + int nWords = Abc_Truth6WordNum( Gia_ManCiNum(p) ); + Vec_Wrd_t * vSims = Vec_WrdStart( nWords * Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; int i; + Gia_ManForEachCi( p, pObj, i ) + assert( Gia_ObjId(p, pObj) == i+1 ); + Vec_Ptr_t * vTruths = Vec_PtrAllocTruthTables( Gia_ManCiNum(p) ); + Gia_ManForEachCi( p, pObj, i ) + Abc_TtCopy( Vec_WrdEntryP(vSims, nWords*(i+1)), (word *)Vec_PtrEntry(vTruths, i), nWords, 0 ); + Vec_PtrFree( vTruths ); + Gia_ManForEachAnd( p, pObj, i ) + Gia_ManSimPatSimAnd( p, i, pObj, nWords, vSims ); + return vSims; +} word * Gia_ManDeriveFuncs( Gia_Man_t * p ) { int nVars2 = (Gia_ManCiNum(p) + 6)/2; diff --git a/src/base/abci/abcDar.c b/src/base/abci/abcDar.c index d5ea77c78..e7874b0ea 100644 --- a/src/base/abci/abcDar.c +++ b/src/base/abci/abcDar.c @@ -18,6 +18,9 @@ ***********************************************************************/ +//#include +//#include + #include "base/abc/abc.h" #include "base/main/main.h" #include "aig/gia/giaAig.h" @@ -36,6 +39,7 @@ #include "proof/pdr/pdr.h" #include "sat/bmc/bmc.h" #include "map/mio/mio.h" +#include "misc/vec/vecMem.h" ABC_NAMESPACE_IMPL_START @@ -4902,6 +4906,275 @@ Abc_Ntk_t * Abc_NtkDarTestNtk( Abc_Ntk_t * pNtk ) } +#if 0 + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Data_ListDirsFilesCompareNames( char ** pp1, char ** pp2 ) +{ + return strcmp( *pp1, *pp2 ); +} +char ** Data_ListDirsFiles(const char *path, const char *ext) +{ + int iItems = 0, nItems = 1000; + char ** pRes = (char **)calloc( sizeof(char*), nItems ); + DIR *dir; + struct dirent *entry; + struct stat statbuf; + + // Open the directory + if ((dir = opendir(path)) == NULL) { + perror("opendir"); + return NULL; + } + + // Read each entry in the directory + while ((entry = readdir(dir)) != NULL) { + char full_path[1024]; + snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name); + + // Get the status of the entry + if (stat(full_path, &statbuf) == -1) { + perror("stat"); + continue; + } + + if (ext == NULL) { + // If no file extension is provided, list subdirectories + if (S_ISDIR(statbuf.st_mode)) { + // Skip "." and ".." directories + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + + // Print the directory name + //printf("%s\n", entry->d_name); + assert( iItems < nItems ); + pRes[iItems] = (char *)calloc( sizeof(char), strlen(entry->d_name)+1 ); + memcpy( pRes[iItems++], entry->d_name, strlen(entry->d_name) ); + } + } else { + // If file extension is provided, list files with that extension + if (S_ISREG(statbuf.st_mode)) { // Check if it's a regular file + const char *dot = strrchr(entry->d_name, '.'); + if (dot && strcmp(dot + 1, ext) == 0) { + // Print the file name + //printf("%s\n", entry->d_name); + assert( iItems <= nItems ); + if ( iItems == nItems ) { + pRes = ABC_REALLOC( char *, pRes, nItems *= 2 ); + memset( pRes + nItems/2, 0, sizeof(char *) * nItems/2 ); + } + pRes[iItems] = (char *)calloc( sizeof(char), strlen(entry->d_name)+1 ); + memcpy( pRes[iItems++], entry->d_name, strlen(entry->d_name) ); + } + } + } + } + + qsort( (void *)pRes, (size_t)iItems, sizeof(char *), (int (*)(const void *, const void *)) Data_ListDirsFilesCompareNames ); + + // Close the directory + closedir(dir); + if ( iItems == 0 ) + ABC_FREE( pRes ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManDeriveNodeClasses( Gia_Man_t * p, Vec_Wrd_t * vSims ) +{ + abctime clkStart = Abc_Clock(); + int nVars = Gia_ManCiNum(p); + int nWords = Abc_Truth6WordNum( nVars ); + Vec_Mem_t * vTtMem = Vec_MemAllocForTTSimple( nVars ); + Vec_Int_t * vRes = Vec_IntStartFull( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; int i; + for ( i = 0; i <= nVars; i++ ) { + int iFunc = Vec_MemHashInsert( vTtMem, Vec_WrdEntryP(vSims, i*nWords) ); + assert( iFunc == i ); + Vec_IntWriteEntry( vRes, i, i ); + } + Gia_ManForEachAnd( p, pObj, i ) + { + word * pTruth = Vec_WrdEntryP( vSims, i*nWords ); + if ( pTruth[0] & 1 ) + for ( int k = 0; k < nWords; k++ ) + pTruth[k] = ~pTruth[k]; + int iFunc = Vec_MemHashInsert(vTtMem, pTruth); + //assert( iFunc > nVars ); + Vec_IntWriteEntry( vRes, i, iFunc ); + } + printf( "Detected %d unique functions among %d nodes. ", Vec_MemEntryNum(vTtMem) - nVars - 1, Gia_ManAndNum(p) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + Vec_MemFree( vTtMem ); + return vRes; +} +int Gia_ManExploreNode_rec( Gia_Man_t * p, int Obj, int Repr, Vec_Int_t * vFuncs ) +{ + if ( Obj == Repr || Vec_IntEntry(vFuncs, Obj) == -1 ) + return 0; + if ( Obj < Repr ) + return 1; + if ( Gia_ObjIsTravIdCurrentId(p, Obj) ) + return 1; + Gia_ObjSetTravIdCurrentId(p, Obj); + Gia_Obj_t * pObj = Gia_ManObj(p, Obj); + if ( !Gia_ManExploreNode_rec( p, Gia_ObjFaninId0(pObj, Obj), Repr, vFuncs ) ) + return 0; + if ( !Gia_ManExploreNode_rec( p, Gia_ObjFaninId1(pObj, Obj), Repr, vFuncs ) ) + return 0; + if ( Vec_IntEntry(vFuncs, Obj) != Obj ) { + if ( !Gia_ManExploreNode_rec( p, Vec_IntEntry(vFuncs, Obj), Repr, vFuncs ) ) + return 0; + } + return 1; +} +int Gia_ManChoiceCheck( Gia_Man_t * p, Gia_Obj_t * pObj, int i, Vec_Int_t * vFuncs ) +{ + if ( Vec_IntEntry(vFuncs, Gia_ObjFaninId0p(p, pObj)) == -1 || Vec_IntEntry(vFuncs, Gia_ObjFaninId1p(p, pObj)) == -1 ) + return 0; + if ( i == Vec_IntEntry(vFuncs, i) ) + return 1; + assert( i > Vec_IntEntry(vFuncs, i) ); + Gia_ManIncrementTravId( p ); + if ( !Gia_ManExploreNode_rec(p, i, Vec_IntEntry(vFuncs, i), vFuncs) ) + return 0; + return 1; +} +void Gia_ManChoicesClean( Gia_Man_t * p, Vec_Int_t * vFuncs ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManForEachAnd( p, pObj, i ) + if ( Vec_IntEntry(vFuncs, i) <= Gia_ManCiNum(p) || !Gia_ManChoiceCheck(p, pObj, i, vFuncs) ) + Vec_IntWriteEntry( vFuncs, i, -1 ); +} +Gia_Man_t * Gia_ManTransformToChoices( Gia_Man_t * p ) +{ + Vec_Wrd_t * Gia_ManDeriveNodeFuncs( Gia_Man_t * p ); + Vec_Wrd_t * vSims = Gia_ManDeriveNodeFuncs( p ); + Vec_Int_t * vFuncs = Gia_ManDeriveNodeClasses( p, vSims ); + Gia_ManChoicesClean( p, vFuncs ); + Vec_WrdFree( vSims ); + + Gia_Man_t * pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManHashAlloc( pNew ); + Gia_Obj_t * pObj; int i; + Gia_ManSetPhase(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) { + if ( Vec_IntEntry(vFuncs, i) == -1 ) + continue; + else if ( Vec_IntEntry(vFuncs, i) == i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else { + int iFunc = Vec_IntEntry(vFuncs, i); + pNew->pSibls[i] = pNew->pSibls[iFunc]; + pNew->pSibls[iFunc] = i; + pObj->Value = Abc_Var2Lit( iFunc, pObj->fPhase ^ Gia_ManObj(p, iFunc)->fPhase ); + //printf( "Adding choice %d -> %d\n", iFunc, i ); + } + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Vec_IntFree( vFuncs ); + return pNew; +} +void Gia_ManTestAppend( Gia_Man_t * pNew, Gia_Man_t * pTwo ) +{ + Gia_Obj_t * pObj; int i; + assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(pTwo) ); + Gia_ManConst0(pTwo)->Value = 0; + Gia_ManForEachCand( pTwo, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_Obj2Lit( pNew, Gia_ManCi( pNew, Gia_ObjCioId(pObj) ) ); + } +} +Gia_Man_t * Abc_NtkDarTestFiles() +{ + char full_path[1024]; + const char *directory_path = "temp"; + const char *ext = "aig"; + char ** pItems = Data_ListDirsFiles(directory_path, ext); + if ( pItems == NULL ) { + printf( "There are no files in directory \"%s\".\n", directory_path ); + return NULL; + } + + //for ( i = 0; pItems[i]; i++ ) + // printf( "%d : %s\n", i, pItems[i] ); + + Gia_Obj_t * pObj; int i; + Gia_Man_t * pNew = NULL; + Gia_Man_t * pTemp = NULL; + for ( i = 0; pItems[i]; i++ ) + { + snprintf(full_path, sizeof(full_path), "%s/%s", directory_path, pItems[i]); + Gia_Man_t * pTwo = Gia_AigerRead( full_path, 0, 0, 0 ); + if ( i == 0 ) { + pNew = Gia_ManStart( 10000 ); + pNew->pName = Abc_UtilStrsav( pTwo->pName ); + pNew->pSpec = Abc_UtilStrsav( pTwo->pSpec ); + for ( int k = 0; k < Gia_ManCiNum(pTwo); k++ ) + Gia_ManAppendCi( pNew ); + } + Gia_ManTestAppend( pNew, pTwo ); + if ( i == 0 ) + pTemp = pTwo; + else + Gia_ManStop( pTwo ); + if ( i < 4 ) + printf( "%d : %s\n", i, pItems[i] ); + } + printf( "Finished reading %d files.\n", i ); + Gia_ManForEachCo( pTemp, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManStop( pTemp ); + + Gia_ManPrintStats( pNew, NULL ); + + pNew = Gia_ManTransformToChoices( pTemp = pNew ); + Gia_ManStop( pTemp ); + + Gia_ManPrintStats( pNew, NULL ); + + for ( i = 0; pItems[i]; i++ ) + free( pItems[i] ); + free( pItems ); + + //Gia_AigerWrite( pNew, "all.aig", 0, 0, 0 ); + //Gia_ManStop( pNew ); + return pNew; +} + +#endif + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// From 6a031620fed69a4aa2e82d13513d0432e2247078 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 30 Apr 2025 12:10:22 -0700 Subject: [PATCH 20/72] Supporting random seed in "lutexact". --- src/base/abci/abc.c | 36 ++++++++++++++++++++++++------------ src/sat/bmc/bmc.h | 1 + src/sat/bmc/bmcMaj.c | 13 +++++++------ 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index dbe69d9ba..53e30af05 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -10548,7 +10548,7 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INKTSFMiaocgvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INKTFMSYiaocgvh" ) ) != EOF ) { switch ( c ) { @@ -10596,15 +10596,6 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->RuntimeLim < 0 ) goto usage; break; - case 'S': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); - goto usage; - } - pPars->pSymStr = argv[globalUtilOptind]; - globalUtilOptind++; - break; case 'F': if ( globalUtilOptind >= argc ) { @@ -10623,6 +10614,26 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->nMintNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + pPars->Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->Seed < 0 ) + goto usage; + break; + case 'Y': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Y\" should be followed by a string.\n" ); + goto usage; + } + pPars->pSymStr = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'i': pPars->fUseIncr ^= 1; break; @@ -10690,7 +10701,7 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutexact [-INKTFM ] [-S string] [-iaocgvh] \n" ); + Abc_Print( -2, "usage: lutexact [-INKTFMS ] [-Y string] [-iaocgvh] \n" ); Abc_Print( -2, "\t exact synthesis of I-input function using N K-input gates\n" ); Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", pPars->nVars ); Abc_Print( -2, "\t-N : the number of K-input nodes [default = %d]\n", pPars->nNodes ); @@ -10698,7 +10709,8 @@ usage: Abc_Print( -2, "\t-T : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); Abc_Print( -2, "\t-F : the number of random functions to try [default = unused]\n" ); Abc_Print( -2, "\t-M : the number of positive minterms in the random function [default = unused]\n" ); - Abc_Print( -2, "\t-S : charasteristic string of a symmetric function [default = %d]\n", pPars->pSymStr ); + Abc_Print( -2, "\t-S : the random seed for random function generation with -F [default = %d]\n", pPars->Seed ); + Abc_Print( -2, "\t-Y : charasteristic string of a symmetric function [default = %d]\n", pPars->pSymStr ); Abc_Print( -2, "\t-i : toggle using incremental solving [default = %s]\n", pPars->fUseIncr ? "yes" : "no" ); Abc_Print( -2, "\t-a : toggle using only AND-gates when K = 2 [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); Abc_Print( -2, "\t-o : toggle using additional optimizations [default = %s]\n", pPars->fFewerVars ? "yes" : "no" ); diff --git a/src/sat/bmc/bmc.h b/src/sat/bmc/bmc.h index 233930178..d7e71113a 100644 --- a/src/sat/bmc/bmc.h +++ b/src/sat/bmc/bmc.h @@ -67,6 +67,7 @@ struct Bmc_EsPar_t_ int RuntimeLim; int nRandFuncs; int nMintNum; + int Seed; int fVerbose; char * pTtStr; char * pSymStr; diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index 5e85536ae..cdd2cec49 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -1580,18 +1580,19 @@ int Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars ) { int i, k, nDecs = 0, nWords = Abc_TtWordNum(pPars->nVars); - word * pFun = ABC_ALLOC( word, nWords ); - Abc_Random(1); - printf( "\n" ); + word * pFun = ABC_ALLOC( word, nWords ); + unsigned Rand0 = Abc_Random(1); + for ( i = 0; i < pPars->Seed; i++ ) + Rand0 = Abc_Random(0); for ( i = 0; i < pPars->nRandFuncs; i++ ) { if ( pPars->nMintNum == 0 ) for ( k = 0; k < nWords; k++ ) - pFun[k] = Abc_RandomW(0); + pFun[k] = Rand0 ^ Abc_RandomW(0); else { Abc_TtClear( pFun, nWords ); for ( k = 0; k < pPars->nMintNum; k++ ) { int iMint = 0; - do iMint = Abc_Random(0) % (1 << pPars->nVars); + do iMint = (Rand0 ^ Abc_Random(0)) % (1 << pPars->nVars); while ( Abc_TtGetBit(pFun, iMint) ); Abc_TtSetBit( pFun, iMint ); } @@ -1607,7 +1608,7 @@ void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars ) nDecs += Exa3_ManExactSynthesis( pPars ); ABC_FREE( pPars->pTtStr ); } - printf( "Decomposable are %d (out of %d) functions (%.2f %%).\n", nDecs, pPars->nRandFuncs, 100.0*nDecs/pPars->nRandFuncs ); + printf( "\nDecomposable are %d (out of %d) functions (%.2f %%).\n", nDecs, pPars->nRandFuncs, 100.0*nDecs/pPars->nRandFuncs ); ABC_FREE( pFun ); } From 391a767c169d0d82a7fa8cfc759d15f6f9cf2fa7 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 1 May 2025 11:51:48 -0700 Subject: [PATCH 21/72] Updating LUT cascade mapping. --- src/base/abci/abcCas.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index def9e34a8..a2bfea56a 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -332,7 +332,7 @@ void Abc_LutBddTest( DdManager * dd, DdNode * bFunc, char ** ppNames, int nNames #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 nLuts, int nRails, int nIters, int fVerbose ) { return NULL; } +word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nStages, int nRails, int nIters, int fVerbose ) { return NULL; } #endif @@ -716,14 +716,19 @@ static inline int Abc_LutCascadeDecStage( char * pGuide, int Iter, Vec_Wrd_t * v Vec_IntShrink( vVarIDs, nFVars+nSVars+nEVars ); return nEVars; } -word * Abc_LutCascadeDec( char * pGuide, word * pTruth, int nVarsOrig, Vec_Int_t * vVarIDs, int nRails, int nLutSize, int fVerbose ) +word * Abc_LutCascadeDec( char * pGuide, word * pTruth, int nVarsOrig, Vec_Int_t * vVarIDs, int nRails, int nLutSize, int nStages, int fVerbose, int * pnStages ) { 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) }; Abc_TtCopy( Vec_WrdArray(vFuncs[0]), pTruth, Abc_TtWordNum(nVars), 0 ); Vec_Wrd_t * vCas = Vec_WrdAlloc( 100 ); Vec_WrdPush( vCas, nVarsOrig ); + if ( pnStages ) *pnStages = 0; for ( i = 0; Vec_IntSize(vVarIDs) > nLutSize; i++ ) { nRVars = Abc_LutCascadeDecStage( pGuide, i, vFuncs, vVarIDs, nRVars, nRails, nLutSize, fVerbose, vCas ); + if ( i+2 > nStages ) { + printf( "The length of the cascade (%d) exceeds the max allowed number of stages (%d).\n", i+2, nStages ); + nRVars = -1; + } if ( nRVars == -1 ) break; } @@ -731,6 +736,7 @@ word * Abc_LutCascadeDec( char * pGuide, word * pTruth, int nVarsOrig, Vec_Int_t Abc_LutCascadeGenOne( vCas, Vec_IntSize(vVarIDs), Vec_IntArray(vVarIDs), Vec_WrdEntry(vCas, 0), Vec_WrdArray(vFuncs[0]) ); Vec_WrdAddToEntry( vCas, 0, -nVarsOrig ); pRes = Vec_WrdReleaseArray(vCas); + if ( pnStages ) *pnStages = i+1; } Vec_WrdFree( vCas ); for ( i = 0; i < 3; i++ ) @@ -814,14 +820,14 @@ Abc_Ntk_t * Abc_NtkLutCascadeFromLuts( word * pLuts, int nVars, Abc_Ntk_t * pNtk } return pNtkNew; } -Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) +Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nStages, 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 nLuts, int nRails, int nIters, int fVerbose ); + //extern word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nStages, 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, nLuts, nRails, nIters, fVerbose ); + //word * pLuts = Abc_LutCascade( pM, nLutSize, nStages, nRails, nIters, fVerbose ); word * pLuts = Abc_LutCascadeTest( pM, nLutSize, 0 ); Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, Abc_NtkCiNum(pNtk), pNtk, nLutSize, fVerbose ) : NULL; ABC_FREE( pLuts ); @@ -829,10 +835,9 @@ Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nR Gia_ManStop( pGia ); return pNew; } -Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int Seed, int fVerbose, char * pGuide ) +Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nStages, int nRails, int nIters, int Seed, int fVerbose, char * pGuide ) { extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk ); - extern word * Abc_LutCascade2( word * p, int nVars, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); int i, nWords = Abc_TtWordNum(Abc_NtkCiNum(pNtk)); word * pCopy = ABC_ALLOC( word, nWords ); Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk ); @@ -858,7 +863,7 @@ Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int n printf( ".\n" ); } - word * pLuts = Abc_LutCascadeDec( pGuide, pTruth1, Abc_NtkCiNum(pNtk), vVarIDs, nRails, nLutSize, fVerbose ); + word * pLuts = Abc_LutCascadeDec( pGuide, pTruth1, Abc_NtkCiNum(pNtk), vVarIDs, nRails, nLutSize, nStages, fVerbose, NULL ); pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, Abc_NtkCiNum(pNtk), pNtk, nLutSize, fVerbose ) : NULL; Vec_IntFree( vVarIDs ); @@ -1371,10 +1376,10 @@ Vec_Wrd_t * Abc_NtkLutCasReadTruths( char * pFileName, int nVarsOrig ) SeeAlso [] ***********************************************************************/ -void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int nLuts, int nRails, int nIters, int Seed, int fVerbose, int fVeryVerbose ) +void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int nStages, int nRails, int nIters, int Seed, int fVerbose, int fVeryVerbose ) { abctime clkStart = Abc_Clock(); - int i, Sum = 0, nTotalLuts = 0, nWords = Abc_TtWordNum(nVarsOrig); + int i, Sum = 0, nStageCount, nTotalLuts = 0, nWords = Abc_TtWordNum(nVarsOrig); Vec_Wrd_t * vTruths = NULL; if ( strstr(pFileName, ".txt") ) vTruths = Abc_NtkLutCasReadTruths( pFileName, nVarsOrig ); @@ -1392,7 +1397,7 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n printf( "Considering %d functions having %d variables from file \"%s\".\n", nFuncs, nVarsOrig, pFileName ); word * pCopy = ABC_ALLOC( word, nWords ); - int Iter = 0, LutStats[100] = {0}; + int Iter = 0, LutStats[100] = {0}, StageStats[100] = {0}; Abc_Random(1); for ( i = 0; i < Seed; i++ ) Abc_Random(0); @@ -1419,7 +1424,7 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n printf( "Decomposing %d-var function into %d-rail cascade of %d-LUTs.\n", nVars, nRails, nLutSize ); } - word * pLuts = Abc_LutCascadeDec( NULL, pTruth, nVarsOrig, vVarIDs, nRails, nLutSize, fVeryVerbose ); + word * pLuts = Abc_LutCascadeDec( NULL, pTruth, nVarsOrig, vVarIDs, nRails, nLutSize, nStages, fVeryVerbose, &nStageCount ); Vec_IntFree( vVarIDs ); if ( pLuts == NULL ) { if ( ++Iter < nIters ) { @@ -1435,6 +1440,7 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n Sum++; nTotalLuts += Abc_LutCascadeCount(pLuts); LutStats[Abc_LutCascadeCount(pLuts)]++; + StageStats[nStageCount]++; word * pTruth2 = Abc_LutCascadeTruth( pLuts, nVarsOrig ); if ( fVeryVerbose ) Abc_LutCascadePrint( pLuts ); @@ -1452,10 +1458,14 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n } ABC_FREE( pCopy ); Vec_WrdFree( vTruths ); - printf( "Statistics for %d-rail LUT cascade:\n", nRails ); + printf( "Level count statistics for %d-rail LUT cascade:\n", nRails ); + for ( i = 0; i < 100; i++ ) + if ( StageStats[i] ) + printf( " %2d level : Function count = %8d (%6.2f %%)\n", i, StageStats[i], 100.0*StageStats[i]/nFuncs ); + printf( "LUT count statistics for %d-rail LUT cascade:\n", nRails ); for ( i = 0; i < 100; i++ ) if ( LutStats[i] ) - printf( " %2d LUT%d : Function count = %8d (%6.2f %%)\n", i, nLutSize, LutStats[i], 100.0*LutStats[i]/nFuncs ); + printf( " %2d LUT%d : Function count = %8d (%6.2f %%)\n", i, nLutSize, LutStats[i], 100.0*LutStats[i]/nFuncs ); printf( "Non-decomp : Function count = %8d (%6.2f %%)\n", nFuncs-Sum, 100.0*(nFuncs-Sum)/Abc_MaxInt(1, nFuncs) ); printf( "Finished %d functions (%.2f LUTs / function; %.2f functions / sec). ", nFuncs, 1.0*nTotalLuts/Sum, 1.0*nFuncs/(((double)(Abc_Clock() - clkStart))/((double)CLOCKS_PER_SEC)) ); From 1c2b935a77669f917f5764f6fd80266197be381b Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 1 May 2025 21:08:46 -0700 Subject: [PATCH 22/72] Adding new feature to "lutexact". --- src/base/abci/abc.c | 8 +++-- src/sat/bmc/bmc.h | 1 + src/sat/bmc/bmcMaj.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 53e30af05..d9af50b8e 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -10548,7 +10548,7 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INKTFMSYiaocgvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INKTFMSYiaocfgvh" ) ) != EOF ) { switch ( c ) { @@ -10646,6 +10646,9 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'c': pPars->fLutCascade ^= 1; break; + case 'f': + pPars->fLutInFixed ^= 1; + break; case 'g': pPars->fGlucose ^= 1; break; @@ -10701,7 +10704,7 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutexact [-INKTFMS ] [-Y string] [-iaocgvh] \n" ); + Abc_Print( -2, "usage: lutexact [-INKTFMS ] [-Y string] [-iaocfgvh] \n" ); Abc_Print( -2, "\t exact synthesis of I-input function using N K-input gates\n" ); Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", pPars->nVars ); Abc_Print( -2, "\t-N : the number of K-input nodes [default = %d]\n", pPars->nNodes ); @@ -10715,6 +10718,7 @@ usage: Abc_Print( -2, "\t-a : toggle using only AND-gates when K = 2 [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); Abc_Print( -2, "\t-o : toggle using additional optimizations [default = %s]\n", pPars->fFewerVars ? "yes" : "no" ); Abc_Print( -2, "\t-c : toggle synthesizing a single-rail cascade [default = %s]\n", pPars->fLutCascade ? "yes" : "no" ); + Abc_Print( -2, "\t-f : toggle fixing LUT inputs in cascade mapping [default = %s]\n", pPars->fLutInFixed ? "yes" : "no" ); Abc_Print( -2, "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon [default = %s]\n", pPars->fGlucose ? "yes" : "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose ? "yes" : "no" ); Abc_Print( -2, "\t-h : print the command usage\n" ); diff --git a/src/sat/bmc/bmc.h b/src/sat/bmc/bmc.h index d7e71113a..b4d993c0a 100644 --- a/src/sat/bmc/bmc.h +++ b/src/sat/bmc/bmc.h @@ -64,6 +64,7 @@ struct Bmc_EsPar_t_ int fQuadrEnc; int fUniqFans; int fLutCascade; + int fLutInFixed; int RuntimeLim; int nRandFuncs; int nMintNum; diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index cdd2cec49..6e50ea981 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -1009,6 +1009,7 @@ struct Exa3_Man_t_ int VarMarks[MAJ_NOBJS][6][MAJ_NOBJS]; // variable marks int VarVals[MAJ_NOBJS]; // values of the first nVars variables Vec_Wec_t * vOutLits; // output vars + Vec_Wec_t * vInVars; // input vars bmcg_sat_solver * pSat; // SAT solver int nUsed[2]; }; @@ -1040,6 +1041,54 @@ static inline int Exa3_ManIsUsed3( Exa3_Man_t * p, int m, int n, int i, int } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Exa3_ChooseInputVars_int( int nVars, int nLuts, int nLutSize ) +{ + Vec_Wec_t * p = Vec_WecStart( nLuts ); + Vec_Int_t * vLevel; int i; + Vec_WecForEachLevel( p, vLevel, i ) { + do { + int iVar = (Abc_Random(0) ^ Abc_Random(0) ^ Abc_Random(0)) % nVars; + Vec_IntPushUniqueOrder( vLevel, iVar ); + } + while ( Vec_IntSize(vLevel) < nLutSize-(int)(i>0) ); + } + return p; +} +Vec_Int_t * Exa3_CountInputVars( int nVars, Vec_Wec_t * p ) +{ + Vec_Int_t * vLevel; int i, k, Obj; + Vec_Int_t * vCounts = Vec_IntStart( nVars ); + Vec_WecForEachLevel( p, vLevel, i ) + Vec_IntForEachEntry( vLevel, Obj, k ) + Vec_IntAddToEntry( vCounts, Obj, 1 ); + return vCounts; +} +Vec_Wec_t * Exa3_ChooseInputVars( int nVars, int nLuts, int nLutSize ) +{ + for ( int i = 0; i < 1000; i++ ) { + Vec_Wec_t * p = Exa3_ChooseInputVars_int( nVars, nLuts, nLutSize ); + Vec_Int_t * q = Exa3_CountInputVars( nVars, p ); + int RetValue = Vec_IntFind( q, 0 ); + Vec_IntFree( q ); + if ( RetValue == -1 ) + return p; + Vec_WecFree( p ); + } + assert( 0 ); + return NULL; +} + /**Function************************************************************* Synopsis [] @@ -1102,6 +1151,19 @@ static int Exa3_ManMarkup( Exa3_Man_t * p ) } } printf( "The number of parameter variables = %d.\n", p->iVar ); + if ( p->pPars->fLutCascade && p->pPars->fLutInFixed ) { + p->vInVars = Exa3_ChooseInputVars( p->nVars, p->nNodes, p->nLutSize ); + if ( 1 ) { + Vec_Int_t * vLevel; int i, Var; + printf( "Using fixed input assignment:\n" ); + Vec_WecForEachLevelReverse( p->vInVars, vLevel, i ) { + printf( "%02d : ", p->nVars+i ); + Vec_IntForEachEntry( vLevel, Var, k ) + printf( "%c ", 'a'+Var ); + printf( "\n" ); + } + } + } return p->iVar; // printout for ( i = p->nObjs - 1; i >= p->nVars; i-- ) @@ -1148,6 +1210,7 @@ static void Exa3_ManFree( Exa3_Man_t * p ) Vec_BitFreeP( &p->vUsed2 ); Vec_BitFreeP( &p->vUsed3 ); Vec_WecFree( p->vOutLits ); + Vec_WecFreeP( &p->vInVars ); ABC_FREE( p ); } @@ -1396,6 +1459,18 @@ static int Exa3_ManAddCnfStart( Exa3_Man_t * p, int fOnlyAnd ) if ( !bmcg_sat_solver_addclause( p->pSat, Vec_IntArray(vArray), Vec_IntSize(vArray) ) ) return 0; } + if ( p->vInVars ) { + Vec_Int_t * vLevel; int Var; + Vec_WecForEachLevel( p->vInVars, vLevel, i ) + { + assert( Vec_IntSize(vLevel) > 0 ); + Vec_IntForEachEntry( vLevel, Var, k ) { + pLits[0] = Abc_Var2Lit( p->VarMarks[p->nVars+i][p->nLutSize-1-k][Var], 0 ); assert(pLits[0]); + if ( !bmcg_sat_solver_addclause( p->pSat, pLits, 1 ) ) + return 0; + } + } + } return 1; } static int Exa3_ManAddCnf( Exa3_Man_t * p, int iMint ) From 75adf123f62de9f0b44412bc1354fc1e43070156 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 1 May 2025 22:41:49 -0700 Subject: [PATCH 23/72] Adding new feature to &nf. --- src/aig/gia/gia.h | 1 + src/aig/gia/giaNf.c | 86 +++++++++++++++++++++++++++++++++++++++++++++ src/base/abci/abc.c | 14 ++++++-- 3 files changed, 99 insertions(+), 2 deletions(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 273c530ec..b2b499eae 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -387,6 +387,7 @@ struct Jf_Par_t_ float Epsilon; float * pTimesArr; float * pTimesReq; + char * ZFile; }; static inline unsigned Gia_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId & 31)); } diff --git a/src/aig/gia/giaNf.c b/src/aig/gia/giaNf.c index 8bcf76b33..b38093f23 100644 --- a/src/aig/gia/giaNf.c +++ b/src/aig/gia/giaNf.c @@ -2161,6 +2161,90 @@ void Nf_ManFixPoDrivers( Nf_Man_t * p ) //printf( "Fixed %d PO drivers.\n", Count ); } +/**Function************************************************************* + + Synopsis [Dump matches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nf_ManDumpMatches( Nf_Man_t * p ) +{ + FILE * pFile = fopen( p->pPars->ZFile, "wb" ); + Gia_Obj_t * pObj; int n, iObj; + // output matches + Gia_ManForEachCi( p->pGia, pObj, n ) + fprintf( pFile, "%d input %.2f\n", Abc_Var2Lit(Gia_ObjId(p->pGia, pObj), 0), 0.0 ); + Gia_ManForEachAnd( p->pGia, pObj, iObj ) { + assert( !Gia_ObjIsBuf(pObj) ); + for ( n = 0; n < 2; n++ ) { + int c, * pCut, * pCutSet = Nf_ObjCutSet( p, iObj ); + Nf_SetForEachCut( pCutSet, pCut, c ) { + if ( Abc_Lit2Var(Nf_CutFunc(pCut)) >= Vec_WecSize(p->vTt2Match) ) + continue; + assert( !Nf_CutIsTriv(pCut, iObj) ); + assert( Nf_CutSize(pCut) <= p->pPars->nLutSize ); + assert( Abc_Lit2Var(Nf_CutFunc(pCut)) < Vec_WecSize(p->vTt2Match) ); + int iFuncLit = Nf_CutFunc(pCut); + int fComplExt = Abc_LitIsCompl(iFuncLit); + Vec_Int_t * v = Vec_WecEntry( p->vTt2Match, Abc_Lit2Var(iFuncLit) ); + int j, k, Info, Offset, iFanin, fComplF; + Vec_IntForEachEntryDouble( v, Info, Offset, j ) { + Nf_Cfg_t Cfg = Nf_Int2Cfg(Offset); + int fCompl = Cfg.fCompl ^ fComplExt; + if ( fCompl != n ) + continue; + Mio_Cell2_t*pC = Nf_ManCell( p, Info ); + assert( Nf_CutSize(pCut) == (int)pC->nFanins ); + fprintf( pFile, "%d ", Abc_Var2Lit(iObj, n) ); + fprintf( pFile, "%s ", pC->pName ); + fprintf( pFile, "%.2f", pC->AreaF ); + Nf_CutForEachVarCompl( pCut, Cfg, iFanin, fComplF, k ) + fprintf( pFile, " %d", Abc_Var2Lit(iFanin, fComplF) ); + fprintf( pFile, "\n" ); + } + } + } + } + Gia_ManForEachCo( p->pGia, pObj, n ) + fprintf( pFile, "%d output %.2f %d\n", Abc_Var2Lit(Gia_ObjId(p->pGia, pObj), 0), 0.0, Gia_ObjFaninLit0p(p->pGia, pObj) ); + // output levels + extern int Gia_ManChoiceLevel( Gia_Man_t * p ); + int LevelMax = Gia_ManChoiceLevel( p->pGia ); + Gia_ManForEachCiId( p->pGia, iObj, n ) + fprintf( pFile, "L%d %d\n", Abc_Var2Lit(iObj, 0), 0 ); + Gia_ManForEachAnd( p->pGia, pObj, iObj ) + fprintf( pFile, "L%d %d\n", Abc_Var2Lit(iObj, 0), Gia_ObjLevelId(p->pGia, iObj) ); + Gia_ManForEachCoId( p->pGia, iObj, n ) + fprintf( pFile, "L%d %d\n", Abc_Var2Lit(iObj, 0), LevelMax+1 ); + // output mapping + Gia_ManForEachCiId( p->pGia, iObj, n ) + if ( Nf_ObjMapRefNum(p, iObj, 1) ) + fprintf( pFile, "M%d %s %.2f %d\n", Abc_Var2Lit(iObj, 1), p->pCells[3].pName, p->pCells[3].AreaF, Abc_Var2Lit(iObj, 0) ); + Gia_ManForEachAnd( p->pGia, pObj, iObj ) + for ( n = 0; n < 2; n++ ) + if ( Nf_ObjMapRefNum(p, iObj, n) ) { + Nf_Mat_t * pM = Nf_ObjMatchBest(p, iObj, n); + if ( pM->fCompl ) { + fprintf( pFile, "M%d %s %.2f %d\n", Abc_Var2Lit(iObj, n), p->pCells[3].pName, p->pCells[3].AreaF, Abc_Var2Lit(iObj, !n) ); + continue; + } + int k, iVar, fCompl, * pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, iObj), pM->CutH ); + Mio_Cell2_t*pC = Nf_ManCell( p, pM->Gate ); + fprintf( pFile, "M%d ", Abc_Var2Lit(iObj, n) ); + fprintf( pFile, "%s ", pC->pName ); + fprintf( pFile, "%.2f", pC->AreaF ); + Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, k ) + fprintf( pFile, " %d", Abc_Var2Lit(iVar, fCompl) ); + fprintf( pFile, "\n" ); + } + fclose( pFile ); +} + /**Function************************************************************* Synopsis [Deriving mapping.] @@ -2216,6 +2300,8 @@ Gia_Man_t * Nf_ManDeriveMapping( Nf_Man_t * p ) } // assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); p->pGia->vCellMapping = vMapping; + if ( p->pPars->ZFile ) + Nf_ManDumpMatches( p ); return p->pGia; } void Nf_ManUpdateStats( Nf_Man_t * p ) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index d9af50b8e..c90c2f7d3 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -44574,7 +44574,7 @@ int Abc_CommandAbc9Nf( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_Man_t * pNew; int c; Nf_ManSetDefaultPars( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFARLEDQWakpqfvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFARLEDQWZakpqfvwh" ) ) != EOF ) { switch ( c ) { @@ -44694,6 +44694,15 @@ int Abc_CommandAbc9Nf( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nVerbLimit < 0 ) goto usage; break; + case 'Z': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Z\" should be followed by an output file name.\n" ); + goto usage; + } + pPars->ZFile = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'a': pPars->fAreaOnly ^= 1; break; @@ -44747,7 +44756,7 @@ usage: sprintf(Buffer, "best possible" ); else sprintf(Buffer, "%d", pPars->DelayTarget ); - Abc_Print( -2, "usage: &nf [-KCFARLEDQ num] [-akpqfvwh]\n" ); + Abc_Print( -2, "usage: &nf [-KCFARLEDQ num] [-Z file] [-akpqfvwh]\n" ); Abc_Print( -2, "\t performs technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", pPars->nLutSizeMax, pPars->nLutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", pPars->nCutNumMax, pPars->nCutNum ); @@ -44758,6 +44767,7 @@ usage: Abc_Print( -2, "\t-E num : the area/edge tradeoff parameter (0 <= num <= 100) [default = %d]\n", pPars->nAreaTuner ); Abc_Print( -2, "\t-D num : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-Q num : internal parameter impacting area of the mapping [default = %d]\n", pPars->nReqTimeFlex ); + Abc_Print( -2, "\t-Z file : the output file name to dump internal match info [default = unused]\n" ); Abc_Print( -2, "\t-a : toggles SAT-based area-oriented mapping (experimental) [default = %s]\n", pPars->fAreaOnly? "yes": "no" ); Abc_Print( -2, "\t-k : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" ); Abc_Print( -2, "\t-p : toggles pin permutation (more matches - better quality) [default = %s]\n", pPars->fPinPerm? "yes": "no" ); From 692b0c69081fb88102f314b835321b7a4a1fbead Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 2 May 2025 08:13:20 -0700 Subject: [PATCH 24/72] Printout of column multiplicity statistics. --- src/base/abci/abc.c | 2 +- src/base/abci/abcCas.c | 34 ++++++++++++++++++++-------------- src/misc/util/utilBSet.c | 3 ++- src/sat/bmc/bmcMaj.c | 4 ++-- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index c90c2f7d3..a5f22d2fc 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -7771,7 +7771,7 @@ int Abc_CommandRunScript( Abc_Frame_t * pAbc, int argc, char ** argv ) strcat( pCommLine, pNumber ); strcat( pCommLine, pSpot+1 ); if ( fVerbose ) - printf( "Iteration %3d : %s\n", c, pCommLine ); + printf( "ITERATION %3d : %s\n", c, pCommLine ); if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pCommLine) ) { Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pCommLine ); goto usage; diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index a2bfea56a..861860d04 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -656,12 +656,12 @@ void Abc_LutCascadeDerive( word * p, int nVars, int nBVars, int Myu, word * pRem } // performs decomposition of one stage -static inline int Abc_LutCascadeDecStage( char * pGuide, int Iter, Vec_Wrd_t * vFuncs[3], Vec_Int_t * vVarIDs, int nRVars, int nRails, int nLutSize, int fVerbose, Vec_Wrd_t * vCas ) +static inline int Abc_LutCascadeDecStage( char * pGuide, int Iter, Vec_Wrd_t * vFuncs[3], Vec_Int_t * vVarIDs, int nRVars, int nRails, int nLutSize, int fVerbose, Vec_Wrd_t * vCas, int * pMyu ) { - extern word Abc_TtFindBVarsSVars( word * p, int nVars, int nRVars, int nRails, int nLutSize, int fVerbose ); + extern word Abc_TtFindBVarsSVars( word * p, int nVars, int nRVars, int nRails, int nLutSize, int fVerbose, int * pMyu ); assert( Vec_IntSize(vVarIDs) > nLutSize ); assert( Vec_IntSize(vVarIDs) <= 24 ); - word Guide = pGuide ? 0 : Abc_TtFindBVarsSVars( Vec_WrdArray(vFuncs[0]), Vec_IntSize(vVarIDs), nRVars, nRails, nLutSize, fVerbose ); + word Guide = pGuide ? 0 : Abc_TtFindBVarsSVars( Vec_WrdArray(vFuncs[0]), Vec_IntSize(vVarIDs), nRVars, nRails, nLutSize, fVerbose, pMyu ); if ( !pGuide && !Guide ) { if ( fVerbose ) printf( "The function is not decomposable with %d rails.\n", nRails ); @@ -716,7 +716,7 @@ static inline int Abc_LutCascadeDecStage( char * pGuide, int Iter, Vec_Wrd_t * v Vec_IntShrink( vVarIDs, nFVars+nSVars+nEVars ); return nEVars; } -word * Abc_LutCascadeDec( char * pGuide, word * pTruth, int nVarsOrig, Vec_Int_t * vVarIDs, int nRails, int nLutSize, int nStages, int fVerbose, int * pnStages ) +word * Abc_LutCascadeDec( char * pGuide, word * pTruth, int nVarsOrig, Vec_Int_t * vVarIDs, int nRails, int nLutSize, int nStages, int fVerbose, int * pnStages, int * pMyu ) { 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) }; @@ -724,7 +724,7 @@ word * Abc_LutCascadeDec( char * pGuide, word * pTruth, int nVarsOrig, Vec_Int_t Vec_Wrd_t * vCas = Vec_WrdAlloc( 100 ); Vec_WrdPush( vCas, nVarsOrig ); if ( pnStages ) *pnStages = 0; for ( i = 0; Vec_IntSize(vVarIDs) > nLutSize; i++ ) { - nRVars = Abc_LutCascadeDecStage( pGuide, i, vFuncs, vVarIDs, nRVars, nRails, nLutSize, fVerbose, vCas ); + nRVars = Abc_LutCascadeDecStage( pGuide, i, vFuncs, vVarIDs, nRVars, nRails, nLutSize, fVerbose, vCas, pMyu ); if ( i+2 > nStages ) { printf( "The length of the cascade (%d) exceeds the max allowed number of stages (%d).\n", i+2, nStages ); nRVars = -1; @@ -863,7 +863,7 @@ Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nStages, int printf( ".\n" ); } - word * pLuts = Abc_LutCascadeDec( pGuide, pTruth1, Abc_NtkCiNum(pNtk), vVarIDs, nRails, nLutSize, nStages, fVerbose, NULL ); + word * pLuts = Abc_LutCascadeDec( pGuide, pTruth1, Abc_NtkCiNum(pNtk), vVarIDs, nRails, nLutSize, nStages, fVerbose, NULL, NULL ); pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, Abc_NtkCiNum(pNtk), pNtk, nLutSize, fVerbose ) : NULL; Vec_IntFree( vVarIDs ); @@ -1379,7 +1379,7 @@ Vec_Wrd_t * Abc_NtkLutCasReadTruths( char * pFileName, int nVarsOrig ) void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int nStages, int nRails, int nIters, int Seed, int fVerbose, int fVeryVerbose ) { abctime clkStart = Abc_Clock(); - int i, Sum = 0, nStageCount, nTotalLuts = 0, nWords = Abc_TtWordNum(nVarsOrig); + int i, Sum = 0, nStageCount = 0, MyuMin = 0, nTotalLuts = 0, nWords = Abc_TtWordNum(nVarsOrig); Vec_Wrd_t * vTruths = NULL; if ( strstr(pFileName, ".txt") ) vTruths = Abc_NtkLutCasReadTruths( pFileName, nVarsOrig ); @@ -1397,7 +1397,7 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n printf( "Considering %d functions having %d variables from file \"%s\".\n", nFuncs, nVarsOrig, pFileName ); word * pCopy = ABC_ALLOC( word, nWords ); - int Iter = 0, LutStats[100] = {0}, StageStats[100] = {0}; + int Iter = 0, LutStats[50] = {0}, StageStats[50] = {0}, MyuStats[50] = {0}; Abc_Random(1); for ( i = 0; i < Seed; i++ ) Abc_Random(0); @@ -1409,7 +1409,7 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n if ( fVeryVerbose ) printf( "\n" ); if ( fVerbose || fVeryVerbose ) - printf( "Function %3d : ", i ); + printf( "Function %4d : ", i ); if ( fVeryVerbose ) Abc_TtPrintHexRev( stdout, pTruth, nVarsOrig ), printf( "\n" ); //continue; @@ -1424,7 +1424,7 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n printf( "Decomposing %d-var function into %d-rail cascade of %d-LUTs.\n", nVars, nRails, nLutSize ); } - word * pLuts = Abc_LutCascadeDec( NULL, pTruth, nVarsOrig, vVarIDs, nRails, nLutSize, nStages, fVeryVerbose, &nStageCount ); + word * pLuts = Abc_LutCascadeDec( NULL, pTruth, nVarsOrig, vVarIDs, nRails, nLutSize, nStages, fVeryVerbose, &nStageCount, &MyuMin ); Vec_IntFree( vVarIDs ); if ( pLuts == NULL ) { if ( ++Iter < nIters ) { @@ -1439,8 +1439,10 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n Iter = 0; Sum++; nTotalLuts += Abc_LutCascadeCount(pLuts); - LutStats[Abc_LutCascadeCount(pLuts)]++; - StageStats[nStageCount]++; + if ( Abc_LutCascadeCount(pLuts) < 50 ) + LutStats[Abc_LutCascadeCount(pLuts)]++; + if ( nStageCount < 50) StageStats[nStageCount]++; + if ( MyuMin < 50 ) MyuStats[MyuMin]++; word * pTruth2 = Abc_LutCascadeTruth( pLuts, nVarsOrig ); if ( fVeryVerbose ) Abc_LutCascadePrint( pLuts ); @@ -1458,12 +1460,16 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n } ABC_FREE( pCopy ); Vec_WrdFree( vTruths ); + printf( "Column multiplicity statistics for %d-rail LUT cascade:\n", nRails ); + for ( i = 0; i < 50; i++ ) + if ( MyuStats[i] ) + printf( " %2d Myu : Function count = %8d (%6.2f %%)\n", i, StageStats[i], 100.0*StageStats[i]/nFuncs ); printf( "Level count statistics for %d-rail LUT cascade:\n", nRails ); - for ( i = 0; i < 100; i++ ) + for ( i = 0; i < 50; i++ ) if ( StageStats[i] ) printf( " %2d level : Function count = %8d (%6.2f %%)\n", i, StageStats[i], 100.0*StageStats[i]/nFuncs ); printf( "LUT count statistics for %d-rail LUT cascade:\n", nRails ); - for ( i = 0; i < 100; i++ ) + for ( i = 0; i < 50; i++ ) if ( LutStats[i] ) printf( " %2d LUT%d : Function count = %8d (%6.2f %%)\n", i, nLutSize, LutStats[i], 100.0*LutStats[i]/nFuncs ); printf( "Non-decomp : Function count = %8d (%6.2f %%)\n", nFuncs-Sum, 100.0*(nFuncs-Sum)/Abc_MaxInt(1, nFuncs) ); diff --git a/src/misc/util/utilBSet.c b/src/misc/util/utilBSet.c index 6f4111eb9..77257b673 100644 --- a/src/misc/util/utilBSet.c +++ b/src/misc/util/utilBSet.c @@ -996,7 +996,7 @@ word * Abc_LutCascade2( word * pFunc, int nVars, int nLutSize, int nLuts, int nR SeeAlso [] ***********************************************************************/ -word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int nLutSize, int fVerbose ) +word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int nLutSize, int fVerbose, int * pMyu ) { Abc_BSEval_t * p = Abc_BSEvalAlloc(); int nPermVars = nVars-nRVars; @@ -1026,6 +1026,7 @@ word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int //printf("Function before: "); Abc_TtPrintHexRev( stdout, pCopy, nVars ); printf( "\n" ); int MyuMin = Abc_BSEvalBest( p, pCopy, pBest, nVars, nRVars, nVars-nLutSize, 0, pPermBest, 0 ); //printf("Function before: "); Abc_TtPrintHexRev( stdout, pCopy, nVars ); printf( "\n" ); + if ( pMyu ) *pMyu = MyuMin; if ( fVerbose ) { printf( "Best perm: " ); diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index 6e50ea981..7c62c5c3a 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -1674,7 +1674,7 @@ void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars ) } pPars->pTtStr = ABC_CALLOC( char, pPars->nVars > 2 ? (1 << (pPars->nVars-2)) + 1 : 2 ); Extra_PrintHexadecimalString( pPars->pTtStr, (unsigned *)pFun, pPars->nVars ); - printf( "\nIteration %d : ", i ); + printf( "\nFunction %4d : ", i ); if ( pPars->nMintNum ) printf( "Random function has %d positive minterms.", pPars->nMintNum ); printf( "\n" ); @@ -1683,7 +1683,7 @@ void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars ) nDecs += Exa3_ManExactSynthesis( pPars ); ABC_FREE( pPars->pTtStr ); } - printf( "\nDecomposable are %d (out of %d) functions (%.2f %%).\n", nDecs, pPars->nRandFuncs, 100.0*nDecs/pPars->nRandFuncs ); + printf( "\nDecomposable are %d (out of %d) functions (%.2f %%).\n\n", nDecs, pPars->nRandFuncs, 100.0*nDecs/pPars->nRandFuncs ); ABC_FREE( pFun ); } From f9e4d06806bd6537c4906e64f6ce60fbf602c555 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 2 May 2025 08:18:12 -0700 Subject: [PATCH 25/72] Column multiplicity statistics --- src/base/abci/abcCas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index 861860d04..2c9fc7a31 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -1463,7 +1463,7 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n printf( "Column multiplicity statistics for %d-rail LUT cascade:\n", nRails ); for ( i = 0; i < 50; i++ ) if ( MyuStats[i] ) - printf( " %2d Myu : Function count = %8d (%6.2f %%)\n", i, StageStats[i], 100.0*StageStats[i]/nFuncs ); + printf( " %2d Myu : Function count = %8d (%6.2f %%)\n", i, MyuStats[i], 100.0*MyuStats[i]/nFuncs ); printf( "Level count statistics for %d-rail LUT cascade:\n", nRails ); for ( i = 0; i < 50; i++ ) if ( StageStats[i] ) @@ -1472,7 +1472,7 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n for ( i = 0; i < 50; i++ ) if ( LutStats[i] ) printf( " %2d LUT%d : Function count = %8d (%6.2f %%)\n", i, nLutSize, LutStats[i], 100.0*LutStats[i]/nFuncs ); - printf( "Non-decomp : Function count = %8d (%6.2f %%)\n", nFuncs-Sum, 100.0*(nFuncs-Sum)/Abc_MaxInt(1, nFuncs) ); + printf( "Non-decomp : Function count = %8d (%6.2f %%)\n", nFuncs-Sum, 100.0*(nFuncs-Sum)/Abc_MaxInt(1, nFuncs) ); printf( "Finished %d functions (%.2f LUTs / function; %.2f functions / sec). ", nFuncs, 1.0*nTotalLuts/Sum, 1.0*nFuncs/(((double)(Abc_Clock() - clkStart))/((double)CLOCKS_PER_SEC)) ); Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); From 5e54ef3affa5fbd7e77e9b47fd4e873b43a5e48a Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 3 May 2025 18:15:11 -0700 Subject: [PATCH 26/72] Adding printout of flops. --- src/aig/gia/giaMan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index d0af551b0..7f3d27826 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -474,6 +474,7 @@ void Gia_ManLogAigStats( Gia_Man_t * p, char * pDumpFile ) fprintf( pTable, " \"name\" : \"%s\",\n", p->pName ); fprintf( pTable, " \"input\" : %d,\n", Gia_ManCiNum(p) ); fprintf( pTable, " \"output\" : %d,\n", Gia_ManCoNum(p) ); + fprintf( pTable, " \"flop\" : %d,\n", Gia_ManRegNum(p) ); fprintf( pTable, " \"and\" : %d,\n", Gia_ManAndNum(p) ); fprintf( pTable, " \"level\" : %d\n", Gia_ManLevelNum(p) ); fprintf( pTable, "}\n" ); From 49d9252f90d52a6153a2969842ede9559888a337 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 5 May 2025 09:03:41 -0700 Subject: [PATCH 27/72] Updating the way min col mult is reported in lutcasdec. --- src/base/abci/abcCas.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index 2c9fc7a31..fcfde345f 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -724,7 +724,7 @@ word * Abc_LutCascadeDec( char * pGuide, word * pTruth, int nVarsOrig, Vec_Int_t Vec_Wrd_t * vCas = Vec_WrdAlloc( 100 ); Vec_WrdPush( vCas, nVarsOrig ); if ( pnStages ) *pnStages = 0; for ( i = 0; Vec_IntSize(vVarIDs) > nLutSize; i++ ) { - nRVars = Abc_LutCascadeDecStage( pGuide, i, vFuncs, vVarIDs, nRVars, nRails, nLutSize, fVerbose, vCas, pMyu ); + nRVars = Abc_LutCascadeDecStage( pGuide, i, vFuncs, vVarIDs, nRVars, nRails, nLutSize, fVerbose, vCas, i ? NULL : pMyu ); if ( i+2 > nStages ) { printf( "The length of the cascade (%d) exceeds the max allowed number of stages (%d).\n", i+2, nStages ); nRVars = -1; @@ -1426,6 +1426,7 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n word * pLuts = Abc_LutCascadeDec( NULL, pTruth, nVarsOrig, vVarIDs, nRails, nLutSize, nStages, fVeryVerbose, &nStageCount, &MyuMin ); Vec_IntFree( vVarIDs ); + if ( MyuMin < 50 ) MyuStats[MyuMin]++; if ( pLuts == NULL ) { if ( ++Iter < nIters ) { i--; @@ -1442,7 +1443,6 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n if ( Abc_LutCascadeCount(pLuts) < 50 ) LutStats[Abc_LutCascadeCount(pLuts)]++; if ( nStageCount < 50) StageStats[nStageCount]++; - if ( MyuMin < 50 ) MyuStats[MyuMin]++; word * pTruth2 = Abc_LutCascadeTruth( pLuts, nVarsOrig ); if ( fVeryVerbose ) Abc_LutCascadePrint( pLuts ); @@ -1463,7 +1463,7 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n printf( "Column multiplicity statistics for %d-rail LUT cascade:\n", nRails ); for ( i = 0; i < 50; i++ ) if ( MyuStats[i] ) - printf( " %2d Myu : Function count = %8d (%6.2f %%)\n", i, MyuStats[i], 100.0*MyuStats[i]/nFuncs ); + printf( " %2d Myu : Function count = %8d (%6.2f %%)\n", i, MyuStats[i], 100.0*MyuStats[i]/nFuncs/nIters ); printf( "Level count statistics for %d-rail LUT cascade:\n", nRails ); for ( i = 0; i < 50; i++ ) if ( StageStats[i] ) From 4560597b311ac5295ebefc0b76305bf0b8b5855f Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 7 May 2025 16:53:51 -0700 Subject: [PATCH 28/72] Utility to duplicate inputs. --- src/aig/gia/giaDup.c | 59 +++++++++++++++++++++++++++++++++++++++ src/base/abci/abcRunGen.c | 2 +- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 4468dfb52..0021f6e18 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -6210,6 +6210,65 @@ void Gia_ManCofClassEnum( Gia_Man_t * p, int nVars ) Vec_IntFree( vIns ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjWhichFanout( Gia_Man_t * p, int iFanin, int iFanout ) +{ + int i, FanId; + Gia_ObjForEachFanoutStaticId( p, iFanin, FanId, i ) + if ( FanId == iFanout ) + return i; + assert( 0 ); + return -1; +} +Gia_Man_t * Gia_ManDupFanouts( Gia_Man_t * p ) +{ + assert( Gia_ManRegNum(p) == 0 ); + Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, f, iLit[2]; + pNew = Gia_ManStart( Gia_ManObjNum(p)+100 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManStaticFanoutStart( p ); + pNew->vNamesIn = Vec_PtrAlloc( 100 ); + pNew->vNamesOut = Vec_PtrAlloc( 100 ); + Gia_ManForEachPi( p, pObj, i ) { + pObj->Value = Gia_ManAppendCi(pNew); + Vec_PtrPush( pNew->vNamesIn, Gia_ObjCiName(p, i) ); + for ( f = 1; f < Gia_ObjFanoutNum(p, pObj); f++ ) { + Gia_ManAppendCi(pNew); + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsavNum(Gia_ObjCiName(p, i), f) ); + } + } + Gia_ManForEachAnd( p, pObj, i ) { + iLit[0] = Gia_ObjFanin0Copy(pObj); + if ( Gia_ObjIsPi(p, Gia_ObjFanin0(pObj)) ) + iLit[0] += 2 * Gia_ObjWhichFanout(p, Gia_ObjFaninId0(pObj, i), i); + iLit[1] = Gia_ObjFanin1Copy(pObj); + if ( Gia_ObjIsPi(p, Gia_ObjFanin1(pObj)) ) + iLit[1] += 2 * Gia_ObjWhichFanout(p, Gia_ObjFaninId1(pObj, i), i); + pObj->Value = Gia_ManAppendAnd( pNew, iLit[0], iLit[1] ); + } + Gia_ManForEachPo( p, pObj, i ) { + iLit[0] = Gia_ObjFanin0Copy(pObj); + if ( Gia_ObjIsPi(p, Gia_ObjFanin0(pObj)) ) + iLit[0] += 2 * Gia_ObjWhichFanout(p, Gia_ObjFaninId0p(p, pObj), Gia_ObjId(p, pObj)); + Gia_ManAppendCo( pNew, iLit[0] ); + Vec_PtrPush( pNew->vNamesOut, Gia_ObjCoName(p, i) ); + } + Gia_ManStaticFanoutStop( p ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcRunGen.c b/src/base/abci/abcRunGen.c index d82ba7fe4..5bd2b3c6e 100644 --- a/src/base/abci/abcRunGen.c +++ b/src/base/abci/abcRunGen.c @@ -110,7 +110,7 @@ void Acb_NtkRunGen( int nInputs, int nMints, int nFuncs, int Seed, int fVerbose, Vec_IntAddToEntry( vNodes, nNodes, 1 ); if ( fVerbose ) { - printf( "Iteration %3d : ", i ); + printf( "Function %4d : ", i ); printf( "Random function has %d positive minterms ", nMints ); printf( "and maps into %d nodes.\n", nNodes ); if ( fVerbose ) From 71b60a9830157d649eeb7afed3d1ce0c82eceb3e Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 7 May 2025 19:53:53 -0700 Subject: [PATCH 29/72] Updating &stochsyn. --- src/aig/gia/giaStoch.c | 540 +++++++++++++++++++++++++++++++++++++--- src/base/abci/abc.c | 24 +- src/base/abci/abcPart.c | 2 +- 3 files changed, 523 insertions(+), 43 deletions(-) diff --git a/src/aig/gia/giaStoch.c b/src/aig/gia/giaStoch.c index 68e23019e..c88bdae6b 100644 --- a/src/aig/gia/giaStoch.c +++ b/src/aig/gia/giaStoch.c @@ -80,8 +80,9 @@ Gia_Man_t * Gia_StochProcessSingle( Gia_Man_t * p, char * pScript, int Rand, int } return pNew; } -void Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int fVerbose ) +Vec_Int_t * Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int fVerbose ) { + Vec_Int_t * vGains = Vec_IntStartFull( Vec_PtrSize(vGias) ); Gia_Man_t * pGia, * pNew; int i; Vec_Int_t * vRands = Vec_IntAlloc( Vec_PtrSize(vGias) ); Abc_Random(1); @@ -90,10 +91,12 @@ void Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) { pNew = Gia_StochProcessSingle( pGia, pScript, Vec_IntEntry(vRands, i), TimeSecs ); + Vec_IntWriteEntry( vGains, i, Gia_ManAndNum(pGia) - Gia_ManAndNum(pNew) ); Gia_ManStop( pGia ); Vec_PtrWriteEntry( vGias, i, pNew ); } Vec_IntFree( vRands ); + return vGains; } /**Function************************************************************* @@ -165,14 +168,14 @@ int Gia_StochProcess1( void * p ) return 1; } -void Gia_StochProcess( Vec_Ptr_t * vGias, char * pScript, int nProcs, int TimeSecs, int fVerbose ) +Vec_Int_t * Gia_StochProcess( Vec_Ptr_t * vGias, char * pScript, int nProcs, int TimeSecs, int fVerbose ) { if ( nProcs <= 2 ) { if ( fVerbose ) printf( "Running non-concurrent synthesis.\n" ), fflush(stdout); - Gia_StochProcessArray( vGias, pScript, TimeSecs, fVerbose ); - return; + return Gia_StochProcessArray( vGias, pScript, TimeSecs, fVerbose ); } + Vec_Int_t * vGains = Vec_IntStartFull( Vec_PtrSize(vGias) ); StochSynData_t * pData = ABC_CALLOC( StochSynData_t, Vec_PtrSize(vGias) ); Vec_Ptr_t * vData = Vec_PtrAlloc( Vec_PtrSize(vGias) ); Gia_Man_t * pGia; int i; @@ -190,11 +193,13 @@ void Gia_StochProcess( Vec_Ptr_t * vGias, char * pScript, int nProcs, int TimeSe Util_ProcessThreads( Gia_StochProcess1, vData, nProcs, TimeSecs, fVerbose ); // replace old AIGs by new AIGs Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) { + Vec_IntWriteEntry( vGains, i, Gia_ManAndNum(pGia) - Gia_ManAndNum(pData[i].pOut) ); Gia_ManStop( pGia ); Vec_PtrWriteEntry( vGias, i, pData[i].pOut ); } Vec_PtrFree( vData ); ABC_FREE( pData ); + return vGains; } /**Function************************************************************* @@ -279,6 +284,428 @@ void Gia_ManStochSynthesis( Vec_Ptr_t * vAigs, char * pScript ) } } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFilterPartitions( Gia_Man_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvNodes, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins, Vec_Int_t * vGains ) +{ + int RetValue = Vec_PtrSize(vvIns); + Vec_Ptr_t * vvInsNew = Vec_PtrAlloc( 10 ); + Vec_Ptr_t * vvOutsNew = Vec_PtrAlloc( 10 ); + Vec_Ptr_t * vvWinsNew = Vec_PtrAlloc( 10 ); + Gia_ManIncrementTravId( p ); + while ( 1 ) { + int i, Gain, iEntry = Vec_IntArgMax(vGains); + if ( iEntry == -1 || Vec_IntEntry(vGains, iEntry) < 0 ) + break; + //printf( "Selecting partition %d with gain %d.\n", iEntry, Vec_IntEntry(vGains, iEntry) ); + Vec_IntWriteEntry( vGains, iEntry, -1 ); + Vec_PtrPush( vvInsNew, Vec_IntDup((Vec_Int_t *)Vec_PtrEntry(vvIns, iEntry)) ); + Vec_PtrPush( vvOutsNew, Vec_IntDup((Vec_Int_t *)Vec_PtrEntry(vvOuts, iEntry)) ); + Vec_PtrPush( vvWinsNew, Gia_ManDupDfs((Gia_Man_t *)Vec_PtrEntry(vWins, iEntry)) ); + extern void Gia_ManMarkTfiTfo( Vec_Int_t * vOne, Gia_Man_t * pMan ); + Gia_ManMarkTfiTfo( (Vec_Int_t *)Vec_PtrEntryLast(vvInsNew), p ); + Vec_IntForEachEntry( vGains, Gain, i ) { + if ( Gain < 0 ) + continue; + Vec_Int_t * vNodes = (Vec_Int_t *)Vec_PtrEntry(vvNodes, i); + Gia_Obj_t * pNode; int j; + Gia_ManForEachObjVec( vNodes, p, pNode, j ) + if ( Gia_ObjIsTravIdCurrent(p, pNode) ) + break; + if ( j < Vec_IntSize(vNodes) ) + Vec_IntWriteEntry( vGains, i, -1 ); + } + } + ABC_SWAP( Vec_Ptr_t, *vvInsNew, *vvIns ); + ABC_SWAP( Vec_Ptr_t, *vvOutsNew, *vvOuts ); + ABC_SWAP( Vec_Ptr_t, *vvWinsNew, *vWins ); + Vec_PtrFreeFunc( vvInsNew, (void (*)(void *)) Vec_IntFree ); + Vec_PtrFreeFunc( vvOutsNew, (void (*)(void *)) Vec_IntFree ); + Vec_PtrFreeFunc( vvWinsNew, (void (*)(void *)) Gia_ManStop ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjDfsMark_rec( Gia_Man_t * pGia, Gia_Obj_t * pObj ) +{ + assert( !pObj->fMark0 ); + if ( Gia_ObjIsTravIdCurrent( pGia, pObj ) ) + return; + Gia_ObjSetTravIdCurrent( pGia, pObj ); + if ( Gia_ObjIsCi(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ObjDfsMark_rec( pGia, Gia_ObjFanin0(pObj) ); + Gia_ObjDfsMark_rec( pGia, Gia_ObjFanin1(pObj) ); +} +void Gia_ObjDfsMark2_rec( Gia_Man_t * pGia, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pFanout; int i; + assert( !pObj->fMark0 ); + if ( Gia_ObjIsTravIdCurrent( pGia, pObj ) ) + return; + Gia_ObjSetTravIdCurrent( pGia, pObj ); + Gia_ObjForEachFanoutStatic( pGia, pObj, pFanout, i ) + Gia_ObjDfsMark2_rec( pGia, pFanout ); +} +Vec_Int_t * Gia_ManDeriveWinNodes( Gia_Man_t * pMan, Vec_Int_t * vIns, Vec_Wec_t * vStore ) +{ + Vec_Int_t * vLevel, * vNodes = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj, * pNext; int i, k, iLevel; + Vec_WecForEachLevel( vStore, vLevel, i ) + Vec_IntClear( vLevel ); + // mark the TFI cones of the inputs + Gia_ManIncrementTravId( pMan ); + Gia_ManForEachObjVec( vIns, pMan, pObj, i ) + Gia_ObjDfsMark_rec( pMan, pObj ); + // add unrelated fanouts of the inputs to storage + Gia_ManForEachObjVec( vIns, pMan, pObj, i ) + Gia_ObjForEachFanoutStatic( pMan, pObj, pNext, k ) + if ( Gia_ObjIsAnd(pNext) && !Gia_ObjIsTravIdCurrent(pMan, pNext) && !pNext->fMark0 ) { + pNext->fMark0 = 1; + Vec_WecPush( vStore, Gia_ObjLevel(pMan, pNext), Gia_ObjId(pMan, pNext) ); + } + // mark the inputs + Gia_ManIncrementTravId( pMan ); + Gia_ManForEachObjVec( vIns, pMan, pObj, i ) + Gia_ObjSetTravIdCurrent(pMan, pObj); + // collect those fanouts that are completely supported by the inputs + Vec_WecForEachLevel( vStore, vLevel, iLevel ) + Gia_ManForEachObjVec( vLevel, pMan, pObj, i ) { + assert( !Gia_ObjIsTravIdCurrent(pMan, pObj) ); + assert( pObj->fMark0 ); + pObj->fMark0 = 0; + if ( !Gia_ObjIsTravIdCurrent(pMan, Gia_ObjFanin0(pObj)) || + !Gia_ObjIsTravIdCurrent(pMan, Gia_ObjFanin1(pObj)) ) + continue; + Gia_ObjSetTravIdCurrent(pMan, pObj); + Vec_IntPush( vNodes, Gia_ObjId(pMan, pObj) ); + assert( Gia_ObjIsAnd(pObj) ); + // add fanouts of this node to storage + Gia_ObjForEachFanoutStatic( pMan, pObj, pNext, k ) + if ( Gia_ObjIsAnd(pNext) && !Gia_ObjIsTravIdCurrent(pMan, pNext) && !pNext->fMark0 ) { + pNext->fMark0 = 1; + assert( Gia_ObjLevel(pMan, pNext) > iLevel ); + Vec_WecPush( vStore, Gia_ObjLevel(pMan, pNext), Gia_ObjId(pMan, pNext) ); + } + } + Vec_IntSort( vNodes, 0 ); + return vNodes; +} +Vec_Ptr_t * Gia_ManDeriveWinNodesAll( Gia_Man_t * pMan, Vec_Ptr_t * vvIns, Vec_Wec_t * vStore ) +{ + Vec_Int_t * vIns; int i; + Vec_Ptr_t * vvNodes = Vec_PtrAlloc( Vec_PtrSize(vvIns) ); + Vec_PtrForEachEntry( Vec_Int_t *, vvIns, vIns, i ) + Vec_PtrPush( vvNodes, Gia_ManDeriveWinNodes(pMan, vIns, vStore) ); + return vvNodes; +} +Vec_Int_t * Gia_ManDeriveWinOuts( Gia_Man_t * pMan, Vec_Int_t * vNodes ) +{ + Vec_Int_t * vOuts = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj, * pNext; int i, k; + // mark the nodes in the window + Gia_ManIncrementTravId( pMan ); + Gia_ManForEachObjVec( vNodes, pMan, pObj, i ) + Gia_ObjSetTravIdCurrent(pMan, pObj); + // collect nodes that have unmarked fanouts + Gia_ManForEachObjVec( vNodes, pMan, pObj, i ) { + Gia_ObjForEachFanoutStatic( pMan, pObj, pNext, k ) + if ( !Gia_ObjIsTravIdCurrent(pMan, pNext) ) + break; + if ( k < Gia_ObjFanoutNum(pMan, pObj) ) + Vec_IntPush( vOuts, Gia_ObjId(pMan, pObj) ); + } + if ( Vec_IntSize(vOuts) == 0 ) + printf( "Window with %d internal nodes has no outputs (are these dangling nodes?).\n", Vec_IntSize(vNodes) ); + return vOuts; +} +Vec_Ptr_t * Gia_ManDeriveWinOutsAll( Gia_Man_t * pMan, Vec_Ptr_t * vvNodes ) +{ + Vec_Int_t * vNodes; int i; + Vec_Ptr_t * vvOuts = Vec_PtrAlloc( Vec_PtrSize(vvNodes) ); + Vec_PtrForEachEntry( Vec_Int_t *, vvNodes, vNodes, i ) + Vec_PtrPush( vvOuts, Gia_ManDeriveWinOuts(pMan, vNodes) ); + return vvOuts; +} +void Gia_ManPermuteLevel( Gia_Man_t * pMan, int Level ) +{ + Gia_Obj_t * pObj, * pNext; int i, k; + Gia_ManForEachAnd( pMan, pObj, i ) { + int LevelMin = Gia_ObjLevel(pMan, pObj), LevelMax = Level + 1; + Gia_ObjForEachFanoutStatic( pMan, pObj, pNext, k ) + if ( Gia_ObjIsAnd(pNext) ) + LevelMax = Abc_MinInt( LevelMax, Gia_ObjLevel(pMan, pNext) ); + if ( LevelMin == LevelMax ) continue; + assert( LevelMin < LevelMax ); + // randomly set level between LevelMin and LevelMax-1 + Gia_ObjSetLevel( pMan, pObj, LevelMin + (Abc_Random(0) % (LevelMax - LevelMin)) ); + assert( Gia_ObjLevel(pMan, pObj) < LevelMax ); + } +} +Vec_Int_t * Gia_ManCollectObjectsPointedTo( Gia_Man_t * pMan, int Level ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj, * pFanin; int i, n; + Gia_ManIncrementTravId( pMan ); + Gia_ManForEachAnd( pMan, pObj, i ) { + if ( Gia_ObjLevel(pMan, pObj) <= Level ) + continue; + for ( n = 0; n < 2; n++ ) { + Gia_Obj_t * pFanin = n ? Gia_ObjFanin1(pObj) : Gia_ObjFanin0(pObj); + if ( Gia_ObjLevel(pMan, pFanin) <= Level && !Gia_ObjIsTravIdCurrent(pMan, pFanin) ) { + Gia_ObjSetTravIdCurrent(pMan, pFanin); + Vec_IntPush( vRes, Gia_ObjId(pMan, pFanin) ); + } + } + } + Gia_ManForEachCo( pMan, pObj, i ) { + pFanin = Gia_ObjFanin0(pObj); + if ( Gia_ObjLevel(pMan, pFanin) <= Level && !Gia_ObjIsTravIdCurrent(pMan, pFanin) && Gia_ObjIsAnd(pFanin) ) { + Gia_ObjSetTravIdCurrent(pMan, pFanin); + Vec_IntPush( vRes, Gia_ObjId(pMan, pFanin) ); + } + } + Vec_IntSort( vRes, 0 ); + return vRes; +} +Vec_Wec_t * Gia_ManCollectObjectsWithSuppLimit( Gia_Man_t * pMan, int Level, int nSuppMax ) +{ + Vec_Wec_t * vResSupps = NULL; + Vec_Int_t * vBelow = Gia_ManCollectObjectsPointedTo( pMan, Level ); + Vec_Wec_t * vSupps = Vec_WecStart( Vec_IntSize(vBelow) ); + Vec_Int_t * vSuppIds = Vec_IntStartFull( Gia_ManObjNum(pMan) ); + Vec_Int_t * vTemp = Vec_IntAlloc(100); + Gia_Obj_t * pObj; int i, Count = 0; + Gia_ManForEachObjVec( vBelow, pMan, pObj, i ) { + Vec_IntWriteEntry( vSuppIds, Gia_ObjId(pMan, pObj), i ); + Vec_IntPush( Vec_WecEntry(vSupps, i), Gia_ObjId(pMan, pObj) ); + } + Gia_ManForEachAnd( pMan, pObj, i ) { + if ( Gia_ObjLevel(pMan, pObj) <= Level ) + continue; + int iSuppId0 = Vec_IntEntry( vSuppIds, Gia_ObjFaninId0(pObj, i) ); + int iSuppId1 = Vec_IntEntry( vSuppIds, Gia_ObjFaninId1(pObj, i) ); + if ( iSuppId0 == -1 || iSuppId1 == -1 ) { + Count++; + continue; + } + Vec_IntClear( vTemp ); + Vec_IntTwoMerge2( Vec_WecEntry(vSupps, iSuppId0), Vec_WecEntry(vSupps, iSuppId1), vTemp ); + if ( Vec_IntSize(vTemp) > nSuppMax ) { + Count++; + continue; + } + Vec_IntWriteEntry( vSuppIds, i, Vec_WecSize(vSupps) ); + Vec_IntAppend( Vec_WecPushLevel(vSupps), vTemp ); + } + // remove those supported nodes that are in the TFI cones of others + Gia_ManIncrementTravId( pMan ); + Gia_ManForEachAnd( pMan, pObj, i ) + if ( Gia_ObjLevel(pMan, pObj) > Level && Vec_IntEntry(vSuppIds, i) >= 0 && !Gia_ObjIsTravIdCurrent(pMan, pObj) ) { + Gia_ObjDfsMark_rec(pMan, pObj); + Gia_ObjSetTravIdPrevious(pMan, pObj); + } + // create the result + vResSupps = Vec_WecAlloc( 100 ); + Gia_ManForEachAnd( pMan, pObj, i ) + if ( Gia_ObjLevel(pMan, pObj) > Level && Vec_IntEntry(vSuppIds, i) >= 0 && !Gia_ObjIsTravIdCurrent(pMan, pObj) ) { + Vec_Int_t * vSupp = Vec_WecEntry( vSupps, Vec_IntEntry(vSuppIds, i) ); + if ( Vec_IntSize(vSupp) < 4 ) + continue; + Vec_Int_t * vThis = Vec_WecPushLevel( vResSupps ); + Vec_IntGrow( vThis, Vec_IntSize(vSupp) + 1 ); + Vec_IntAppend( vThis, vSupp ); + //Vec_IntPush( vThis, Gia_ObjId(pObj) ); + } + //printf( "Inputs = %d. Nodes with %d-support = %d. Nodes with larger support = %d. Selected outputs = %d.\n", + // Vec_IntSize(vBelow), nSuppMax, Vec_WecSize(vSupps), Count, Vec_WecSize(vResSupps) ); + Vec_WecFree( vSupps ); + Vec_IntFree( vSuppIds ); + Vec_IntFree( vBelow ); + Vec_IntFree( vTemp ); + return vResSupps; +} +// removes all supports that overlap with this one +void Gia_ManSelectRemove( Vec_Wec_t * vSupps, Vec_Int_t * vOne ) +{ + Vec_Int_t * vLevel; int i; + Vec_WecForEachLevel( vSupps, vLevel, i ) + if ( Vec_IntTwoCountCommon(vLevel, vOne) > 0 ) + Vec_IntClear( vLevel ); + Vec_WecRemoveEmpty( vSupps ); +} +// marks TFI/TFO of this one +void Gia_ManMarkTfiTfo( Vec_Int_t * vOne, Gia_Man_t * pMan ) +{ + int i; Gia_Obj_t * pObj; + Gia_ManForEachObjVec( vOne, pMan, pObj, i ) { + //Gia_ObjSetTravIdPrevious(pMan, pObj); + //Gia_ObjDfsMark_rec( pMan, pObj ); + Gia_ObjSetTravIdPrevious(pMan, pObj); + Gia_ObjDfsMark2_rec( pMan, pObj ); + } +} +// removes all supports that overlap with the TFI/TFO cones of this one +void Gia_ManSelectRemove2( Vec_Wec_t * vSupps, Vec_Int_t * vOne, Gia_Man_t * pMan ) +{ + Vec_Int_t * vLevel; int i, k; Gia_Obj_t * pObj; + Gia_ManForEachObjVec( vOne, pMan, pObj, i ) { + Gia_ObjSetTravIdPrevious(pMan, pObj); + Gia_ObjDfsMark_rec( pMan, pObj ); + Gia_ObjSetTravIdPrevious(pMan, pObj); + Gia_ObjDfsMark2_rec( pMan, pObj ); + } + Vec_WecForEachLevel( vSupps, vLevel, i ) { + Gia_ManForEachObjVec( vLevel, pMan, pObj, k ) + if ( Gia_ObjIsTravIdCurrent(pMan, pObj) ) + break; + if ( k < Vec_IntSize(vLevel) ) + Vec_IntClear( vLevel ); + } + Vec_WecRemoveEmpty( vSupps ); +} +// removes all supports that are contained in this one +void Gia_ManSelectRemove3( Vec_Wec_t * vSupps, Vec_Int_t * vOne ) +{ + Vec_Int_t * vLevel; int i; + Vec_WecForEachLevel( vSupps, vLevel, i ) + if ( Vec_IntTwoCountCommon(vLevel, vOne) == Vec_IntSize(vLevel) ) + Vec_IntClear( vLevel ); + Vec_WecRemoveEmpty( vSupps ); +} +Vec_Ptr_t * Gia_ManDeriveWinInsAll( Vec_Wec_t * vSupps, int nSuppMax, Gia_Man_t * pMan, int fOverlap ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( 100 ); + Gia_ManIncrementTravId( pMan ); + while ( Vec_WecSize(vSupps) > 0 ) { + int i, Item, iRand = Abc_Random(0) % Vec_WecSize(vSupps); + Vec_Int_t * vLevel, * vLevel2 = Vec_WecEntry( vSupps, iRand ); + Vec_Int_t * vCopy = Vec_IntDup( vLevel2 ); + if ( Vec_IntSize(vLevel2) == nSuppMax ) { + Vec_PtrPush( vRes, vCopy ); + if ( fOverlap ) + Gia_ManSelectRemove3( vSupps, vCopy ); + else + Gia_ManSelectRemove2( vSupps, vCopy, pMan ); + continue; + } + // find another support, which maximizes the union but does not exceed nSuppMax + int iBest = iRand, nUnion = Vec_IntSize(vCopy); + Vec_WecForEachLevel( vSupps, vLevel, i ) { + if ( i == iRand ) continue; + int nCommon = Vec_IntTwoCountCommon(vLevel, vCopy); + int nUnionCur = Vec_IntSize(vLevel) + Vec_IntSize(vCopy) - nCommon; + if ( nUnionCur <= nSuppMax && nUnion < nUnionCur ) { + nUnion = nUnionCur; + iBest = i; + } + } + vLevel = Vec_WecEntry( vSupps, iBest ); + Vec_IntForEachEntry( vLevel, Item, i ) + Vec_IntPushUniqueOrder( vCopy, Item ); + Vec_PtrPush( vRes, vCopy ); + if ( fOverlap ) + Gia_ManSelectRemove3( vSupps, vCopy ); + else + Gia_ManSelectRemove2( vSupps, vCopy, pMan ); + } + return vRes; +} +Gia_Man_t * Gia_ManDupFromArrays( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( 5000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vCis, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vCos, p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); + return pNew; +} +Vec_Ptr_t * Gia_ManDupWindows( Gia_Man_t * pMan, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvNodes, Vec_Ptr_t * vvOuts ) +{ + Vec_Int_t * vNodes; int i; + Vec_Ptr_t * vWins = Vec_PtrAlloc( Vec_PtrSize(vvIns) ); + assert( Vec_PtrSize(vvIns) == Vec_PtrSize(vvNodes) ); + assert( Vec_PtrSize(vvOuts) == Vec_PtrSize(vvNodes) ); + Gia_ManFillValue( pMan ); + Gia_ManCleanMark01( pMan ); + Vec_PtrForEachEntry( Vec_Int_t *, vvNodes, vNodes, i ) { + Vec_Int_t * vIns = (Vec_Int_t *)Vec_PtrEntry(vvIns, i); + Vec_Int_t * vOuts = (Vec_Int_t *)Vec_PtrEntry(vvOuts, i); + Gia_Man_t * pNew = Gia_ManDupFromArrays( pMan, vIns, vNodes, vOuts ); + Vec_PtrPush( vWins, pNew ); + } + return vWins; +} +int Gia_ManLevelR( Gia_Man_t * pMan ) +{ + int i, LevelMax = Gia_ManLevelRNum( pMan ); + Gia_Obj_t * pNode; + Gia_ManForEachObj( pMan, pNode, i ) + Gia_ObjSetLevel( pMan, pNode, (int)(LevelMax - Gia_ObjLevel(pMan, pNode) + 1) ); + Gia_ManForEachCi( pMan, pNode, i ) + Gia_ObjSetLevel( pMan, pNode, 0 ); + return LevelMax; +} +Vec_Ptr_t * Gia_ManExtractPartitions( Gia_Man_t * pMan, int Iter, int nSuppMax, Vec_Ptr_t ** pvIns, Vec_Ptr_t ** pvOuts, Vec_Ptr_t ** pvNodes, int fOverlap ) +{ + // if ( Gia_ManCiNum(pMan) <= nSuppMax ) { + // Vec_Ptr_t * vWins = Vec_PtrAlloc( 1 ); + // Vec_PtrPush( vWins, Gia_ManDupDfs(pMan) ); + // *pvIns = *pvOuts = *pvNodes = NULL; + // return vWins; + // } + // int iUseRevL = Iter % 3 == 0 ? 0 : Abc_Random(0) & 1; + int iUseRevL = Abc_Random(0) & 1; + int LevelMax = iUseRevL ? Gia_ManLevelR(pMan) : Gia_ManLevelNum(pMan); + // int LevelCut = Iter % 3 == 0 ? 0 : LevelMax > 8 ? 2 + (Abc_Random(0) % (LevelMax - 4)) : 0; + int LevelCut = LevelMax > 8 ? (Abc_Random(0) % (LevelMax - 4)) : 0; + //printf( "Using %s cut level %d (out of %d)\n", iUseRevL ? "reverse": "direct", LevelCut, LevelMax ); + // Gia_ManPermuteLevel( pMan, LevelMax ); + Vec_Wec_t * vStore = Vec_WecStart( LevelMax+1 ); + Vec_Wec_t * vSupps = Gia_ManCollectObjectsWithSuppLimit( pMan, LevelCut, nSuppMax ); + Vec_Ptr_t * vIns = Gia_ManDeriveWinInsAll( vSupps, nSuppMax, pMan, fOverlap ); + Vec_Ptr_t * vNodes = Gia_ManDeriveWinNodesAll( pMan, vIns, vStore ); + Vec_Ptr_t * vOuts = Gia_ManDeriveWinOutsAll( pMan, vNodes ); + Vec_Ptr_t * vWins = Gia_ManDupWindows( pMan, vIns, vNodes, vOuts ); + Vec_WecFree( vSupps ); + Vec_WecFree( vStore ); + *pvIns = vIns; + *pvOuts = vOuts; + *pvNodes = vNodes; + return vWins; +} + + + /**Function************************************************************* Synopsis [] @@ -358,7 +785,8 @@ Vec_Ptr_t * Gia_ManDupDivide( Gia_Man_t * p, Vec_Wec_t * vCis, Vec_Wec_t * vAnds Vec_PtrPush( vAigs, Gia_ManDupDivideOne(p, Vec_WecEntry(vCis, i), Vec_WecEntry(vAnds, i), Vec_WecEntry(vCos, i)) ); } //Gia_ManStochSynthesis( vAigs, pScript ); - Gia_StochProcess( vAigs, pScript, nProcs, TimeOut, 0 ); + Vec_Int_t * vGains = Gia_StochProcess( vAigs, pScript, nProcs, TimeOut, 0 ); + Vec_IntFree( vGains ); return vAigs; } Gia_Man_t * Gia_ManDupStitch( Gia_Man_t * p, Vec_Wec_t * vCis, Vec_Wec_t * vAnds, Vec_Wec_t * vCos, Vec_Ptr_t * vAigs, int fHash ) @@ -554,7 +982,7 @@ Vec_Wec_t * Gia_ManStochOutputs( Gia_Man_t * p, Vec_Wec_t * vAnds ) SeeAlso [] ***********************************************************************/ -void Gia_ManStochSyn( int nMaxSize, int nIters, int TimeOut, int Seed, int fVerbose, char * pScript, int nProcs ) +void Gia_ManStochSyn( int nSuppMax, int nMaxSize, int nIters, int TimeOut, int Seed, int fVerbose, char * pScript, int nProcs ) { abctime nTimeToStop = TimeOut ? Abc_Clock() + TimeOut * CLOCKS_PER_SEC : 0; abctime clkStart = Abc_Clock(); @@ -564,43 +992,83 @@ void Gia_ManStochSyn( int nMaxSize, int nIters, int TimeOut, int Seed, int fVerb Abc_Random(1); for ( i = 0; i < 10+Seed; i++ ) Abc_Random(0); - if ( fVerbose ) - printf( "Running %d iterations of script \"%s\".\n", nIters, pScript ); - for ( i = 0; i < nIters; i++ ) - { - abctime clk = Abc_Clock(); - Gia_Man_t * pGia = Gia_ManDupWithMapping( Abc_FrameReadGia(Abc_FrameGetGlobalFrame()) ); - Vec_Wec_t * vAnds = Gia_ManStochNodes( pGia, nMaxSize, Abc_Random(0) & 0x7FFFFFFF ); - Vec_Wec_t * vIns = Gia_ManStochInputs( pGia, vAnds ); - Vec_Wec_t * vOuts = Gia_ManStochOutputs( pGia, vAnds ); - Vec_Ptr_t * vAigs = Gia_ManDupDivide( pGia, vIns, vAnds, vOuts, pScript, nProcs, TimeOut ); - Gia_Man_t * pNew = Gia_ManDupStitchMap( pGia, vIns, vAnds, vOuts, vAigs ); - int fMapped = Gia_ManHasMapping(pGia) && Gia_ManHasMapping(pNew); - Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); - if ( fVerbose ) - printf( "Iteration %3d : Using %3d partitions. Reducing %6d to %6d %s. ", - i, Vec_PtrSize(vAigs), fMapped ? Gia_ManLutNum(pGia) : Gia_ManAndNum(pGia), - fMapped ? Gia_ManLutNum(pNew) : Gia_ManAndNum(pNew), - fMapped ? "LUTs" : "ANDs" ); - if ( fVerbose ) - Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); - Gia_ManStop( pGia ); - Vec_PtrFreeFunc( vAigs, (void (*)(void *)) Gia_ManStop ); - Vec_WecFree( vAnds ); - Vec_WecFree( vIns ); - Vec_WecFree( vOuts ); - if ( nTimeToStop && Abc_Clock() > nTimeToStop ) + if ( fVerbose ) { + printf( "Running %d iterations of the script \"%s\"", nIters, pScript ); + if ( nProcs > 2 ) + printf( " using %d concurrent threads.\n", nProcs-1 ); + else + printf( " without concurrency.\n" ); + fflush(stdout); + } + if ( !nSuppMax ) { + for ( i = 0; i < nIters; i++ ) { - printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i ); - break; + abctime clk = Abc_Clock(); + Gia_Man_t * pGia = Gia_ManDupWithMapping( Abc_FrameReadGia(Abc_FrameGetGlobalFrame()) ); + Vec_Wec_t * vAnds = Gia_ManStochNodes( pGia, nMaxSize, Abc_Random(0) & 0x7FFFFFFF ); + Vec_Wec_t * vIns = Gia_ManStochInputs( pGia, vAnds ); + Vec_Wec_t * vOuts = Gia_ManStochOutputs( pGia, vAnds ); + Vec_Ptr_t * vAigs = Gia_ManDupDivide( pGia, vIns, vAnds, vOuts, pScript, nProcs, TimeOut ); + Gia_Man_t * pNew = Gia_ManDupStitchMap( pGia, vIns, vAnds, vOuts, vAigs ); + int fMapped = Gia_ManHasMapping(pGia) && Gia_ManHasMapping(pNew); + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); + if ( fVerbose ) + printf( "Iteration %3d : Using %3d partitions. Reducing %6d to %6d %s. ", + i, Vec_PtrSize(vAigs), fMapped ? Gia_ManLutNum(pGia) : Gia_ManAndNum(pGia), + fMapped ? Gia_ManLutNum(pNew) : Gia_ManAndNum(pNew), + fMapped ? "LUTs" : "ANDs" ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + Gia_ManStop( pGia ); + Vec_PtrFreeFunc( vAigs, (void (*)(void *)) Gia_ManStop ); + Vec_WecFree( vAnds ); + Vec_WecFree( vIns ); + Vec_WecFree( vOuts ); + if ( nTimeToStop && Abc_Clock() > nTimeToStop ) + { + printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i ); + break; + } + } + } + else { + int fOverlap = 1; + Vec_Ptr_t * vIns = NULL, * vOuts = NULL, * vNodes = NULL; + for ( i = 0; i < nIters; i++ ) + { + extern Gia_Man_t * Gia_ManDupInsertWindows( Gia_Man_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vAigs ); + abctime clk = Abc_Clock(); + Gia_Man_t * pGia = Gia_ManDup( Abc_FrameReadGia(Abc_FrameGetGlobalFrame()) ); Gia_ManStaticFanoutStart(pGia); + Vec_Ptr_t * vAigs = Gia_ManExtractPartitions( pGia, i, nSuppMax, &vIns, &vOuts, &vNodes, fOverlap ); + Vec_Int_t * vGains = Gia_StochProcess( vAigs, pScript, nProcs, TimeOut, 0 ); + int nPartsInit = fOverlap ? Gia_ManFilterPartitions( pGia, vIns, vNodes, vOuts, vAigs, vGains ) : Vec_PtrSize(vIns); + Gia_Man_t * pNew = Gia_ManDupInsertWindows( pGia, vIns, vOuts, vAigs ); Gia_ManStaticFanoutStop(pGia); + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); + if ( fVerbose ) + printf( "Iteration %3d : Using %3d -> %3d partitions. Reducing node count from %6d to %6d. ", + i, nPartsInit, Vec_PtrSize(vAigs), Gia_ManAndNum(pGia), Gia_ManAndNum(pNew) ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + // cleanup + Gia_ManStop( pGia ); + Vec_PtrFreeFunc( vAigs, (void (*)(void *)) Gia_ManStop ); + Vec_IntFreeP( &vGains ); + if ( vIns ) Vec_PtrFreeFunc( vIns, (void (*)(void *)) Vec_IntFree ); + if ( vOuts ) Vec_PtrFreeFunc( vOuts, (void (*)(void *)) Vec_IntFree ); + if ( vNodes ) Vec_PtrFreeFunc( vNodes, (void (*)(void *)) Vec_IntFree ); + if ( nTimeToStop && Abc_Clock() > nTimeToStop ) + { + printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i ); + break; + } } } fMapped &= Gia_ManHasMapping(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); nLutEnd = fMapped ? Gia_ManLutNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())) : 0; nEnd = Gia_ManAndNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); if ( fVerbose ) - printf( "Cumulatively reduced %d %s after %d iterations. ", - fMapped ? nLutBeg - nLutEnd : nBeg - nEnd, fMapped ? "LUTs" : "ANDs", nIters ); + printf( "Cumulatively reduced %d %s (%.2f %%) after %d iterations. ", + fMapped ? nLutBeg - nLutEnd : nBeg - nEnd, fMapped ? "LUTs" : "nodes", 100.0*(nBeg - nEnd)/Abc_MaxInt(nBeg, 1), nIters ); if ( fVerbose ) Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); } diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index a5f22d2fc..4eec2d4b2 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -53488,10 +53488,10 @@ usage: ***********************************************************************/ int Abc_CommandAbc9StochSyn( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Gia_ManStochSyn( int nMaxSize, int nIters, int TimeOut, int Seed, int fVerbose, char * pScript, int nProcs ); - int c, nMaxSize = 1000, nIters = 10, TimeOut = 0, Seed = 0, nProcs = 1, fVerbose = 0; char * pScript; + extern void Gia_ManStochSyn( int nSuppMax, int nMaxSize, int nIters, int TimeOut, int Seed, int fVerbose, char * pScript, int nProcs ); + int c, nSuppMax = 0, nMaxSize = 1000, nIters = 10, TimeOut = 0, Seed = 0, nProcs = 1, fVerbose = 0; char * pScript; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NITSPvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "NMITSPvh" ) ) != EOF ) { switch ( c ) { @@ -53501,6 +53501,17 @@ int Abc_CommandAbc9StochSyn( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } + nSuppMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSuppMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } nMaxSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nMaxSize < 0 ) @@ -53570,14 +53581,15 @@ int Abc_CommandAbc9StochSyn( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } pScript = Abc_UtilStrsav( argv[globalUtilOptind] ); - Gia_ManStochSyn( nMaxSize, nIters, TimeOut, Seed, fVerbose, pScript, nProcs ); + Gia_ManStochSyn( nSuppMax, nMaxSize, nIters, TimeOut, Seed, fVerbose, pScript, nProcs ); ABC_FREE( pScript ); return 0; usage: - Abc_Print( -2, "usage: &stochsyn [-NITSP ] [-tvh]