From 136bae27d890cf9eb71f16200107cef6e2fa64f7 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Sat, 16 Sep 2023 19:43:03 +0800 Subject: [PATCH 001/133] Refactor(Typo): Typo update in read_aiger comment --- src/base/io/ioReadAiger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/io/ioReadAiger.c b/src/base/io/ioReadAiger.c index 9cf41413d..93cfef2da 100644 --- a/src/base/io/ioReadAiger.c +++ b/src/base/io/ioReadAiger.c @@ -433,7 +433,7 @@ Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ) else { assert( Init == Abc_Var2Lit(1+Abc_NtkPiNum(pNtkNew)+i, 0) ); - // unitialized value of the latch is the latch literal according to http://fmv.jku.at/hwmcc11/beyond1.pdf + // uninitialized value of the latch is the latch literal according to http://fmv.jku.at/hwmcc11/beyond1.pdf Abc_LatchSetInitDc( Abc_NtkBox(pNtkNew, i) ); } while ( *pCur != ' ' && *pCur != '\n' ) pCur++; From 6e1323caa2ec4b37cfc689c385ae4fd9c6d507d5 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Sat, 16 Sep 2023 22:31:47 +0800 Subject: [PATCH 002/133] Refactor(Typo): Typo update in bblif comment --- src/misc/bbl/bblif.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc/bbl/bblif.h b/src/misc/bbl/bblif.h index b48593701..af6025da3 100644 --- a/src/misc/bbl/bblif.h +++ b/src/misc/bbl/bblif.h @@ -237,7 +237,7 @@ extern void Bbl_ManDumpBinaryBlif( Bbl_Man_t * p, char * pFileName ); // (3) reading the data manager from file extern Bbl_Man_t * Bbl_ManReadBinaryBlif( char * pFileName ); -// (4) returning the mapped network after reading the data manaager from file +// (4) returning the mapped network after reading the data manager from file extern char * Bbl_ManName( Bbl_Man_t * p ); extern int Bbl_ObjIsInput( Bbl_Obj_t * p ); extern int Bbl_ObjIsOutput( Bbl_Obj_t * p ); From 7ec8f170949ea44bda3c9ab2b3235cb6bfa45a77 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Sun, 17 Sep 2023 13:27:00 +0800 Subject: [PATCH 003/133] Refactor(Typo): Typo update in write_aiger message --- src/base/io/ioWriteAiger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base/io/ioWriteAiger.c b/src/base/io/ioWriteAiger.c index 0a68c7eec..cad335d4f 100644 --- a/src/base/io/ioWriteAiger.c +++ b/src/base/io/ioWriteAiger.c @@ -680,7 +680,7 @@ void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int f b.f = fopen( pFileName, "wb" ); if ( b.f == NULL ) { - fprintf( stdout, "Ioa_WriteBlif(): Cannot open the output file \"%s\".\n", pFileName ); + fprintf( stdout, "Io_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); ABC_FREE(b.buf); return; } @@ -688,7 +688,7 @@ void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int f b.b = BZ2_bzWriteOpen( &bzError, b.f, 9, 0, 0 ); if ( bzError != BZ_OK ) { BZ2_bzWriteClose( &bzError, b.b, 0, NULL, NULL ); - fprintf( stdout, "Ioa_WriteBlif(): Cannot start compressed stream.\n" ); + fprintf( stdout, "Io_WriteAiger(): Cannot start compressed stream.\n" ); fclose( b.f ); ABC_FREE(b.buf); return; From 05c897a7534d2bfa9f30c58306bd344a0f028afc Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Sun, 17 Sep 2023 19:34:56 +0800 Subject: [PATCH 004/133] Refactor(Typo): Typo in read_aiger --- src/base/io/ioReadAiger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/io/ioReadAiger.c b/src/base/io/ioReadAiger.c index 93cfef2da..200247bbd 100644 --- a/src/base/io/ioReadAiger.c +++ b/src/base/io/ioReadAiger.c @@ -440,7 +440,7 @@ Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ) } if ( *pCur != '\n' ) { - fprintf( stdout, "The initial value of latch number %d is not recongnized.\n", i ); + fprintf( stdout, "The initial value of latch number %d is not recognized.\n", i ); return NULL; } pCur++; From eae19f7a626f81378d50694fc21cb221e1c82a74 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Mon, 18 Sep 2023 13:56:18 +0800 Subject: [PATCH 005/133] Refactor(Typo): Typo in strash --- 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 4bb3a4344..4fe3e0014 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -3775,7 +3775,7 @@ usage: Abc_Print( -2, "usage: strash [-acrih]\n" ); Abc_Print( -2, "\t transforms combinational logic into an AIG\n" ); Abc_Print( -2, "\t-a : toggles between using all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "DFS" ); - Abc_Print( -2, "\t-c : toggles cleanup to remove the dagling AIG nodes [default = %s]\n", fCleanup? "all": "DFS" ); + Abc_Print( -2, "\t-c : toggles cleanup to remove the dangling AIG nodes [default = %s]\n", fCleanup? "all": "DFS" ); Abc_Print( -2, "\t-r : toggles using the record of AIG subgraphs [default = %s]\n", fRecord? "yes": "no" ); Abc_Print( -2, "\t-i : toggles complementing the POs of the AIG [default = %s]\n", fComplOuts? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); From 3781c1df612a45bbebe041cd1af2ec1d3b2d44ff Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Sun, 24 Sep 2023 19:31:37 +0800 Subject: [PATCH 006/133] Refactor(Typo): Link is NOT FOUND page(not available), change to the book name --- src/base/abci/abc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 4fe3e0014..c99956149 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -9343,8 +9343,7 @@ usage: Abc_Print( -2, "\t synthesizes the smallest circuit composed of two-input gates\n" ); Abc_Print( -2, "\t for the only NPN class of 5-input functions that requires 12 gates;\n" ); Abc_Print( -2, "\t all other functions can be realized with 11 two-input gates or less\n" ); - Abc_Print( -2, "\t (see Section 7.1.2 \"Boolean evaluation\" in the book by Donald Knuth\n" ); - Abc_Print( -2, "\t http://www.cs.utsa.edu/~wagner/knuth/fasc0c.pdf)\n" ); + Abc_Print( -2, "\t (see Section 7.1.2 \"Boolean evaluation\" in the book The Art of Computer Programming by Donald Knuth)\n" ); return 1; } From ecf6255985f162cb26e3f4e33de28bf94728c77d Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Tue, 26 Sep 2023 14:24:02 +0800 Subject: [PATCH 007/133] Refactor(Typo):Missing a parameter fUseLutLib and use fSaveBest twice --- 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 c99956149..70f83bf62 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -1547,7 +1547,7 @@ usage: Abc_Print( -2, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" ); Abc_Print( -2, "\t-b : toggles saving the best logic network in \"best.blif\" [default = %s]\n", fSaveBest? "yes": "no" ); Abc_Print( -2, "\t-d : toggles dumping statistics about the network into file [default = %s]\n", fDumpResult? "yes": "no" ); - Abc_Print( -2, "\t-l : toggles printing delay of LUT mapping using LUT library [default = %s]\n", fSaveBest? "yes": "no" ); + Abc_Print( -2, "\t-l : toggles printing delay of LUT mapping using LUT library [default = %s]\n", fUseLutLib? "yes": "no" ); Abc_Print( -2, "\t-t : toggles printing runtime statistics [default = %s]\n", fPrintTime? "yes": "no" ); Abc_Print( -2, "\t-m : toggles printing MUX statistics [default = %s]\n", fPrintMuxes? "yes": "no" ); Abc_Print( -2, "\t-p : toggles printing power dissipation due to switching [default = %s]\n", fPower? "yes": "no" ); From 6836863e55356ebcb70e3984d6493cb217e0c142 Mon Sep 17 00:00:00 2001 From: phsauter Date: Wed, 27 Sep 2023 18:16:59 +0200 Subject: [PATCH 008/133] Fix Segault in scl Fixes a regression that was introduced in #232 by myself. Reverts back to correct version introduced in #228. This was likely introduced in a careless merge before creating PR #232. --- src/map/scl/sclSize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/map/scl/sclSize.c b/src/map/scl/sclSize.c index e09c56e67..97955210e 100644 --- a/src/map/scl/sclSize.c +++ b/src/map/scl/sclSize.c @@ -200,7 +200,7 @@ void Abc_SclTimeNtkPrint( SC_Man * p, int fShowAll, int fPrintPath ) while ( pObj && Abc_ObjIsNode(pObj) ) { i++; - nLength = Abc_MaxInt( nLength, strlen(Abc_SclObjCell(pObj)->pName) ); + nLength = Abc_MaxInt( nLength, Abc_SclObjCell(pObj) ? strlen(Abc_SclObjCell(pObj)->pName) : 2 /* strlen("pi") */ ); pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj ); } From c2fdb86a4db8d3d37f2963787589289d1802ac16 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Sat, 7 Oct 2023 13:53:22 +0800 Subject: [PATCH 009/133] Refactor(Typo): Typo in ACD --- src/base/abci/abcLutmin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base/abci/abcLutmin.c b/src/base/abci/abcLutmin.c index 11605eb14..8a4e679ab 100644 --- a/src/base/abci/abcLutmin.c +++ b/src/base/abci/abcLutmin.c @@ -430,10 +430,10 @@ Abc_Obj_t * Abc_NtkBddCurtis( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t int b, c, u, i; assert( nBits + 2 <= nLutSize ); assert( nLutSize < Abc_ObjFaninNum(pNode) ); - // start BDDs for the decompoosed blocks + // start BDDs for the decomposed blocks for ( b = 0; b < nBits; b++ ) bBits[b] = Cudd_ReadLogicZero(ddNew), Cudd_Ref( bBits[b] ); - // add each bound set minterm to one of the blccks + // add each bound set minterm to one of the blocks Vec_PtrForEachEntry( DdNode *, vCofs, bCof, c ) { Vec_PtrForEachEntry( DdNode *, vUniq, bUniq, u ) From cd711089d72adb027b93b0860ba45387c239807e Mon Sep 17 00:00:00 2001 From: Mahesh Madhav Date: Tue, 3 Sep 2024 04:30:14 +0000 Subject: [PATCH 010/133] Perf improvement in satsolver Switch one FP divide to an FP multiply (variable is constant). Calculate ratio inside of verbosity clause, since that is where it is used. --- src/sat/bsat/satSolver.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/sat/bsat/satSolver.c b/src/sat/bsat/satSolver.c index eea280293..ebb6fcce1 100644 --- a/src/sat/bsat/satSolver.c +++ b/src/sat/bsat/satSolver.c @@ -62,7 +62,8 @@ static inline double drand(double* seed) { *seed *= 1389796; q = (int)(*seed / 2147483647); *seed -= (double)q * 2147483647; - return *seed / 2147483647; } + return *seed * 4.6566128752457969e-10; // 1.0/2147483647.0 +} // Returns a random integer 0 <= x < size. Seed must never be 0. @@ -1954,12 +1955,12 @@ int sat_solver_solve_internal(sat_solver* s) while (status == l_Undef){ ABC_INT64_T nof_conflicts; - double Ratio = (s->stats.learnts == 0)? 0.0 : - s->stats.learnts_literals / (double)s->stats.learnts; if ( s->nRuntimeLimit && Abc_Clock() > s->nRuntimeLimit ) break; if (s->verbosity >= 1) { + double Ratio = (s->stats.learnts == 0)? 0.0 : + s->stats.learnts_literals / (double)s->stats.learnts; printf("| %9.0f | %7.0f %8.0f | %7.0f %7.0f %8.0f %7.1f | %6.3f %% |\n", (double)s->stats.conflicts, (double)s->stats.clauses, From ad8f8a2aabb7531df5a8ec6091494da2462a4f6a Mon Sep 17 00:00:00 2001 From: Mahesh Madhav Date: Tue, 3 Sep 2024 04:48:07 +0000 Subject: [PATCH 011/133] Convert the other divide to a multiply --- src/sat/bsat/satSolver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sat/bsat/satSolver.c b/src/sat/bsat/satSolver.c index ebb6fcce1..6b246a2e6 100644 --- a/src/sat/bsat/satSolver.c +++ b/src/sat/bsat/satSolver.c @@ -60,7 +60,7 @@ static void printlits(lit* begin, lit* end) static inline double drand(double* seed) { int q; *seed *= 1389796; - q = (int)(*seed / 2147483647); + q = (int)(*seed * 4.6566128752457969e-10); // 1.0/2147483647.0; *seed -= (double)q * 2147483647; return *seed * 4.6566128752457969e-10; // 1.0/2147483647.0 } From 2e3384390a6cc4896bbaeb3453995abfafa0b9bc Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 7 Oct 2024 14:10:02 +0700 Subject: [PATCH 012/133] Updating "lutexact" to run on symmetric functions. --- src/base/abci/abc.c | 23 +++++++++++++++++++---- src/sat/bmc/bmc.h | 3 ++- src/sat/bmc/bmcMaj.c | 14 +++++++++++++- src/sat/bmc/bmcMaj2.c | 14 +++++++++++++- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 3c560b71e..dce8cec1f 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -9810,7 +9810,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, "INKTiaocgvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INKTSiaocgvh" ) ) != EOF ) { switch ( c ) { @@ -9858,6 +9858,15 @@ 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 a file name.\n" ); + goto usage; + } + pPars->pSymStr = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'i': pPars->fUseIncr ^= 1; break; @@ -9884,16 +9893,21 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( argc == globalUtilOptind + 1 ) pPars->pTtStr = argv[globalUtilOptind]; - if ( pPars->pTtStr == NULL ) + if ( pPars->pTtStr == NULL && pPars->pSymStr == NULL ) { Abc_Print( -1, "Truth table should be given on the command line.\n" ); return 1; } - if ( (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) + if ( pPars->pTtStr && (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) { Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (pPars->nVars-2)), strlen(pPars->pTtStr) ); return 1; } + if ( pPars->pSymStr && pPars->nVars+1 != strlen(pPars->pSymStr) ) + { + Abc_Print( -1, "The char string of the %d-variable symmetric function should have %d zeros and ones (instead of %d).\n", pPars->nVars, pPars->nVars+1, strlen(pPars->pSymStr) ); + return 1; + } if ( pPars->nVars > pPars->nNodes * (pPars->nLutSize - 1) + 1 ) { Abc_Print( -1, "Function with %d variales cannot be implemented with %d %d-input LUTs.\n", pPars->nVars, pPars->nNodes, pPars->nLutSize ); @@ -9916,12 +9930,13 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutexact [-INKT ] [-iaocgvh] \n" ); + Abc_Print( -2, "usage: lutexact [-INKT ] [-S 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 ); Abc_Print( -2, "\t-K : the number of node fanins [default = %d]\n", pPars->nLutSize ); Abc_Print( -2, "\t-T : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); + Abc_Print( -2, "\t-S : 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 795296e6f..11578a56b 100644 --- a/src/sat/bmc/bmc.h +++ b/src/sat/bmc/bmc.h @@ -66,6 +66,7 @@ struct Bmc_EsPar_t_ int RuntimeLim; int fVerbose; char * pTtStr; + char * pSymStr; }; static inline void Bmc_EsParSetDefault( Bmc_EsPar_t * pPars ) @@ -88,7 +89,7 @@ static inline void Bmc_EsParSetDefault( Bmc_EsPar_t * pPars ) pPars->fUniqFans = 0; pPars->fLutCascade = 0; pPars->RuntimeLim = 0; - pPars->fVerbose = 1; + pPars->fVerbose = 0; } diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index b6ff80a58..f89d74ea1 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -1504,7 +1504,17 @@ void Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) int i, status, iMint = 1; abctime clkTotal = Abc_Clock(); Exa3_Man_t * p; int fCompl = 0; - word pTruth[16]; Abc_TtReadHex( pTruth, pPars->pTtStr ); + word pTruth[16]; + if ( pPars->pSymStr ) { + word * pFun = Abc_TtSymFunGenerate( pPars->pSymStr, pPars->nVars ); + pPars->pTtStr = ABC_CALLOC( char, pPars->nVars > 2 ? (1 << (pPars->nVars-2)) + 1 : 2 ); + Extra_PrintHexadecimalString( pPars->pTtStr, (unsigned *)pFun, pPars->nVars ); + printf( "Generated symmetric function: %s\n", pPars->pTtStr ); + ABC_FREE( pFun ); + } + if ( pPars->pTtStr ) + Abc_TtReadHex( pTruth, pPars->pTtStr ); + else assert( 0 ); assert( pPars->nVars <= 10 ); assert( pPars->nLutSize <= 6 ); p = Exa3_ManAlloc( pPars, pTruth ); @@ -1541,6 +1551,8 @@ void Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); if ( iMint == -1 ) Exa3_ManDumpBlif( p, fCompl ); + if ( pPars->pSymStr ) + ABC_FREE( pPars->pTtStr ); Exa3_ManFree( p ); } diff --git a/src/sat/bmc/bmcMaj2.c b/src/sat/bmc/bmcMaj2.c index 8becc6321..665b61611 100644 --- a/src/sat/bmc/bmcMaj2.c +++ b/src/sat/bmc/bmcMaj2.c @@ -1387,7 +1387,17 @@ void Exa3_ManExactSynthesis2( Bmc_EsPar_t * pPars ) int i, status, iMint = 1; abctime clkTotal = Abc_Clock(); Exa3_Man_t * p; int fCompl = 0; - word pTruth[16]; Abc_TtReadHex( pTruth, pPars->pTtStr ); + word pTruth[16]; + if ( pPars->pSymStr ) { + word * pFun = Abc_TtSymFunGenerate( pPars->pSymStr, pPars->nVars ); + pPars->pTtStr = ABC_CALLOC( char, pPars->nVars > 2 ? (1 << (pPars->nVars-2)) + 1 : 2 ); + Extra_PrintHexadecimalString( pPars->pTtStr, (unsigned *)pFun, pPars->nVars ); + printf( "Generated symmetric function: %s\n", pPars->pTtStr ); + ABC_FREE( pFun ); + } + if ( pPars->pTtStr ) + Abc_TtReadHex( pTruth, pPars->pTtStr ); + else assert( 0 ); assert( pPars->nVars <= 10 ); assert( pPars->nLutSize <= 6 ); p = Exa3_ManAlloc( pPars, pTruth ); @@ -1422,6 +1432,8 @@ void Exa3_ManExactSynthesis2( Bmc_EsPar_t * pPars ) Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); if ( iMint == -1 ) Exa3_ManDumpBlif( p, fCompl ); + if ( pPars->pSymStr ) + ABC_FREE( pPars->pTtStr ); Exa3_ManFree( p ); } From 707442e0915dd7fdbfc5742b04ef16429373075a Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 8 Oct 2024 10:01:29 +0700 Subject: [PATCH 013/133] Bug fix in &scorr. --- src/aig/gia/giaEquiv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/aig/gia/giaEquiv.c b/src/aig/gia/giaEquiv.c index 09def827d..e4f5a0d25 100644 --- a/src/aig/gia/giaEquiv.c +++ b/src/aig/gia/giaEquiv.c @@ -2770,7 +2770,10 @@ void Gia_ManTransferEquivs2( Gia_Man_t * p, Gia_Man_t * pOld ) { Vec_IntClear( vClass ); Gia_ClassForEachObj( p, i, k ) - Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) ); + if ( (int)Gia_ManObj(p, k)->Value >= 0 ) + Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) ); + if ( Vec_IntSize( vClass ) <= 1 ) + continue; assert( Vec_IntSize( vClass ) > 1 ); Vec_IntSort( vClass, 0 ); iRepr = Vec_IntEntry( vClass, 0 ); From 46f2300b7b055138f237c0eff0d85afe49d5de1c Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 15 Oct 2024 14:45:09 +0200 Subject: [PATCH 014/133] Performance improvements in ACD --- src/map/if/acd/ac_decomposition.hpp | 65 ++++++++++++++++------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index c6a526e08..4d87923db 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -294,6 +294,7 @@ private: pst->num_luts = best_multiplicity <= 2 ? 2 : best_multiplicity <= 4 ? 3 : best_multiplicity <= 8 ? 4 : 5; + pst->num_edges = ( pst->num_luts - 1 ) * ( num_vars - best_free_set ) + ( pst->num_luts - 1 ) + best_free_set; } return true; @@ -510,7 +511,7 @@ private: } } while ( combinations_offset_next( free_set_size, offset, pComb, pInvPerm, tt ) ); - std::array res_perm = {0}; + std::array res_perm; if ( best_cost > ( 1 << ( ps.lut_size - free_set_size ) ) ) { @@ -543,7 +544,7 @@ private: } /* enumerate combinations */ - std::array res_perm = {0}; + std::array res_perm; do { @@ -803,31 +804,43 @@ private: } } support_minimization_encodings = std::vector>( num_combs ); - generate_support_minimization_encodings_rec( 0, 0, 0, count ); + generate_support_minimization_encodings_rec( 0, 0, 0, count, best_multiplicity >> 1, true ); + assert( count == num_combs ); + return; } - else if ( best_multiplicity > 8 ) + + /* constraint the number of offset classes for a strict encoding */ + int32_t min_set_size = 1; + if ( best_multiplicity <= 4 ) + min_set_size = 2; + else if ( best_multiplicity <= 8 ) + min_set_size = 4; + else + min_set_size = 8; + min_set_size = best_multiplicity - min_set_size; + + if ( best_multiplicity > 8 ) { - /* combinations are 2^(mu - 1) */ - num_combs = 1u << ( best_multiplicity - 1 ); + /* distinct elements in 2 indistinct bins with at least `min_set_size` elements in the indistinct bins */ + uint32_t class_sizes[13] = { 3, 3, 15, 25, 35, 35, 255, 501, 957, 1749, 3003, 4719, 6435 }; + num_combs = class_sizes[best_multiplicity - 3]; support_minimization_encodings = std::vector>( num_combs ); - generate_support_minimization_encodings_rec( 0, 0, 0, count ); + generate_support_minimization_encodings_rec( 0, 0, 0, count, min_set_size, true ); } else { - /* combinations are 2*3^(mu - 1) */ - for ( uint32_t i = 1; i < best_multiplicity; ++i ) - { - num_combs = ( num_combs << 1 ) + num_combs; - } + /* distinct elements in 3 bins, of which 2 are indistinct, and with at least `min_set_size` elements in the indistinct bins */ + uint32_t class_sizes[13] = { 6, 3, 90, 130, 105, 35, 9330, 23436, 48708, 78474, 91377, 70785, 32175 }; + num_combs = class_sizes[best_multiplicity - 3]; support_minimization_encodings = std::vector>( num_combs ); - generate_support_minimization_encodings_rec( 0, 0, 0, count ); + generate_support_minimization_encodings_rec( 0, 0, 0, count, min_set_size, true ); } assert( count == num_combs ); } template - void generate_support_minimization_encodings_rec( uint32_t onset, uint32_t offset, uint32_t var, uint32_t& count ) + void generate_support_minimization_encodings_rec( uint32_t onset, uint32_t offset, uint32_t var, uint32_t& count, int32_t min_set_size, bool first ) { if ( var == best_multiplicity ) { @@ -839,6 +852,11 @@ private: return; } } + else if ( __builtin_popcount( onset ) < min_set_size || __builtin_popcount( offset ) < min_set_size ) + { + /* ON-set and OFF-set must be populated with at least min_set_size elements */ + return; + } support_minimization_encodings[count][0] = onset; support_minimization_encodings[count][1] = offset; @@ -849,23 +867,23 @@ private: /* var in DCSET */ if ( enable_dcset ) { - generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + generate_support_minimization_encodings_rec( onset, offset, var + 1, count, min_set_size, first ); } /* move var in ONSET */ onset |= 1 << var; - generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + generate_support_minimization_encodings_rec( onset, offset, var + 1, count, min_set_size, false ); onset &= ~( 1 << var ); /* remove symmetries */ - if ( var == 0 ) + if ( first ) { return; } /* move var in OFFSET */ offset |= 1 << var; - generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + generate_support_minimization_encodings_rec( onset, offset, var + 1, count, min_set_size, false ); offset &= ~( 1 << var ); } @@ -1016,15 +1034,6 @@ private: uint32_t const onset = support_minimization_encodings[i][0]; uint32_t const offset = support_minimization_encodings[i][1]; - uint32_t ones_onset = __builtin_popcount( onset ); - uint32_t ones_offset = __builtin_popcount( offset ); - - /* filter columns that do not distinguish pairs */ - if ( ones_onset == 0 || ones_offset == 0 || ones_onset == best_multiplicity || ones_offset == best_multiplicity ) - { - continue; - } - /* compute function and distinguishable seed dichotomies */ uint64_t column[2] = { 0, 0 }; STT tt; @@ -1503,4 +1512,4 @@ private: ABC_NAMESPACE_CXX_HEADER_END -#endif // _ACD_H_ \ No newline at end of file +#endif // _ACD_H_ From 52c842b648a030bc881af1e0fd001c23e94b6502 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 15 Oct 2024 17:54:38 +0200 Subject: [PATCH 015/133] Cleaning code --- src/map/if/acd/ac_decomposition.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index 4d87923db..55097a453 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -512,7 +512,7 @@ private: } while ( combinations_offset_next( free_set_size, offset, pComb, pInvPerm, tt ) ); std::array res_perm; - + if ( best_cost > ( 1 << ( ps.lut_size - free_set_size ) ) ) { return std::make_tuple( local_best_tt, res_perm, UINT32_MAX ); From d1f78b36cb8c095142b6e5016817d4dc633c8e3a Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 15 Oct 2024 19:00:45 +0200 Subject: [PATCH 016/133] Bug fix (just in the code; it does not affect the execution) --- src/map/if/acd/acdXX.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/map/if/acd/acdXX.hpp b/src/map/if/acd/acdXX.hpp index 13d1bdddf..833e45ba3 100644 --- a/src/map/if/acd/acdXX.hpp +++ b/src/map/if/acd/acdXX.hpp @@ -665,7 +665,7 @@ private: : cost <= 32 ? 4 : 5; - if ( ss_vars_needed + free_set_size < 6 ) + if ( ss_vars_needed + free_set_size < ps.lut_size ) { /* look for a shared variable */ best_multiplicity = cost; From baf4ddb16acb94fbfe75ac0fe6a99330ba1e315a Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 15 Oct 2024 19:04:49 +0200 Subject: [PATCH 017/133] Bug fix (just in the code; it does not affect the execution) --- src/map/if/acd/acdXX.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/map/if/acd/acdXX.hpp b/src/map/if/acd/acdXX.hpp index 833e45ba3..cf9bd6a27 100644 --- a/src/map/if/acd/acdXX.hpp +++ b/src/map/if/acd/acdXX.hpp @@ -610,7 +610,7 @@ private: : cost <= 32 ? 4 : 5; - if ( ss_vars_needed + free_set_size < 6 ) + if ( ss_vars_needed + free_set_size < ps.lut_size ) { /* look for a shared variable */ best_multiplicity = cost; From 74e7c64662e20aa39cfabf413668fd94540013d1 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 21 Oct 2024 13:16:29 +0700 Subject: [PATCH 018/133] Bug fix in &scorr --- src/proof/cec/cecCorr.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/proof/cec/cecCorr.c b/src/proof/cec/cecCorr.c index c3edf61ff..8d4c730a1 100644 --- a/src/proof/cec/cecCorr.c +++ b/src/proof/cec/cecCorr.c @@ -1320,9 +1320,9 @@ Vec_Int_t * Gia_ManFindStopFlops( Gia_Man_t * p, int nFlopIncFreq, int fVerbose if ( Spot >= 0 && Vec_IntEntry(vAvail, i) == 0 ) Vec_IntPush( vHeads, i ); Vec_IntForEachEntry( vHeads, Spot, i ) { - Vec_IntFill( vAvail, Gia_ManRegNum(p), 0 ); + Gia_ManIncrementTravId( p ); for ( k = 0, Temp = Spot; Vec_IntEntry(vNexts, Temp) >= 0; k++, Temp = Vec_IntEntry(vNexts, Temp) ) { - if ( Vec_IntEntry(vAvail, Temp) ) + if ( Gia_ObjUpdateTravIdCurrentId(p, Temp) ) break; Vec_IntWriteEntry( vAvail, Temp, 1 ); } @@ -1331,9 +1331,13 @@ Vec_Int_t * Gia_ManFindStopFlops( Gia_Man_t * p, int nFlopIncFreq, int fVerbose nItems++; if ( vRes == NULL ) vRes = Vec_IntAlloc( 100 ); - for ( k = 0, Temp = Spot; Vec_IntEntry(vNexts, Temp) >= 0; k++, Temp = Vec_IntEntry(vNexts, Temp) ) + Gia_ManIncrementTravId( p ); + for ( k = 0, Temp = Spot; Vec_IntEntry(vNexts, Temp) >= 0; k++, Temp = Vec_IntEntry(vNexts, Temp) ) { + if ( Gia_ObjUpdateTravIdCurrentId(p, Temp) ) + break; if ( k % nFlopIncFreq == 0 ) Vec_IntPush( vRes, Temp ); + } } while ( Vec_IntEntry(vNexts, Spot) >= 0 ) { From f1773bd612b65046b8dbbbbd74cac838da624899 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 21 Oct 2024 15:15:08 +0700 Subject: [PATCH 019/133] Procedure to detect node equivalences across two AIGs. --- src/aig/gia/giaUtil.c | 111 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/aig/gia/giaUtil.c b/src/aig/gia/giaUtil.c index 41c56c1fa..de7149935 100644 --- a/src/aig/gia/giaUtil.c +++ b/src/aig/gia/giaUtil.c @@ -3453,6 +3453,117 @@ Gia_Man_t * Gia_ManDupInsertWindows( Gia_Man_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t return pNew; } +/**Function************************************************************* + + Synopsis [Computing equivalent nodes across the two AIGs.] + + Description [Assumes that both AIGs are structurally hashed without dandling nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCreateDualOutputMiter( Gia_Man_t * p0, Gia_Man_t * p1 ) +{ + Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; + assert( Gia_ManCiNum(p0) == Gia_ManCiNum(p1) ); + assert( Gia_ManCoNum(p0) == Gia_ManCoNum(p1) ); + // start the manager + pNew = Gia_ManStart( Gia_ManObjNum(p0) + Gia_ManObjNum(p1) ); + pNew->pName = Abc_UtilStrsav( "miter" ); + Gia_ManFillValue( p0 ); + Gia_ManFillValue( p1 ); + // map combinational inputs + Gia_ManConst0(p0)->Value = 0; + Gia_ManConst0(p1)->Value = 0; + Gia_ManForEachCi( p0, pObj, i ) + Gia_ManCi(p1, i)->Value = pObj->Value = Gia_ManAppendCi( pNew ); + // map internal nodes and outputs + Gia_ManHashAlloc( pNew ); + Gia_ManForEachAnd( p0, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + assert( Gia_ManAndNum(pNew) == Gia_ManAndNum(p0) ); // the input AIG p0 is structurally hashed + Gia_ManForEachAnd( p1, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // add the outputs + Gia_ManForEachCo( p0, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachCo( p1, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + printf( "The two AIGs have %d structurally equivalent nodes.\n", Gia_ManAndNum(p0) + Gia_ManAndNum(p1) - Gia_ManAndNum(pNew) ); + // there should be no dangling nodes (otherwise, the second AIG may not be structurally hashed) + int nDangling = Gia_ManMarkDangling(pNew); + assert( nDangling == 0 ); + Gia_ManCleanMark01(pNew); + return pNew; +} +Vec_Int_t * Gia_ManFindMutualEquivs( Gia_Man_t * p0, Gia_Man_t * p1, int nConflictLimit, int fVerbose ) +{ + Vec_Int_t * vPairs = Vec_IntAlloc( 100 ); + // derive the miter + Gia_Man_t * pMiter = Gia_ManCreateDualOutputMiter( p0, p1 ); + //Gia_ManPrintStats( pMiter, NULL ); + //Gia_AigerWrite( pMiter, "out.aig", 0, 0, 0 ); + // perform SAT sweeping + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pNew = Cec4_ManSimulateTest3( pMiter, nConflictLimit, fVerbose ); + Gia_ManStop( pNew ); + // now, pMiter is annotated with the equiv class info + + // here we collect AIG node pairs with the following properties: + // - the first node belongs to p0; the second node belongs to p1 + // - both nodes are internal nodes of p0 and p1 (not primary inputs/outputs) + // - these nodes are combinationally equivalent (possibly up to the complement) + // - these nodes are "singleton" equivalences (no other nodes in p0 and p1 are equivalent to them) + // - these nodes are not structurally equivalent (that is, they have structurally different TFI logic cones) + + // count the number of nodes in each equivalence class + Vec_Int_t * vCounts = Vec_IntStart( Gia_ManObjNum(pMiter) ); + Gia_Obj_t * pObj; int i, k; + Gia_ManForEachClass( pMiter, i ) + Gia_ClassForEachObj( pMiter, i, k ) + Vec_IntAddToEntry( vCounts, i, 1 ); + + // map each miter node coming from p1 into the corresponding node in p1 + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(pMiter) ); + int iStartP1 = 1 + Gia_ManPiNum(p0) + Gia_ManAndNum(p0); + Gia_ManForEachAnd( p1, pObj, i ) + if ( Abc_Lit2Var(pObj->Value) >= iStartP1 ) // node from p1 (not from p0) + Vec_IntWriteEntry( vMap, Abc_Lit2Var(pObj->Value), i ); + + // go through functionally (not structurally!) equivalent nodes in the second AIG + // and collect those node pairs from p0 and p1 whose equivalence class contains exactly two nodes + for ( i = iStartP1; i < Gia_ManObjNum(pMiter) - Gia_ManCoNum(pMiter); i++ ) { + assert( Gia_ObjIsAnd(Gia_ManObj(pMiter, i)) ); + int Repr = Gia_ObjRepr(pMiter, i); + if ( Repr == GIA_VOID || Repr >= iStartP1 || Vec_IntEntry(vCounts, Repr) != 2 ) + continue; + assert( Repr < iStartP1 ); // node in p0 + assert( Vec_IntEntry(vMap, i) > 0 ); // node in p1 + Vec_IntPushTwo( vPairs, Repr, Vec_IntEntry(vMap, i) ); + } + // cleanup + Vec_IntFree( vMap ); + Vec_IntFree( vCounts ); + Gia_ManStop( pMiter ); + return vPairs; +} +void Gia_ManFindMutualEquivsTest() +{ + Gia_Man_t * p0 = Gia_AigerRead( "p0.aig", 0, 0, 0 ); + Gia_Man_t * p1 = Gia_AigerRead( "p1.aig", 0, 0, 0 ); + Vec_Int_t * vPairs = Gia_ManFindMutualEquivs( p0, p1, 0, 0 ); + printf( "Pair Aig0 node Aig1 node\n" ); + int i, Obj0, Obj1; + Vec_IntForEachEntryDouble( vPairs, Obj0, Obj1, i ) + printf( "%3d %6d %6d\n", i/2, Obj0, Obj1 ); + Gia_ManStop( p0 ); + Gia_ManStop( p1 ); + Vec_IntFree( vPairs ); +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// From cb2140dc0c0a2390f8aa1aa3d8be379a27b05785 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 21 Oct 2024 20:37:52 +0700 Subject: [PATCH 020/133] Adding PI/PO name transfer after mapping+retiming. --- src/aig/gia/giaSif.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/aig/gia/giaSif.c b/src/aig/gia/giaSif.c index c52ab4dd9..4df5c47f7 100644 --- a/src/aig/gia/giaSif.c +++ b/src/aig/gia/giaSif.c @@ -645,6 +645,25 @@ Gia_Man_t * Gia_ManSifPerform( Gia_Man_t * p, int nLutSize, int fEvalOnly, int f pNew = Gia_ManSifTransform( p, vCuts, vTimes, nLutSize, Upper, fVerbose ); Vec_IntFree( vCuts ); Vec_IntFree( vTimes ); + //Gia_ManTransferTiming( pNew, p ); + if ( p->vNamesIn ) { + char * pName; int i; + pNew->vNamesIn = p->vNamesIn; p->vNamesIn = NULL; + Vec_PtrForEachEntryStart( char *, pNew->vNamesIn, pName, i, Gia_ManPiNum(pNew) ) + ABC_FREE( pName ); + Vec_PtrShrink( pNew->vNamesIn, Gia_ManPiNum(pNew) ); + for ( i = 0; i < Gia_ManRegNum(pNew); i++ ) + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsavNum("_fo", i) ); + } + if ( p->vNamesOut ) { + char * pName; int i; + pNew->vNamesOut = p->vNamesOut; p->vNamesOut = NULL; + Vec_PtrForEachEntryStart( char *, pNew->vNamesOut, pName, i, Gia_ManPoNum(pNew) ) + ABC_FREE( pName ); + Vec_PtrShrink( pNew->vNamesOut, Gia_ManPoNum(pNew) ); + for ( i = 0; i < Gia_ManRegNum(pNew); i++ ) + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsavNum("_fi", i) ); + } return pNew; } From ecd948027e11630d5337f75bd3d825ebba95357c Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 23 Oct 2024 14:49:57 +0700 Subject: [PATCH 021/133] Fixing assertion failures in &put. --- 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 9e643b043..6bf1c2338 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -32313,7 +32313,7 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 0, "Internal nodes names are not transferred.\n" ); // decouple CI/CO with the same name - if ( pAbc->pGia->vNamesIn || pAbc->pGia->vNamesOut ) + if ( !Abc_NtkIsStrash(pNtk) && (pAbc->pGia->vNamesIn || pAbc->pGia->vNamesOut) ) Abc_NtkRedirectCiCo( pNtk ); // transfer timing information From 091ff4e7a9adf6ee5a7705d99b27de571eb7edbc Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 5 Nov 2024 19:23:04 -0800 Subject: [PATCH 022/133] Adding generation of random functions to "lutexact" --- src/base/abci/abc.c | 23 +++++++++++++++++++---- src/sat/bmc/bmc.h | 1 + src/sat/bmc/bmcMaj.c | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 6bf1c2338..ec891dea8 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -9805,11 +9805,12 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ); extern void Exa3_ManExactSynthesis2( Bmc_EsPar_t * pPars ); + extern void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars ); int c; Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INKTSiaocgvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INKTSRiaocgvh" ) ) != EOF ) { switch ( c ) { @@ -9866,6 +9867,15 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pSymStr = argv[globalUtilOptind]; globalUtilOptind++; break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by a file name.\n" ); + goto usage; + } + pPars->nRandFuncs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; case 'i': pPars->fUseIncr ^= 1; break; @@ -9892,7 +9902,7 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( argc == globalUtilOptind + 1 ) pPars->pTtStr = argv[globalUtilOptind]; - if ( pPars->pTtStr == NULL && pPars->pSymStr == NULL ) + if ( pPars->pTtStr == NULL && pPars->pSymStr == NULL && pPars->nRandFuncs == 0 ) { Abc_Print( -1, "Truth table should be given on the command line.\n" ); return 1; @@ -9922,19 +9932,24 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Node size should not be more than 6 inputs.\n" ); return 1; } - if ( pPars->fGlucose ) + if ( pPars->nRandFuncs ) { + pPars->fGlucose = 1; + Exa3_ManExactSynthesisRand( pPars ); + } + else if ( pPars->fGlucose ) Exa3_ManExactSynthesis( pPars ); else Exa3_ManExactSynthesis2( pPars ); return 0; usage: - Abc_Print( -2, "usage: lutexact [-INKT ] [-S string] [-iaocgvh] \n" ); + Abc_Print( -2, "usage: lutexact [-INKTR ] [-S 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 ); Abc_Print( -2, "\t-K : the number of node fanins [default = %d]\n", pPars->nLutSize ); Abc_Print( -2, "\t-T : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); + Abc_Print( -2, "\t-R : the number of random functions to try [default = unused]\n" ); Abc_Print( -2, "\t-S : 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" ); diff --git a/src/sat/bmc/bmc.h b/src/sat/bmc/bmc.h index 11578a56b..f39a09726 100644 --- a/src/sat/bmc/bmc.h +++ b/src/sat/bmc/bmc.h @@ -64,6 +64,7 @@ struct Bmc_EsPar_t_ int fUniqFans; int fLutCascade; int RuntimeLim; + int nRandFuncs; int fVerbose; char * pTtStr; char * pSymStr; diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index f89d74ea1..d03b1aba0 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -1555,6 +1555,23 @@ void Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) ABC_FREE( pPars->pTtStr ); Exa3_ManFree( p ); } +void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars ) +{ + int i, k, nWords = Abc_TtWordNum(pPars->nVars); + word * pFun = ABC_ALLOC( word, nWords ); + Abc_RandomW(1); + for ( i = 0; i < pPars->nRandFuncs; i++ ) { + for ( k = 0; k < nWords; k++ ) + pFun[k] = Abc_RandomW(0); + pPars->pTtStr = ABC_CALLOC( char, pPars->nVars > 2 ? (1 << (pPars->nVars-2)) + 1 : 2 ); + Extra_PrintHexadecimalString( pPars->pTtStr, (unsigned *)pFun, pPars->nVars ); + printf( "Generated random function: %s\n", pPars->pTtStr ); + Exa3_ManExactSynthesis( pPars ); + ABC_FREE( pPars->pTtStr ); + } + ABC_FREE( pFun ); +} + /**Function************************************************************* From c787e32f86597ffce2080534c1093f02e8c9f8d5 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 5 Nov 2024 22:01:07 -0800 Subject: [PATCH 023/133] Adding postiive minterm count for random functions generated by "lutexact". --- src/base/abci/abc.c | 16 +++++++++++++--- src/sat/bmc/bmc.h | 1 + src/sat/bmc/bmcMaj.c | 30 ++++++++++++++++++++++-------- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index ec891dea8..428ba2c37 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -9803,14 +9803,14 @@ usage: ***********************************************************************/ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ); + extern int Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ); extern void Exa3_ManExactSynthesis2( Bmc_EsPar_t * pPars ); extern void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars ); int c; Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INKTSRiaocgvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INKTSRMiaocgvh" ) ) != EOF ) { switch ( c ) { @@ -9876,6 +9876,15 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->nRandFuncs = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by a file name.\n" ); + goto usage; + } + pPars->nMintNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; case 'i': pPars->fUseIncr ^= 1; break; @@ -9943,13 +9952,14 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutexact [-INKTR ] [-S string] [-iaocgvh] \n" ); + Abc_Print( -2, "usage: lutexact [-INKTRM ] [-S 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 ); Abc_Print( -2, "\t-K : the number of node fanins [default = %d]\n", pPars->nLutSize ); Abc_Print( -2, "\t-T : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); Abc_Print( -2, "\t-R : 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-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" ); diff --git a/src/sat/bmc/bmc.h b/src/sat/bmc/bmc.h index f39a09726..92fbb7422 100644 --- a/src/sat/bmc/bmc.h +++ b/src/sat/bmc/bmc.h @@ -65,6 +65,7 @@ struct Bmc_EsPar_t_ int fLutCascade; int RuntimeLim; int nRandFuncs; + int nMintNum; int fVerbose; char * pTtStr; char * pSymStr; diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index d03b1aba0..168f7fc55 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -1499,9 +1499,9 @@ void Exa3_ManPrint( Exa3_Man_t * p, int i, int iMint, abctime clk ) printf( "Conf =%9d ", bmcg_sat_solver_conflictnum(p->pSat) ); Abc_PrintTime( 1, "Time", clk ); } -void Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) +int Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) { - int i, status, iMint = 1; + int i, status, Res = 0, iMint = 1; abctime clkTotal = Abc_Clock(); Exa3_Man_t * p; int fCompl = 0; word pTruth[16]; @@ -1542,7 +1542,7 @@ void Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) if ( pPars->fVerbose && status != GLUCOSE_UNDEC ) Exa3_ManPrint( p, i, iMint, Abc_Clock() - clkTotal ); if ( iMint == -1 ) - Exa3_ManPrintSolution( p, fCompl ); + Exa3_ManPrintSolution( p, fCompl ), Res = 1; else if ( status == GLUCOSE_UNDEC ) printf( "The problem timed out after %d sec.\n", pPars->RuntimeLim ); else @@ -1554,21 +1554,35 @@ void Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) if ( pPars->pSymStr ) ABC_FREE( pPars->pTtStr ); Exa3_ManFree( p ); + return Res; } void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars ) { - int i, k, nWords = Abc_TtWordNum(pPars->nVars); + int i, k, nDecs = 0, nWords = Abc_TtWordNum(pPars->nVars); word * pFun = ABC_ALLOC( word, nWords ); - Abc_RandomW(1); + Abc_Random(1); + printf( "\n" ); for ( i = 0; i < pPars->nRandFuncs; i++ ) { - for ( k = 0; k < nWords; k++ ) - pFun[k] = Abc_RandomW(0); + if ( pPars->nMintNum == 0 ) + for ( k = 0; k < nWords; k++ ) + pFun[k] = 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); + while ( Abc_TtGetBit(pFun, iMint) ); + Abc_TtSetBit( pFun, iMint ); + } + } pPars->pTtStr = ABC_CALLOC( char, pPars->nVars > 2 ? (1 << (pPars->nVars-2)) + 1 : 2 ); Extra_PrintHexadecimalString( pPars->pTtStr, (unsigned *)pFun, pPars->nVars ); printf( "Generated random function: %s\n", pPars->pTtStr ); - Exa3_ManExactSynthesis( pPars ); + nDecs += Exa3_ManExactSynthesis( pPars ); ABC_FREE( pPars->pTtStr ); + printf( "\n" ); } + printf( "Decomposable are %d (out of %d) functions (%.2f %%).\n", nDecs, pPars->nRandFuncs, 100.0*nDecs/pPars->nRandFuncs ); ABC_FREE( pFun ); } From aeb977286f56144bf873066be15f9d4794dfe288 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 10 Nov 2024 18:54:35 -0800 Subject: [PATCH 024/133] Updates to LUT cascade synthesis. --- src/base/abci/abc.c | 52 ++++++++++- src/base/abci/abcCas.c | 9 +- src/bdd/extrab/extraLutCas.h | 176 ++++++++++++++++++++++++++++++++++- 3 files changed, 223 insertions(+), 14 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 428ba2c37..8e87106b2 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -8847,11 +8847,11 @@ usage: ***********************************************************************/ int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; - int c, nLutSize = 6, fVerbose = 0; + int c, nLutSize = 6, nLuts = 8, nRails = 1, nIters = 1, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KNRIvh" ) ) != EOF ) { switch ( c ) { @@ -8866,6 +8866,39 @@ int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nLutSize < 0 ) goto usage; break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLuts < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nRails = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRails < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; case 'v': fVerbose ^= 1; break; @@ -8891,7 +8924,13 @@ int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Run command \"strash\" to convert the network into an AIG.\n" ); return 1; } - pNtkRes = Abc_NtkLutCascade( pNtk, nLutSize, fVerbose ); + if ( Abc_NtkCiNum(pNtk) > nLutSize + (nLutSize - nRails) * (nLuts - 1) ) + { + Abc_Print( -1, "Cannot decompose %d-input function into a %d-rail cascade of %d %d-LUTs (max suppose size = %d).\n", + Abc_NtkCiNum(pNtk), nRails, nLuts, nLutSize, nLutSize + (nLutSize - nRails) * (nLuts - 1) ); + return 1; + } + pNtkRes = Abc_NtkLutCascade( pNtk, nLutSize, nLuts, nRails, nIters, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "LUT cascade mapping failed.\n" ); @@ -8901,9 +8940,12 @@ int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutcas [-K ] [-vh]\n" ); + Abc_Print( -2, "usage: lutcas [-KNRI ] [-vh]\n" ); Abc_Print( -2, "\t derives single-rail LUT cascade for the primary output function\n" ); Abc_Print( -2, "\t-K : the number of LUT inputs [default = %d]\n", nLutSize ); + Abc_Print( -2, "\t-N : the number of LUTs in the cascade [default = %d]\n", nLuts ); + Abc_Print( -2, "\t-R : the number of direct connections (rails) [default = %d]\n", nRails ); + Abc_Print( -2, "\t-I : the number of iterations when looking for a solution [default = %d]\n", nIters ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index b81d813d6..eddb2c1a1 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -119,7 +119,7 @@ Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVer #else Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ) { return NULL; } -word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int fVerbose ) { return NULL; } +word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) { return NULL; } #endif @@ -251,14 +251,15 @@ Abc_Ntk_t * Abc_NtkLutCascadeFromLuts( word * pLuts, Abc_Ntk_t * pNtk, int nLutS } return pNtkNew; } -Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ) +Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) { extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk ); extern Mini_Aig_t * Gia_ManToMiniAig( Gia_Man_t * pGia ); - extern word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int fVerbose ); + extern word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk ); Mini_Aig_t * pM = Gia_ManToMiniAig( pGia ); - word * pLuts = Abc_LutCascade( pM, nLutSize, fVerbose ); + word * pLuts = Abc_LutCascade( pM, nLutSize, nLuts, nRails, nIters, fVerbose ); + //word * pLuts = Abc_LutCascadeTest( pM, nLutSize, 0 ); Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, pNtk, nLutSize, fVerbose ) : NULL; ABC_FREE( pLuts ); Mini_AigStop( pM ); diff --git a/src/bdd/extrab/extraLutCas.h b/src/bdd/extrab/extraLutCas.h index 1308c2bee..6723525d1 100644 --- a/src/bdd/extrab/extraLutCas.h +++ b/src/bdd/extrab/extraLutCas.h @@ -107,6 +107,159 @@ Vec_Ptr_t * Abc_LutCasCollapse( Mini_Aig_t * p, DdManager * dd, int nBddLimit, i return vFuncs; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_LutBddScan( DdManager * dd, DdNode * bFunc, int nVars ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( 1 << nVars ); + Vec_Ptr_t * vRes2 = Vec_PtrAlloc( 1 << nVars ); + Vec_PtrPush( vRes, bFunc ); + int v, Level = Cudd_ReadPerm( dd, Cudd_NodeReadIndex(bFunc) ); + for ( v = 0; v < dd->size; v++ ) + printf( "%2d : perm = %d invperm = %d\n", v, dd->perm[v], dd->invperm[v] ); + for ( v = 0; v < nVars; v++ ) + { + int i, LevelCur = Level + v; + Vec_PtrClear( vRes2 ); + DdNode * bTemp; + Vec_PtrForEachEntry( DdNode *, vRes, bTemp, i ) { + int LevelTemp = Cudd_ReadPerm( dd, Cudd_NodeReadIndex(bTemp) ); + if ( LevelTemp == LevelCur ) { + Vec_PtrPush( vRes2, Cudd_NotCond(Cudd_E(bTemp), Cudd_IsComplement(bTemp)) ); + Vec_PtrPush( vRes2, Cudd_NotCond(Cudd_T(bTemp), Cudd_IsComplement(bTemp)) ); + } + else if ( LevelTemp > LevelCur ) { + Vec_PtrPush( vRes2, bTemp ); + Vec_PtrPush( vRes2, bTemp ); + } + else assert( 0 ); + } + ABC_SWAP( Vec_Ptr_t *, vRes, vRes2 ); + //Vec_PtrForEachEntry( DdNode *, vRes, bTemp, i ) + // printf( "%p ", bTemp ); + //printf( "\n" ); + } + Vec_PtrFree( vRes2 ); + assert( Vec_PtrSize(vRes) == (1 << nVars) ); + return vRes; +} +char * Abc_LutBddToTruth( Vec_Ptr_t * vFuncs ) +{ + assert( Vec_PtrSize(vFuncs) <= 256 ); + char * pRes = ABC_CALLOC( char, Vec_PtrSize(vFuncs)+1 ); + void * pTemp, * pStore[256] = {Vec_PtrEntry(vFuncs, 0)}; + int i, k, nStore = 1; pRes[0] = 'a'; + Vec_PtrForEachEntryStart( void *, vFuncs, pTemp, i, 1 ) { + for ( k = 0; k < nStore; k++ ) + if ( pStore[k] == pTemp ) + break; + if ( k == nStore ) + pStore[nStore++] = pTemp; + pRes[i] = 'a' + (char)k; + } + return pRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_NtkPrecomputeData() +{ + char * pRes = ABC_CALLOC( char, 1 << 16 ); + int i, k, b; + for ( i = 0; i < 256; i++ ) { + int nOnes = __builtin_popcount(i); + char * pTemp = pRes + 256*i; + for ( k = 0; k < 256; k++ ) { + int iMask = 0, Counts[2] = {nOnes, 0}; + for ( b = 0; b < 8; Counts[(i >> b++)&1]++ ) + if ( (k >> b) & 1 ) + iMask |= 1 << Counts[(i >> b)&1]; + pTemp[iMask] = (char)k; + assert( Counts[1] == nOnes ); + } + } + for ( i = 0; i < 16; i++, printf("\n") ) + for ( printf("%x : ", i), k = 0; k < 16; k++ ) + printf( "%x=%x ", k, (int)pRes[i*256+k] ); + return pRes; +} + +int Abc_NtkDecPatCount( int iFirst, int nStep, int MyuMax, char * pDecPat, char * pPermInfo ) +{ + int s, k, nPats = 1; + char Pats[256] = { pDecPat[(int)pPermInfo[iFirst]] }; + assert( MyuMax <= 256 ); + for ( s = 1; s < nStep; s++ ) { + char Entry = pDecPat[(int)pPermInfo[iFirst+s]]; + for ( k = 0; k < nPats; k++ ) + if ( Pats[k] == Entry ) + break; + if ( k < nPats ) + continue; + if ( nPats == MyuMax ) + return MyuMax + 1; + assert( nPats < 256 ); + Pats[nPats++] = Entry; + } + return nPats; +} +int Abc_NtkDecPatDecompose_rec( int Mask, int nMaskVars, int iStart, int nVars, int nDiffs, int nRails, char * pDecPat, char * pPermInfo ) +{ + if ( nDiffs == 0 || iStart == nVars ) + return 0; + int v, m, nMints = 1 << nVars; + for ( v = iStart; v < nVars; v++ ) { + int MaskThis = Mask & ~(1 << v); + int nStep = 1 << (nMaskVars - 1); + int MyuMax = 0; + for ( m = 0; m < nMints; m += nStep ) { + int MyuCur = Abc_NtkDecPatCount( m, nStep, 1 << nDiffs, pDecPat, pPermInfo+256*MaskThis ); + MyuMax = Abc_MaxInt( MyuMax, MyuCur ); + } + if ( MyuMax > (1 << nDiffs) ) + continue; + if ( MyuMax <= (1 << nRails) ) + return MaskThis; + MaskThis = Abc_NtkDecPatDecompose_rec( MaskThis, nMaskVars-1, v+1, nVars, nDiffs-1, nRails, pDecPat, pPermInfo ); + if ( MaskThis ) + return MaskThis; + } + return 0; +} +int Abc_NtkDecPatDecompose( int nVars, int nRails, char * pDecPat, char * pPermInfo ) +{ + int BoundSet = ~(~0 << nVars); + int Myu = Abc_NtkDecPatCount( 0, 1 << nVars, 256, pDecPat, pPermInfo + 256*BoundSet ); + int Log2 = Abc_Base2Log( Myu ); + if ( Log2 <= nRails ) + return BoundSet; + return Abc_NtkDecPatDecompose_rec( BoundSet, nVars, 0, nVars, Log2 - nRails, nRails, pDecPat, pPermInfo ); +} + +int Abc_NtkCascadeDecompose( int nVars, int nRails, char * pDecPat, char * pPermInfo ) +{ + return 0; +} + + /**Function************************************************************* @@ -159,12 +312,12 @@ void Abc_LutCasPrintDsd( DdManager * dd, DdNode * bFunc, int fVerbose ) } Dsd_ManagerStop( pManDsd ); } -DdNode * Abc_LutCasBuildBdds( Mini_Aig_t * p, DdManager ** pdd ) +DdNode * Abc_LutCasBuildBdds( Mini_Aig_t * p, DdManager ** pdd, int fReorder ) { DdManager * dd = Cudd_Init( Mini_AigPiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + if ( fReorder ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); Vec_Ptr_t * vFuncs = Abc_LutCasCollapse( p, dd, 10000, 0 ); - Cudd_AutodynDisable( dd ); + if ( fReorder ) Cudd_AutodynDisable( dd ); if ( vFuncs == NULL ) { Extra_StopManager( dd ); return NULL; @@ -174,15 +327,28 @@ DdNode * Abc_LutCasBuildBdds( Mini_Aig_t * p, DdManager ** pdd ) *pdd = dd; return bNode; } -static inline word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int fVerbose ) +static inline word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) { DdManager * dd = NULL; - DdNode * bFunc = Abc_LutCasBuildBdds( p, &dd ); + DdNode * bFunc = Abc_LutCasBuildBdds( p, &dd, 0 ); if ( bFunc == NULL ) return NULL; + char * pPermInfo = Abc_NtkPrecomputeData(); Abc_LutCasPrintDsd( dd, bFunc, 1 ); + + Vec_Ptr_t * vTemp = Abc_LutBddScan( dd, bFunc, nLutSize ); + char * pTruth = Abc_LutBddToTruth( vTemp ); + + int BoundSet = Abc_NtkDecPatDecompose( nLutSize, nRails, pTruth, pPermInfo ); + printf( "Pattern %s : Bound set = %d\n", pTruth, BoundSet ); + + ABC_FREE( pTruth ); + Vec_PtrFree( vTemp ); + Cudd_RecursiveDeref( dd, bFunc ); Extra_StopManager( dd ); + ABC_FREE( pPermInfo ); + printf( "\n" ); word * pLuts = NULL; return pLuts; } From f2e4ceb0e30432d2a3e846c08ebc0bd191ef11dc Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 10 Nov 2024 19:12:40 -0800 Subject: [PATCH 025/133] Update to "lutexact". --- src/sat/bmc/bmcMaj.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index 168f7fc55..68601338e 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -953,7 +953,7 @@ void Exa_ManExactSynthesis( Bmc_EsPar_t * pPars ) } if ( status == GLUCOSE_UNDEC ) { - printf( "The problem timed out after %d sec.\n", pPars->RuntimeLim ); + printf( "The solver timed out after %d sec.\n", pPars->RuntimeLim ); break; } iMint = Exa_ManEval( p ); @@ -1544,7 +1544,7 @@ int Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) if ( iMint == -1 ) Exa3_ManPrintSolution( p, fCompl ), Res = 1; else if ( status == GLUCOSE_UNDEC ) - printf( "The problem timed out after %d sec.\n", pPars->RuntimeLim ); + printf( "The solver timed out after %d sec.\n", pPars->RuntimeLim ); else printf( "The problem has no solution.\n" ); printf( "Added = %d. Tried = %d. ", p->nUsed[1], p->nUsed[0] ); @@ -1577,10 +1577,14 @@ 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( "Generated random function: %s\n", pPars->pTtStr ); + printf( "\nIteration %d : ", i ); + if ( pPars->nMintNum ) + printf( "Random function has %d positive minterms.", pPars->nMintNum ); + printf( "\n" ); + if ( pPars->fVerbose ) + printf( "Truth table : %s\n", pPars->pTtStr ); nDecs += Exa3_ManExactSynthesis( pPars ); ABC_FREE( pPars->pTtStr ); - printf( "\n" ); } printf( "Decomposable are %d (out of %d) functions (%.2f %%).\n", nDecs, pPars->nRandFuncs, 100.0*nDecs/pPars->nRandFuncs ); ABC_FREE( pFun ); From b5a76d8ba321d4fb5d2f4a7ad145b2b020f4f2e9 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 10 Nov 2024 19:30:24 -0800 Subject: [PATCH 026/133] Compilation problem. --- src/bdd/extrab/extraLutCas.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bdd/extrab/extraLutCas.h b/src/bdd/extrab/extraLutCas.h index 6723525d1..38a5dcd26 100644 --- a/src/bdd/extrab/extraLutCas.h +++ b/src/bdd/extrab/extraLutCas.h @@ -27,6 +27,11 @@ #define inline __inline // compatible with MS VS 6.0 #endif +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +#endif + #include #include #include From 3aff0af0c544ac8fda316a4095a6e201652097da Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 11 Nov 2024 21:02:59 -0800 Subject: [PATCH 027/133] Adding command for generating sorters. --- src/aig/gia/giaGen.c | 59 ++++++++++++++++++++++++++++++++++++++++ src/base/abci/abc.c | 64 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 122 insertions(+), 1 deletion(-) diff --git a/src/aig/gia/giaGen.c b/src/aig/gia/giaGen.c index 03b194e7c..a807fe60f 100644 --- a/src/aig/gia/giaGen.c +++ b/src/aig/gia/giaGen.c @@ -1302,6 +1302,65 @@ Gia_Man_t * Gia_ManGenMux( int nIns, char * pNums ) return p; } + +/**Function************************************************************* + + Synopsis [Generates N-bit sorter using pair-wise sorting algorithm.] + + Description [https://en.wikipedia.org/wiki/Pairwise_sorting_network] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManGenSorterOne( Gia_Man_t * p, int * pLits, int i, int k ) +{ + int Lit1 = Gia_ManAppendAnd( p, pLits[i], pLits[k] ); + int Lit2 = Gia_ManAppendOr ( p, pLits[i], pLits[k] ); + pLits[i] = Lit1; + pLits[k] = Lit2; +} +static inline void Gia_ManGenSorterConstrMerge( Gia_Man_t * p, int * pLits, int lo, int hi, int r ) +{ + int i, step = r * 2; + if ( step < hi - lo ) + { + Gia_ManGenSorterConstrMerge( p, pLits, lo, hi-r, step ); + Gia_ManGenSorterConstrMerge( p, pLits, lo+r, hi, step ); + for ( i = lo+r; i < hi-r; i += step ) + Gia_ManGenSorterOne( p, pLits, i, i+r ); + } +} +static inline void Gia_ManGenSorterConstrRange( Gia_Man_t * p, int * pLits, int lo, int hi ) +{ + if ( hi - lo >= 1 ) + { + int i, mid = lo + (hi - lo) / 2; + for ( i = lo; i <= mid; i++ ) + Gia_ManGenSorterOne( p, pLits, i, i + (hi - lo + 1) / 2 ); + Gia_ManGenSorterConstrRange( p, pLits, lo, mid ); + Gia_ManGenSorterConstrRange( p, pLits, mid+1, hi ); + Gia_ManGenSorterConstrMerge( p, pLits, lo, hi, 1 ); + } +} +Gia_Man_t * Gia_ManGenSorter( int LogN ) +{ + int i, nVars = 1 << LogN; + int nVarsAlloc = nVars + 2 * (nVars * LogN * (LogN-1) / 4 + nVars - 1); + Vec_Int_t * vLits = Vec_IntAlloc( nVars ); + Gia_Man_t * p = Gia_ManStart( 1 + 2*nVars + nVarsAlloc ); + p->pName = Abc_UtilStrsav( "sorter" ); + for ( i = 0; i < nVars; i++ ) + Vec_IntPush( vLits, Gia_ManAppendCi(p) ); + Gia_ManGenSorterConstrRange( p, Vec_IntArray(vLits), 0, nVars - 1 ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCo( p, Vec_IntEntry(vLits, i) ); + Vec_IntFree( vLits ); + return p; +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 8e87106b2..0140edf51 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -616,6 +616,7 @@ static int Abc_CommandAbc9Odc ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9GenRel ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenMux ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenComp ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenSorter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenNeuron ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Window ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9FunAbs ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1420,6 +1421,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&genrel", Abc_CommandAbc9GenRel, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&genmux", Abc_CommandAbc9GenMux, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&gencomp", Abc_CommandAbc9GenComp, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&gensorter", Abc_CommandAbc9GenSorter, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&genneuron", Abc_CommandAbc9GenNeuron, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&window", Abc_CommandAbc9Window, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&funabs", Abc_CommandAbc9FunAbs, 0 ); @@ -54083,7 +54085,67 @@ usage: Abc_Print( -2, "\t-i : toggles using interleaved variable ordering [default = %s]\n", fInter ? "yes": "no" ); 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, "\tstring : the sizes of control input groups\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9GenSorter( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManGenSorter( int LogN ); + Gia_Man_t * pTemp = NULL; + int c, LogN = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + LogN = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( LogN < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( LogN == 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9GenComp(): The number of inputs should be defined on the command line \"-K num\".\n" ); + return 0; + } + pTemp = Gia_ManGenSorter( LogN ); + Abc_FrameUpdateGia( pAbc, pTemp ); + if ( fVerbose ) + Abc_Print( 1, "Generated %d-input sorter composed of %d elementary 2-bit sorters.\n", 1 << LogN, (1 << LogN) * LogN * (LogN-1) / 4 + (1 << LogN) - 1 ); + return 0; + +usage: + Abc_Print( -2, "usage: &gensorter [-K ] [-vh]\n" ); + Abc_Print( -2, "\t generates the sorter using pair-wise sorting algorithm\n" ); + Abc_Print( -2, "\t-K num : the base-2 log of the number of inputs [default = undefined]\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"); return 1; } From 1f3cf0aad976d3bab09b5c96ec9ca7c825d55636 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 17 Nov 2024 15:44:32 -0800 Subject: [PATCH 028/133] Experiment with "scorr". --- src/base/abci/abc.c | 17 +++++++++++++++-- src/proof/ssw/ssw.h | 1 + src/proof/ssw/sswAig.c | 8 ++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 0140edf51..0d8f5c5f1 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -23148,7 +23148,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Ssw_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLSIVMNXcmplkodsefqvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLSIVMNXRcmplkodsefqvwh" ) ) != EOF ) { switch ( c ) { @@ -23273,6 +23273,18 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nLimitMax < 0 ) goto usage; break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nSkip = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nSkip < 0 ) + goto usage; + break; + case 'c': pPars->fConstrs ^= 1; break; @@ -23394,7 +23406,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: scorr [-PQFCLSIVMNX ] [-cmplkodsefqvwh]\n" ); + Abc_Print( -2, "usage: scorr [-PQFCLSIVMNXR ] [-cmplkodsefqvwh]\n" ); Abc_Print( -2, "\t performs sequential sweep using K-step induction\n" ); Abc_Print( -2, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize ); Abc_Print( -2, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize ); @@ -23408,6 +23420,7 @@ usage: Abc_Print( -2, "\t-M num : min call num needed to recycle the SAT solver [default = %d]\n", pPars->nRecycleCalls2 ); Abc_Print( -2, "\t-N num : set last POs to be constraints (use with -c) [default = %d]\n", nConstrs ); Abc_Print( -2, "\t-X num : the number of iterations of little or no improvement [default = %d]\n", pPars->nLimitMax ); + Abc_Print( -2, "\t-R num : the number used to skip some constraints [default = %d]\n", pPars->nSkip ); Abc_Print( -2, "\t-c : toggle using explicit constraints [default = %s]\n", pPars->fConstrs? "yes": "no" ); Abc_Print( -2, "\t-m : toggle full merge if constraints are present [default = %s]\n", pPars->fMergeFull? "yes": "no" ); Abc_Print( -2, "\t-p : toggle aligning polarity of SAT variables [default = %s]\n", pPars->fPolarFlip? "yes": "no" ); diff --git a/src/proof/ssw/ssw.h b/src/proof/ssw/ssw.h index 7299e37d1..608b709e5 100644 --- a/src/proof/ssw/ssw.h +++ b/src/proof/ssw/ssw.h @@ -74,6 +74,7 @@ struct Ssw_Pars_t_ int fEquivDump; // enables dumping equivalences int fEquivDump2; // enables dumping equivalences int fStopWhenGone; // stop when PO output is not a candidate constant + int nSkip; // optimized latch correspondence int fLatchCorrOpt; // perform register correspondence (optimized) int nSatVarMax; // max number of SAT vars before recycling SAT solver (optimized latch corr only) diff --git a/src/proof/ssw/sswAig.c b/src/proof/ssw/sswAig.c index acd8f919f..ec744dc4b 100644 --- a/src/proof/ssw/sswAig.c +++ b/src/proof/ssw/sswAig.c @@ -120,8 +120,10 @@ static inline void Ssw_FramesConstrainNode( Ssw_Man_t * p, Aig_Man_t * pFrames, // add the constraint if ( fTwoPos ) { - Aig_ObjCreateCo( pFrames, pObjNew2 ); - Aig_ObjCreateCo( pFrames, pObjNew ); + if ( p->pPars->nSkip == 0 ||rand() % p->pPars->nSkip == 0 ) { + Aig_ObjCreateCo( pFrames, pObjNew2 ); + Aig_ObjCreateCo( pFrames, pObjNew ); + } } else { @@ -158,6 +160,8 @@ Aig_Man_t * Ssw_FramesWithClasses( Ssw_Man_t * p ) Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreateCi(pFrames) ); // add timeframes iLits = 0; + if ( p->pPars->nSkip ) + srand(1); for ( f = 0; f < p->pPars->nFramesK; f++ ) { // map constants and PIs From 14168eb5092ddcd2f1c1e6683e38beb3612dc58c Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 27 Nov 2024 22:01:27 -0800 Subject: [PATCH 029/133] Updating command "rungen" to generate random functions. --- src/base/abci/abc.c | 81 +++++++++++++++++++++++++++++-------- src/base/abci/abcRunGen.c | 84 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 146 insertions(+), 19 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 0d8f5c5f1..39df508cf 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -7441,14 +7441,58 @@ usage: ***********************************************************************/ int Abc_CommandRunGen( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Acb_NtkRunGen( char * pFileNames[2], int fVerbose ); - char * pFileNames[4] = {NULL}; - int c, fVerbose = 0; + extern void Acb_NtkRunGen( int nInputs, int nMints, int nFuncs, int Seed, int fVerbose, char * pScript ); + int c, nInputs = 10, nMints = 10, nFuncs = 10, Seed = 0, fVerbose = 0; char * pScript = NULL; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "IMRSCvh" ) ) != EOF ) { switch ( c ) { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nInputs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMints = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nFuncs = 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; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by a script.\n" ); + goto usage; + } + pScript = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'v': fVerbose ^= 1; break; @@ -7458,21 +7502,24 @@ int Abc_CommandRunGen( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( argc - globalUtilOptind != 2 ) + if ( pScript == NULL ) { - Abc_Print( 1, "Expecting two file names on the command line.\n" ); - goto usage; + Abc_Print( -1, "Command line switch \"-C\" should be specified and followed by a string.\n" ); + goto usage; } - for ( c = 0; c < 2; c++ ) - pFileNames[c] = argv[globalUtilOptind+c]; - Acb_NtkRunGen( pFileNames, fVerbose ); + Acb_NtkRunGen( nInputs, nMints, nFuncs, Seed, fVerbose, pScript ); return 0; usage: - Abc_Print( -2, "usage: rungen [-vh] \n" ); - Abc_Print( -2, "\t experimental command\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"); + Abc_Print( -2, "usage: rungen [-IMRS num] [-C script] [-vh]\n" ); + Abc_Print( -2, "\t running the script on a set of randomly generated functions\n" ); + Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", nInputs ); + Abc_Print( -2, "\t-M : the number of positive minterms in the random function [default = %d]\n", nMints ); + Abc_Print( -2, "\t-R : the number of random functions to try [default = %d]\n", nFuncs ); + Abc_Print( -2, "\t-S : the random seed [default = %d]\n", Seed ); + Abc_Print( -2, "\t-C : the script to apply [default = provided by the user]\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; } @@ -9905,7 +9952,7 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'S': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-S\" should be followed by a file name.\n" ); + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } pPars->pSymStr = argv[globalUtilOptind]; @@ -9914,7 +9961,7 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'R': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-R\" should be followed by a file name.\n" ); + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } pPars->nRandFuncs = atoi(argv[globalUtilOptind]); @@ -9923,7 +9970,7 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'M': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-M\" should be followed by a file name.\n" ); + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } pPars->nMintNum = atoi(argv[globalUtilOptind]); diff --git a/src/base/abci/abcRunGen.c b/src/base/abci/abcRunGen.c index 9130fdad0..d82ba7fe4 100644 --- a/src/base/abci/abcRunGen.c +++ b/src/base/abci/abcRunGen.c @@ -19,7 +19,16 @@ ***********************************************************************/ #include "base/abc/abc.h" -#include "opt/cut/cut.h" +#include "base/main/main.h" +#include "base/cmd/cmd.h" +#include "misc/util/utilTruth.h" + +#ifdef WIN32 +#include +#define unlink _unlink +#else +#include +#endif ABC_NAMESPACE_IMPL_START @@ -42,8 +51,79 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ -void Acb_NtkRunGen( char * pFileNames[2], int fVerbose ) +int Abc_NtkRunGenOne( Abc_Ntk_t * p, char * pScript ) +{ + Abc_FrameReplaceCurrentNetwork( Abc_FrameGetGlobalFrame(), p ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return 0; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return 0; + } + Abc_FrameSetBatchMode( 0 ); + } + Abc_Ntk_t * pTemp = Abc_FrameReadNtk(Abc_FrameGetGlobalFrame()); + return Abc_NtkNodeNum(pTemp); +} +void Acb_NtkRunGen( int nInputs, int nMints, int nFuncs, int Seed, int fVerbose, char * pScript ) { + abctime clkStart = Abc_Clock(); + Vec_Int_t * vNodes = Vec_IntAlloc( 1000 ); + int i, k, nNodes, nWords = Abc_TtWordNum(nInputs); + word * pFun = ABC_ALLOC( word, nWords ); + Abc_Ntk_t * pNtkNew; char * pTtStr, * pSop; + Abc_Random(1); + for ( i = 0; i < 10+Seed; i++ ) + Abc_Random(0); + printf( "Synthesizing %d random %d-variable functions with %d positive minterms using script \"%s\".\n", nFuncs, nInputs, nMints, pScript ); + for ( i = 0; i < nFuncs; i++ ) + { + if ( nMints == 0 ) + for ( k = 0; k < nWords; k++ ) + pFun[k] = Abc_RandomW(0); + else { + Abc_TtClear( pFun, nWords ); + for ( k = 0; k < nMints; k++ ) { + int iMint = 0; + do iMint = Abc_Random(0) % (1 << nInputs); + while ( Abc_TtGetBit(pFun, iMint) ); + Abc_TtSetBit( pFun, iMint ); + } + } + pTtStr = ABC_CALLOC( char, nInputs > 2 ? (1 << (nInputs-2)) + 1 : 2 ); + Extra_PrintHexadecimalString( pTtStr, (unsigned *)pFun, nInputs ); + pSop = Abc_SopFromTruthHex( pTtStr ); + pNtkNew = Abc_NtkCreateWithNode( pSop ); + nNodes = Abc_NtkRunGenOne( pNtkNew, pScript ); + if ( nNodes >= Vec_IntSize(vNodes) ) + Vec_IntSetEntry( vNodes, nNodes, 0 ); + Vec_IntAddToEntry( vNodes, nNodes, 1 ); + + if ( fVerbose ) { + printf( "Iteration %3d : ", i ); + printf( "Random function has %d positive minterms ", nMints ); + printf( "and maps into %d nodes.\n", nNodes ); + if ( fVerbose ) + printf( "Truth table : %s\n", pTtStr ); + } + ABC_FREE( pTtStr ); + ABC_FREE( pSop ); + } + Vec_IntForEachEntry( vNodes, i, k ) + if ( i ) + printf( "Nodes %3d : Functions %3d Ratio %5.2f %%\n", k, i, 100.0*i/nFuncs ); + ABC_FREE( pFun ); + Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); } //////////////////////////////////////////////////////////////////////// From 01c9a65a476c45c8232244967f16779ce2d34c0b Mon Sep 17 00:00:00 2001 From: Ethan Mahintorabi Date: Mon, 2 Dec 2024 05:46:10 +0000 Subject: [PATCH 030/133] map: Add Mio_Library_t* parameter to Abc_NtkMap This lets users of the ABC API call map without relying on the static Mio_Library_t* in Abc_FrameReadLibGen. --- src/base/abci/abc.c | 7 ++++--- src/base/abci/abcMap.c | 7 ++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 39df508cf..5441eb973 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -60,6 +60,7 @@ #include "opt/sbd/sbd.h" #include "bool/rpo/rpo.h" #include "map/mpm/mpm.h" +#include "map/mio/mio.h" #include "opt/fret/fretime.h" #include "opt/nwk/nwkMerge.h" #include "base/acb/acbPar.h" @@ -19168,7 +19169,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) int fUseBuffs; int fVerbose; int c; - extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fSkipFanout, int fUseProfile, int fUseBuffs, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, Mio_Library_t* userLib, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fSkipFanout, int fUseProfile, int fUseBuffs, int fVerbose ); extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); pNtk = Abc_FrameReadNtk(pAbc); @@ -19319,7 +19320,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) } Abc_Print( 0, "The network was strashed and balanced before mapping.\n" ); // get the new network - pNtkRes = Abc_NtkMap( pNtk, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); + pNtkRes = Abc_NtkMap( pNtk, /*userLib=*/NULL, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); if ( pNtkRes == NULL ) { Abc_NtkDelete( pNtk ); @@ -19331,7 +19332,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) else { // get the new network - pNtkRes = Abc_NtkMap( pNtk, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); + pNtkRes = Abc_NtkMap( pNtk, /*userLib=*/NULL, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Mapping has failed.\n" ); diff --git a/src/base/abci/abcMap.c b/src/base/abci/abcMap.c index 0c84a04b8..07b685eea 100644 --- a/src/base/abci/abcMap.c +++ b/src/base/abci/abcMap.c @@ -59,7 +59,7 @@ static Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Sup SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fSkipFanout, int fUseProfile, int fUseBuffs, int fVerbose ) +Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, Mio_Library_t* userLib, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fSkipFanout, int fUseProfile, int fUseBuffs, int fVerbose ) { static int fUseMulti = 0; int fShowSwitching = 1; @@ -88,6 +88,11 @@ Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, double AreaMulti, Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() ); Abc_FrameSetLibSuper( NULL ); } + + if ( userLib != NULL ) { + pLib = userLib; + } + // quit if there is no library if ( pLib == NULL ) { From 7391a297bb632c9acef8b66ab5cc040211fec773 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Fri, 6 Dec 2024 18:13:32 +0800 Subject: [PATCH 031/133] Refactor(MemLeak): MemLeak fix in orchestrate --- src/base/abci/abcOrchestration.c | 35 +++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/base/abci/abcOrchestration.c b/src/base/abci/abcOrchestration.c index af36939dd..5d12a529b 100644 --- a/src/base/abci/abcOrchestration.c +++ b/src/base/abci/abcOrchestration.c @@ -3383,26 +3383,43 @@ clk = Abc_Clock(); Rwr_ManAddTimeUpdate( pManRwr, Abc_Clock() - clk ); if ( fCompl ) Dec_GraphComplement( pGraph ); ops_rwr++; + if(pFFormRef != NULL){ + Dec_GraphFree( pFFormRef ); + } + if(pFFormRes != NULL){ + Dec_GraphFree( pFFormRes ); + } continue; } // if (((! (pManRes->nLastGain < 0)) && (! (pManRes->nLastGain < nGain)) && (! (nGain < pManRef->nLastGain))) || ((! (pManRes->nLastGain < 0)) && (! (pManRes->nLastGain < pManRef->nLastGain)) && (! (pManRef->nLastGain < nGain)))){ if (((! (pManRes->nLastGain < 0)) && (! (pManRes->nLastGain < nGain)) && (! (pManRes->nLastGain < pManRef->nLastGain)))){ // update with Resub - if ( pFFormRes == NULL ) + if ( pFFormRes == NULL ) { + if (pFFormRef != NULL) { + Dec_GraphFree(pFFormRef); + } continue; + } pManRes->nTotalGain += pManRes->nLastGain; clk = Abc_Clock(); Dec_GraphUpdateNetwork( pNode, pFFormRes, fUpdateLevel, pManRes->nLastGain ); pManRes->timeNtk += Abc_Clock() - clk; Dec_GraphFree( pFFormRes ); ops_res++; + if( pFFormRef != NULL ){ + Dec_GraphFree( pFFormRef); + } continue; } // if (((! (pManRef->nLastGain < 0)) && (! (pManRef->nLastGain < nGain)) && (! (nGain < pManRes->nLastGain))) || ((! (pManRef->nLastGain < 0)) && (! (pManRef->nLastGain < pManRes->nLastGain)) && (! (pManRes->nLastGain < nGain)))){ if (((! (pManRef->nLastGain < 0)) && (! (pManRef->nLastGain < nGain)) && (! (pManRef->nLastGain < pManRes->nLastGain)))){ // update with Refactor - if ( pFFormRef == NULL ) + if ( pFFormRef == NULL ) { + if( pFFormRes != NULL) { + Dec_GraphFree(pFFormRes); + } continue; + } clk = Abc_Clock(); if ( !Dec_GraphUpdateNetwork( pNode, pFFormRef, fUpdateLevel, pManRef->nLastGain ) ) { @@ -3413,9 +3430,21 @@ clk = Abc_Clock(); pManRef->timeNtk += Abc_Clock() - clk; Dec_GraphFree( pFFormRef ); ops_ref++; + if(pFFormRes != NULL){ + Dec_GraphFree( pFFormRes ); + } + continue; + } + else{ + ops_null++; + if( pFFormRef != NULL ){ + Dec_GraphFree( pFFormRef); + } + if(pFFormRes != NULL){ + Dec_GraphFree( pFFormRes ); + } continue; } - else{ops_null++; continue;} } /* From 6754da13f27e9a84f23c4dea50b9d204754c8af9 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 8 Dec 2024 00:19:54 -0800 Subject: [PATCH 032/133] Compiler warning. --- src/aig/gia/giaAigerExt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aig/gia/giaAigerExt.c b/src/aig/gia/giaAigerExt.c index d149b0a5e..d9f86f294 100644 --- a/src/aig/gia/giaAigerExt.c +++ b/src/aig/gia/giaAigerExt.c @@ -314,7 +314,7 @@ int Gia_AigerWriteCellMappingInstance( Gia_Man_t * p, unsigned char * pBuffer, i Vec_Str_t * Gia_AigerWriteCellMappingDoc( Gia_Man_t * p ) { unsigned char * pBuffer; - int i, iFan, nCells = 0, nInstances = 0, nSize = 8, nSize2 = 0; + int i, nCells = 0, nInstances = 0, nSize = 8, nSize2 = 0; Mio_Cell2_t * pCells = Mio_CollectRootsNewDefault2( 6, &nCells, 0 ); assert( pCells ); From 8ba3d9b91c3d529223e90bcab0e9094bc015eac7 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 14 Dec 2024 13:44:18 -0800 Subject: [PATCH 033/133] Trying anothe resource limit in scorr. --- src/base/abci/abc.c | 17 +++++++++--- src/proof/ssw/ssw.h | 1 + src/proof/ssw/sswAig.c | 60 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 5441eb973..cbf98551e 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -23196,7 +23196,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Ssw_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLSIVMNXRcmplkodsefqvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLSIVMNXRBcmplkodsefqvwh" ) ) != EOF ) { switch ( c ) { @@ -23332,7 +23332,17 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nSkip < 0 ) goto usage; break; - + case 'B': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nSkipLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nSkipLimit < 0 ) + goto usage; + break; case 'c': pPars->fConstrs ^= 1; break; @@ -23454,7 +23464,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: scorr [-PQFCLSIVMNXR ] [-cmplkodsefqvwh]\n" ); + Abc_Print( -2, "usage: scorr [-PQFCLSIVMNXRB ] [-cmplkodsefqvwh]\n" ); Abc_Print( -2, "\t performs sequential sweep using K-step induction\n" ); Abc_Print( -2, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize ); Abc_Print( -2, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize ); @@ -23469,6 +23479,7 @@ usage: Abc_Print( -2, "\t-N num : set last POs to be constraints (use with -c) [default = %d]\n", nConstrs ); Abc_Print( -2, "\t-X num : the number of iterations of little or no improvement [default = %d]\n", pPars->nLimitMax ); Abc_Print( -2, "\t-R num : the number used to skip some constraints [default = %d]\n", pPars->nSkip ); + Abc_Print( -2, "\t-B num : the limit on the size of constraints to skip [default = %d]\n", pPars->nSkipLimit ); Abc_Print( -2, "\t-c : toggle using explicit constraints [default = %s]\n", pPars->fConstrs? "yes": "no" ); Abc_Print( -2, "\t-m : toggle full merge if constraints are present [default = %s]\n", pPars->fMergeFull? "yes": "no" ); Abc_Print( -2, "\t-p : toggle aligning polarity of SAT variables [default = %s]\n", pPars->fPolarFlip? "yes": "no" ); diff --git a/src/proof/ssw/ssw.h b/src/proof/ssw/ssw.h index 608b709e5..bb4ff7594 100644 --- a/src/proof/ssw/ssw.h +++ b/src/proof/ssw/ssw.h @@ -75,6 +75,7 @@ struct Ssw_Pars_t_ int fEquivDump2; // enables dumping equivalences int fStopWhenGone; // stop when PO output is not a candidate constant int nSkip; + int nSkipLimit; // optimized latch correspondence int fLatchCorrOpt; // perform register correspondence (optimized) int nSatVarMax; // max number of SAT vars before recycling SAT solver (optimized latch corr only) diff --git a/src/proof/ssw/sswAig.c b/src/proof/ssw/sswAig.c index ec744dc4b..247a614ae 100644 --- a/src/proof/ssw/sswAig.c +++ b/src/proof/ssw/sswAig.c @@ -75,6 +75,57 @@ void Ssw_FrmStop( Ssw_Frm_t * p ) ABC_FREE( p ); } +/**Function************************************************************* + + Synopsis [Computes the size of two-output cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjDeref_rec( Aig_Obj_t * pNode ) +{ + int Counter = 1; + assert( pNode->nRefs > 0 ); + if ( --pNode->nRefs > 0 ) + return 0; + assert( pNode->nRefs == 0 ); + if ( Aig_ObjIsCi(pNode) || Aig_ObjIsConst1(pNode) ) + return 0; + Counter += Aig_ObjDeref_rec( Aig_ObjFanin0(pNode) ); + Counter += Aig_ObjDeref_rec( Aig_ObjFanin1(pNode) ); + return Counter; +} +int Aig_ObjRef_rec( Aig_Obj_t * pNode ) +{ + int Counter = 1; + assert( pNode->nRefs >= 0 ); + if ( pNode->nRefs++ > 0 ) + return 0; + assert( pNode->nRefs == 1 ); + if ( Aig_ObjIsCi(pNode) || Aig_ObjIsConst1(pNode) ) + return 0; + Counter += Aig_ObjRef_rec( Aig_ObjFanin0(pNode) ); + Counter += Aig_ObjRef_rec( Aig_ObjFanin1(pNode) ); + return Counter; +} +int Aig_ManConeSize( Aig_Obj_t * pNode0, Aig_Obj_t * pNode1 ) +{ + pNode0 = Aig_Regular(pNode0); + pNode1 = Aig_Regular(pNode1); + Aig_ObjRef( pNode0 ); + Aig_ObjRef( pNode1 ); + int Count0 = Aig_ObjDeref_rec(pNode0) + Aig_ObjDeref_rec(pNode1); + int Count1 = Aig_ObjRef_rec(pNode0) + Aig_ObjRef_rec(pNode1); + Aig_ObjDeref( pNode0 ); + Aig_ObjDeref( pNode1 ); + assert( Count0 == Count1 ); + return Count0; +} + /**Function************************************************************* Synopsis [Performs speculative reduction for one node.] @@ -120,7 +171,13 @@ static inline void Ssw_FramesConstrainNode( Ssw_Man_t * p, Aig_Man_t * pFrames, // add the constraint if ( fTwoPos ) { - if ( p->pPars->nSkip == 0 ||rand() % p->pPars->nSkip == 0 ) { + if ( p->pPars->nSkipLimit ) { + if ( Aig_ManConeSize(pObjNew, pObjNew2) < p->pPars->nSkipLimit ) { + Aig_ObjCreateCo( pFrames, pObjNew2 ); + Aig_ObjCreateCo( pFrames, pObjNew ); + } + } + else if ( p->pPars->nSkip == 0 || rand() % p->pPars->nSkip == 0 ) { Aig_ObjCreateCo( pFrames, pObjNew2 ); Aig_ObjCreateCo( pFrames, pObjNew ); } @@ -193,7 +250,6 @@ Aig_Man_t * Ssw_FramesWithClasses( Ssw_Man_t * p ) // add the POs for the latch outputs of the last frame Saig_ManForEachLo( p->pAig, pObj, i ) Aig_ObjCreateCo( pFrames, Ssw_ObjFrame( p, pObj, p->pPars->nFramesK ) ); - // remove dangling nodes Aig_ManCleanup( pFrames ); // make sure the satisfying assignment is node assigned From a8c65f134343c6795ec30f97f2903635288070c2 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Tue, 17 Dec 2024 14:05:58 +0800 Subject: [PATCH 034/133] Fix(&put): &put bug with choices Related: #349 --- src/base/abci/abc.c | 2 +- src/base/abci/abcDar.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 5441eb973..6615ed33d 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -32395,7 +32395,7 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) else { Abc_Ntk_t * pNtkNoCh; - Abc_Print( -1, "Transforming AIG with %d choice nodes.\n", Gia_ManEquivCountClasses(pAbc->pGia) ); + Abc_Print( 0, "Transforming AIG with %d choice nodes.\n", Gia_ManEquivCountClasses(pAbc->pGia) ); // create network without choices pMan = Gia_ManToAig( pAbc->pGia, 0 ); pNtkNoCh = Abc_NtkFromAigPhase( pMan ); diff --git a/src/base/abci/abcDar.c b/src/base/abci/abcDar.c index a209143f3..d5ea77c78 100644 --- a/src/base/abci/abcDar.c +++ b/src/base/abci/abcDar.c @@ -1221,6 +1221,8 @@ Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) Aig_ManForEachNode( pMan, pObj, i ) { pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); + } + Aig_ManForEachNode( pMan, pObj, i ) { if ( (pTemp = Aig_ObjEquiv(pMan, pObj)) ) { assert( pTemp->pData != NULL ); From 99648e132fb975c0281d5936a998b3f1329baa2f Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Wed, 18 Dec 2024 18:43:38 +0100 Subject: [PATCH 035/133] [CEC][SimGen][CLI] Added command line function to call SimGen main function. --- src/base/abci/abc.c | 126 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index cbf98551e..551bb74e5 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -477,6 +477,7 @@ static int Abc_CommandAbc9Scorr ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Choice ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Sat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SatEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SimGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Fraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9CFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Srm ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1276,6 +1277,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&choice", Abc_CommandAbc9Choice, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sat", Abc_CommandAbc9Sat, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&satenum", Abc_CommandAbc9SatEnum, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim_gen", Abc_CommandAbc9SimGen, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&fraig", Abc_CommandAbc9Fraig, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cfraig", Abc_CommandAbc9CFraig, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&srm", Abc_CommandAbc9Srm, 0 ); @@ -39175,6 +39177,130 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [Abc_CommandAbc9SimGen] + + Description [This function calls SimGen tool] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +int Abc_CommandAbc9SimGen( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Cec_SimGenSetParDefault( Cec_ParSimGen_t * pPars ); + extern Gia_Man_t * Cec_SimGenRun( Gia_Man_t * pAig, Cec_ParSimGen_t * pPars ); + + Cec_ParSimGen_t ParsFra, * pPars = &ParsFra; Gia_Man_t * pTemp; + int c; + Cec_SimGenSetParDefault( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "OSstiwvV" ) ) != EOF ) + { + switch ( c ) + { + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + pPars->bitwidthOutgold = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->bitwidthOutgold <= 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->bitwidthSim = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->bitwidthSim <= 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->nMaxStep = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMaxStep <= 0 ) + goto usage; + break; + case 't': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-t\" should be followed by an integer.\n" ); + goto usage; + } + pPars->timeOutSim = atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMaxStep <= 0 ) + goto usage; + break; + case 'i': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-i\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMaxIter = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMaxIter <= -2 ) + goto usage; + break; + case 'w': + pPars->fUseWatchlist = 1; + break; + case 'v': + pPars->fVerbose = 1; + break; + case 'V': + pPars->fVeryVerbose = 1; + break; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Fraig(): There is no AIG.\n" ); + return 1; + } + + pTemp = Cec_SimGenRun(pAbc->pGia, pPars ); + if ( pAbc->pGia->pCexSeq != NULL ) + { + pAbc->Status = 0; + pAbc->nFrames = 0; + Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); + } + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &sim_gen [-EOSsivV ] [-v] \n" ); + Abc_Print( -2, "\t performs combinational SAT sweeping applying SimGen\n" ); + Abc_Print( -2, "\t-O num : the bitwidth of the output gold [default = %d]\n", pPars->bitwidthOutgold ); + Abc_Print( -2, "\t-S num : the bitwidth of the simulation vectors [default = %d]\n", pPars->bitwidthSim ); + Abc_Print( -2, "\t-s num : the maximum number of SimGen steps [default = %d]\n", pPars->nMaxStep ); + Abc_Print( -2, "\t-t num : the timeout value after which Smart Simulation Pattern Generation terminates [default = %.0f]\n", pPars->timeOutSim); + Abc_Print( -2, "\t-i num : the maximum number of iterations [default = %d]\n", pPars->nMaxIter ); + Abc_Print( -2, "\t-w : activates the watchlist feature [default = %d]\n", pPars->fUseWatchlist); + Abc_Print( -2, "\t-v : verbose [default = %d]\n", pPars->fVerbose ); + Abc_Print( -2, "\t-V : very verbose [default = %d]\n", pPars->fVeryVerbose ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] From 070ae52a46559db0c23c089e0330f5682907d1aa Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Wed, 18 Dec 2024 19:36:50 +0100 Subject: [PATCH 036/133] [CEC][SimGen][Custom Parameters] Added custom parameters for SimGen CEC algo --- src/proof/cec/cec.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index 10101e6c0..e14ecabe2 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -201,6 +201,27 @@ struct Cec_ParSeq_t_ int fVerbose; // verbose stats }; +// CEC SimGen parameters +typedef struct Cec_ParSimGen_t_ Cec_ParSimGen_t; +struct Cec_ParSimGen_t_ +{ + int fVerbose; // verbose flag + int fVeryVerbose; // verbose flag + int bitwidthOutgold; // bitwidth of the output gold + int bitwidthSim; // bitwidth of the simulation vectors + int nMaxStep; // maximum number of SimGen steps + int nMaxIter; // maximum number of iterations + char * outGold; // data containing outgold + float timeOutSim; // timeout for simulation + int fUseWatchlist; // use watchlist + float fImplicationTime; // time spent in implication + int nImplicationExecution; // number of times implication was executed + int nImplicationSuccess; // number of times implication was successful + int nImplicationTotalChecks; // number of times implication was checked + int nImplicationSuccessChecks; // number of times implication was successful + Cec_ParFra_t * pCECPars; // parameters of CEC +}; + //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// From cbd4456805e940f1a5bdd7416a7b3e11abd0279d Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Wed, 18 Dec 2024 19:53:44 +0100 Subject: [PATCH 037/133] [CEC][SimGen][Experiment ID] Added experiment ID option to test different experiments with simgen --- src/base/abci/abc.c | 13 ++++++++++++- src/proof/cec/cec.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 551bb74e5..1a4b58d1e 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -39198,10 +39198,21 @@ int Abc_CommandAbc9SimGen( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; Cec_SimGenSetParDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "OSstiwvV" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "EOSstiwvV" ) ) != EOF ) { switch ( c ) { + case 'E': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-E\" should be followed by an integer.\n" ); + goto usage; + } + pPars->expId = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->expId < 0 ) + goto usage; + break; case 'O': if ( globalUtilOptind >= argc ) { diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index e14ecabe2..ae9f5122c 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -207,6 +207,7 @@ struct Cec_ParSimGen_t_ { int fVerbose; // verbose flag int fVeryVerbose; // verbose flag + int expId; // experiment ID for SimGen int bitwidthOutgold; // bitwidth of the output gold int bitwidthSim; // bitwidth of the simulation vectors int nMaxStep; // maximum number of SimGen steps From 91dcfae02039f50b0f71c2d6b540732ab9ef48b9 Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Wed, 18 Dec 2024 19:56:12 +0100 Subject: [PATCH 038/133] [CEC][SimGen][Experiment ID] Added experiment ID option to test different experiments with simgen --- src/base/abci/abc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 1a4b58d1e..a5672a5ef 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -39300,6 +39300,7 @@ int Abc_CommandAbc9SimGen( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: Abc_Print( -2, "usage: &sim_gen [-EOSsivV ] [-v] \n" ); Abc_Print( -2, "\t performs combinational SAT sweeping applying SimGen\n" ); + Abc_Print( -2, "\t-E num : the experiment ID for SimGen [default = %d]\n", pPars->expId ); Abc_Print( -2, "\t-O num : the bitwidth of the output gold [default = %d]\n", pPars->bitwidthOutgold ); Abc_Print( -2, "\t-S num : the bitwidth of the simulation vectors [default = %d]\n", pPars->bitwidthSim ); Abc_Print( -2, "\t-s num : the maximum number of SimGen steps [default = %d]\n", pPars->nMaxStep ); From 0ea9929e65f1286e6aba4a27447af9bfe585ffca Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Thu, 19 Dec 2024 14:22:26 +0100 Subject: [PATCH 039/133] [CEC][SimGen][Man new data struct] Added new variables in Gia_Man to save truth tables, MFFC infos and luts rankings for simgen. Modified also the function type to extract MFFC info --- src/aig/gia/gia.h | 7 +++++++ src/aig/gia/giaResub.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index bb9e7ad7a..015a1da22 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -249,6 +249,11 @@ struct Gia_Man_t_ int iFirstPoId; int iFirstAndObj; int iFirstPoObj; + Vec_Str_t * vTTISOPs; // truth tables from ISOP computation + Vec_Int_t * vTTLut; // truth tables from ISOP computation + Vec_Int_t * vMFFCsInfo; // MFFC information + Vec_Int_t * vMFFCsLuts; // MFFCs for each lut + Vec_Ptr_t * vLutsRankings; // LUTs rankings of inputs }; @@ -1843,6 +1848,8 @@ extern void Bnd_ManPrintStats(); // util extern Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec_Bit_t* vEI_phase, Vec_Bit_t* vEO_phase ); +extern int Gia_ObjCheckMffc( Gia_Man_t * p, Gia_Obj_t * pRoot, int Limit, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t * vInners ); + ABC_NAMESPACE_HEADER_END diff --git a/src/aig/gia/giaResub.c b/src/aig/gia/giaResub.c index fc6fd7bf0..8ce2f3d33 100644 --- a/src/aig/gia/giaResub.c +++ b/src/aig/gia/giaResub.c @@ -68,7 +68,7 @@ int Gia_ObjCheckMffc_rec( Gia_Man_t * p,Gia_Obj_t * pObj, int Limit, Vec_Int_t * return 0; return 1; } -static inline int Gia_ObjCheckMffc( Gia_Man_t * p, Gia_Obj_t * pRoot, int Limit, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t * vInners ) +inline int Gia_ObjCheckMffc( Gia_Man_t * p, Gia_Obj_t * pRoot, int Limit, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t * vInners ) { int RetValue, iObj, i; Vec_IntClear( vNodes ); From 87a3cafa44e7bfd65bc768c2e2757d2034cfae59 Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Thu, 19 Dec 2024 14:23:19 +0100 Subject: [PATCH 040/133] [CEC][SimGen][Main Algo] Added main algorithm of SimGen and all necessary utility functions --- src/proof/cec/cecSatG2.c | 2202 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 2202 insertions(+) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 554fd550d..65aa6be0c 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -21,6 +21,9 @@ #include "aig/gia/gia.h" #include "misc/util/utilTruth.h" #include "cec.h" +#include "bdd/extrab/extraBdd.h" +#include "base/abc/abc.h" +#include "map/if/if.h" #define USE_GLUCOSE2 @@ -222,6 +225,38 @@ void Cec4_ManSetParams( Cec_ParFra_t * pPars ) pPars->fBMiterInfo = 0; // printing BMiter information } +/**Function************************************************************* + + Synopsis [Default parameter settings.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_SimGenSetParDefault( Cec_ParSimGen_t * pPars ) +{ + memset( pPars, 0, sizeof(Cec_ParSimGen_t) ); + pPars->fVerbose = 0; // verbose output + pPars->fVeryVerbose = 0; // verbose output and outputs files + pPars->bitwidthOutgold = 2; // bitwidth of the output golden model + pPars->bitwidthSim = 31; // bitwidth of the simulation vectors + pPars->expId = 1; // experiment ID + pPars->nMaxStep = 20; // the maximum number of steps + pPars->nMaxIter = -1; // the maximum number of iterations + pPars->timeOutSim = 1000.0; // the timeout for simulation in sec + pPars->fUseWatchlist = 0; // use watchlist + pPars->fImplicationTime = 0.0; // time spent in implication + pPars->nImplicationExecution = 0; // the number of implication executions + pPars->nImplicationSuccess = 0; // the number of implication successes + pPars->nImplicationTotalChecks = 0; // the number of implication checks + pPars->nImplicationSuccessChecks = 0; // the number of implication successful checks + pPars->pCECPars = (Cec_ParFra_t *) malloc(sizeof( Cec_ParFra_t )); // parameters of CEC + Cec4_ManSetParams( pPars->pCECPars ); +} + /**Function************************************************************* Synopsis [] @@ -2186,6 +2221,2173 @@ void Cec4_ManSimulateTest5( Gia_Man_t * p, int nConfs, int fVerbose ) Gia_ManStop( pAig ); } +/**Function************************************************************* + + Synopsis [Get ISOP LUT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void getISOPObjId( Gia_Man_t * pMan, int ObjId, char * pSop[2] , int nCubes[2] ){ + + assert( Gia_ObjIsLut(pMan, ObjId)); + char * pSopInfo = pMan->vTTISOPs->pArray + Vec_IntEntry( pMan->vTTLut, ObjId ); + int k; + // get the ISOPs positive polarity + for(k = 0; k < 2; k++ ){ + nCubes[k] = *pSopInfo; + pSopInfo++; + if(nCubes[k] == 0){ + pSop[k] = NULL; + continue; + } + pSop[k] = pSopInfo; + pSopInfo += nCubes[k] * 2; + } +} + + +/**Function************************************************************* + + Synopsis [Encode SOPs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +Vec_Str_t * encodeSOP(char * pSop, int nFanins, int nCubes){ + + Vec_Str_t * vSop = Vec_StrAlloc( nCubes * 2 ); + char pEncodeCube = 0; + char pDCs = 0; + int fanin=0; + while( *pSop != '\0'){ + if( *pSop == '\0') + continue; + if ( *pSop == '-' ){ + //pDCs |= ( 1 << (nFanins - fanin - 1) ); + pDCs |= ( 1 << fanin ); + } else if ( *pSop == '1' ){ + //pEncodeCube |= ( 1 << (nFanins - fanin - 1) ); + pEncodeCube |= ( 1 << fanin ); + } + fanin++; + if(fanin == nFanins){ + Vec_StrPush( vSop, pEncodeCube ); + Vec_StrPush( vSop, pDCs ); + pEncodeCube = 0; + pDCs = 0; + fanin = 0; + pSop += 3; + } + pSop++; + } + return vSop; + +} + +/**Function************************************************************* + + Synopsis [Extract SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +char * extractSOP( DdManager * dd, DdNode * bFunc, int nFanins, int polarity, int * _nCubes){ + + Vec_Str_t * vCube = Vec_StrAlloc( 100 ); + int nCubes; char * pSop; + DdNode * bCover, * zCover; + if( polarity == 0){ + bCover = Cudd_zddIsop( dd, Cudd_Not(bFunc), Cudd_Not(bFunc), &zCover ); + } else { + bCover = Cudd_zddIsop( dd, bFunc, bFunc, &zCover ); + } + Cudd_Ref( zCover ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + nCubes = Abc_CountZddCubes( dd, zCover ); + pSop = ABC_ALLOC( char, (nFanins + 3) * nCubes + 1 ); + pSop[(nFanins + 3) * nCubes] = 0; + // create the SOP + Vec_StrFill( vCube, nFanins, '-' ); + Vec_StrPush( vCube, '\0' ); + Abc_ConvertZddToSop( dd, zCover, pSop, nFanins, vCube, polarity ); + Cudd_RecursiveDerefZdd( dd, zCover ); + + if ( pSop == NULL || nFanins != Abc_SopGetVarNum( pSop )){ + if ( pSop == NULL ) + printf("SOP generation failed.\n"); + else { + ABC_FREE( pSop ); + printf( "Node has %d fanins but its SOP has support size %d.\n", nFanins, Abc_SopGetVarNum( pSop )); + } + fflush( stdout ); + Vec_StrFree( vCube ); + return NULL; + } + + Vec_StrFree( vCube ); + *_nCubes = nCubes; + return pSop; +} + +/**Function************************************************************* + + Synopsis [Compute ISOPs of both polarities.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void computeISOPs( Gia_Man_t * p, Abc_Ntk_t * pNtkNew ){ + + Abc_Obj_t * pObjNew; + DdManager * dd = (DdManager *)pNtkNew->pManFunc; + DdNode * bFunc; + char * pSop; + DdNode * bCover; + int nCubes, i, jjj; + Vec_Str_t * encodedSop; + // compute SOP sizes + Vec_Int_t * vGuide = Vec_IntAlloc( Abc_NtkObjNumMax(pNtkNew) ); + Vec_IntFill( vGuide, Abc_NtkObjNumMax(pNtkNew), -1 ); + // Collect BDDs in array + Vec_Ptr_t * vFuncs = Vec_PtrStart( Abc_NtkObjNumMax(pNtkNew) ); + assert( !Cudd_ReorderingStatus(dd, (Cudd_ReorderingType *)&nCubes) ); + Abc_NtkForEachNode( pNtkNew, pObjNew, i ) + if ( !Abc_ObjIsBarBuf(pObjNew) ) + Vec_PtrWriteEntry( vFuncs, i, pObjNew->pData ); + // compute the number of cubes in the ISOPs and detemine polarity + nCubes = Extra_bddCountCubes( dd, (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs), -1, ABC_INFINITY, Vec_IntArray(vGuide) ); + Vec_PtrFree( vFuncs ); + assert( Abc_NtkHasBdd(pNtkNew) ); + if ( dd->size > 0 ) + Cudd_zddVarsFromBddVars( dd, 2 ); + + // go through the objects + Abc_NtkForEachNode( pNtkNew, pObjNew, i ) + { + // derive ISOPs in both polarities + if ( Abc_ObjIsBarBuf(pObjNew) ) + continue; + assert( pObjNew->pData ); + bFunc = (DdNode *)pObjNew->pData; + int nFanins = Abc_ObjFaninNum(pObjNew); + assert( nFanins <= 8); // we only support 8 fanins due to the data structure of vTTISOPs + // Check if node function is constant + if ( Cudd_IsConstant(bFunc) ){ + pSop = ABC_ALLOC( char, nFanins + 4 ); + pSop[0] = ' '; + pSop[1] = '0' + (int)(bFunc == Cudd_ReadOne(dd)); + pSop[2] = '\n'; + pSop[3] = '\0'; + ABC_FREE( pSop ); + // it's not a LUT, it should be skipped + continue; + } + // save location of the ISOP info in vTTISOPs + Vec_IntInsert( p->vTTLut, pObjNew->iTemp , p->vTTISOPs->nSize ); + + // get the ZDD of the negative polarity + pSop = extractSOP( dd, bFunc, nFanins, 0 , &nCubes); + if ( pSop == NULL ) + goto cleanup; + // encode the sop and save it in the vTTISOPs + encodedSop = encodeSOP( pSop, nFanins, nCubes ); + Vec_StrPush( p->vTTISOPs, (char) nCubes ); + if (nCubes > 0){ + for (jjj = 0; jjj < nCubes; jjj++){ + Vec_StrPush( p->vTTISOPs, encodedSop->pArray[jjj*2] ); Vec_StrPush( p->vTTISOPs, encodedSop->pArray[jjj*2+1] ); + } + } + Vec_StrFree( encodedSop ); + ABC_FREE( pSop ); + + // get the ZDD of the positive polarity + pSop = extractSOP( dd, bFunc, nFanins, 1 , &nCubes); + if ( pSop == NULL ) + goto cleanup; + // encode the sop and save it in the vTTISOPs + encodedSop = encodeSOP( pSop, nFanins, nCubes ); + Vec_StrPush( p->vTTISOPs, (char) nCubes ); + if (nCubes > 0){ + for (jjj = 0; jjj < nCubes; jjj++){ + Vec_StrPush( p->vTTISOPs, encodedSop->pArray[jjj*2] ); Vec_StrPush( p->vTTISOPs, encodedSop->pArray[jjj*2+1] ); + } + } + Vec_StrFree( encodedSop ); + ABC_FREE( pSop ); + + } + + +cleanup: + // free all used memory to generate SOPs + Vec_IntFree( vGuide ); + Abc_NtkDelete( pNtkNew ); + return; +} + + +/**Function************************************************************* + + Synopsis [Derive SOPs with positive and negative polarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +void Cec_DeriveSOPs( Gia_Man_t * p ){ + + // generate the structure to contain LUT ids and their corresponding TTISOPS + int nCountLuts = Gia_ManLutNum(p); + p->vTTISOPs = Vec_StrAlloc( nCountLuts * 10); + p->vTTLut = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( p->vTTLut, Gia_ManObjNum(p), -1 ); + + // Transform the Gia into a HOP network + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjNew, * pObjNewLi, * pObjNewLo, * pConst0 = NULL; + Gia_Obj_t * pObj, * pObjLi, * pObjLo; + Vec_Ptr_t * vReflect = Vec_PtrStart( Gia_ManObjNum(p) ); + int i, k, jjj, iFan, nDupGates, nCountMux = 0; + assert( Gia_ManHasMapping(p) ); + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_AIG, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(p->pName); + pNtkNew->pSpec = Extra_UtilStrsav(p->pSpec); + Gia_ManFillValue( p ); + // create constant + pConst0 = Abc_NtkCreateNodeConst0( pNtkNew ); + Gia_ManConst0(p)->Value = Abc_ObjId(pConst0); + // create PIs + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Abc_ObjId( Abc_NtkCreatePi( pNtkNew ) ); + // create POs + Gia_ManForEachPo( p, pObj, i ) + pObj->Value = Abc_ObjId( Abc_NtkCreatePo( pNtkNew ) ); + // create as many latches as there are registers in the manager + Gia_ManForEachRiRo( p, pObjLi, pObjLo, i ) + { + pObjNew = Abc_NtkCreateLatch( pNtkNew ); + pObjNewLi = Abc_NtkCreateBi( pNtkNew ); + pObjNewLo = Abc_NtkCreateBo( pNtkNew ); + Abc_ObjAddFanin( pObjNew, pObjNewLi ); + Abc_ObjAddFanin( pObjNewLo, pObjNew ); + pObjLi->Value = Abc_ObjId( pObjNewLi ); + pObjLo->Value = Abc_ObjId( pObjNewLo ); + Abc_LatchSetInit0( pObjNew ); + } + Gia_ManForEachLut( p, i ) + { + pObj = Gia_ManObj(p, i); + assert( pObj->Value == ~0 ); + if ( Gia_ObjLutSize(p, i) == 0 ) + { + pObj->Value = Abc_ObjId(pConst0); + continue; + } + pObjNew = Abc_NtkCreateNode( pNtkNew ); + Gia_LutForEachFanin( p, i, iFan, k ) + Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtkNew, Gia_ObjValue(Gia_ManObj(p, iFan))) ); + pObjNew->pData = Abc_ObjHopFromGia( (Hop_Man_t *)pNtkNew->pManFunc, p, i, vReflect ); + pObjNew->fPersist = 0; + pObj->Value = Abc_ObjId( pObjNew ); + pObjNew->iTemp = i; + } + + Vec_PtrFree( vReflect ); + + // HOP -> BDD + Abc_NtkAigToBdd(pNtkNew); + + // Determine both polarity ISOPs + computeISOPs( p, pNtkNew ); + + return; + +} + +/**Function************************************************************* + + Synopsis [Compute MFFCs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void computeMFFCs( Gia_Man_t * p ){ + + + int i, ith_fan, iFan; + Vec_Int_t * vNodes, * vLeaves, * vInners; + vNodes = Vec_IntAlloc( 100 ); + vLeaves = Vec_IntAlloc( 10 ); + vInners = Vec_IntAlloc( 100 ); + Vec_Int_t * vNodesNew, * vLeavesNew, * vInnersNew; + vNodesNew = Vec_IntAlloc( 100 ); + vLeavesNew = Vec_IntAlloc( 10 ); + vInnersNew = Vec_IntAlloc( 100 ); + p->vMFFCsLuts = Vec_IntStartFull( Gia_ManObjNum(p) ); + //Vec_IntFill( p->vMFFCsLuts, Gia_ManObjNum(p), -1 ); + p->vMFFCsInfo = Vec_IntAlloc( Gia_ManLutNum(p) * 5 ); + Gia_ManCreateRefs( p ); + Gia_ManForEachLut( p, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, i ); + + if ( !Gia_ObjRefNum(p, pObj) ) + continue; + if ( !Gia_ObjCheckMffc(p, pObj, 10000, vNodes, vLeaves, vInners) ) + continue; + + Vec_IntInsert( p->vMFFCsLuts, i , Vec_IntSize(p->vMFFCsInfo) ); + Gia_LutForEachFanin( p, i, iFan, ith_fan ){ + if (Vec_IntFind(vNodes, iFan) != -1){ + if(Gia_ObjIsCi(Gia_ManObj(p, iFan)) == 1){ + Vec_IntPush(p->vMFFCsInfo, Gia_ObjLevelId(p, i) ); // push the level of the CI + continue; + } + Gia_Obj_t * pObjFanin = Gia_ManObj( p, iFan ); + if ( !Gia_ObjRefNum(p, pObjFanin) ){ + Vec_IntPush(p->vMFFCsInfo, 0); + continue; + } + if ( !Gia_ObjCheckMffc(p, pObjFanin, 10000, vNodesNew, vLeavesNew, vInnersNew)){ + Vec_IntPush(p->vMFFCsInfo, 0); + continue; + } + assert( Vec_IntSize(vLeavesNew) > 0); + int quality = evaluate_mffc(p, i, iFan, vLeavesNew); + Vec_IntPush(p->vMFFCsInfo, quality); + + } else { + Vec_IntPush( p->vMFFCsInfo, 0 ); + } + + } + } + Vec_IntFree( vNodes ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vInners ); + Vec_IntFree( vNodesNew ); + Vec_IntFree( vLeavesNew ); + Vec_IntFree( vInnersNew ); + +} +/**Function************************************************************* + + Synopsis [Evaluate MFFC depth.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +int evaluate_mffc(Gia_Man_t * p, int rootId, int fanId, Vec_Int_t * vLeaves){ + + int quality = 0, jMFFCLeaf; + int nLeaves = Vec_IntSize(vLeaves); + for(jMFFCLeaf = 0; jMFFCLeaf < nLeaves ; jMFFCLeaf++){ + int idMFFCLeaf = Vec_IntEntry(vLeaves, jMFFCLeaf); + int level_leaf = Gia_ObjLevelId(p, idMFFCLeaf) ; + int level_root = Gia_ObjLevelId(p, fanId) ; + quality += level_root - level_leaf; + } + if( quality != 0 && nLeaves > 0) + quality /= nLeaves; + return quality; + +} + +/**Function************************************************************* + + Synopsis [Evaluate MFFC depth.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +int extract_quality_mffc(Gia_Man_t * p, int ObjId, char pDCs){ + + if( Vec_IntEntry( p->vMFFCsLuts, ObjId ) == -1) + return 0; + assert( Vec_IntEntry( p->vMFFCsLuts, ObjId ) != -1); + int * pMFFC = p->vMFFCsInfo->pArray + Vec_IntEntry( p->vMFFCsLuts, ObjId ); + int iFan, ith_fan, qualityMFFC, quality = 0; + int nFanins = Gia_ObjLutSize(p, ObjId); + Gia_LutForEachFanin( p, ObjId, iFan, ith_fan ){ + int qualityMFFC = *pMFFC; + if (qualityMFFC == 0 || (pDCs & (1 << ith_fan)) > 0){ // count the cones without don't cares + pMFFC++; + continue; + } + quality += qualityMFFC; + pMFFC++; + } + return quality; + +} + +/**Function************************************************************* + + Synopsis [Generate LUTs Ranking for SimGen algo.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +int * sortArray( int * array, int n ){ + + int i, j, temp; + int * positions = (int *) malloc( n * sizeof(int) ); + for(i = 0; i < n; i++) + positions[i] = i; + for(i = 0; i < n; i++){ + for(j = i+1; j < n; j++){ + if(array[i] < array[j]){ + temp = array[i]; + array[i] = array[j]; + array[j] = temp; + temp = positions[i]; + positions[i] = positions[j]; + positions[j] = temp; + } + } + } + return positions; + +} + +void generateLutsRankings( Gia_Man_t * p){ + + p->vLutsRankings = Vec_PtrStart( Gia_ManObjNum(p) ); + Vec_Int_t * vLutsRankingsTmp = Vec_IntAlloc( Gia_ManLutNum(p) * 5 ); + int LutId, iii, k, jjj; + char * pSop[2]; int nCubes[2]; int nFanins; + Gia_ManForEachLut( p, LutId ) + { + nFanins = Gia_ObjLutSize(p, LutId); + Vec_PtrInsert( p->vLutsRankings, LutId, vLutsRankingsTmp->pArray + Vec_IntSize(vLutsRankingsTmp) ); + int ranks[nFanins]; + int fanins[nFanins]; + Gia_LutForEachFanin( p, LutId, k, iii ){ + fanins[iii] = k; + ranks[iii] = 0; + } + + nFanins = Gia_ObjLutSize(p, LutId); + getISOPObjId( p, LutId, pSop, nCubes ); + for(k = 0; k < 2; k++){ + for(iii = 0; iii < nCubes[k]; iii++){ + char pCube = pSop[k][iii*2]; char pDCs = pSop[k][iii*2+1]; + for(jjj = 0; jjj < nFanins; jjj++){ + if ( (pDCs & (1 << jjj)) == 0 ) + ranks[jjj]++; + } + } + } + int * positions = sortArray( ranks, nFanins ); + for(jjj = 0; jjj < nFanins; jjj++){ + Vec_IntPush( vLutsRankingsTmp, fanins[positions[jjj]] ); + } + free( positions ); + } + //Vec_IntFree( vLutsRankingsTmp ); +} + +/**Function************************************************************* + + Synopsis [Generate Nodes Watchlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +Vec_Ptr_t * generateWatchList( Gia_Man_t * p ){ + + Vec_Ptr_t * vWatchList = Vec_PtrStart( Gia_ManObjNum(p) ); + int LutId; + Gia_ManForEachLut( p, LutId ) + { + int * ranking = (int *) Vec_PtrEntry( p->vLutsRankings, LutId ); + int nodeId = ranking[0]; + if( Vec_PtrEntry( vWatchList, nodeId ) == NULL ){ + Vec_Int_t * vWatchListTmp = Vec_IntAlloc( 5 ); + Vec_PtrWriteEntry( vWatchList, nodeId, vWatchListTmp ); + Vec_IntPush( vWatchListTmp, LutId ); + //Vec_IntFree( vWatchListTmp ); + } else { + Vec_IntPush( (Vec_Int_t *) Vec_PtrEntry( vWatchList, nodeId ), LutId ); + } + } + return vWatchList; +} + +/**Function************************************************************* + + Synopsis [Fill in the fanout vectors for the LUTs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void Gia_generateFanoutMapping( Gia_Man_t * p ) +{ + int iObj, iFanin, k; + assert( Gia_ManHasMapping(p) ); + Vec_WecFreeP( &p->vFanouts2 ); + p->vFanouts2 = Vec_WecStart( Gia_ManObjNum(p) ); + Gia_ManForEachLut( p, iObj ) + { + Gia_LutForEachFanin( p, iObj, iFanin, k ) + { + Vec_WecPush( p->vFanouts2, iFanin, iObj ); + } + } +} + +/**Function************************************************************* + + Synopsis [Remove all non-LUT nodes from equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +void Cec_RemoveNonLutNodes( Gia_Man_t * p){ + + int i, iRepr, kElement, firstLutId, prevLutId; + Vec_Int_t * vLutIds = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManForEachClass0( p, iRepr ) + { + Gia_ClassForEachObj1( p, iRepr, kElement ){ + Vec_IntPush( vLutIds, kElement ); + } + + firstLutId = -1; prevLutId = -1; + if( !Gia_ObjIsLut(p, iRepr) ){ + Gia_ObjSetRepr( p, iRepr, GIA_VOID ); + Gia_ObjSetNext( p, iRepr, 0 ); + } else { + firstLutId = iRepr; + prevLutId = iRepr; + } + Vec_IntForEachEntry( vLutIds, kElement, i ){ + + if( !Gia_ObjIsLut(p, kElement) ){ + Gia_ObjSetRepr( p, kElement, GIA_VOID ); + Gia_ObjSetNext( p, kElement, 0 ); + continue; + } + if(firstLutId == -1){ + Gia_ObjSetRepr( p, kElement, GIA_VOID ); + firstLutId = kElement; + prevLutId = kElement; + } else { + Gia_ObjSetRepr( p, kElement, firstLutId ); + Gia_ObjSetNext( p, prevLutId , kElement ); + prevLutId = kElement; + } + } + Vec_IntClear( vLutIds ); + // no lut found + if(firstLutId == -1){ + continue; + } + Gia_ObjSetNext( p, prevLutId, 0 ); + + } + Vec_IntFree( vLutIds ); +} + +/**Function************************************************************* + + Synopsis [Simulate the CIs with random values with specific bitwidth.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +static inline void Cec_ObjSimCiSimGen( Gia_Man_t * p, int iObj , int bitwidth) +{ + int w; + word * pSim = Cec4_ObjSim( p, iObj ); + word wMask = (1 << bitwidth) -1; + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = Abc_RandomW( 0 ) & wMask; + pSim[0] <<= 1; +} + +void Cec_ManSimulateCisSimGen( Gia_Man_t * p, int bitwidth ) +{ + int i, Id; + Gia_ManForEachCiId( p, Id, i ) + Cec_ObjSimCiSimGen( p, Id , bitwidth); + p->iPatsPi = 0; +} + +/**Function************************************************************* + + Synopsis [Simulate the CIs with random values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +void executeRandomSim( Gia_Man_t * p, Cec4_Man_t * pMan , int dynSim, int nMaxIter , int bitwidthSim , int verbose ){ + + clock_t start_time = clock(); + int i; + int numClass = 100000; + int oldNumClass = 0, iMaxNumber = 200, iNumber = 0; + if(dynSim){ + while (numClass != oldNumClass && iNumber < iMaxNumber) + { + oldNumClass = numClass; + Cec_ManSimulateCisSimGen( p, bitwidthSim ); + Cec4_ManSimulate( p, pMan ); + int quality = evaluate_equiv_classes(p, 0); + if (verbose) + printf("Time elapsed: %f (classes size: %d)\n", (float)(clock() - start_time)/CLOCKS_PER_SEC, quality); + numClass = totalNumClasses(p); + iNumber++; + } + + + } else { + for(i = 0; i < nMaxIter; i++){ + Cec_ManSimulateCisSimGen( p, bitwidthSim ); + Cec4_ManSimulate( p, pMan ); + int quality = evaluate_equiv_classes(p, 0); + Cec_RemoveNonLutNodes( p ); + if (verbose) + printf("Time elapsed: %f (classes size: %d)\n", (float)(clock() - start_time)/CLOCKS_PER_SEC, quality); + } + } +} + +/**Function************************************************************* + + Synopsis [Evaluate equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +int evaluate_equiv_classes(Gia_Man_t * p, int verbose){ + + int i, k; + int quality = 0; + Gia_ManForEachClass0( p, i ) + { + Gia_ClassForEachObj1( p, i, k ){ + quality++; + } + } + + if (verbose) + printf("**Quality = %d\n", quality); + + return quality; +} + +/**Function************************************************************* + + Synopsis [Export Equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void exportEquivClasses(Gia_Man_t * p, char * filename){ + + FILE * pFile; + pFile = fopen( filename, "wb" ); + Gia_Obj_t * pObj; int i, j, iii = 0; + Gia_ManForEachClass0( p, i ) + { + fprintf( pFile, "Class %d: %d ", iii , i); + Gia_ClassForEachObj1( p, i, j ){ + fprintf( pFile, " %d ", j ); + } + fprintf(pFile, "\n"); + iii++; + } + fclose( pFile ); + + +} + +/**Function************************************************************* + + Synopsis [Compute total number of classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +int totalNumClasses(Gia_Man_t * p){ + int iRepr; + int numClasses = 0; + Gia_ManForEachClass0( p, iRepr ){ + numClasses++; + } + return numClasses; +} + + +/**Function************************************************************* + + Synopsis [Generate the output golden values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +char * generateOutGoldValues(Gia_Man_t * p){ + + char * pOutGold = (char *) malloc( sizeof(char) * Gia_ManObjNum(p) ); + int i, k; + Gia_Obj_t * pObj; + int cnt = 85; // 0b01010101 + Gia_ManForEachLut( p, i ){ + pOutGold[i] = (char) 0; + } + Gia_ManForEachClass0( p, i ){ + pOutGold[i] = (char) cnt; + cnt ^= 1; + Gia_ClassForEachObj1( p, i, k ){ + pOutGold[k] = (char) cnt; + cnt ^= 1; + } + } + return pOutGold; + +} + +/**Function************************************************************* + + Synopsis [Check if it exists at least one class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +int existsOneClass(Gia_Man_t * p){ + int iRepr; + Gia_ManForEachClass0( p, iRepr ){ + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Extract nth equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +Vec_Int_t * extractNthClass(Gia_Man_t * p, int nth_class){ + + Vec_Int_t * vClass = Vec_IntAlloc( Gia_ManLutNum(p) ); + int iRepr, jLut, iii; + Gia_ManForEachClass0( p, iRepr ){ + if(nth_class == 0){ + Vec_IntPush(vClass, iRepr); + Gia_ClassForEachObj1( p, iRepr, jLut ) + Vec_IntPush(vClass, jLut); + break; + } + nth_class--; + } + assert(Vec_IntSize(vClass) > 0); + return vClass; + +} + +/**Function************************************************************* + + Synopsis [Compute the LUTs order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +Vec_Int_t * computeLutsOrder(Gia_Man_t * p, int reorder_type){ + + Vec_Int_t * luts_order = Vec_IntAlloc( Gia_ManLutNum(p) ); + int * luts_tmp = (int *) malloc( sizeof(int) * Gia_ManLutNum(p)); + int iRepr, jLut, iii, jjj, kkk; + Gia_Obj_t * pObj; + Gia_ManForEachClass0( p, iRepr ){ + luts_tmp[ 0 ] = iRepr; + iii = 1; + Gia_ClassForEachObj1( p, iRepr, jLut ){ + if(reorder_type == 0){ // decreasing level order + int found = 0; + for(jjj = 0; jjj < iii; jjj++){ + if(Gia_ObjLevel(p, jLut) <= Gia_ObjLevel(p, luts_tmp[jjj])){ + for (kkk = iii; kkk > jjj; kkk--) { + luts_tmp[kkk] = luts_tmp[kkk - 1]; + } + luts_tmp[jjj] = jLut; + found = 1; + break; + } + } + if(!found){ + luts_tmp[iii] = jLut; + } + iii++; + } else if(reorder_type == 1) { // increasing level order + int found = 0; + for(jjj = 0; jjj < iii; jjj++){ + if(Gia_ObjLevel(p, jLut) >= Gia_ObjLevel(p, luts_tmp[jjj])){ + for (kkk = iii; kkk > jjj; kkk--) { + luts_tmp[kkk] = luts_tmp[kkk - 1]; + } + luts_tmp[jjj] = jLut; + found = 1; + break; + } + } + if(!found){ + luts_tmp[iii] = jLut; + } + iii++; + } + } + for(kkk = 0; kkk < iii; kkk++) + Vec_IntPush(luts_order, luts_tmp[kkk] ); + } + free(luts_tmp); + return luts_order; + +} + + +/**Function************************************************************* + + Synopsis [Compute the fanin cones.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +void computeFaninCones_rec(Gia_Man_t * p, int ObjId, Vec_Int_t * vLutsFaninCones ){ + + int FaninId, jth_fanin; + Gia_LutForEachFanin( p, ObjId, FaninId, jth_fanin ){ + if( Vec_IntEntry( vLutsFaninCones, FaninId ) == 0 ){ + Vec_IntWriteEntry( vLutsFaninCones, FaninId, 1 ); + if( Gia_ObjIsCi( Gia_ManObj(p, FaninId) ) == 0 ) + computeFaninCones_rec( p, FaninId, vLutsFaninCones ); + } + } +} + +Vec_Int_t * computeFaninCones( Gia_Man_t * p, Vec_Int_t * vLuts ){ + + int i, FaninId, jth_fanin; + Gia_Obj_t * pObj; + Vec_Int_t * vLutsFaninCones = Vec_IntStart(Gia_ManObjNum(p)); + Vec_IntForEachEntry( vLuts, i, jth_fanin ){ + computeFaninCones_rec( p, i, vLutsFaninCones ); + } + return vLutsFaninCones; + +} + + +/**Function************************************************************* + + Synopsis [Check compatibility ISOP and Vec.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +int checkCompatibilityCube( Gia_Man_t * pMan, char * pCube, int nFanins, char * pCubeGold ){ + + // double check this function!!!! + + + int i; + char pCubeOnes = *pCube; char pDCs = *(pCube+1); + char pCubeGoldOnes = *pCubeGold; char pCubeNotAssigned = *(pCubeGold+1); + + char pSkipBits = pDCs | pCubeNotAssigned; + char pConflictBits = pCubeOnes ^ pCubeGoldOnes; + char isConflict = ~pSkipBits & pConflictBits; + if ( isConflict ) + return 0; + + return 1; + +} + + +/**Function************************************************************* + + Synopsis [Compute quality of SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +int compute_quality_sop(Gia_Man_t * p , char * pSop, int ObjId ,int nFanins, int experimentID){ + + int quality = 0; + char pValues = *pSop; + pSop++; + char pDCs = *(pSop); + switch (experimentID){ + case 1: // Reverse Simulation + case 2: // Simple Implication + case 3: // Advanced Implication + break; + case 4: // Advanced Implication + Count DCs + while (pDCs > 0){ + if(pDCs & 1 == 1) + quality += p->nLevels * 5; // the presence of DCs is more important than mffc + pDCs = pDCs >> 1; + } + break; + case 5: // Advanced Implication + Count DC + FFC + while (pDCs > 0){ + if(pDCs & 1 == 1) + quality += p->nLevels * 5; // the presence of DCs is more important than mffc + pDCs = pDCs >> 1; + } + pDCs = *(pSop); + quality += extract_quality_mffc(p, ObjId, pDCs); + break; + default: + break; + } + return quality; +} + + +/**Function************************************************************* + + Synopsis [Execute roulette wheel.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +int rouletteWheel( Vec_Int_t * vQualitySops, int numValid){ + + int i; + int candidateRows[numValid]; + float totalSum; + totalSum = 0.0; + for ( i = 0; i < numValid; i++ ) + totalSum += (float) Vec_IntEntry(vQualitySops, i); + + unsigned int randValue = Aig_ManRandom(0); + float randValueNormalized = (float) ((float)randValue / __UINT32_MAX__); + float randomNum = randValueNormalized * totalSum; + + // Select the index based on inverse proportional probability + float cumulativeProbability = 0.0; + for ( i = 0; i < numValid; i++ ) { + cumulativeProbability += Vec_IntEntry(vQualitySops, i); + if (cumulativeProbability > randomNum) { + return i; + } + } + return -1; +} + +/**Function************************************************************* + + Synopsis [Select SOP depending on quality value and the experimentID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +int selectSop( Vec_Int_t * vQualitySops, int ith_max_quality, int experimentID){ + + assert(experimentID > 0); // random simulation should not be used here + int numValid = Vec_IntSize(vQualitySops); + int idSelected = -1, iii, jQuality; + switch (experimentID){ + //case 1: + // idSelected = Aig_ManRandom(0) % numValid; + // break; + default: + idSelected = rouletteWheel( vQualitySops, numValid); + break; + } + if(idSelected == -1){ + idSelected = ith_max_quality; + } + assert( idSelected != -1); + return idSelected; +} + +/**Function************************************************************* + + Synopsis [Check implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +int check_implication( Gia_Man_t * p, int ObjId , int validBit , int fanoutValue, int fanoutNotSet, char * inputsFaninsValues, char * networkValues1s, char * networkValuesNotSet , int experimentID){ + + assert(experimentID > 1); + int ith_cube, jjj; + int nFanins = Gia_ObjLutSize(p, ObjId); + char * pSopBoth[2]; int nCubesBoth[2]; + getISOPObjId( p, ObjId, pSopBoth, nCubesBoth ); + + if (fanoutNotSet == 0){ + // case in which the output is set // backward implication + char * pSop = pSopBoth[fanoutValue]; + int nCubes = nCubesBoth[fanoutValue]; + char * pValue = pSop; + int compatible = 0; + int lastCube = 0; + for(ith_cube = 0; ith_cube < nCubes; ith_cube++){ + if(checkCompatibilityCube( p, pSop + ith_cube * 2, nFanins, inputsFaninsValues ) ){ + compatible++; + lastCube = ith_cube; + } + } + + + if(compatible == 1){ + char selectedSop = *(pSop + lastCube * 2); + char selectedDCs = *(pSop + lastCube * 2 + 1); + assert(0); // to finish implementing + return 1; + } else if (compatible == 0){ + return -1; + } + + return 0; + } + // forward implication + int compatible[2]; + compatible[0] = 0; + compatible[1] = 0; + for(jjj = 0; jjj < 2; jjj++){ + + char * pSop = pSopBoth[jjj]; + int nCubes = nCubesBoth[jjj]; + char * pValue = pSop; + for(ith_cube = 0; ith_cube < nCubes; ith_cube++){ + if(checkCompatibilityCube( p, pSop + ith_cube * 2, nFanins, inputsFaninsValues ) ){ + compatible[jjj]++; + if(compatible[jjj] > 1) + break; + } + } + } + + if(compatible[0] > 0 && compatible[1] > 0){ + return 0; + } else if (compatible[0] == 0 && compatible[1] == 0){ + return -1; + } + + if(experimentID == 2){ + // simple implication + if(compatible[0] > 1 || compatible[1] > 1){ + return 0; + } + char mask = 1 << validBit; + if(compatible[0] == 1){ + networkValuesNotSet[ObjId] &= (~mask); + } else { + networkValues1s[ObjId] |= (1 << validBit); + networkValuesNotSet[ObjId] &= (~mask); + } + return 1; + } else if (experimentID > 2){ + // advanced implication + char mask = 1 << validBit; + if(compatible[0] >= 1){ + networkValuesNotSet[ObjId] &= (~mask); + } else { + networkValues1s[ObjId] |= (1 << validBit); + networkValuesNotSet[ObjId] &= (~mask); + } + return 1; + } + + assert(0); + +} + + +/**Function************************************************************* + + Synopsis [Check compatibility of cubes for implications.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +int checkCompatibilityImplication( Gia_Man_t * p, Cec_ParSimGen_t * pPars, char * netValid, int objId, char * networkValues1s, char * networkValuesNotSet , Vec_Int_t * vLuts2Imply, Vec_Int_t * vLutsValidity , int experimentID){ + + + char _valid_vecs = *netValid; + char inputsFaninsValues[2] = {0, 0}; + int firstElement = 0; + int iii = -1, FaninId, jjj; + pPars->nImplicationTotalChecks++; + while (_valid_vecs > 0){ + iii++; + if( (_valid_vecs & 1) == 0){ + _valid_vecs = _valid_vecs >> 1; + continue; + } + // retrieve value of the fanout + char mask = 1 << iii; + int fanoutValue = (networkValues1s[objId] & mask) >> iii; + int fanoutNotSet = (networkValuesNotSet[objId] & mask) >> iii; + + if(fanoutNotSet == 0){ + // disable backward implication in this function + _valid_vecs = _valid_vecs >> 1; + continue; + } + // re-arrange fanin values format + Gia_LutForEachFanin( p, objId, FaninId, jjj ){ + char valueFanin = networkValues1s[FaninId]; + char valueFaninNotSet = networkValuesNotSet[FaninId]; + inputsFaninsValues[0] |= ( ((valueFanin & mask) >> iii) << jjj); + inputsFaninsValues[1] |= ( ((valueFaninNotSet & mask) >> iii) << jjj); + } + + + if(fanoutNotSet == 0 && inputsFaninsValues[1] == 0){ + _valid_vecs = _valid_vecs >> 1; + continue; + } + + int status = check_implication( p, objId, iii, fanoutValue, fanoutNotSet, inputsFaninsValues, networkValues1s, networkValuesNotSet , experimentID); + if(status == -1){ + *netValid = *netValid & ~(1 << iii); + } else if( status == 1){ + if(firstElement == 0){ + pPars->nImplicationSuccessChecks++; + Vec_IntPush( vLutsValidity, 1 << iii ); + Vec_IntPush( vLuts2Imply, objId ); + } else { + Vec_IntWriteEntry( vLutsValidity, Vec_IntSize(vLutsValidity) - 1, Vec_IntEntry(vLutsValidity, Vec_IntSize(vLutsValidity) - 1) | (1 << iii) ); + } + } + + _valid_vecs = _valid_vecs >> 1; + } + + if( *netValid == 0){ + return 0; + } + + return 1; +} + +/**Function************************************************************* + + Synopsis [Compute list of luts to imply.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +int computeLutsToImply( Gia_Man_t * p, Cec_ParSimGen_t * pPars, char * netValid, int ObjId, char * networkValues1s, char * networkValuesNotSet , Vec_Int_t * vLutsFaninCones, Vec_Int_t * vLuts2Imply, Vec_Int_t * vLutsValidity , Vec_Ptr_t * vNodesWatchlist, int experimentID){ + + int i, ith_fanout, FanoutId, jth_fanout, LutId, FaninId, k; + + if(vNodesWatchlist == NULL){ + // Option 1: iterate through fanouts to check if there can be an implication and if yes, apply it + Gia_LutForEachFanout2( p, ObjId, FanoutId, jth_fanout ){ + if( Vec_IntEntry(vLutsFaninCones, FanoutId) == 0){ + // if the lut FanoutId is not in any cone, it shouldn't be considered + continue; + } + int status = checkCompatibilityImplication( p, pPars, netValid, FanoutId, networkValues1s, networkValuesNotSet, vLuts2Imply, vLutsValidity, experimentID); + if(status <= 0){ + return status; + } + } + } else { + // Option 2: iterate through the watchlist to check if there can be an implication and if yes, apply it + Vec_Int_t * vWatchlist = (Vec_Int_t *) Vec_PtrEntry( vNodesWatchlist, ObjId ); + if(vWatchlist == NULL){ + return 1; + } + Vec_IntForEachEntry( vWatchlist, FanoutId, i ){ + if( Vec_IntEntry(vLutsFaninCones, FanoutId) == 0){ + // if the lut FanoutId is not in any cone, it shouldn't be considered + continue; + } + int status = checkCompatibilityImplication( p, pPars, netValid, FanoutId, networkValues1s, networkValuesNotSet, vLuts2Imply, vLutsValidity, experimentID); + if(status <= 0){ + return status; + } + } + // update watchlist of LUTs + Vec_IntForEachEntry( vWatchlist, LutId, i ){ + int * ranking = (int *) Vec_PtrEntry( p->vLutsRankings, LutId ); + int FaninSize = Gia_ObjLutSize( p, LutId ), newWatchK = -1; + for(k = 0; k < FaninSize ; k++){ + if(ranking[k] == ObjId){ + newWatchK = k+1; + break; + } + } + assert(newWatchK != -1); + if(newWatchK >= FaninSize){ // the LUT is already fully watched + continue; + } + int newWatch = ranking[newWatchK]; + Vec_Int_t * vNewWatch = (Vec_Int_t *) Vec_PtrEntry( vNodesWatchlist, newWatch ); + if(vNewWatch == NULL){ // case in which there was no watch for a certain variable + vNewWatch = Vec_IntAlloc( 10 ); + Vec_PtrWriteEntry( vNodesWatchlist, newWatch, vNewWatch ); + Vec_IntPush( vNewWatch, LutId ); + } else { + if(Vec_IntFind(vNewWatch, LutId) == -1){ + Vec_IntPush( vNewWatch, LutId ); + } + } + } + + } + return 1; + +} + +/**Function************************************************************* + + Synopsis [Execute implications.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +int executeImplications( Gia_Man_t * p, Cec_ParSimGen_t * pPars, char * netValid, int ObjId, char * networkValues1s, char * networkValuesNotSet , Vec_Int_t * vLutsFaninCones, Vec_Ptr_t * vNodesWatchlist , int experimentID){ + + assert( *netValid > 0); + pPars->nImplicationExecution++; + int iii = -1, FanoutId, jth_fanout, jjj, FaninId; + Vec_Int_t * vLuts2Imply = Vec_IntAlloc( 10 ); + Vec_Int_t * vLutsValidity = Vec_IntAlloc( 10 ); + + // first compute the list of luts to imply + int status = computeLutsToImply( p, pPars, netValid, ObjId, networkValues1s, networkValuesNotSet, vLutsFaninCones, vLuts2Imply, vLutsValidity, vNodesWatchlist , experimentID); + if(status <= 0){ + Vec_IntFree( vLuts2Imply ); + Vec_IntFree( vLutsValidity ); + return status; + } + + // second recursively go through the implied luts if there is any implication that can be applied + Vec_IntForEachEntry( vLuts2Imply, FanoutId, iii ){ + pPars->nImplicationSuccess++; + char validFanoutId = Vec_IntEntry(vLutsValidity, iii); + status = executeImplications( p, pPars, &validFanoutId, FanoutId, networkValues1s, networkValuesNotSet, vLutsFaninCones, vNodesWatchlist ,experimentID); + if (status == -1){ + Vec_IntFree( vLuts2Imply ); + Vec_IntFree( vLutsValidity ); + return -1; + } + } + + + Vec_IntFree( vLuts2Imply ); + Vec_IntFree( vLutsValidity ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Compute network values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +int computeNetworkValues(Gia_Man_t * p, Cec_ParSimGen_t * pPars, int ObjId , char * netValid, char lutValues1s, char * networkValues1s, char * networkValuesNotSet , Vec_Int_t * modifiedLuts , Vec_Int_t * vLutsFaninCones , Vec_Ptr_t * vNodesWatchlist , int experimentID ){ + + assert(experimentID > 0); + assert( *netValid > 0 ); + + if( Gia_ObjIsCi( Gia_ManObj(p, ObjId) ) ){ + printf("[ERROR] It is not possible to call computeNetworkValues for PIs"); + return -1; + } + char * pSopBoth[2]; int nCubesBoth[2]; + char * pSop; int nCube, ith_cube, jth_fanin, FaninId; + getISOPObjId( p, ObjId, pSopBoth, nCubesBoth ); + Vec_Ptr_t * vSops = Vec_PtrAlloc( 8 ); // for now consider only 8 parallalel SOPs due to char size + Vec_Int_t * vQualitySops = Vec_IntAlloc( 8 ); // compute qualities of SOPs + Vec_Int_t * vCubeId = Vec_IntAlloc( 8 ); // save ids of the selected cubes + char _valid_vecs = *netValid; + char _desired_values = lutValues1s; + int iii = -1, max_quality, ith_max_quality, ithSop, validNum =0; + int nFanins = Gia_ObjLutSize(p, ObjId); + // first compute all SOPs that are available + while (_valid_vecs > 0){ + iii++; + if( (_valid_vecs & 1) == 0){ + _valid_vecs = _valid_vecs >> 1; + _desired_values = _desired_values >> 1; + continue; + } + validNum++; + if( (_desired_values & 1) == 0){ + // negative polarity + pSop = pSopBoth[0]; + nCube = nCubesBoth[0]; + } else { + // positive polarity + pSop = pSopBoth[1]; + nCube = nCubesBoth[1]; + } + Vec_IntClear(vQualitySops); // reset the quality of the SOPs + Vec_IntClear(vCubeId); // reset the ids of the cubes + char valuesFaninsMasked[2] = {0, 0}; // re-arrange all the fanin values for a specific iteration + Gia_LutForEachFanin( p, ObjId, FaninId, jth_fanin ){ + char valuesFanin = networkValues1s[FaninId]; + char valueFaninNotSet = networkValuesNotSet[FaninId]; + char mask = 1 << iii; + valuesFaninsMasked[0] |= ( ((valuesFanin & mask) >> iii) << jth_fanin); + valuesFaninsMasked[1] |= ( ((valueFaninNotSet & mask) >> iii) << jth_fanin); + } + max_quality = 0; + ith_max_quality = -1; + for(ith_cube = 0; ith_cube < nCube; ith_cube++){ + if(checkCompatibilityCube( p, pSop + ith_cube * 2, nFanins, valuesFaninsMasked ) ){ + int quality = 1; + quality += compute_quality_sop(p, pSop + ith_cube * 2, ObjId , nFanins, experimentID); + if(quality > max_quality){ + max_quality = quality; + ith_max_quality = ith_cube; + } + Vec_IntPush(vQualitySops, quality); + Vec_IntPush(vCubeId, ith_cube); + } + } + if(ith_max_quality == -1){ // no cube found that respects the values of the fanins + // the vector is not valid + validNum--; + *netValid = *netValid & ~(1 << iii); + } else { + int _idCube = selectSop(vQualitySops, ith_max_quality, experimentID); + int idSop = Vec_IntEntry(vCubeId, _idCube); + Vec_PtrPush( vSops, pSop + idSop * 2 ); + } + _valid_vecs = _valid_vecs >> 1; + _desired_values = _desired_values >> 1; + } + Vec_IntFree( vQualitySops ); + Vec_IntFree( vCubeId ); + assert( validNum == Vec_IntSize(vSops) ); + _valid_vecs = *netValid; + // if not SOP available is valid return 0 ( not -1 since the valid vector might have been modified to skip DCs // there might be some valid SOPs for the next fanin) + if( _valid_vecs == 0){ + //printInfoLutValues( p, ObjId, netValid, lutValues1s, networkValues1s, networkValuesNotSet); + //printf("[WARNING] No valid SOPs found for node %d\n", ObjId); + Vec_PtrFree( vSops ); + return 0; + } + Vec_IntPush( modifiedLuts, ObjId ); + // second traverse the graph applying the selected SOPs + Gia_LutForEachFanin( p, ObjId, FaninId, jth_fanin ){ + // re-arrange SOPs as luts values across multiple iterations for each fanin + iii = -1; + validNum = -1; + _valid_vecs = *netValid; + char valuesFanin1s = 0; + char valuesFaninDCs = 0; + while (_valid_vecs > 0){ + iii++; + if( (_valid_vecs & 1) == 0){ + _valid_vecs = _valid_vecs >> 1; + continue; + } + validNum++; + char mask_fanin = 1 << jth_fanin; + + pSop = Vec_PtrEntry(vSops, validNum); + char pSop1s = *pSop; + pSop++; + char pSopDCs = *pSop; + valuesFanin1s |= ( (pSop1s & mask_fanin) >> jth_fanin) << iii; + valuesFaninDCs |= ( (pSopDCs & mask_fanin) >> jth_fanin) << iii; + _valid_vecs = _valid_vecs >> 1; + } + + // compute the values of the fanin + char prevNetValue = networkValues1s[FaninId]; + char prevNetValueNotSet = networkValuesNotSet[FaninId]; + char values2propagate = ~valuesFaninDCs & *netValid & prevNetValueNotSet; + networkValues1s[FaninId] |= valuesFanin1s & values2propagate; + networkValuesNotSet[FaninId] &= valuesFaninDCs & *netValid; + + if(values2propagate == 0){ + continue; // no value 2 propagate + } + + // apply implications + char tmp_values2propagate = values2propagate; + int status; + char difference_valid; + if(experimentID > 1){ + clock_t start_time = clock(); + status = executeImplications(p, pPars, &values2propagate, FaninId, networkValues1s, networkValuesNotSet , vLutsFaninCones, vNodesWatchlist , experimentID); + pPars->fImplicationTime += (float)(clock() - start_time)/CLOCKS_PER_SEC; + if( status == -1){ + networkValues1s[FaninId] = prevNetValue; + networkValuesNotSet[FaninId] = prevNetValueNotSet; + Vec_PtrFree( vSops ); + return -1; + } + assert( tmp_values2propagate >= values2propagate ); + // remove the values that are not valid + difference_valid = tmp_values2propagate ^ values2propagate; + if( difference_valid ){ + // some values are not valid + networkValuesNotSet[FaninId] &= ~difference_valid; + *netValid &= ~difference_valid; + // update also the validity signal and corresponding values + values2propagate = ~valuesFaninDCs & *netValid & prevNetValueNotSet; + networkValues1s[FaninId] |= valuesFanin1s & values2propagate; + networkValuesNotSet[FaninId] &= valuesFaninDCs & *netValid; + tmp_values2propagate = values2propagate; + } + values2propagate = tmp_values2propagate; + if(values2propagate == 0){ + continue; // no value 2 propagate + } + } + + if( !Gia_ObjIsCi( Gia_ManObj(p, FaninId) ) ){ + //printf("***********************\n"); + //printInfoLutValues( p, ObjId, netValid, lutValues1s, networkValues1s, networkValuesNotSet); + status = computeNetworkValues(p, pPars, FaninId, &values2propagate, valuesFanin1s, networkValues1s, networkValuesNotSet, modifiedLuts, vLutsFaninCones, vNodesWatchlist , experimentID); + if(status == -1){ + networkValues1s[FaninId] = prevNetValue; + networkValuesNotSet[FaninId] = prevNetValueNotSet; + Vec_PtrFree( vSops ); + return -1; + } + assert( tmp_values2propagate >= values2propagate ); + difference_valid = tmp_values2propagate ^ values2propagate; + if( difference_valid ){ + // some values are not valid + networkValuesNotSet[FaninId] &= ~difference_valid; + *netValid &= ~difference_valid; + } + } + } + + Vec_PtrFree( vSops ); + + return 1; +} + + +/**Function************************************************************* + + Synopsis [Set values of primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +void saveInputVectors( Gia_Man_t * p, Cec4_Man_t * pMan, char * pValues){ + + int i, Id, w; + Gia_ManForEachCiId( p, Id, i ){ + word * pSim = Cec4_ObjSim( p, Id ); + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = (word)pValues[ Id ]; + pSim[0] <<= 1; + } +} + +/**Function************************************************************* + + Synopsis [Export Simulation values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void exportSimValues( Gia_Man_t * p, char * filename ) +{ + FILE * pFile; + pFile = fopen( filename, "wb" ); + Gia_Obj_t * pObj; int i, j; + Gia_ManForEachObj( p, pObj, i ) + { + word * pSim = Cec4_ObjSim( p, i ); + fprintf( pFile, "Obj %d ", i ); + for(j = 0; j < p->nSimWords; j++){ + fprintf( pFile, "[%d]: %x ", j, pSim[j] ); + } + fprintf(pFile, "\n"); + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Compute Input Vectors using SimGen.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +int computeInputVectors(Gia_Man_t * p, Cec4_Man_t * pMan, Cec_ParSimGen_t * pPars , Vec_Int_t * vLuts , char * outGold, int outGold_bitwidth , Vec_Int_t * vLutsFaninCones , Vec_Ptr_t * vNodesWatchlist , int experimentID){ + + char * networkValues1s, * networkValuesNotSet; // data structure containing the values inside the network + char networkValid = (char) (1 << outGold_bitwidth) - 1; // keeps track which array out of the 8 is valid + int iRepr, jLut, mainLoop_condition, iii, numLuts, numPis = Gia_ManPiNum(p); + + numLuts = Vec_IntSize(vLuts); + assert(numLuts > 0); + + networkValues1s = (char *) malloc( Gia_ManObjNum(p)); + memset(networkValues1s, 0, sizeof(char) * Gia_ManObjNum(p)); + networkValuesNotSet = (char *) malloc( Gia_ManObjNum(p)); + memset(networkValuesNotSet, 0xFF, sizeof(char) * Gia_ManObjNum(p)); + mainLoop_condition = numLuts > 0; + iii = 0; + int success = 0, lastjGold = -1; + while ( mainLoop_condition ){ + jLut = Vec_IntEntry(vLuts, iii); + char jLutGold = outGold[jLut]; + + // TODO: Dynamic outgold + + // check if the value of the lut has been set already or not + char lutValueNotSet = networkValuesNotSet[jLut]; + char lutValues1s = networkValues1s[jLut]; + if( lutValueNotSet & networkValid){ + + char netValid = networkValid & lutValueNotSet; + char * networkValues1sCopy = (char *) malloc( Gia_ManObjNum(p)); + memcpy(networkValues1sCopy, networkValues1s, sizeof(char) * Gia_ManObjNum(p)); + char * networkValuesNotSetCopy = (char *) malloc( Gia_ManObjNum(p)); + memcpy(networkValuesNotSetCopy, networkValuesNotSet, sizeof(char) * Gia_ManObjNum(p)); + Vec_Int_t * modifiedLuts = Vec_IntAlloc( Gia_ManLutNum(p) ); + // add the first lut to the modified luts + Vec_IntPush(modifiedLuts, jLut); + networkValues1sCopy[jLut] |= jLutGold & netValid; + networkValuesNotSetCopy[jLut] &= ~netValid; + // traverse the graph to retrieve values in the middle of the network + int status = computeNetworkValues(p, pPars, jLut , &netValid, jLutGold, networkValues1sCopy, networkValuesNotSetCopy, modifiedLuts, vLutsFaninCones, vNodesWatchlist , experimentID); + if( status == -1 ){ + Vec_IntFree(modifiedLuts); + free(networkValues1sCopy); + free(networkValuesNotSetCopy); + goto exit_cond; + } + + char orig_netValid = networkValid & lutValueNotSet; + char difference_valid = orig_netValid ^ netValid; + if( difference_valid == orig_netValid){ + if(pPars->fVeryVerbose) + printf("FAILED 0 out of %d - node %d (gold = %d valid = %d)\n", outGold_bitwidth, jLut, jLutGold, netValid); + } else if( difference_valid != 0){ + int jjj = 0, iLut; + Vec_IntForEachEntry( modifiedLuts, iLut, jjj ){ + networkValues1sCopy[jLut] = networkValues1s[iLut]; + networkValuesNotSetCopy[jLut] = networkValuesNotSet[iLut]; + } + memcpy(networkValues1s, networkValues1sCopy, sizeof(char) * Gia_ManObjNum(p)); + memcpy(networkValuesNotSet, networkValuesNotSetCopy, sizeof(char) * Gia_ManObjNum(p)); + + int different = 0; + while (difference_valid != 0) { + if (difference_valid & 1) { + different++; + } + difference_valid >>= 1; + } + if( outGold_bitwidth - different >= 2){ // at least 2 bits should be respected + if(lastjGold != jLutGold){ + success += 1; + lastjGold = jLutGold; + } + } + if(pPars->fVeryVerbose) + printf("SUCCESSFUL %d out of %d - node %d (gold = %d valid = %d)\n", outGold_bitwidth - different, outGold_bitwidth, jLut, jLutGold, netValid); + } else { + if(lastjGold != jLutGold){ + success += 1; + lastjGold = jLutGold; + } + memcpy(networkValues1s, networkValues1sCopy, sizeof(char) * Gia_ManObjNum(p)); + memcpy(networkValuesNotSet, networkValuesNotSetCopy, sizeof(char) * Gia_ManObjNum(p)); + if(pPars->fVeryVerbose) + printf("SUCCESSFUL %d out of %d - node %d (gold = %d valid = %d)\n", outGold_bitwidth, outGold_bitwidth, jLut, jLutGold, netValid); + } + + + free(networkValues1sCopy); + free(networkValuesNotSetCopy); + Vec_IntFree(modifiedLuts); + + + } else { // all the different values that are still valid have been set + char luts_values = lutValues1s & networkValid; + char out_gold_values = jLutGold & networkValid; + char validAssignments = ~( luts_values ^ out_gold_values ) & networkValid; + char numOnes = 0; + if (validAssignments != 0){ + while (validAssignments != 0) { + if (validAssignments & 1) { + numOnes++; + } + validAssignments >>= 1; + } + } + validAssignments = ~( luts_values ^ out_gold_values ) & networkValid; + if(pPars->fVeryVerbose) + printf("(1) SUCCESSFUL %d out of %d - node %d (gold = %d valid = %d)\n", numOnes, outGold_bitwidth, jLut, jLutGold, validAssignments); + } + + iii++; + mainLoop_condition = (iii < numLuts); + } + + if(success >= 2){ + saveInputVectors(p, pMan, networkValues1s); + Cec4_ManSimulate( p, pMan ); + if( pPars->fVerbose || pPars->fVeryVerbose){ + printf("**Exporting simulation values in file sim_values.txt\n"); + exportSimValues( p, "sim_values.txt" ); + } + } + + +exit_cond: + free(networkValues1s); + free(networkValuesNotSet); + + if(success < 2){ + return -1; + } else { + return 1; + } + +} + + +/**Function************************************************************* + + Synopsis [Core function of SimGen.] + + Description [] + + SideEffects [] + + SeeAlso [] +***********************************************************************/ + + +void executeControlledSim(Gia_Man_t * p, Cec4_Man_t * pMan, Cec_ParSimGen_t * pPars , int levelOrder, int experimentID){ + + char * outGold; + int outGold_bitwidth = pPars->bitwidthOutgold; + int numClasses = totalNumClasses(p); + int iTrials = 0, outer_loop_condition = iTrials < (numClasses * 1.5); + int nthClass = 0, status, oldNumClasses = numClasses, iter; + Vec_Int_t * luts_order, * vecTmp; + Vec_Int_t * vLutsFaninCones; + clock_t start_time = clock(); + outGold = generateOutGoldValues(p); // generate the first outgold values + pPars->outGold = outGold; + Vec_Ptr_t * vNodesWatchList = NULL; + if(pPars->fUseWatchlist){ + printf("**Activating watchlist feauture\n"); + } + while( existsOneClass(p) && outer_loop_condition ){ + luts_order = extractNthClass(p, nthClass); + if( levelOrder != -1 ){ + // test different luts orders on which to apply simgen + luts_order = computeLutsOrder(p, 1); // incresing level order // TODO: redo taking luts_order as input + } + // compute the fanin cones of the luts to apply implication only in the cone + vLutsFaninCones = computeFaninCones( p, luts_order ); + if(pPars->fUseWatchlist){ + vNodesWatchList = generateWatchList(p); + } + status = computeInputVectors(p, pMan, pPars, luts_order, outGold, pPars->bitwidthOutgold, vLutsFaninCones, vNodesWatchList, experimentID); + if( status == -1 ){ + if(pPars->fVerbose || pPars->fVeryVerbose) + printf("FAILED - no valid input vectors found for class %d\n", nthClass); + nthClass++; + } else { + numClasses = totalNumClasses(p); + if (oldNumClasses == numClasses){ + nthClass++; + } + oldNumClasses = numClasses; + free(outGold); + outGold = generateOutGoldValues(p); // generate a new outgold since the classes are updated + pPars->outGold = outGold; + if(pPars->fVerbose || pPars->fVeryVerbose) + printf("SUCCESSFUL - input vectors found for class %d\n", nthClass); + //nthClass = 0; + } + + Vec_IntFree(vLutsFaninCones); + Vec_IntFree(luts_order); + if(pPars->fUseWatchlist){ + Vec_PtrForEachEntry( Vec_Int_t *, vNodesWatchList, vecTmp, iter ){ + if (vecTmp != NULL) + Vec_IntFree(vecTmp); + } + Vec_PtrFree(vNodesWatchList); + } + if(nthClass >= numClasses){ + nthClass = 0; + if (oldNumClasses == numClasses){ + iTrials++; + } + oldNumClasses = numClasses; + iTrials++; + } + outer_loop_condition = iTrials < 3; + clock_t end_time = clock(); + if ( (float)(end_time - start_time)/CLOCKS_PER_SEC > pPars->timeOutSim){ // hard limit of 1000 sec + printf("Timeout of %f sec reached\n", pPars->timeOutSim); + break; + } + if(pPars->fVerbose || pPars->fVeryVerbose){ + int quality = evaluate_equiv_classes(p, 0); + printf("Time elapsed: %f (classes quality: %d)\n", (float)(clock() - start_time)/CLOCKS_PER_SEC, quality); + } + } + + //drawNetworkGia( p, "network.dot"); + //drawConeNetworkGia( p, "cone_network.dot", 31); + + free(outGold); + +} + +/**Function************************************************************* + + Synopsis [Call SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void Cec4_CallSATsolver(Gia_Man_t * p, Cec4_Man_t * pMan, Cec_ParFra_t * pPars){ + + extern Gia_Obj_t * Cec4_ManFindRepr( Gia_Man_t * p, Cec4_Man_t * pMan, int iObj ); + int i; + Gia_Obj_t * pObj, * pRepr; + p->iPatsPi = 0; + Vec_WrdFill( p->vSimsPi, Vec_WrdSize(p->vSimsPi), 0 ); + pMan->nSatSat = 0; + pMan->pNew = Cec4_ManStartNew( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + Gia_Obj_t * pObjNew; + pMan->nAndNodes++; + if ( Gia_ObjIsXor(pObj) ) + pObj->Value = Gia_ManHashXorReal( pMan->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManHashAnd( pMan->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( pPars->nLevelMax && Gia_ObjLevel(p, pObj) > pPars->nLevelMax ) + continue; + pObjNew = Gia_ManObj( pMan->pNew, Abc_Lit2Var(pObj->Value) ); + if ( Gia_ObjIsAnd(pObjNew) ) + if ( Vec_BitEntry(pMan->vFails, Gia_ObjFaninId0(pObjNew, Abc_Lit2Var(pObj->Value))) || + Vec_BitEntry(pMan->vFails, Gia_ObjFaninId1(pObjNew, Abc_Lit2Var(pObj->Value))) ) + Vec_BitWriteEntry( pMan->vFails, Abc_Lit2Var(pObjNew->Value), 1 ); + //if ( Gia_ObjIsAnd(pObjNew) ) + // Gia_ObjSetAndLevel( pMan->pNew, pObjNew ); + // select representative based on candidate equivalence classes + pRepr= Gia_ObjReprObj( p, i ); + if ( pRepr == NULL ) + continue; + if ( 1 ) // select representative based on recent counter-examples + { + pRepr = (Gia_Obj_t *) Cec4_ManFindRepr( p, pMan, i ); + if ( pRepr == NULL ) + continue; + } + int id_obj = Gia_ObjId( p, pObj ); + int id_repr = Gia_ObjId( p, pRepr ); + + if ( Abc_Lit2Var(pObj->Value) == Abc_Lit2Var(pRepr->Value)) + { + if ( pPars->fBMiterInfo ) + { + Bnd_ManMerge( id_repr, id_obj, pObj->fPhase ^ pRepr->fPhase ); + } + if((pObj->Value ^ pRepr->Value) != (pObj->fPhase ^ pRepr->fPhase)){ + pObj->Value = Abc_LitNotCond( pRepr->Value, pObj->fPhase ^ pRepr->fPhase ); + } + assert( (pObj->Value ^ pRepr->Value) == (pObj->fPhase ^ pRepr->fPhase) ); + Gia_ObjSetProved( p, i ); + if ( Gia_ObjId(p, pRepr) == 0 ) + pMan->iLastConst = i; + continue; + } + if ( Cec4_ManSweepNode(pMan, i, Gia_ObjId(p, pRepr)) && Gia_ObjProved(p, i) ) + { + if (pPars->fBMiterInfo){ + + Bnd_ManMerge( id_repr, id_obj, pObj->fPhase ^ pRepr->fPhase ); + // printf( "proven %d merged into %d (phase : %d)\n", Gia_ObjId(p, pObj), Gia_ObjId(p,pRepr), pObj->fPhase ^ pRepr -> fPhase ); + + } + pObj->Value = Abc_LitNotCond( pRepr->Value, pObj->fPhase ^ pRepr->fPhase ); + + + } + } + + printf( "SAT calls = %d: P = %d (0=%d a=%.2f m=%d) D = %d (0=%d a=%.2f m=%d) F = %d Sim = %d Recyc = %d Xor = %.2f %%\n", + pMan->nSatUnsat + pMan->nSatSat + pMan->nSatUndec, + pMan->nSatUnsat, pMan->nConflicts[1][0], (float)pMan->nConflicts[1][1]/Abc_MaxInt(1, pMan->nSatUnsat-pMan->nConflicts[1][0]), pMan->nConflicts[1][2], + pMan->nSatSat, pMan->nConflicts[0][0], (float)pMan->nConflicts[0][1]/Abc_MaxInt(1, pMan->nSatSat -pMan->nConflicts[0][0]), pMan->nConflicts[0][2], + pMan->nSatUndec, + pMan->nSimulates, pMan->nRecycles, 100.0*pMan->nGates[1]/Abc_MaxInt(1, pMan->nGates[0]+pMan->nGates[1]) ); + +} + +/**Function************************************************************* + + Synopsis [Print encoded cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void printEncodedCube( char pCube, char pDCs, int nFanins ){ + + int i; + for (i = 0; i < nFanins; i++){ + if ( pCube & (1 << i) ) + printf("1"); + else if ( pDCs & (1 << i) ) + printf("-"); + else + printf("0"); + } + printf("\n"); + +} + +/**Function************************************************************* + + Synopsis [Print ISOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void printISOP( char * pSop, int nCubes, int nFanins ){ + + int jth_cube = 0; + while (jth_cube < nCubes){ + char pCube = *pSop; pSop++; + char pDCs = *pSop; pSop++; + printEncodedCube( pCube, pDCs, nFanins ); + jth_cube++; + } + +} + +/**Function************************************************************* + + Synopsis [Print ISOP LUT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void printISOPLUT(Gia_Man_t * pMan, int ObjId){ + + assert( Gia_ObjIsLut(pMan, ObjId)); + char * pSop[2]; int nCubes[2]; + getISOPObjId( pMan, ObjId, pSop, nCubes ); + printf("Negative Polarity\n"); + printISOP( pSop[0], nCubes[0], Gia_ObjLutSize(pMan, ObjId) ); + printf("Positive Polarity\n"); + printISOP( pSop[1], nCubes[1], Gia_ObjLutSize(pMan, ObjId) ); + +} + +/**Function************************************************************* + + Synopsis [Execute SimGen.] + + Description [] + + SideEffects [] + + SeeAlso [] +***********************************************************************/ + +Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ + + + Cec4_Man_t * pManSim; + Gia_Obj_t * pObj, * pRepr; + int i, fSimulate = 1, k, iFan; + + + // apply technology mapping + If_Par_t IfPars, * pIfPars = &IfPars; + Gia_ManSetIfParsDefault( pIfPars ); + pIfPars->nLutSize = 6; + Gia_Man_t * pMapped = Gia_ManPerformMapping( p, pIfPars ); + pManSim = Cec4_ManCreate( pMapped, pPars->pCECPars ); + + Cec_DeriveSOPs( pMapped ); + + if (pPars->fVeryVerbose) + { + printf("**Printing LUTs information**\n"); + Gia_ManForEachLut( pMapped, i ){ + printf("LUT %d\n", i); + Gia_LutForEachFanin( pMapped, i, iFan, k ){ + printf("\tFANIN %d\n", iFan); + } + printISOPLUT( pMapped, i ); + } + } + + // compute MFFCs + Gia_ManLevelNum( pMapped); // compute levels + computeMFFCs( pMapped ); + if (pPars->fUseWatchlist) { + generateLutsRankings( pMapped ); + } + + + // generate vectors of fanouts + Gia_generateFanoutMapping( pMapped ); + + // simulate n rounds of random simulation and create classes + Cec4_ManSimAlloc( pMapped, 1 ); + if(pPars->nMaxIter >= 0){ + executeRandomSim( pMapped, pManSim, 0, pPars->nMaxIter, pPars->bitwidthSim , pPars->fVeryVerbose); + } else if (pPars->nMaxIter == -1){ + executeRandomSim( pMapped, pManSim, 1, pPars->nMaxIter, pPars->bitwidthSim , pPars->fVeryVerbose); + } else { + printf("Invalid number of iterations %d\n", pPars->nMaxIter); + return NULL; + } + + Cec_RemoveNonLutNodes( pMapped ); // remove all the non-LUT nodes from the equivalence classes + + if(pPars->fVerbose || pPars->fVeryVerbose){ + // IMPORTANT: the number of classes changes due to the previous operation + evaluate_equiv_classes(pMapped, 1); + printf("**Printing Class information before running the Sim algos in file pre_classes.txt**\n"); + exportEquivClasses(pMapped, "pre_classes.txt"); + } + //Cec4_ManPrintClasses2(pMapped); + clock_t begin = clock(); + assert(pPars->expId > 0); + executeControlledSim( pMapped, pManSim, pPars, -1 , pPars->expId ); + + float implicationSuccessRate = (float)pPars->nImplicationSuccess / (float)pPars->nImplicationExecution; + float implicationSuccessCheckRate = (float)pPars->nImplicationSuccessChecks / (float)pPars->nImplicationTotalChecks; + printf("Time elapsed: %f (implication time %f - %f successful recursions - %f successful checks)\n", (double)(clock() - begin) / CLOCKS_PER_SEC, pPars->fImplicationTime, implicationSuccessRate, implicationSuccessCheckRate); + + //Cec4_ManPrintClasses2(pMapped); + if(pPars->fVerbose || pPars->fVeryVerbose){ + printf("**Printing Class information before running the Sim algos in file post_classes.txt**\n"); + exportEquivClasses(pMapped, "post_classes.txt"); + evaluate_equiv_classes(pMapped, 1); + } + + + + // call SAT solver + Cec4_CallSATsolver(pMapped, pManSim, pPars->pCECPars); + + if (pPars->fVerbose || pPars->fVeryVerbose){ + pManSim->pPars->fVerbose = 1; // print the ending stats of sat calls + } + // free memory + Vec_IntFree( pMapped->vTTLut ); + Vec_StrFree( pMapped->vTTISOPs ); + Cec4_ManDestroy( pManSim ); + Gia_ManStop( pMapped ); + + return p; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// From 30af6f9868c42befe098fea9cd99f248d4199801 Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Thu, 19 Dec 2024 17:25:45 +0100 Subject: [PATCH 041/133] [CEC][SimGen][CLI] Change name of command for simgen --- src/base/abci/abc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index a5672a5ef..635687ab3 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -1277,7 +1277,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&choice", Abc_CommandAbc9Choice, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sat", Abc_CommandAbc9Sat, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&satenum", Abc_CommandAbc9SatEnum, 0 ); - Cmd_CommandAdd( pAbc, "ABC9", "&sim_gen", Abc_CommandAbc9SimGen, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&fraigSimGen", Abc_CommandAbc9SimGen, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&fraig", Abc_CommandAbc9Fraig, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cfraig", Abc_CommandAbc9CFraig, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&srm", Abc_CommandAbc9Srm, 0 ); @@ -39298,7 +39298,7 @@ int Abc_CommandAbc9SimGen( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &sim_gen [-EOSsivV ] [-v] \n" ); + Abc_Print( -2, "usage: &fraigSimGen [-EOSsivV ] [-v] \n" ); Abc_Print( -2, "\t performs combinational SAT sweeping applying SimGen\n" ); Abc_Print( -2, "\t-E num : the experiment ID for SimGen [default = %d]\n", pPars->expId ); Abc_Print( -2, "\t-O num : the bitwidth of the output gold [default = %d]\n", pPars->bitwidthOutgold ); From b999084ade4ebc316251b3f94d9f036b633c616d Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Thu, 19 Dec 2024 18:12:28 +0100 Subject: [PATCH 042/133] [CEC][SimGen][CLI] Removed option of nMaxStep since it was unused --- src/base/abci/abc.c | 16 ++-------------- src/proof/cec/cec.h | 1 - src/proof/cec/cecSatG2.c | 1 - 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 635687ab3..426f90fd5 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -39198,7 +39198,7 @@ int Abc_CommandAbc9SimGen( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; Cec_SimGenSetParDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "EOSstiwvV" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "EOStiwvV" ) ) != EOF ) { switch ( c ) { @@ -39235,17 +39235,6 @@ int Abc_CommandAbc9SimGen( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->bitwidthSim <= 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->nMaxStep = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nMaxStep <= 0 ) - goto usage; - break; case 't': if ( globalUtilOptind >= argc ) { @@ -39254,7 +39243,7 @@ int Abc_CommandAbc9SimGen( Abc_Frame_t * pAbc, int argc, char ** argv ) } pPars->timeOutSim = atof(argv[globalUtilOptind]); globalUtilOptind++; - if ( pPars->nMaxStep <= 0 ) + if ( pPars->timeOutSim <= 0 ) goto usage; break; case 'i': @@ -39303,7 +39292,6 @@ usage: Abc_Print( -2, "\t-E num : the experiment ID for SimGen [default = %d]\n", pPars->expId ); Abc_Print( -2, "\t-O num : the bitwidth of the output gold [default = %d]\n", pPars->bitwidthOutgold ); Abc_Print( -2, "\t-S num : the bitwidth of the simulation vectors [default = %d]\n", pPars->bitwidthSim ); - Abc_Print( -2, "\t-s num : the maximum number of SimGen steps [default = %d]\n", pPars->nMaxStep ); Abc_Print( -2, "\t-t num : the timeout value after which Smart Simulation Pattern Generation terminates [default = %.0f]\n", pPars->timeOutSim); Abc_Print( -2, "\t-i num : the maximum number of iterations [default = %d]\n", pPars->nMaxIter ); Abc_Print( -2, "\t-w : activates the watchlist feature [default = %d]\n", pPars->fUseWatchlist); diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index ae9f5122c..4db2df726 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -210,7 +210,6 @@ struct Cec_ParSimGen_t_ int expId; // experiment ID for SimGen int bitwidthOutgold; // bitwidth of the output gold int bitwidthSim; // bitwidth of the simulation vectors - int nMaxStep; // maximum number of SimGen steps int nMaxIter; // maximum number of iterations char * outGold; // data containing outgold float timeOutSim; // timeout for simulation diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 65aa6be0c..0b021c0ed 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -244,7 +244,6 @@ void Cec_SimGenSetParDefault( Cec_ParSimGen_t * pPars ) pPars->bitwidthOutgold = 2; // bitwidth of the output golden model pPars->bitwidthSim = 31; // bitwidth of the simulation vectors pPars->expId = 1; // experiment ID - pPars->nMaxStep = 20; // the maximum number of steps pPars->nMaxIter = -1; // the maximum number of iterations pPars->timeOutSim = 1000.0; // the timeout for simulation in sec pPars->fUseWatchlist = 0; // use watchlist From c104d9cb72360fef3d6182a0be79253eeae41eb7 Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Sat, 21 Dec 2024 14:26:54 +0100 Subject: [PATCH 043/133] [CEC][SimGen][Warnings] Re-adjusted code to remove unused variables and avoid warnings compilation --- src/proof/cec/cecSatG2.c | 189 ++++++++++++++++++++------------------- 1 file changed, 96 insertions(+), 93 deletions(-) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 0b021c0ed..1d688785c 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -2308,6 +2308,9 @@ Vec_Str_t * encodeSOP(char * pSop, int nFanins, int nCubes){ char * extractSOP( DdManager * dd, DdNode * bFunc, int nFanins, int polarity, int * _nCubes){ + extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ); + extern int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ); + Vec_Str_t * vCube = Vec_StrAlloc( 100 ); int nCubes; char * pSop; DdNode * bCover, * zCover; @@ -2363,7 +2366,6 @@ void computeISOPs( Gia_Man_t * p, Abc_Ntk_t * pNtkNew ){ DdManager * dd = (DdManager *)pNtkNew->pManFunc; DdNode * bFunc; char * pSop; - DdNode * bCover; int nCubes, i, jjj; Vec_Str_t * encodedSop; // compute SOP sizes @@ -2461,6 +2463,8 @@ cleanup: void Cec_DeriveSOPs( Gia_Man_t * p ){ + extern Hop_Obj_t * Abc_ObjHopFromGia( Hop_Man_t * pHopMan, Gia_Man_t * p, int GiaId, Vec_Ptr_t * vCopies ); + // generate the structure to contain LUT ids and their corresponding TTISOPS int nCountLuts = Gia_ManLutNum(p); p->vTTISOPs = Vec_StrAlloc( nCountLuts * 10); @@ -2472,7 +2476,7 @@ void Cec_DeriveSOPs( Gia_Man_t * p ){ Abc_Obj_t * pObjNew, * pObjNewLi, * pObjNewLo, * pConst0 = NULL; Gia_Obj_t * pObj, * pObjLi, * pObjLo; Vec_Ptr_t * vReflect = Vec_PtrStart( Gia_ManObjNum(p) ); - int i, k, jjj, iFan, nDupGates, nCountMux = 0; + int i, k, iFan; assert( Gia_ManHasMapping(p) ); pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_AIG, 1 ); // duplicate the name and the spec @@ -2530,6 +2534,34 @@ void Cec_DeriveSOPs( Gia_Man_t * p ){ } +/**Function************************************************************* + + Synopsis [Evaluate MFFC depth.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +int evaluate_mffc(Gia_Man_t * p, int rootId, int fanId, Vec_Int_t * vLeaves){ + + int quality = 0, jMFFCLeaf; + int nLeaves = Vec_IntSize(vLeaves); + for(jMFFCLeaf = 0; jMFFCLeaf < nLeaves ; jMFFCLeaf++){ + int idMFFCLeaf = Vec_IntEntry(vLeaves, jMFFCLeaf); + int level_leaf = Gia_ObjLevelId(p, idMFFCLeaf) ; + int level_root = Gia_ObjLevelId(p, fanId) ; + quality += level_root - level_leaf; + } + if( quality != 0 && nLeaves > 0) + quality /= nLeaves; + return quality; + +} + /**Function************************************************************* Synopsis [Compute MFFCs.] @@ -2601,33 +2633,7 @@ void computeMFFCs( Gia_Man_t * p ){ Vec_IntFree( vInnersNew ); } -/**Function************************************************************* - Synopsis [Evaluate MFFC depth.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -int evaluate_mffc(Gia_Man_t * p, int rootId, int fanId, Vec_Int_t * vLeaves){ - - int quality = 0, jMFFCLeaf; - int nLeaves = Vec_IntSize(vLeaves); - for(jMFFCLeaf = 0; jMFFCLeaf < nLeaves ; jMFFCLeaf++){ - int idMFFCLeaf = Vec_IntEntry(vLeaves, jMFFCLeaf); - int level_leaf = Gia_ObjLevelId(p, idMFFCLeaf) ; - int level_root = Gia_ObjLevelId(p, fanId) ; - quality += level_root - level_leaf; - } - if( quality != 0 && nLeaves > 0) - quality /= nLeaves; - return quality; - -} /**Function************************************************************* @@ -2647,8 +2653,8 @@ int extract_quality_mffc(Gia_Man_t * p, int ObjId, char pDCs){ return 0; assert( Vec_IntEntry( p->vMFFCsLuts, ObjId ) != -1); int * pMFFC = p->vMFFCsInfo->pArray + Vec_IntEntry( p->vMFFCsLuts, ObjId ); - int iFan, ith_fan, qualityMFFC, quality = 0; - int nFanins = Gia_ObjLutSize(p, ObjId); + int iFan, ith_fan, quality = 0; + //int nFanins = Gia_ObjLutSize(p, ObjId); Gia_LutForEachFanin( p, ObjId, iFan, ith_fan ){ int qualityMFFC = *pMFFC; if (qualityMFFC == 0 || (pDCs & (1 << ith_fan)) > 0){ // count the cones without don't cares @@ -2717,7 +2723,8 @@ void generateLutsRankings( Gia_Man_t * p){ getISOPObjId( p, LutId, pSop, nCubes ); for(k = 0; k < 2; k++){ for(iii = 0; iii < nCubes[k]; iii++){ - char pCube = pSop[k][iii*2]; char pDCs = pSop[k][iii*2+1]; + //char pCube = pSop[k][iii*2]; + char pDCs = pSop[k][iii*2+1]; for(jjj = 0; jjj < nFanins; jjj++){ if ( (pDCs & (1 << jjj)) == 0 ) ranks[jjj]++; @@ -2880,6 +2887,57 @@ void Cec_ManSimulateCisSimGen( Gia_Man_t * p, int bitwidth ) p->iPatsPi = 0; } +/**Function************************************************************* + + Synopsis [Evaluate equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +int evaluate_equiv_classes(Gia_Man_t * p, int verbose){ + + int i, k; + int quality = 0; + Gia_ManForEachClass0( p, i ) + { + Gia_ClassForEachObj1( p, i, k ){ + quality++; + } + } + + if (verbose) + printf("**Quality = %d\n", quality); + + return quality; +} + + +/**Function************************************************************* + + Synopsis [Compute total number of classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +int totalNumClasses(Gia_Man_t * p){ + int iRepr; + int numClasses = 0; + Gia_ManForEachClass0( p, iRepr ){ + numClasses++; + } + return numClasses; +} + /**Function************************************************************* Synopsis [Simulate the CIs with random values.] @@ -2924,34 +2982,6 @@ void executeRandomSim( Gia_Man_t * p, Cec4_Man_t * pMan , int dynSim, int nMaxIt } } -/**Function************************************************************* - - Synopsis [Evaluate equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -************************************************************************/ - -int evaluate_equiv_classes(Gia_Man_t * p, int verbose){ - - int i, k; - int quality = 0; - Gia_ManForEachClass0( p, i ) - { - Gia_ClassForEachObj1( p, i, k ){ - quality++; - } - } - - if (verbose) - printf("**Quality = %d\n", quality); - - return quality; -} /**Function************************************************************* @@ -2969,7 +2999,7 @@ void exportEquivClasses(Gia_Man_t * p, char * filename){ FILE * pFile; pFile = fopen( filename, "wb" ); - Gia_Obj_t * pObj; int i, j, iii = 0; + int i, j, iii = 0; Gia_ManForEachClass0( p, i ) { fprintf( pFile, "Class %d: %d ", iii , i); @@ -2984,26 +3014,6 @@ void exportEquivClasses(Gia_Man_t * p, char * filename){ } -/**Function************************************************************* - - Synopsis [Compute total number of classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -int totalNumClasses(Gia_Man_t * p){ - int iRepr; - int numClasses = 0; - Gia_ManForEachClass0( p, iRepr ){ - numClasses++; - } - return numClasses; -} /**Function************************************************************* @@ -3022,7 +3032,6 @@ char * generateOutGoldValues(Gia_Man_t * p){ char * pOutGold = (char *) malloc( sizeof(char) * Gia_ManObjNum(p) ); int i, k; - Gia_Obj_t * pObj; int cnt = 85; // 0b01010101 Gia_ManForEachLut( p, i ){ pOutGold[i] = (char) 0; @@ -3074,7 +3083,7 @@ int existsOneClass(Gia_Man_t * p){ Vec_Int_t * extractNthClass(Gia_Man_t * p, int nth_class){ Vec_Int_t * vClass = Vec_IntAlloc( Gia_ManLutNum(p) ); - int iRepr, jLut, iii; + int iRepr, jLut; Gia_ManForEachClass0( p, iRepr ){ if(nth_class == 0){ Vec_IntPush(vClass, iRepr); @@ -3106,7 +3115,6 @@ Vec_Int_t * computeLutsOrder(Gia_Man_t * p, int reorder_type){ Vec_Int_t * luts_order = Vec_IntAlloc( Gia_ManLutNum(p) ); int * luts_tmp = (int *) malloc( sizeof(int) * Gia_ManLutNum(p)); int iRepr, jLut, iii, jjj, kkk; - Gia_Obj_t * pObj; Gia_ManForEachClass0( p, iRepr ){ luts_tmp[ 0 ] = iRepr; iii = 1; @@ -3180,8 +3188,7 @@ void computeFaninCones_rec(Gia_Man_t * p, int ObjId, Vec_Int_t * vLutsFaninCones Vec_Int_t * computeFaninCones( Gia_Man_t * p, Vec_Int_t * vLuts ){ - int i, FaninId, jth_fanin; - Gia_Obj_t * pObj; + int i, jth_fanin; Vec_Int_t * vLutsFaninCones = Vec_IntStart(Gia_ManObjNum(p)); Vec_IntForEachEntry( vLuts, i, jth_fanin ){ computeFaninCones_rec( p, i, vLutsFaninCones ); @@ -3205,10 +3212,6 @@ Vec_Int_t * computeFaninCones( Gia_Man_t * p, Vec_Int_t * vLuts ){ int checkCompatibilityCube( Gia_Man_t * pMan, char * pCube, int nFanins, char * pCubeGold ){ - // double check this function!!!! - - - int i; char pCubeOnes = *pCube; char pDCs = *(pCube+1); char pCubeGoldOnes = *pCubeGold; char pCubeNotAssigned = *(pCubeGold+1); @@ -3238,7 +3241,7 @@ int checkCompatibilityCube( Gia_Man_t * pMan, char * pCube, int nFanins, char * int compute_quality_sop(Gia_Man_t * p , char * pSop, int ObjId ,int nFanins, int experimentID){ int quality = 0; - char pValues = *pSop; + //char pValues = *pSop; pSop++; char pDCs = *(pSop); switch (experimentID){ @@ -3373,9 +3376,9 @@ int check_implication( Gia_Man_t * p, int ObjId , int validBit , int fanoutValue if(compatible == 1){ - char selectedSop = *(pSop + lastCube * 2); - char selectedDCs = *(pSop + lastCube * 2 + 1); - assert(0); // to finish implementing + //char selectedSop = *(pSop + lastCube * 2); + //char selectedDCs = *(pSop + lastCube * 2 + 1); + assert(0); // TODO: implement the case in which the output is set return 1; } else if (compatible == 0){ return -1; From a6de82377d12e9d7e8363fc3ae4e6ace278eb950 Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Sat, 21 Dec 2024 15:57:47 +0100 Subject: [PATCH 044/133] [CEC][SimGen][Warnings] Re-adjusted code to remove unused variables and avoid warnings compilation --- src/proof/cec/cecSatG2.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 1d688785c..c62acf878 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -3122,7 +3122,7 @@ Vec_Int_t * computeLutsOrder(Gia_Man_t * p, int reorder_type){ if(reorder_type == 0){ // decreasing level order int found = 0; for(jjj = 0; jjj < iii; jjj++){ - if(Gia_ObjLevel(p, jLut) <= Gia_ObjLevel(p, luts_tmp[jjj])){ + if(Gia_ObjLevelId(p, jLut) <= Gia_ObjLevelId(p, luts_tmp[jjj])){ for (kkk = iii; kkk > jjj; kkk--) { luts_tmp[kkk] = luts_tmp[kkk - 1]; } @@ -3138,7 +3138,7 @@ Vec_Int_t * computeLutsOrder(Gia_Man_t * p, int reorder_type){ } else if(reorder_type == 1) { // increasing level order int found = 0; for(jjj = 0; jjj < iii; jjj++){ - if(Gia_ObjLevel(p, jLut) >= Gia_ObjLevel(p, luts_tmp[jjj])){ + if(Gia_ObjLevelId(p, jLut) >= Gia_ObjLevelId(p, luts_tmp[jjj])){ for (kkk = iii; kkk > jjj; kkk--) { luts_tmp[kkk] = luts_tmp[kkk - 1]; } @@ -3251,14 +3251,14 @@ int compute_quality_sop(Gia_Man_t * p , char * pSop, int ObjId ,int nFanins, int break; case 4: // Advanced Implication + Count DCs while (pDCs > 0){ - if(pDCs & 1 == 1) + if((pDCs & 1) == 1) quality += p->nLevels * 5; // the presence of DCs is more important than mffc pDCs = pDCs >> 1; } break; case 5: // Advanced Implication + Count DC + FFC while (pDCs > 0){ - if(pDCs & 1 == 1) + if((pDCs & 1) == 1) quality += p->nLevels * 5; // the presence of DCs is more important than mffc pDCs = pDCs >> 1; } @@ -3287,13 +3287,12 @@ int compute_quality_sop(Gia_Man_t * p , char * pSop, int ObjId ,int nFanins, int int rouletteWheel( Vec_Int_t * vQualitySops, int numValid){ int i; - int candidateRows[numValid]; float totalSum; totalSum = 0.0; for ( i = 0; i < numValid; i++ ) totalSum += (float) Vec_IntEntry(vQualitySops, i); - unsigned int randValue = Aig_ManRandom(0); + unsigned int randValue = Gia_ManRandom(0); float randValueNormalized = (float) ((float)randValue / __UINT32_MAX__); float randomNum = randValueNormalized * totalSum; @@ -3324,7 +3323,7 @@ int selectSop( Vec_Int_t * vQualitySops, int ith_max_quality, int experimentID){ assert(experimentID > 0); // random simulation should not be used here int numValid = Vec_IntSize(vQualitySops); - int idSelected = -1, iii, jQuality; + int idSelected = -1; switch (experimentID){ //case 1: // idSelected = Aig_ManRandom(0) % numValid; @@ -3364,7 +3363,6 @@ int check_implication( Gia_Man_t * p, int ObjId , int validBit , int fanoutValue // case in which the output is set // backward implication char * pSop = pSopBoth[fanoutValue]; int nCubes = nCubesBoth[fanoutValue]; - char * pValue = pSop; int compatible = 0; int lastCube = 0; for(ith_cube = 0; ith_cube < nCubes; ith_cube++){ @@ -3394,7 +3392,6 @@ int check_implication( Gia_Man_t * p, int ObjId , int validBit , int fanoutValue char * pSop = pSopBoth[jjj]; int nCubes = nCubesBoth[jjj]; - char * pValue = pSop; for(ith_cube = 0; ith_cube < nCubes; ith_cube++){ if(checkCompatibilityCube( p, pSop + ith_cube * 2, nFanins, inputsFaninsValues ) ){ compatible[jjj]++; @@ -3527,7 +3524,7 @@ int checkCompatibilityImplication( Gia_Man_t * p, Cec_ParSimGen_t * pPars, char int computeLutsToImply( Gia_Man_t * p, Cec_ParSimGen_t * pPars, char * netValid, int ObjId, char * networkValues1s, char * networkValuesNotSet , Vec_Int_t * vLutsFaninCones, Vec_Int_t * vLuts2Imply, Vec_Int_t * vLutsValidity , Vec_Ptr_t * vNodesWatchlist, int experimentID){ - int i, ith_fanout, FanoutId, jth_fanout, LutId, FaninId, k; + int i, FanoutId, jth_fanout, LutId, k; if(vNodesWatchlist == NULL){ // Option 1: iterate through fanouts to check if there can be an implication and if yes, apply it @@ -3605,7 +3602,7 @@ int executeImplications( Gia_Man_t * p, Cec_ParSimGen_t * pPars, char * netValid assert( *netValid > 0); pPars->nImplicationExecution++; - int iii = -1, FanoutId, jth_fanout, jjj, FaninId; + int iii = -1, FanoutId; Vec_Int_t * vLuts2Imply = Vec_IntAlloc( 10 ); Vec_Int_t * vLutsValidity = Vec_IntAlloc( 10 ); @@ -3664,7 +3661,7 @@ int computeNetworkValues(Gia_Man_t * p, Cec_ParSimGen_t * pPars, int ObjId , ch Vec_Int_t * vCubeId = Vec_IntAlloc( 8 ); // save ids of the selected cubes char _valid_vecs = *netValid; char _desired_values = lutValues1s; - int iii = -1, max_quality, ith_max_quality, ithSop, validNum =0; + int iii = -1, max_quality, ith_max_quality, validNum =0; int nFanins = Gia_ObjLutSize(p, ObjId); // first compute all SOPs that are available while (_valid_vecs > 0){ @@ -3722,7 +3719,7 @@ int computeNetworkValues(Gia_Man_t * p, Cec_ParSimGen_t * pPars, int ObjId , ch } Vec_IntFree( vQualitySops ); Vec_IntFree( vCubeId ); - assert( validNum == Vec_IntSize(vSops) ); + assert( validNum == Vec_PtrSize(vSops) ); _valid_vecs = *netValid; // if not SOP available is valid return 0 ( not -1 since the valid vector might have been modified to skip DCs // there might be some valid SOPs for the next fanin) if( _valid_vecs == 0){ @@ -3873,7 +3870,7 @@ void exportSimValues( Gia_Man_t * p, char * filename ) word * pSim = Cec4_ObjSim( p, i ); fprintf( pFile, "Obj %d ", i ); for(j = 0; j < p->nSimWords; j++){ - fprintf( pFile, "[%d]: %x ", j, pSim[j] ); + fprintf( pFile, "[%d]: %lu ", j, pSim[j] ); } fprintf(pFile, "\n"); } @@ -3896,7 +3893,7 @@ int computeInputVectors(Gia_Man_t * p, Cec4_Man_t * pMan, Cec_ParSimGen_t * pPar char * networkValues1s, * networkValuesNotSet; // data structure containing the values inside the network char networkValid = (char) (1 << outGold_bitwidth) - 1; // keeps track which array out of the 8 is valid - int iRepr, jLut, mainLoop_condition, iii, numLuts, numPis = Gia_ManPiNum(p); + int jLut, mainLoop_condition, iii, numLuts; numLuts = Vec_IntSize(vLuts); assert(numLuts > 0); @@ -4044,7 +4041,7 @@ exit_cond: void executeControlledSim(Gia_Man_t * p, Cec4_Man_t * pMan, Cec_ParSimGen_t * pPars , int levelOrder, int experimentID){ char * outGold; - int outGold_bitwidth = pPars->bitwidthOutgold; + //int outGold_bitwidth = pPars->bitwidthOutgold; int numClasses = totalNumClasses(p); int iTrials = 0, outer_loop_condition = iTrials < (numClasses * 1.5); int nthClass = 0, status, oldNumClasses = numClasses, iter; @@ -4302,8 +4299,7 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ Cec4_Man_t * pManSim; - Gia_Obj_t * pObj, * pRepr; - int i, fSimulate = 1, k, iFan; + int i, k, iFan; // apply technology mapping From bd80d2e4594a431d699bf5b90f08c463fcea8393 Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Sat, 21 Dec 2024 16:04:45 +0100 Subject: [PATCH 045/133] [CEC][SimGen][Warnings] Re-adjusted code to remove unused variables and avoid warnings compilation --- src/proof/cec/cecSatG2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index c62acf878..c9a0f170f 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -3746,7 +3746,7 @@ int computeNetworkValues(Gia_Man_t * p, Cec_ParSimGen_t * pPars, int ObjId , ch validNum++; char mask_fanin = 1 << jth_fanin; - pSop = Vec_PtrEntry(vSops, validNum); + pSop = (char *) Vec_PtrEntry(vSops, validNum); char pSop1s = *pSop; pSop++; char pSopDCs = *pSop; From f407156de611da2b6747faa4371f520ddd9f0a9d Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Sat, 21 Dec 2024 16:19:47 +0100 Subject: [PATCH 046/133] [CEC][SimGen][Warnings] Re-adjusted code to remove unused variables and avoid warnings compilation --- src/aig/gia/giaResub.c | 2 +- src/proof/cec/cecSatG2.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/aig/gia/giaResub.c b/src/aig/gia/giaResub.c index 8ce2f3d33..a4141a050 100644 --- a/src/aig/gia/giaResub.c +++ b/src/aig/gia/giaResub.c @@ -68,7 +68,7 @@ int Gia_ObjCheckMffc_rec( Gia_Man_t * p,Gia_Obj_t * pObj, int Limit, Vec_Int_t * return 0; return 1; } -inline int Gia_ObjCheckMffc( Gia_Man_t * p, Gia_Obj_t * pRoot, int Limit, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t * vInners ) +int Gia_ObjCheckMffc( Gia_Man_t * p, Gia_Obj_t * pRoot, int Limit, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t * vInners ) { int RetValue, iObj, i; Vec_IntClear( vNodes ); diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index c9a0f170f..ab7dae988 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -2708,12 +2708,14 @@ void generateLutsRankings( Gia_Man_t * p){ Vec_Int_t * vLutsRankingsTmp = Vec_IntAlloc( Gia_ManLutNum(p) * 5 ); int LutId, iii, k, jjj; char * pSop[2]; int nCubes[2]; int nFanins; + int * ranks, * fanins; Gia_ManForEachLut( p, LutId ) { nFanins = Gia_ObjLutSize(p, LutId); Vec_PtrInsert( p->vLutsRankings, LutId, vLutsRankingsTmp->pArray + Vec_IntSize(vLutsRankingsTmp) ); - int ranks[nFanins]; - int fanins[nFanins]; + assert( nFanins > 0 ); + ranks = (int*) malloc( nFanins * sizeof(int) ); + fanins = (int*) malloc( nFanins * sizeof(int) ); Gia_LutForEachFanin( p, LutId, k, iii ){ fanins[iii] = k; ranks[iii] = 0; @@ -2736,6 +2738,8 @@ void generateLutsRankings( Gia_Man_t * p){ Vec_IntPush( vLutsRankingsTmp, fanins[positions[jjj]] ); } free( positions ); + free( ranks ); + free( fanins ); } //Vec_IntFree( vLutsRankingsTmp ); } @@ -3286,14 +3290,14 @@ int compute_quality_sop(Gia_Man_t * p , char * pSop, int ObjId ,int nFanins, int int rouletteWheel( Vec_Int_t * vQualitySops, int numValid){ - int i; + int i, max_int = 0xffffffff; float totalSum; totalSum = 0.0; for ( i = 0; i < numValid; i++ ) totalSum += (float) Vec_IntEntry(vQualitySops, i); unsigned int randValue = Gia_ManRandom(0); - float randValueNormalized = (float) ((float)randValue / __UINT32_MAX__); + float randValueNormalized = (float) ((float)randValue / max_int); float randomNum = randValueNormalized * totalSum; // Select the index based on inverse proportional probability From 8a1c28bf0f37cdf35f007b932451418eaf053352 Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Sat, 21 Dec 2024 20:15:40 +0100 Subject: [PATCH 047/133] [CEC][SimGen][LUT mapping] Adding option to consider an already mapped circuit before executing SimGen --- src/proof/cec/cecSatG2.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index ab7dae988..1e058c29c 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -4304,13 +4304,22 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ Cec4_Man_t * pManSim; int i, k, iFan; - + Gia_Man_t * pMapped; - // apply technology mapping - If_Par_t IfPars, * pIfPars = &IfPars; - Gia_ManSetIfParsDefault( pIfPars ); - pIfPars->nLutSize = 6; - Gia_Man_t * pMapped = Gia_ManPerformMapping( p, pIfPars ); + if (!Gia_ManHasMapping(p)){ + // apply technology mapping if not already done + If_Par_t IfPars, * pIfPars = &IfPars; + Gia_ManSetIfParsDefault( pIfPars ); + pIfPars->nLutSize = 6; + pMapped = Gia_ManPerformMapping( p, pIfPars ); + if(pPars->fVerbose) + printf("Performing LUT-mapping\n"); + } else { + pMapped = Gia_ManDup( p ); + Gia_ManDupMapping( pMapped, p ); + if(pPars->fVerbose) + printf("Using already mapped network\n"); + } pManSim = Cec4_ManCreate( pMapped, pPars->pCECPars ); Cec_DeriveSOPs( pMapped ); From ef8c35f95d660c224b7d756fd432e0d5a50b965d Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Sat, 21 Dec 2024 20:22:02 +0100 Subject: [PATCH 048/133] [CEC][SimGen][LUT mapping] Adding option to consider an already mapped circuit before executing SimGen --- src/proof/cec/cecSatG2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 1e058c29c..33259bfe4 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -4301,7 +4301,7 @@ void printISOPLUT(Gia_Man_t * pMan, int ObjId){ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ - + extern void Gia_ManDupMapping( Gia_Man_t * pNew, Gia_Man_t * p ); Cec4_Man_t * pManSim; int i, k, iFan; Gia_Man_t * pMapped; From 207cfddaa8c3aa72780a5244ff3dc6dd0f92ff0b Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 21 Dec 2024 21:24:45 -0800 Subject: [PATCH 049/133] Experiments with structural LUT cascade mapping. --- src/base/abci/abc.c | 154 ++++++++++++++- src/base/abci/abcCas.c | 413 +++++++++++++++++++++++++++++++++++++++ src/base/io/ioWriteDot.c | 2 +- src/misc/nm/nmApi.c | 4 +- 4 files changed, 569 insertions(+), 4 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 426f90fd5..a74be918e 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -154,6 +154,7 @@ static int Abc_CommandResubCore ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandResubCheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLutCasDec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLutCas ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandVarMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -955,6 +956,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "resub_check", Abc_CommandResubCheck, 0 ); // Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "lutcasdec", Abc_CommandLutCasDec, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "lutcas", Abc_CommandLutCas, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "extract", Abc_CommandExtract, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "varmin", Abc_CommandVarMin, 0 ); @@ -8886,6 +8888,7 @@ usage: return 1; } + /**Function************************************************************* Synopsis [] @@ -8897,7 +8900,7 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; @@ -9003,6 +9006,155 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkLutCascadeMap( Abc_Ntk_t * pNtk, int nLutsMax, int nIters, int fDelayLut, int fDelayRoute, int fDelayDirect, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; + int c, nLutSize = 6, nLutsMax = 8, nIters = 1000, Seed = 0, fVerbose = 0; + int fDelayLut = 10, fDelayRoute = 30, fDelayDirect = 3; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KMISLWDfvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 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; + } + nLutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutsMax < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Seed < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + fDelayLut = atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( fDelayLut < 0 ) + goto usage; + break; + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + fDelayRoute = atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( fDelayRoute < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + fDelayDirect = atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( fDelayDirect < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Run command \"if\" or any other LUT mapper to map the current network into LUTs.\n" ); + return 1; + } + if ( Abc_NtkGetFaninMax(pNtk) > nLutSize ) + { + Abc_Print( -1, "The current network contains nodes with fanin count (%d) exceeding the LUT size (%d).\n", Abc_NtkGetFaninMax(pNtk), nLutSize ); + return 1; + } + srand( Seed ); + pNtkRes = Abc_NtkLutCascadeMap( pNtk, nLutsMax, nIters, fDelayLut, fDelayRoute, fDelayDirect, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "LUT cascade mapping failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: lutcas [-KMISLWD ] [-vh]\n" ); + Abc_Print( -2, "\t decomposes the current network 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 number of LUTs in the cascade [default = %d]\n", nLutsMax ); + Abc_Print( -2, "\t-I : the number of iterations when looking for a solution [default = %d]\n", nIters ); + Abc_Print( -2, "\t-S : the random seed used to randimize solutions [default = %d]\n", Seed ); + Abc_Print( -2, "\t-L : the intrinsic LUT delay [default = %f]\n", fDelayLut ); + Abc_Print( -2, "\t-W : the routable wire delay [default = %f]\n", fDelayRoute ); + Abc_Print( -2, "\t-D : the non-routable wire delay [default = %f]\n", fDelayDirect ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index eddb2c1a1..7fea2b54a 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -267,6 +267,419 @@ Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nR return pNew; } + +/**Function************************************************************* + + Synopsis [Structural LUT cascade mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +typedef struct Abc_LutCas_t_ Abc_LutCas_t; +struct Abc_LutCas_t_ +{ + // mapped network + Abc_Ntk_t * pNtk; + // parameters + int nLutSize; + int nLutsMax; + int nIters; + int fDelayLut; + int fDelayRoute; + int fDelayDirect; + int fVerbose; + // internal data + int DelayMax; + Vec_Int_t * vTime[2]; // timing info + Vec_Int_t * vCrits[2]; // critical terminals + Vec_Int_t * vPath[2]; // direct connections + Vec_Wec_t * vStack; // processing queue + Vec_Int_t * vZeroSlack; // zero-slack nodes + Vec_Int_t * vCands; // direct edge candidates + Vec_Int_t * vTrace; // modification trace + Vec_Int_t * vTraceBest; // modification trace +}; + +Abc_LutCas_t * Abc_LutCasAlloc( Abc_Ntk_t * pNtk, int nLutsMax, int nIters, int fDelayLut, int fDelayRoute, int fDelayDirect, int fVerbose ) +{ + Abc_LutCas_t * p = ABC_ALLOC( Abc_LutCas_t, 1 ); + p->pNtk = pNtk; + p->nLutSize = 6; + p->nLutsMax = nLutsMax; + p->nIters = nIters; + p->fDelayLut = fDelayLut; + p->fDelayRoute = fDelayRoute; + p->fDelayDirect = fDelayDirect; + p->fVerbose = fVerbose; + p->vTime[0] = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + p->vTime[1] = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + p->vCrits[0] = Vec_IntAlloc(1000); + p->vCrits[1] = Vec_IntAlloc(1000); + p->vPath[0] = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + p->vPath[1] = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + p->vStack = Vec_WecStart( Abc_NtkLevel(pNtk) + 1 ); + p->vZeroSlack = Vec_IntAlloc( 1000 ); + p->vCands = Vec_IntAlloc( 1000 ); + p->vTrace = Vec_IntAlloc( 1000 ); + p->vTraceBest = Vec_IntAlloc( 1000 ); + return p; +} +void Abc_LutCasFree( Abc_LutCas_t * p ) +{ + Vec_IntFree( p->vTime[0] ); + Vec_IntFree( p->vTime[1] ); + Vec_IntFree( p->vCrits[0] ); + Vec_IntFree( p->vCrits[1] ); + Vec_IntFree( p->vPath[0] ); + Vec_IntFree( p->vPath[1] ); + Vec_WecFree( p->vStack ); + Vec_IntFree( p->vZeroSlack ); + Vec_IntFree( p->vCands ); + Vec_IntFree( p->vTrace ); + Vec_IntFree( p->vTraceBest ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Structural LUT cascade mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkFindPathTimeD_rec( Abc_LutCas_t * p, Abc_Obj_t * pObj ) +{ + if ( !Abc_ObjIsNode(pObj) || !Abc_ObjFaninNum(pObj) ) + return 0; + if ( Vec_IntEntry(p->vTime[0], pObj->Id) > 0 ) + return Vec_IntEntry(p->vTime[0], pObj->Id); + Abc_Obj_t * pNext; int i, Delay, DelayMax = 0; + Abc_ObjForEachFanin( pObj, pNext, i ) { + Delay = Abc_NtkFindPathTimeD_rec( p, pNext ); + Delay += Vec_IntEntry(p->vPath[0], pObj->Id) == pNext->Id ? p->fDelayDirect : p->fDelayRoute; + DelayMax = Abc_MaxInt( DelayMax, Delay + p->fDelayLut ); + } + Vec_IntWriteEntry( p->vTime[0], pObj->Id, DelayMax ); + return DelayMax; +} +int Abc_NtkFindPathTimeD( Abc_LutCas_t * p ) +{ + Abc_Obj_t * pObj; int i, Delay, DelayMax = 0; + Vec_IntFill( p->vTime[0], Abc_NtkObjNumMax(p->pNtk), 0 ); + Abc_NtkForEachCo( p->pNtk, pObj, i ) { + Delay = Abc_NtkFindPathTimeD_rec( p, Abc_ObjFanin0(pObj) ); + DelayMax = Abc_MaxInt( DelayMax, Delay + p->fDelayRoute ); + } + Vec_IntClear( p->vCrits[0] ); + Abc_NtkForEachCo( p->pNtk, pObj, i ) + if ( DelayMax == Vec_IntEntry(p->vTime[0], Abc_ObjFaninId0(pObj)) + p->fDelayRoute ) + Vec_IntPush( p->vCrits[0], pObj->Id ); + return DelayMax; +} +int Abc_NtkFindPathTimeR_rec( Abc_LutCas_t * p, Abc_Obj_t * pObj ) +{ + if ( Abc_ObjIsCo(pObj) ) + return 0; + if ( Vec_IntEntry(p->vTime[1], pObj->Id) > 0 ) + return Vec_IntEntry(p->vTime[1], pObj->Id) + (Abc_ObjIsNode(pObj) ? p->fDelayLut : 0); + Abc_Obj_t * pNext; int i; float Delay, DelayMax = 0; + Abc_ObjForEachFanout( pObj, pNext, i ) { + Delay = Abc_NtkFindPathTimeR_rec( p, pNext ); + Delay += Vec_IntEntry(p->vPath[0], pNext->Id) == pObj->Id ? p->fDelayDirect : p->fDelayRoute; + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + Vec_IntWriteEntry( p->vTime[1], pObj->Id, DelayMax ); + return DelayMax + (Abc_ObjIsNode(pObj) ? p->fDelayLut : 0); +} +int Abc_NtkFindPathTimeR( Abc_LutCas_t * p ) +{ + Abc_Obj_t * pObj; int i; int Delay, DelayMax = 0; + Vec_IntFill( p->vTime[1], Abc_NtkObjNumMax(p->pNtk), 0 ); + Abc_NtkForEachCi( p->pNtk, pObj, i ) { + Delay = Abc_NtkFindPathTimeR_rec( p, pObj ); + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + Vec_IntClear( p->vCrits[1] ); + Abc_NtkForEachCi( p->pNtk, pObj, i ) + if ( DelayMax == Vec_IntEntry(p->vTime[1], pObj->Id) ) + Vec_IntPush( p->vCrits[1], pObj->Id ); + return DelayMax; +} +void Abc_NtkFindCriticalEdges( Abc_LutCas_t * p ) +{ + Abc_Obj_t * pObj, * pFanin; int i, k; + Vec_IntClear( p->vCands ); + Abc_NtkForEachNode( p->pNtk, pObj, i ) { + if ( Vec_IntEntry(p->vPath[0], pObj->Id) ) + continue; + if ( Vec_IntEntry(p->vTime[0], pObj->Id) + Vec_IntEntry(p->vTime[1], pObj->Id) < p->DelayMax ) + continue; + assert( Vec_IntEntry(p->vTime[0], pObj->Id) + Vec_IntEntry(p->vTime[1], pObj->Id == p->DelayMax) ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( Abc_ObjIsNode(pFanin) && !Vec_IntEntry(p->vPath[1], pFanin->Id) && + Vec_IntEntry(p->vTime[0], pFanin->Id) + p->fDelayRoute + p->fDelayLut == Vec_IntEntry(p->vTime[0], pObj->Id) ) + Vec_IntPushTwo( p->vCands, pObj->Id, pFanin->Id ); + } +} +int Abc_NtkFindTiming( Abc_LutCas_t * p ) +{ + int Delay0 = Abc_NtkFindPathTimeD( p ); + int Delay1 = Abc_NtkFindPathTimeR( p ); + assert( Delay0 == Delay1 ); + p->DelayMax = Delay0; + Abc_NtkFindCriticalEdges( p ); + return Delay0; +} + +int Abc_NtkUpdateNodeD( Abc_LutCas_t * p, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pNext; int i; int Delay, DelayMax = 0; + Abc_ObjForEachFanin( pObj, pNext, i ) { + Delay = Vec_IntEntry( p->vTime[0], pNext->Id ); + Delay += Vec_IntEntry(p->vPath[0], pObj->Id) == pNext->Id ? p->fDelayDirect : p->fDelayRoute; + DelayMax = Abc_MaxInt( DelayMax, Delay + p->fDelayLut ); + } + int DelayOld = Vec_IntEntry( p->vTime[0], pObj->Id ); + Vec_IntWriteEntry( p->vTime[0], pObj->Id, DelayMax ); + assert( DelayOld >= DelayMax ); + return DelayOld > DelayMax; +} +int Abc_NtkUpdateNodeR( Abc_LutCas_t * p, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pNext; int i; float Delay, DelayMax = 0; + Abc_ObjForEachFanout( pObj, pNext, i ) { + Delay = Vec_IntEntry(p->vTime[1], pNext->Id) + (Abc_ObjIsNode(pNext) ? p->fDelayLut : 0); + Delay += Vec_IntEntry(p->vPath[0], pNext->Id) == pObj->Id ? p->fDelayDirect : p->fDelayRoute; + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + int DelayOld = Vec_IntEntry( p->vTime[1], pObj->Id ); + Vec_IntWriteEntry( p->vTime[1], pObj->Id, DelayMax ); + assert( DelayOld >= DelayMax ); + return DelayOld > DelayMax; +} +int Abc_NtkUpdateTiming( Abc_LutCas_t * p, int Node, int Fanin ) +{ + Abc_Obj_t * pNode = Abc_NtkObj( p->pNtk, Node ); + Abc_Obj_t * pFanin = Abc_NtkObj( p->pNtk, Fanin ); + Abc_Obj_t * pNext, * pTemp; Vec_Int_t * vLevel; int i, k, j; + assert( Abc_ObjIsNode(pNode) && Abc_ObjIsNode(pFanin) ); + Vec_WecForEachLevel( p->vStack, vLevel, i ) + Vec_IntClear( vLevel ); + Abc_NtkIncrementTravId( p->pNtk ); + Abc_NodeSetTravIdCurrentId( p->pNtk, Node ); + Abc_NodeSetTravIdCurrentId( p->pNtk, Fanin ); + Vec_WecPush( p->vStack, pNode->Level, Node ); + Vec_WecPush( p->vStack, pFanin->Level, Fanin ); + Vec_WecForEachLevelStart( p->vStack, vLevel, i, pNode->Level ) + Abc_NtkForEachObjVec( vLevel, p->pNtk, pTemp, k ) { + if ( !Abc_NtkUpdateNodeD(p, pTemp) ) + continue; + Abc_ObjForEachFanout( pTemp, pNext, j ) { + if ( Abc_NodeIsTravIdCurrent(pNext) || Abc_ObjIsCo(pNext) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + Vec_WecPush( p->vStack, pNext->Level, pNext->Id ); + } + } + Vec_WecForEachLevelReverseStartStop( p->vStack, vLevel, i, pFanin->Level+1, 0 ) + Abc_NtkForEachObjVec( vLevel, p->pNtk, pTemp, k ) { + if ( !Abc_NtkUpdateNodeR(p, pTemp) ) + continue; + Abc_ObjForEachFanin( pTemp, pNext, j ) { + if ( Abc_NodeIsTravIdCurrent(pNext) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + Vec_WecPush( p->vStack, pNext->Level, pNext->Id ); + } + } + j = 0; + Abc_NtkForEachObjVec( p->vCrits[0], p->pNtk, pTemp, i ) + if ( Vec_IntEntry(p->vTime[0], Abc_ObjFaninId0(pTemp)) + p->fDelayRoute == p->DelayMax ) + Vec_IntWriteEntry( p->vCrits[0], j++, pTemp->Id ); + Vec_IntShrink( p->vCrits[0], j ); + j = 0; + Abc_NtkForEachObjVec( p->vCrits[1], p->pNtk, pTemp, i ) + if ( Vec_IntEntry(p->vTime[1], pTemp->Id) == p->DelayMax ) + Vec_IntWriteEntry( p->vCrits[1], j++, pTemp->Id ); + Vec_IntShrink( p->vCrits[1], j ); + if ( Vec_IntSize(p->vCrits[0]) && Vec_IntSize(p->vCrits[1]) ) { + int j = 0, Node2, Fanin2; + Vec_IntForEachEntryDouble( p->vCands, Node2, Fanin2, i ) + if ( !Vec_IntEntry(p->vPath[0], Node2) && !Vec_IntEntry(p->vPath[1], Fanin2) && + Vec_IntEntry(p->vTime[0], Node2) + Vec_IntEntry(p->vTime[1], Node2) == p->DelayMax && + Vec_IntEntry(p->vTime[0], Fanin2) + p->fDelayRoute + p->fDelayLut == Vec_IntEntry(p->vTime[0], Node2) ) + Vec_IntWriteEntry( p->vCands, j++, Node2 ), Vec_IntWriteEntry( p->vCands, j++, Fanin2 ); + Vec_IntShrink( p->vCands, j ); + return p->DelayMax; + } + int DelayOld = p->DelayMax; + Abc_NtkFindTiming(p); + assert( DelayOld > p->DelayMax ); + return p->DelayMax; +} + +/**Function************************************************************* + + Synopsis [Structural LUT cascade mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkAddEdges( Abc_LutCas_t * p ) +{ + int nEdgesMax = 10000; + Vec_IntClear( p->vTrace ); + Vec_IntFill( p->vPath[0], Vec_IntSize(p->vPath[0]), 0 ); + Vec_IntFill( p->vPath[1], Vec_IntSize(p->vPath[1]), 0 ); + Abc_NtkFindTiming( p ); + if ( p->fVerbose ) + printf( "Start : %d\n", p->DelayMax ); + int i, LastChange = 0; + for ( i = 0; i < nEdgesMax; i++ ) + { + float DelayPrev = p->DelayMax; + if ( Vec_IntSize(p->vCands) == 0 ) + break; + int Index = rand() % Vec_IntSize(p->vCands)/2; + int Node = Vec_IntEntry( p->vCands, 2*Index ); + int Fanin = Vec_IntEntry( p->vCands, 2*Index+1 ); + assert( Vec_IntEntry( p->vPath[0], Node ) == 0 ); + Vec_IntWriteEntry( p->vPath[0], Node, Fanin ); + assert( Vec_IntEntry( p->vPath[1], Fanin ) == 0 ); + Vec_IntWriteEntry( p->vPath[1], Fanin, Node ); + Vec_IntPushTwo( p->vTrace, Node, Fanin ); + //Abc_NtkFindTiming( p ); + Abc_NtkUpdateTiming( p, Node, Fanin ); + assert( DelayPrev >= p->DelayMax ); + if ( DelayPrev > p->DelayMax ) + LastChange = i+1; + DelayPrev = p->DelayMax; + if ( p->fVerbose ) + printf( "%5d : %d : %4d -> %4d\n", i, p->DelayMax, Fanin, Node ); + } + Vec_IntShrink( p->vTrace, 2*LastChange ); + return p->DelayMax; +} +Vec_Wec_t * Abc_NtkProfileCascades( Abc_Ntk_t * pNtk, Vec_Int_t * vTrace ) +{ + Vec_Wec_t * vCasc = Vec_WecAlloc( 100 ); + Vec_Int_t * vMap = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + Vec_Int_t * vPath = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + Vec_Int_t * vCounts = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + Abc_Obj_t * pObj; int i, Node, Fanin, Count, nCascs = 0; + Vec_IntForEachEntryDouble( vTrace, Node, Fanin, i ) { + assert( Vec_IntEntry(vPath, Node) == 0 ); + Vec_IntWriteEntry( vPath, Node, Fanin ); + Vec_IntWriteEntry( vMap, Fanin, 1 ); + } + Abc_NtkForEachNode( pNtk, pObj, i ) { + if ( Vec_IntEntry(vMap, pObj->Id) ) + continue; + if ( Vec_IntEntry(vPath, pObj->Id) == 0 ) + continue; + Vec_Int_t * vLevel = Vec_WecPushLevel( vCasc ); + Node = pObj->Id; + Vec_IntPush( vLevel, Node ); + while ( (Node = Vec_IntEntry(vPath, Node)) ) + Vec_IntPush( vLevel, Node ); + Vec_IntAddToEntry( vCounts, Vec_IntSize(vLevel), 1 ); + } + printf( "Cascades: " ); + Vec_IntForEachEntry( vCounts, Count, i ) + if ( Count ) + printf( "%d=%d ", i, Count ), nCascs += Count; + printf( "\n" ); + Vec_IntFree( vMap ); + Vec_IntFree( vPath ); + Vec_IntFree( vCounts ); + return vCasc; +} +void Abc_LutCasAssignNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Wec_t * vCascs ) +{ + Abc_Obj_t * pObj; Vec_Int_t * vLevel; int i, k; char pName[100]; + Vec_Int_t * vMap = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachCo( pNtkNew, pObj, i ) + Vec_IntWriteEntry( vMap, Abc_ObjFaninId0(pObj), pObj->Id ); + Vec_WecForEachLevel( vCascs, vLevel, i ) { + Abc_NtkForEachObjVec( vLevel, pNtk, pObj, k ) { + assert( Abc_ObjIsNode(pObj) ); + sprintf( pName, "c%d_n%d", i, k ); + if ( Vec_IntEntry(vMap, pObj->pCopy->Id) == 0 ) + Abc_ObjAssignName( Abc_NtkObj(pNtkNew, pObj->pCopy->Id), pName, NULL ); + else { + Nm_ManDeleteIdName( pNtkNew->pManName, Vec_IntEntry(vMap, pObj->pCopy->Id) ); + Abc_ObjAssignName( Abc_NtkObj(pNtkNew, Vec_IntEntry(vMap, pObj->pCopy->Id)), pName, NULL ); + } + } + } + Vec_IntFree( vMap ); +} +void Abc_NtkLutCascadeDumpResults( char * pDumpFile, char * pTest, int Nodes, int Edges, int Levs, int DelStart, int DelStop, float DelRatio, int EdgesUsed, float EdgeRatio, int Cascs, float AveLength, abctime time ) +{ + FILE * pTable = fopen( pDumpFile, "a+" ); + fprintf( pTable, "%s,", pTest+28 ); + fprintf( pTable, "%d,", Nodes ); + fprintf( pTable, "%d,", Edges ); + fprintf( pTable, "%d,", Levs ); + fprintf( pTable, "%d,", DelStart ); + fprintf( pTable, "%d,", DelStop ); + fprintf( pTable, "%.2f,", DelRatio ); + fprintf( pTable, "%d,", EdgesUsed ); + fprintf( pTable, "%.2f,", EdgeRatio ); + fprintf( pTable, "%d,", Cascs ); + fprintf( pTable, "%.1f,", AveLength ); + fprintf( pTable, "%.2f,", 1.0*((double)(time))/((double)CLOCKS_PER_SEC) ); + fprintf( pTable, "\n" ); + fclose( pTable ); +} + +Abc_Ntk_t * Abc_NtkLutCascadeMap( Abc_Ntk_t * pNtk, int nLutsMax, int nIters, int fDelayLut, int fDelayRoute, int fDelayDirect, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Abc_Ntk_t * pNtkNew = NULL; + Abc_LutCas_t * p = Abc_LutCasAlloc( pNtk, nLutsMax, nIters, fDelayLut, fDelayRoute, fDelayDirect, fVerbose ); + int i, IterBest = 0, DelayStart = Abc_NtkFindTiming( p ), DelayBest = DelayStart, nEdges = Abc_NtkGetTotalFanins(pNtk); + //printf( "Delays: LUT (%d) Route (%d) Direct (%d). Iters = %d. LUTs = %d.\n", fDelayLut, fDelayRoute, fDelayDirect, nIters, Abc_NtkNodeNum(pNtk) ); + Vec_IntFill( p->vTraceBest, Abc_NtkNodeNum(pNtk), 0 ); + for ( i = 0; i < nIters; i++ ) + { + if ( fVerbose ) + printf( "ITERATION %2d:\n", i ); + float Delay = Abc_NtkAddEdges( p ); + if ( DelayBest < Delay || (DelayBest == Delay && Vec_IntSize(p->vTraceBest) <= Vec_IntSize(p->vTrace)) ) + continue; + IterBest = i; + DelayBest = Delay; + ABC_SWAP( Vec_Int_t *, p->vTrace, p->vTraceBest ); + } + printf( "Delay reduction %d -> %d (-%.2f %%) is found after iter %d with %d edges (%.2f %%). ", + DelayStart, DelayBest, 100.0*(DelayStart - DelayBest)/DelayStart, IterBest, Vec_IntSize(p->vTraceBest)/2, 50.0*Vec_IntSize(p->vTraceBest)/nEdges ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Vec_Wec_t * vCascs = Abc_NtkProfileCascades( p->pNtk, p->vTraceBest ); +// Abc_NtkLutCascadeDumpResults( "stats.csv", pNtk->pName, Abc_NtkNodeNum(pNtk), nEdges, Abc_NtkLevel(pNtk), DelayStart, DelayBest, 100.0*(DelayStart - DelayBest)/DelayStart, +// Vec_IntSize(p->vTraceBest)/2, 50.0*Vec_IntSize(p->vTraceBest)/nEdges, Vec_WecSize(vCascs), 0.5*Vec_IntSize(p->vTraceBest)/Abc_MaxInt(1, Vec_WecSize(vCascs)), Abc_Clock() - clk ); + Abc_LutCasFree( p ); + pNtkNew = Abc_NtkDup( pNtk ); + Abc_LutCasAssignNames( pNtk, pNtkNew, vCascs ); + Vec_WecFree( vCascs ); + return pNtkNew; +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/io/ioWriteDot.c b/src/base/io/ioWriteDot.c index dc1f97698..2c067bd11 100644 --- a/src/base/io/ioWriteDot.c +++ b/src/base/io/ioWriteDot.c @@ -317,7 +317,7 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho if ( AigNodeId > 0 ) fprintf( pFile, " Node%d [label = \"%s%d\\n%s\"", pNode->Id, Abc_LitIsCompl(AigNodeId) ? "-":"+", Abc_Lit2Var(AigNodeId), pSopString ); else - fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); + fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id+1, pSopString ); // fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, // SuppSize, // pSopString ); diff --git a/src/misc/nm/nmApi.c b/src/misc/nm/nmApi.c index ab3340325..39071ce57 100644 --- a/src/misc/nm/nmApi.c +++ b/src/misc/nm/nmApi.c @@ -116,7 +116,7 @@ char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char // check if the object with this ID is already stored if ( (pEntry = Nm_ManTableLookupId(p, ObjId)) ) { - printf( "Nm_ManStoreIdName(): Entry with the same ID already exists.\n" ); + printf( "Nm_ManStoreIdName(): Entry with ID %d already exists.\n", ObjId ); return NULL; } // create a new entry @@ -152,7 +152,7 @@ void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId ) pEntry = Nm_ManTableLookupId(p, ObjId); if ( pEntry == NULL ) { - printf( "Nm_ManDeleteIdName(): This entry is not in the table.\n" ); + printf( "Nm_ManDeleteIdName(): Entry with ID %d is not in the table.\n", ObjId ); return; } // remove entry from the table From 42c2c54969b794af466bed49525c411022ee993a Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 22 Dec 2024 14:15:35 -0800 Subject: [PATCH 050/133] Fixing a big-endian issue in SOP manipulation and factoring. --- src/misc/mvc/mvcUtils.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/misc/mvc/mvcUtils.c b/src/misc/mvc/mvcUtils.c index d938169a3..5ce59daee 100644 --- a/src/misc/mvc/mvcUtils.c +++ b/src/misc/mvc/mvcUtils.c @@ -276,7 +276,8 @@ int Mvc_CoverSetCubeSizes( Mvc_Cover_t * pCover ) int nBytes, nOnes; // get the number of unsigned chars in the cube's bit strings - nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0); +// nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0); + nBytes = sizeof(Mvc_CubeWord_t) * pCover->nWords; // big-endian issue // iterate through the cubes Mvc_CoverForEachCube( pCover, pCube ) { @@ -298,13 +299,14 @@ int Mvc_CoverSetCubeSizes( Mvc_Cover_t * pCover ) Synopsis [Counts the cube sizes.] - Description [] + Description [This procedure works incorrectly on big-endian machines.] SideEffects [] SeeAlso [] ***********************************************************************/ +/* int Mvc_CoverGetCubeSize( Mvc_Cube_t * pCube ) { unsigned char * pByte, * pByteStart, * pByteStop; @@ -322,6 +324,7 @@ int Mvc_CoverGetCubeSize( Mvc_Cube_t * pCube ) nOnes += bit_count[*pByte]; return nOnes; } +*/ /**Function************************************************************* @@ -351,7 +354,8 @@ int Mvc_CoverCountCubePairDiffs( Mvc_Cover_t * pCover, unsigned char pDiffs[] ) // allocate a temporary mask pMask = Mvc_CubeAlloc( pCover ); // get the number of unsigned chars in the cube's bit strings - nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0); +// nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0); + nBytes = sizeof(Mvc_CubeWord_t) * pCover->nWords; // big-endian issue // iterate through the cubes nCubePairs = 0; Mvc_CoverForEachCube( pCover, pCube1 ) From fdd66a8963939bd5a75bc519083f6106bfb934c8 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Mon, 23 Dec 2024 23:24:47 +0800 Subject: [PATCH 051/133] Fix(&if -x): Conditional jump or move depends on uninitialised value(s) From Valgrind: ==44570== Conditional jump or move depends on uninitialised value(s) ==44570== at 0x9DEBA1: Dau_DsdRemoveBraces (dauMerge.c:563) ==44570== by 0x9D1F53: Dau_DsdDecompose (dauDsd.c:1926) ==44570== by 0x835523: If_DsdManCompute (ifDsd.c:2073) ==44570== by 0x84177C: If_ObjPerformMappingAnd (ifMap.c:315) ==44570== by 0x843720: If_ManPerformMappingRound (ifMap.c:667) ==44570== by 0x813A01: If_ManPerformMappingComb (ifCore.c:126) ==44570== by 0x813C88: If_ManPerformMapping (ifCore.c:91) ==44570== by 0xE5F147: Gia_ManPerformMappingInt (giaIf.c:2503) ==44570== by 0xE60976: Gia_ManPerformMapping (giaIf.c:2566) ==44570== by 0x543605: Abc_CommandAbc9If (abc.c:41910) ==44570== by 0x654739: CmdCommandDispatch (cmdUtils.c:157) ==44570== by 0x64E0F2: Cmd_CommandExecute (cmdApi.c:210) --- src/opt/dau/dauMerge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opt/dau/dauMerge.c b/src/opt/dau/dauMerge.c index 0fbd126be..e4f7bedcc 100644 --- a/src/opt/dau/dauMerge.c +++ b/src/opt/dau/dauMerge.c @@ -560,7 +560,7 @@ void Dau_DsdRemoveBraces( char * pDsd, int * pMatches ) for ( q = p; *p; p++ ) if ( *p != ' ' ) { - if ( *p == '!' && *(q-1) == '!' && p != q ) + if ( *p == '!' && p != q && *(q-1) == '!' ) { q--; continue; From e21399f3bcbca421e7c856ffd31142141096d5e6 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 23 Dec 2024 08:54:34 -0800 Subject: [PATCH 052/133] Compiler warning. --- src/aig/miniaig/ndr.h | 3 ++- src/base/abci/abc.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/aig/miniaig/ndr.h b/src/aig/miniaig/ndr.h index 193730636..1d2211f96 100644 --- a/src/aig/miniaig/ndr.h +++ b/src/aig/miniaig/ndr.h @@ -219,7 +219,8 @@ static inline void Ndr_DataPushString( Ndr_Data_t * p, int ObjType, int Type, ch { //word Truth = (word)pFunc; //Ndr_DataPushArray( p, Type, 2, (int *)&Truth ); - Ndr_DataPushArray( p, Type, 2, (int *)&pFunc ); + int nInts = (strlen(pFunc) + 1 + sizeof(int) - 1) / sizeof(int); + Ndr_DataPushArray( p, Type, nInts, (int *)&pFunc ); } else { diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index b79c6a86f..1c9d9f6d5 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -9147,9 +9147,9 @@ usage: Abc_Print( -2, "\t-M : the maximum number of LUTs in the cascade [default = %d]\n", nLutsMax ); Abc_Print( -2, "\t-I : the number of iterations when looking for a solution [default = %d]\n", nIters ); Abc_Print( -2, "\t-S : the random seed used to randimize solutions [default = %d]\n", Seed ); - Abc_Print( -2, "\t-L : the intrinsic LUT delay [default = %f]\n", fDelayLut ); - Abc_Print( -2, "\t-W : the routable wire delay [default = %f]\n", fDelayRoute ); - Abc_Print( -2, "\t-D : the non-routable wire delay [default = %f]\n", fDelayDirect ); + Abc_Print( -2, "\t-L : the intrinsic LUT delay [default = %d]\n", fDelayLut ); + Abc_Print( -2, "\t-W : the routable wire delay [default = %d]\n", fDelayRoute ); + Abc_Print( -2, "\t-D : the non-routable wire delay [default = %d]\n", fDelayDirect ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; From b81df1744ffcab47c18511a8c62aad914e4daf3a Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 23 Dec 2024 10:00:37 -0800 Subject: [PATCH 053/133] Removing unhelpful assertion. --- src/aig/gia/giaMan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index 8ce1db834..d0af551b0 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -807,7 +807,7 @@ void Gia_ManPrintNpnClasses( Gia_Man_t * p ) int i, k, iFan, Class, OtherClasses, OtherClasses2, nTotal, Counter, Counter2; unsigned * pTruth; int nLutSize = 0; assert( Gia_ManHasMapping(p) ); - assert( Gia_ManLutSizeMax( p ) <= 4 ); + //assert( Gia_ManLutSizeMax( p ) <= 4 ); vLeaves = Vec_IntAlloc( 100 ); vVisited = Vec_IntAlloc( 100 ); vTruth = Vec_IntAlloc( (1<<16) ); From cc894c590561edee25ecaeb74395eb02a8916f9c Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 23 Dec 2024 17:03:29 -0800 Subject: [PATCH 054/133] Deleting unused files. --- src/opt/mfs/mfsCore_.c | 394 ---------------------------- src/opt/mfs/mfsResub_.c | 567 ---------------------------------------- 2 files changed, 961 deletions(-) delete mode 100644 src/opt/mfs/mfsCore_.c delete mode 100644 src/opt/mfs/mfsResub_.c diff --git a/src/opt/mfs/mfsCore_.c b/src/opt/mfs/mfsCore_.c deleted file mode 100644 index 38e407bc3..000000000 --- a/src/opt/mfs/mfsCore_.c +++ /dev/null @@ -1,394 +0,0 @@ -/**CFile**************************************************************** - - FileName [mfsCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The good old minimization with complete don't-cares.] - - Synopsis [Core procedures of this package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mfsCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mfsInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMfsParsDefault( Mfs_Par_t * pPars ) -{ - memset( pPars, 0, sizeof(Mfs_Par_t) ); - pPars->nWinTfoLevs = 2; - pPars->nFanoutsMax = 10; - pPars->nDepthMax = 20; - pPars->nWinSizeMax = 300; - pPars->nGrowthLevel = 0; - pPars->nBTLimit = 5000; - pPars->fResub = 1; - pPars->fArea = 0; - pPars->fMoreEffort = 0; - pPars->fSwapEdge = 0; - pPars->fOneHotness = 0; - pPars->fVerbose = 0; - pPars->fVeryVerbose = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMfsResub( Mfs_Man_t * p, Abc_Obj_t * pNode ) -{ - clock_t clk; - p->nNodesTried++; - // prepare data structure for this node - Mfs_ManClean( p ); - // compute window roots, window support, and window nodes -clk = clock(); - p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); - p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); - p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); -p->timeWin += clock() - clk; - if ( p->pPars->nWinSizeMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinSizeMax ) - return 1; - // compute the divisors of the window -clk = clock(); - p->vDivs = Abc_MfsComputeDivisors( p, pNode, Abc_ObjRequiredLevel(pNode) - 1 ); - p->nTotalDivs += Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode); -p->timeDiv += clock() - clk; - // construct AIG for the window -clk = clock(); - p->pAigWin = Abc_NtkConstructAig( p, pNode ); -p->timeAig += clock() - clk; - // translate it into CNF -clk = clock(); - p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) ); -p->timeCnf += clock() - clk; - // create the SAT problem -clk = clock(); - p->pSat = Abc_MfsCreateSolverResub( p, NULL, 0, 0 ); - if ( p->pSat == NULL ) - { - p->nNodesBad++; - return 1; - } - // solve the SAT problem - if ( p->pPars->fPower ) - Abc_NtkMfsEdgePower( p, pNode ); - else if ( p->pPars->fSwapEdge ) - Abc_NtkMfsEdgeSwapEval( p, pNode ); - else - { - Abc_NtkMfsResubNode( p, pNode ); - if ( p->pPars->fMoreEffort ) - Abc_NtkMfsResubNode2( p, pNode ); - } -p->timeSat += clock() - clk; - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMfsNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) -{ - Hop_Obj_t * pObj; - int RetValue; - float dProb; - extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ); - - int nGain; - clock_t clk; - p->nNodesTried++; - // prepare data structure for this node - Mfs_ManClean( p ); - // compute window roots, window support, and window nodes -clk = clock(); - p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); - p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); - p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); -p->timeWin += clock() - clk; - // count the number of patterns -// p->dTotalRatios += Abc_NtkConstraintRatio( p, pNode ); - // construct AIG for the window -clk = clock(); - p->pAigWin = Abc_NtkConstructAig( p, pNode ); -p->timeAig += clock() - clk; - // translate it into CNF -clk = clock(); - p->pCnf = Cnf_DeriveSimple( p->pAigWin, Abc_ObjFaninNum(pNode) ); -p->timeCnf += clock() - clk; - // create the SAT problem -clk = clock(); - p->pSat = Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); - if ( p->pSat && p->pPars->fOneHotness ) - Abc_NtkAddOneHotness( p ); - if ( p->pSat == NULL ) - return 0; - // solve the SAT problem - RetValue = Abc_NtkMfsSolveSat( p, pNode ); - p->nTotConfLevel += p->pSat->stats.conflicts; -p->timeSat += clock() - clk; - if ( RetValue == 0 ) - { - p->nTimeOutsLevel++; - p->nTimeOuts++; - return 0; - } - // minimize the local function of the node using bi-decomposition - assert( p->nFanins == Abc_ObjFaninNum(pNode) ); - dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0; - pObj = Abc_NodeIfNodeResyn( p->pManDec, pNode->pNtk->pManFunc, pNode->pData, p->nFanins, p->vTruth, p->uCare, dProb ); - nGain = Hop_DagSize(pNode->pData) - Hop_DagSize(pObj); - if ( nGain >= 0 ) - { - p->nNodesDec++; - p->nNodesGained += nGain; - p->nNodesGainedLevel += nGain; - pNode->pData = pObj; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) -{ - extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); - - Bdc_Par_t Pars = {0}, * pDecPars = &Pars; - ProgressBar * pProgress; - Mfs_Man_t * p; - Abc_Obj_t * pObj; - Vec_Vec_t * vLevels; - Vec_Ptr_t * vNodes; - int i, k, nNodes, nFaninMax; - clock_t clk = clock(), clk2; - int nTotalNodesBeg = Abc_NtkNodeNum(pNtk); - int nTotalEdgesBeg = Abc_NtkGetTotalFanins(pNtk); - - assert( Abc_NtkIsLogic(pNtk) ); - nFaninMax = Abc_NtkGetFaninMax(pNtk); - if ( pPars->fResub ) - { - if ( nFaninMax > 8 ) - { - printf( "Nodes with more than %d fanins will not be processed.\n", 8 ); - nFaninMax = 8; - } - } - else - { - if ( nFaninMax > MFS_FANIN_MAX ) - { - printf( "Nodes with more than %d fanins will not be processed.\n", MFS_FANIN_MAX ); - nFaninMax = MFS_FANIN_MAX; - } - } - // perform the network sweep - Abc_NtkSweep( pNtk, 0 ); - // convert into the AIG - if ( !Abc_NtkToAig(pNtk) ) - { - fprintf( stdout, "Converting to AIGs has failed.\n" ); - return 0; - } - assert( Abc_NtkHasAig(pNtk) ); - - // start the manager - p = Mfs_ManAlloc( pPars ); - p->pNtk = pNtk; - p->nFaninMax = nFaninMax; - - // precomputer power-aware metrics - if ( pPars->fPower ) - { - extern Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne ); - if ( pPars->fResub ) - p->vProbs = Abc_NtkPowerEstimate( pNtk, 0 ); - else - p->vProbs = Abc_NtkPowerEstimate( pNtk, 1 ); - printf( "Total switching before = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); - } - - if ( pNtk->pExcare ) - { - Abc_Ntk_t * pTemp; - if ( Abc_NtkPiNum(pNtk->pExcare) != Abc_NtkCiNum(pNtk) ) - printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n", - Abc_NtkPiNum(pNtk->pExcare), Abc_NtkCiNum(pNtk) ); - else - { - pTemp = Abc_NtkStrash( pNtk->pExcare, 0, 0, 0 ); - p->pCare = Abc_NtkToDar( pTemp, 0, 0 ); - Abc_NtkDelete( pTemp ); - p->vSuppsInv = Aig_ManSupportsInverse( p->pCare ); - } - } - if ( p->pCare != NULL ) - printf( "Performing optimization with %d external care clauses.\n", Aig_ManPoNum(p->pCare) ); - // prepare the BDC manager - if ( !pPars->fResub ) - { - pDecPars->nVarsMax = (nFaninMax < 3) ? 3 : nFaninMax; - pDecPars->fVerbose = pPars->fVerbose; - p->vTruth = Vec_IntAlloc( 0 ); - p->pManDec = Bdc_ManAlloc( pDecPars ); - } - - // label the register outputs - if ( p->pCare ) - { - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pData = (void *)(PORT_PTRUINT_T)i; - } - - // compute levels - Abc_NtkLevel( pNtk ); - Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); - - // compute don't-cares for each node - nNodes = 0; - p->nTotalNodesBeg = nTotalNodesBeg; - p->nTotalEdgesBeg = nTotalEdgesBeg; - if ( pPars->fResub ) - { - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); - Abc_NtkForEachNode( pNtk, pObj, i ) - { - if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax ) - continue; - if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax ) - continue; - if ( !p->pPars->fVeryVerbose ) - Extra_ProgressBarUpdate( pProgress, i, NULL ); - if ( pPars->fResub ) - Abc_NtkMfsResub( p, pObj ); - else - Abc_NtkMfsNode( p, pObj ); - } - Extra_ProgressBarStop( pProgress ); - } - else - { - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); - vLevels = Abc_NtkLevelize( pNtk ); - Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 ) - { - if ( !p->pPars->fVeryVerbose ) - Extra_ProgressBarUpdate( pProgress, nNodes, NULL ); - p->nNodesGainedLevel = 0; - p->nTotConfLevel = 0; - p->nTimeOutsLevel = 0; - clk2 = clock(); - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax ) - break; - if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax ) - continue; - if ( pPars->fResub ) - Abc_NtkMfsResub( p, pObj ); - else - Abc_NtkMfsNode( p, pObj ); - } - nNodes += Vec_PtrSize(vNodes); - if ( pPars->fVerbose ) - { - printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %% ", - k, Vec_PtrSize(vNodes), - 1.0*p->nNodesGainedLevel/Vec_PtrSize(vNodes), - 1.0*p->nTotConfLevel/Vec_PtrSize(vNodes), - 100.0*p->nTimeOutsLevel/Vec_PtrSize(vNodes) ); - PRT( "Time", clock() - clk2 ); - } - } - Extra_ProgressBarStop( pProgress ); - Vec_VecFree( vLevels ); - } - Abc_NtkStopReverseLevels( pNtk ); - - // perform the sweeping - if ( !pPars->fResub ) - { - extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose ); -// Abc_NtkSweep( pNtk, 0 ); -// Abc_NtkBidecResyn( pNtk, 0 ); - } - - p->nTotalNodesEnd = Abc_NtkNodeNum(pNtk); - p->nTotalEdgesEnd = Abc_NtkGetTotalFanins(pNtk); - - // undo labesl - if ( p->pCare ) - { - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pData = NULL; - } - if ( pPars->fPower ) - printf( "Total switching after = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); - - // free the manager - p->timeTotal = clock() - clk; - Mfs_ManStop( p ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/opt/mfs/mfsResub_.c b/src/opt/mfs/mfsResub_.c deleted file mode 100644 index b79ccd9e5..000000000 --- a/src/opt/mfs/mfsResub_.c +++ /dev/null @@ -1,567 +0,0 @@ -/**CFile**************************************************************** - - FileName [mfsResub.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The good old minimization with complete don't-cares.] - - Synopsis [Procedures to perform resubstitution.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mfsResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mfsInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Updates the network after resubstitution.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMfsUpdateNetwork( Mfs_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc ) -{ - Abc_Obj_t * pObjNew, * pFanin; - int k; - // create the new node - pObjNew = Abc_NtkCreateNode( pObj->pNtk ); - pObjNew->pData = pFunc; - Vec_PtrForEachEntry( vFanins, pFanin, k ) - Abc_ObjAddFanin( pObjNew, pFanin ); - // replace the old node by the new node -//printf( "Replacing node " ); Abc_ObjPrint( stdout, pObj ); -//printf( "Inserting node " ); Abc_ObjPrint( stdout, pObjNew ); - // update the level of the node - Abc_NtkUpdate( pObj, pObjNew, p->vLevels ); -} - -/**Function************************************************************* - - Synopsis [Prints resub candidate stats.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p ) -{ - Abc_Obj_t * pFanin, * pNode; - int i, k, nAreaCrits = 0, nAreaExpanse = 0; - int nFaninMax = Abc_NtkGetFaninMax(p->pNtk); - Abc_NtkForEachNode( p->pNtk, pNode, i ) - Abc_ObjForEachFanin( pNode, pFanin, k ) - { - if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) - { - nAreaCrits++; - nAreaExpanse += (int)(Abc_ObjFaninNum(pNode) < nFaninMax); - } - } - printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n", - nAreaCrits, nAreaExpanse ); -} - -/**Function************************************************************* - - Synopsis [Tries resubstitution.] - - Description [Returns 1 if it is feasible, or 0 if c-ex is found.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMfsTryResubOnce( Mfs_Man_t * p, int * pCands, int nCands ) -{ - unsigned * pData; - int RetValue, iVar, i; - p->nSatCalls++; - RetValue = sat_solver_solve( p->pSat, pCands, pCands + nCands, (sint64)p->pPars->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); -// assert( RetValue == l_False || RetValue == l_True ); - if ( RetValue == l_False ) - return 1; - if ( RetValue != l_True ) - { - p->nTimeOuts++; - return -1; - } - p->nSatCexes++; - // store the counter-example - Vec_IntForEachEntry( p->vProjVars, iVar, i ) - { - pData = Vec_PtrEntry( p->vDivCexes, i ); - if ( !sat_solver_var_value( p->pSat, iVar ) ) // remove 0s!!! - { - assert( Aig_InfoHasBit(pData, p->nCexes) ); - Aig_InfoXorBit( pData, p->nCexes ); - } - } - p->nCexes++; - return 0; -} - -/**Function************************************************************* - - Synopsis [Performs resubstitution for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMfsSolveSatResub( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate ) -{ - int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80; - unsigned * pData; - int pCands[MFS_FANIN_MAX]; - int RetValue, iVar, i, nCands, nWords, w; - clock_t clk; - Abc_Obj_t * pFanin; - Hop_Obj_t * pFunc; - assert( iFanin >= 0 ); - - // clean simulation info - Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); - p->nCexes = 0; - if ( fVeryVerbose ) - { - printf( "\n" ); - printf( "Node %5d : Level = %2d. Divs = %3d. Fanin = %d (out of %d). MFFC = %d\n", - pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), - iFanin, Abc_ObjFaninNum(pNode), - Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 ); - } - - // try fanins without the critical fanin - nCands = 0; - Vec_PtrClear( p->vFanins ); - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - if ( i == iFanin ) - continue; - Vec_PtrPush( p->vFanins, pFanin ); - iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i; - pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVars, iVar ), 1 ); - } - RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands ); - if ( RetValue == -1 ) - return 0; - if ( RetValue == 1 ) - { - if ( fVeryVerbose ) - printf( "Node %d: Fanin %d can be removed.\n", pNode->Id, iFanin ); - p->nNodesResub++; - p->nNodesGainedLevel++; - if ( fSkipUpdate ) - return 1; -clk = clock(); - // derive the function - pFunc = Abc_NtkMfsInterplate( p, pCands, nCands ); - if ( pFunc == NULL ) - return 0; - // update the network - Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); -p->timeInt += clock() - clk; - return 1; - } - - if ( fOnlyRemove ) - return 0; - - if ( fVeryVerbose ) - { - for ( i = 0; i < 8; i++ ) - printf( " " ); - for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ ) - printf( "%d", i % 10 ); - for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) - if ( i == iFanin ) - printf( "*" ); - else - printf( "%c", 'a' + i ); - printf( "\n" ); - } - iVar = -1; - while ( 1 ) - { - float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL); - assert( (pProbab != NULL) == p->pPars->fPower ); - if ( fVeryVerbose ) - { - printf( "%3d: %2d ", p->nCexes, iVar ); - for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) - { - pData = Vec_PtrEntry( p->vDivCexes, i ); - printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) ); - } - printf( "\n" ); - } - - // find the next divisor to try - nWords = Aig_BitWordNum(p->nCexes); - assert( nWords <= p->nDivWords ); - for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) - { - if ( p->pPars->fPower ) - { - Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar); - // only accept the divisor if it is "cool" - if ( pProbab[Abc_ObjId(pDiv)] >= 0.2 ) - continue; - } - pData = Vec_PtrEntry( p->vDivCexes, iVar ); - for ( w = 0; w < nWords; w++ ) - if ( pData[w] != ~0 ) - break; - if ( w == nWords ) - break; - } - if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) ) - return 0; - - pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVars, iVar), 1 ); - RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+1 ); - if ( RetValue == -1 ) - return 0; - if ( RetValue == 1 ) - { - if ( fVeryVerbose ) - printf( "Node %d: Fanin %d can be replaced by divisor %d.\n", pNode->Id, iFanin, iVar ); - p->nNodesResub++; - p->nNodesGainedLevel++; - if ( fSkipUpdate ) - return 1; -clk = clock(); - // derive the function - pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+1 ); - if ( pFunc == NULL ) - return 0; - // update the network - Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) ); - Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); -p->timeInt += clock() - clk; - return 1; - } - if ( p->nCexes >= p->pPars->nDivMax ) - break; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Performs resubstitution for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMfsSolveSatResub2( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int iFanin2 ) -{ - int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80; - unsigned * pData, * pData2; - int pCands[MFS_FANIN_MAX]; - int RetValue, iVar, iVar2, i, w, nCands, nWords, fBreak; - clock_t clk; - Abc_Obj_t * pFanin; - Hop_Obj_t * pFunc; - assert( iFanin >= 0 ); - assert( iFanin2 >= 0 || iFanin2 == -1 ); - - // clean simulation info - Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); - p->nCexes = 0; - if ( fVeryVerbose ) - { - printf( "\n" ); - printf( "Node %5d : Level = %2d. Divs = %3d. Fanins = %d/%d (out of %d). MFFC = %d\n", - pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), - iFanin, iFanin2, Abc_ObjFaninNum(pNode), - Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 ); - } - - // try fanins without the critical fanin - nCands = 0; - Vec_PtrClear( p->vFanins ); - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - if ( i == iFanin || i == iFanin2 ) - continue; - Vec_PtrPush( p->vFanins, pFanin ); - iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i; - pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVars, iVar ), 1 ); - } - RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands ); - if ( RetValue == -1 ) - return 0; - if ( RetValue == 1 ) - { - if ( fVeryVerbose ) - printf( "Node %d: Fanins %d/%d can be removed.\n", pNode->Id, iFanin, iFanin2 ); - p->nNodesResub++; - p->nNodesGainedLevel++; -clk = clock(); - // derive the function - pFunc = Abc_NtkMfsInterplate( p, pCands, nCands ); - if ( pFunc == NULL ) - return 0; - // update the network - Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); -p->timeInt += clock() - clk; - return 1; - } - - if ( fVeryVerbose ) - { - for ( i = 0; i < 11; i++ ) - printf( " " ); - for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ ) - printf( "%d", i % 10 ); - for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) - if ( i == iFanin || i == iFanin2 ) - printf( "*" ); - else - printf( "%c", 'a' + i ); - printf( "\n" ); - } - iVar = iVar2 = -1; - while ( 1 ) - { - if ( fVeryVerbose ) - { - printf( "%3d: %2d %2d ", p->nCexes, iVar, iVar2 ); - for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) - { - pData = Vec_PtrEntry( p->vDivCexes, i ); - printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) ); - } - printf( "\n" ); - } - - // find the next divisor to try - nWords = Aig_BitWordNum(p->nCexes); - assert( nWords <= p->nDivWords ); - fBreak = 0; - for ( iVar = 1; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) - { - pData = Vec_PtrEntry( p->vDivCexes, iVar ); - for ( iVar2 = 0; iVar2 < iVar; iVar2++ ) - { - pData2 = Vec_PtrEntry( p->vDivCexes, iVar2 ); - for ( w = 0; w < nWords; w++ ) - if ( (pData[w] | pData2[w]) != ~0 ) - break; - if ( w == nWords ) - { - fBreak = 1; - break; - } - } - if ( fBreak ) - break; - } - if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) ) - return 0; - - pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVars, iVar2), 1 ); - pCands[nCands+1] = toLitCond( Vec_IntEntry(p->vProjVars, iVar), 1 ); - RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+2 ); - if ( RetValue == -1 ) - return 0; - if ( RetValue == 1 ) - { - if ( fVeryVerbose ) - printf( "Node %d: Fanins %d/%d can be replaced by divisors %d/%d.\n", pNode->Id, iFanin, iFanin2, iVar, iVar2 ); - p->nNodesResub++; - p->nNodesGainedLevel++; -clk = clock(); - // derive the function - pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+2 ); - if ( pFunc == NULL ) - return 0; - // update the network - Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar2) ); - Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) ); - assert( Vec_PtrSize(p->vFanins) == nCands + 2 ); - Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); -p->timeInt += clock() - clk; - return 1; - } - if ( p->nCexes >= p->pPars->nDivMax ) - break; - } - return 0; -} - - -/**Function************************************************************* - - Synopsis [Evaluates the possibility of replacing given edge by another edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin; - int i; - Abc_ObjForEachFanin( pNode, pFanin, i ) - Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 1 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Evaluates the possibility of replacing given edge by another edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin; - float * pProbab = (float *)p->vProbs->pArray; - int i; - // try replacing area critical fanins - Abc_ObjForEachFanin( pNode, pFanin, i ) - if ( pProbab[pFanin->Id] >= 0.4 ) - { - if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Performs resubstitution for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMfsResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin; - int i; - // try replacing area critical fanins - Abc_ObjForEachFanin( pNode, pFanin, i ) - if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) - { - if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) - return 1; - } - // try removing redundant edges - if ( !p->pPars->fArea ) - { - Abc_ObjForEachFanin( pNode, pFanin, i ) - if ( Abc_ObjIsCi(pFanin) || Abc_ObjFanoutNum(pFanin) != 1 ) - { - if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) - return 1; - } - } - if ( Abc_ObjFaninNum(pNode) == p->nFaninMax ) - return 0; - // try replacing area critical fanins while adding two new fanins - Abc_ObjForEachFanin( pNode, pFanin, i ) - if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) - { - if ( Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) ) - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Performs resubstitution for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMfsResubNode2( Mfs_Man_t * p, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin, * pFanin2; - int i, k; -/* - Abc_ObjForEachFanin( pNode, pFanin, i ) - if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) - { - if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) - return 1; - } -*/ - if ( Abc_ObjFaninNum(pNode) < 2 ) - return 0; - // try replacing one area critical fanin and one other fanin while adding two new fanins - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) - { - // consider second fanin to remove at the same time - Abc_ObjForEachFanin( pNode, pFanin2, k ) - { - if ( i != k && Abc_NtkMfsSolveSatResub2( p, pNode, i, k ) ) - return 1; - } - } - } - return 0; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - From 733fec328ce1dc60378b95390a7338e99552e3b7 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 23 Dec 2024 20:04:21 -0800 Subject: [PATCH 055/133] Fixing big-endian problems in mfs2 and &mfs. --- src/aig/gia/giaMfs.c | 6 ++++++ src/aig/gia/giaTruth.c | 5 +++++ src/base/abci/abcMfs.c | 2 ++ src/misc/util/utilTruth.h | 17 +++++++++++++++++ src/opt/sfm/sfmCnf.c | 5 +++++ src/opt/sfm/sfmCore.c | 2 +- src/opt/sfm/sfmSat.c | 10 +++++----- 7 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/aig/gia/giaMfs.c b/src/aig/gia/giaMfs.c index a0e6caed4..7ddef2b89 100644 --- a/src/aig/gia/giaMfs.c +++ b/src/aig/gia/giaMfs.c @@ -395,7 +395,9 @@ Gia_Man_t * Gia_ManInsertMfs( Gia_Man_t * p, Sfm_Ntk_t * pNtk, int fAllBoxes ) int nVarsNew; Abc_TtSimplify( pTruth, Vec_IntArray(vLeaves), Vec_IntSize(vLeaves), &nVarsNew ); Vec_IntShrink( vLeaves, nVarsNew ); + Abc_TtFlipVar5( pTruth, Vec_IntSize(vLeaves) ); iLitNew = Gia_ManFromIfLogicCreateLut( pNew, pTruth, vLeaves, vCover, vMapping, vMapping2 ); + Abc_TtFlipVar5( pTruth, Vec_IntSize(vLeaves) ); if ( MapSize < Vec_IntSize(vMapping2) ) { assert( Vec_IntEntryLast(vMapping2) == Abc_Lit2Var(iLitNew) ); @@ -403,7 +405,11 @@ Gia_Man_t * Gia_ManInsertMfs( Gia_Man_t * p, Sfm_Ntk_t * pNtk, int fAllBoxes ) } } else + { + Abc_TtFlipVar5( pTruth, Vec_IntSize(vLeaves) ); iLitNew = Gia_ManFromIfLogicCreateLut( pNew, pTruth, vLeaves, vCover, vMapping, vMapping2 ); + Abc_TtFlipVar5( pTruth, Vec_IntSize(vLeaves) ); + } } else if ( Abc_LitIsCompl(iGroup) ) // internal CI { diff --git a/src/aig/gia/giaTruth.c b/src/aig/gia/giaTruth.c index c24748ede..0845eae96 100644 --- a/src/aig/gia/giaTruth.c +++ b/src/aig/gia/giaTruth.c @@ -559,6 +559,11 @@ void Gia_ObjComputeTruthTableStart( Gia_Man_t * p, int nVarsMax ) p->vTtMemory = Vec_WrdStart( p->nTtWords * 64 ); p->vTtNums = Vec_IntAlloc( Gia_ManObjNum(p) + 1000 ); Vec_IntFill( p->vTtNums, Vec_IntCap(p->vTtNums), -ABC_INFINITY ); + if ( nVarsMax >= 6 ) { + word * pTruth; int i; + Vec_PtrForEachEntry( word *, p->vTtInputs, pTruth, i ) + Abc_TtFlipVar5( pTruth, nVarsMax ); + } } void Gia_ObjComputeTruthTableStop( Gia_Man_t * p ) { diff --git a/src/base/abci/abcMfs.c b/src/base/abci/abcMfs.c index 0533d189f..90fa268ed 100644 --- a/src/base/abci/abcMfs.c +++ b/src/base/abci/abcMfs.c @@ -22,6 +22,7 @@ #include "bool/kit/kit.h" #include "opt/sfm/sfm.h" #include "base/io/ioAbc.h" +#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START @@ -330,6 +331,7 @@ void Abc_NtkInsertMfs( Abc_Ntk_t * pNtk, Sfm_Ntk_t * p ) // update fanins vArray = Sfm_NodeReadFanins( p, pNode->iTemp ); pTruth = Sfm_NodeReadTruth( p, pNode->iTemp ); + Abc_TtFlipVar5( pTruth, Vec_IntSize(vArray) ); pNode->pData = Abc_SopCreateFromTruthIsop( (Mem_Flex_t *)pNtk->pManFunc, Vec_IntSize(vArray), pTruth, vCover ); if ( Abc_SopGetVarNum((char *)pNode->pData) == 0 ) continue; diff --git a/src/misc/util/utilTruth.h b/src/misc/util/utilTruth.h index 323c96467..6cfab7109 100644 --- a/src/misc/util/utilTruth.h +++ b/src/misc/util/utilTruth.h @@ -3854,6 +3854,23 @@ static inline word * Abc_TtSymFunGenerate( char * pOnes, int nVars ) return pTruth; } +/**Function************************************************************* + + Synopsis [Fix big-endian when dealilng with 5-var truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_TtFlipVar5( word * p, int nVars ) +{ + int Test = 1; + if ( *((char *)&Test) == 0 && nVars > 5 ) + Abc_TtFlip( p, Abc_TtWordNum(nVars), 5 ); +} ABC_NAMESPACE_HEADER_END diff --git a/src/opt/sfm/sfmCnf.c b/src/opt/sfm/sfmCnf.c index e3af7e011..7c917fa7e 100644 --- a/src/opt/sfm/sfmCnf.c +++ b/src/opt/sfm/sfmCnf.c @@ -110,6 +110,9 @@ int Sfm_TruthToCnf( word Truth, word * pTruth, int nVars, Vec_Int_t * vCover, Ve { int i, k, c, RetValue, Literal, Cube, nCubes = 0; assert( nVars > 0 ); + + Abc_TtFlipVar5( &Truth, nVars ); + Abc_TtFlipVar5( pTruth, nVars ); for ( c = 0; c < 2; c ++ ) { if ( nVars <= 6 ) @@ -145,6 +148,8 @@ int Sfm_TruthToCnf( word Truth, word * pTruth, int nVars, Vec_Int_t * vCover, Ve Vec_StrPush( vCnf, (char)-1 ); } } + Abc_TtFlipVar5( pTruth, nVars ); + return nCubes; } } diff --git a/src/opt/sfm/sfmCore.c b/src/opt/sfm/sfmCore.c index f363e1cb0..a98829759 100644 --- a/src/opt/sfm/sfmCore.c +++ b/src/opt/sfm/sfmCore.c @@ -169,7 +169,7 @@ p->timeSat += Abc_Clock() - clk; { printf( "%3d: %3d ", p->nCexes, iVar ); Vec_WrdForEachEntry( p->vDivCexes, uSign, i ) - printf( "%d", Abc_InfoHasBit((unsigned *)&uSign, p->nCexes-1) ); + printf( "%d", Abc_TtGetBit(&uSign, p->nCexes-1) ); printf( "\n" ); } // find the next divisor to try diff --git a/src/opt/sfm/sfmSat.c b/src/opt/sfm/sfmSat.c index c83f86883..5d670f81d 100644 --- a/src/opt/sfm/sfmSat.c +++ b/src/opt/sfm/sfmSat.c @@ -213,8 +213,8 @@ word Sfm_ComputeInterpolant( Sfm_Ntk_t * p ) if ( Vec_IntEntry(p->vValues, i) ^ sat_solver_var_value(p->pSat, iVar) ) // insert 1 { pSign = Vec_WrdEntryP( p->vDivCexes, i ); - assert( !Abc_InfoHasBit( (unsigned *)pSign, p->nCexes) ); - Abc_InfoXorBit( (unsigned *)pSign, p->nCexes ); + assert( !Abc_TtGetBit( pSign, p->nCexes) ); + Abc_TtXorBit( pSign, p->nCexes ); } p->nCexes++; return SFM_SAT_SAT; @@ -284,8 +284,8 @@ int Sfm_ComputeInterpolantInt( Sfm_Ntk_t * p, word Truth[2] ) if ( Value ^ sat_solver_var_value(p->pSat, iVar) ) // insert 1 { word * pSign = Vec_WrdEntryP( p->vDivCexes, i ); - assert( !Abc_InfoHasBit( (unsigned *)pSign, p->nCexes) ); - Abc_InfoXorBit( (unsigned *)pSign, p->nCexes ); + assert( !Abc_TtGetBit( pSign, p->nCexes) ); + Abc_TtXorBit( pSign, p->nCexes ); } } p->nCexes++; @@ -310,7 +310,7 @@ word Sfm_ComputeInterpolant2( Sfm_Ntk_t * p ) ResP = Abc_Tt6Isop( Truth[1], ~Truth[0], Vec_IntSize(p->vDivIds), &nCubesP ); ResN = Abc_Tt6Isop( Truth[0], ~Truth[1], Vec_IntSize(p->vDivIds), &nCubesN ); Res = nCubesP <= nCubesN ? ResP : ~ResN; - //Dau_DsdPrintFromTruth( &Res, Vec_IntSize(p->vDivIds) ); + //Dau_DsdPrintFromTruth( &Res, Vec_IntSize(p->vDivIds) ); return Res; } From 14d46bfef84ea0f4b1b3a138baef8bd9dc78bd31 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 23 Dec 2024 20:26:00 -0800 Subject: [PATCH 056/133] Fixing big-endian problem if &fx and &deepsyn. --- src/aig/gia/giaFx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/aig/gia/giaFx.c b/src/aig/gia/giaFx.c index c20241ed1..7517072e7 100644 --- a/src/aig/gia/giaFx.c +++ b/src/aig/gia/giaFx.c @@ -217,7 +217,9 @@ Vec_Wec_t * Gia_ManFxRetrieve( Gia_Man_t * p, Vec_Str_t ** pvCompl, int fReverse int nVars = Gia_ObjLutSize( p, i ); int * pVars = Gia_ObjLutFanins( p, i ); word * pTruth = Vec_WrdEntryP( vTruths, Counter++ * nWords ); + Abc_TtFlipVar5( pTruth, nVars ); int Status = Kit_TruthIsop( (unsigned *)pTruth, nVars, vCover, 1 ); + Abc_TtFlipVar5( pTruth, nVars ); if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) ) { Vec_StrWriteEntry( *pvCompl, pObj->Value, (char)(Vec_IntSize(vCover) == 0) ); From 463cf6a7df6f6ac9da1b1b9756ece647c897d046 Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Tue, 24 Dec 2024 11:06:00 +0100 Subject: [PATCH 057/133] [CEC][SimGen][ABC Integration] Removed SAT solver calls and saving the simulation vectors in an internal data structure to pass to other functions. --- src/proof/cec/cecSatG2.c | 116 +++++++++++++++++++++++++++++++++++---- 1 file changed, 104 insertions(+), 12 deletions(-) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 33259bfe4..1a27162ee 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -2942,6 +2942,37 @@ int totalNumClasses(Gia_Man_t * p){ return numClasses; } +/**Function************************************************************* + + Synopsis [Save PI simulation values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +************************************************************************/ + +void saveSimVectors( Gia_Man_t * p, Vec_Ptr_t * pValues, int bitLength, int jth_word, int kth_bit){ + + int i, Id; + int nWords = bitLength / 64; + assert(nWords == 0); // Not considering case with large outgold values + Gia_ManForEachCiId( p, Id, i ){ + Vec_Wrd_t * pValuesPi = Vec_PtrEntry( pValues, i ); + word pValuePiJWord = 0; + if(kth_bit == 0){ + Vec_WrdPush( pValuesPi, 0 ); + } else { + pValuePiJWord = Vec_WrdEntry( pValuesPi, jth_word ); + } + word * pSim = Cec4_ObjSim( p, Id ); + pValuePiJWord = (pSim[0] << kth_bit) ^ pValuePiJWord; + Vec_WrdWriteEntry( pValuesPi, jth_word, pValuePiJWord ); + } +} + /**Function************************************************************* Synopsis [Simulate the CIs with random values.] @@ -2954,10 +2985,10 @@ int totalNumClasses(Gia_Man_t * p){ ************************************************************************/ -void executeRandomSim( Gia_Man_t * p, Cec4_Man_t * pMan , int dynSim, int nMaxIter , int bitwidthSim , int verbose ){ +void executeRandomSim( Gia_Man_t * p, Cec4_Man_t * pMan , int dynSim, int nMaxIter , int bitwidthSim , Vec_Ptr_t * vSimSave, int verbose ){ clock_t start_time = clock(); - int i; + int i, j, k, Id; int numClass = 100000; int oldNumClass = 0, iMaxNumber = 200, iNumber = 0; if(dynSim){ @@ -2971,6 +3002,13 @@ void executeRandomSim( Gia_Man_t * p, Cec4_Man_t * pMan , int dynSim, int nMaxIt printf("Time elapsed: %f (classes size: %d)\n", (float)(clock() - start_time)/CLOCKS_PER_SEC, quality); numClass = totalNumClasses(p); iNumber++; + Gia_ManForEachCiId( p, Id, j ){ + Vec_Wrd_t * vSimPI = Vec_PtrEntry( vSimSave, j ); + word * pSim = Cec4_ObjSim( p, Id ); + for( k = 0; k < p->nSimWords; k++ ){ + Vec_WrdPush( vSimPI, pSim[k] ); + } + } } @@ -2982,6 +3020,13 @@ void executeRandomSim( Gia_Man_t * p, Cec4_Man_t * pMan , int dynSim, int nMaxIt Cec_RemoveNonLutNodes( p ); if (verbose) printf("Time elapsed: %f (classes size: %d)\n", (float)(clock() - start_time)/CLOCKS_PER_SEC, quality); + Gia_ManForEachCiId( p, Id, j ){ + Vec_Wrd_t * vSimPI = Vec_PtrEntry( vSimSave, j ); + word * pSim = Cec4_ObjSim( p, Id ); + for( k = 0; k < p->nSimWords; k++ ){ + Vec_WrdPush( vSimPI, pSim[k] ); + } + } } } } @@ -3893,7 +3938,7 @@ void exportSimValues( Gia_Man_t * p, char * filename ) ************************************************************************/ -int computeInputVectors(Gia_Man_t * p, Cec4_Man_t * pMan, Cec_ParSimGen_t * pPars , Vec_Int_t * vLuts , char * outGold, int outGold_bitwidth , Vec_Int_t * vLutsFaninCones , Vec_Ptr_t * vNodesWatchlist , int experimentID){ +int computeInputVectors(Gia_Man_t * p, Cec4_Man_t * pMan, Cec_ParSimGen_t * pPars , Vec_Int_t * vLuts , char * outGold, int outGold_bitwidth , Vec_Int_t * vLutsFaninCones , Vec_Ptr_t * vNodesWatchlist , Vec_Ptr_t * vSimSave ,int experimentID){ char * networkValues1s, * networkValuesNotSet; // data structure containing the values inside the network char networkValid = (char) (1 << outGold_bitwidth) - 1; // keeps track which array out of the 8 is valid @@ -4010,6 +4055,16 @@ int computeInputVectors(Gia_Man_t * p, Cec4_Man_t * pMan, Cec_ParSimGen_t * pPar if(success >= 2){ saveInputVectors(p, pMan, networkValues1s); Cec4_ManSimulate( p, pMan ); + // saving the pi simulation values in a compacted format + int jth_word = p->iData & 0xFFFF; + int kth_bit = (p->iData & 0xFFFF0000) >> 16; + if( kth_bit + outGold_bitwidth >= 64 ){ + kth_bit = 0; + jth_word += 1; + } + saveSimVectors(p, vSimSave, outGold_bitwidth, jth_word, kth_bit); + kth_bit += outGold_bitwidth; + p->iData = (kth_bit << 16) | jth_word; if( pPars->fVerbose || pPars->fVeryVerbose){ printf("**Exporting simulation values in file sim_values.txt\n"); exportSimValues( p, "sim_values.txt" ); @@ -4042,7 +4097,7 @@ exit_cond: ***********************************************************************/ -void executeControlledSim(Gia_Man_t * p, Cec4_Man_t * pMan, Cec_ParSimGen_t * pPars , int levelOrder, int experimentID){ +void executeControlledSim(Gia_Man_t * p, Cec4_Man_t * pMan, Cec_ParSimGen_t * pPars , int levelOrder, Vec_Ptr_t * vSimSave, int experimentID){ char * outGold; //int outGold_bitwidth = pPars->bitwidthOutgold; @@ -4069,7 +4124,7 @@ void executeControlledSim(Gia_Man_t * p, Cec4_Man_t * pMan, Cec_ParSimGen_t * pP if(pPars->fUseWatchlist){ vNodesWatchList = generateWatchList(p); } - status = computeInputVectors(p, pMan, pPars, luts_order, outGold, pPars->bitwidthOutgold, vLutsFaninCones, vNodesWatchList, experimentID); + status = computeInputVectors(p, pMan, pPars, luts_order, outGold, pPars->bitwidthOutgold, vLutsFaninCones, vNodesWatchList, vSimSave, experimentID); if( status == -1 ){ if(pPars->fVerbose || pPars->fVeryVerbose) printf("FAILED - no valid input vectors found for class %d\n", nthClass); @@ -4303,8 +4358,9 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ extern void Gia_ManDupMapping( Gia_Man_t * pNew, Gia_Man_t * p ); Cec4_Man_t * pManSim; - int i, k, iFan; + int i, k, iFan, nWordsPerCi; Gia_Man_t * pMapped; + Vec_Ptr_t * vSimPisSave; if (!Gia_ManHasMapping(p)){ // apply technology mapping if not already done @@ -4347,17 +4403,29 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ // generate vectors of fanouts Gia_generateFanoutMapping( pMapped ); - // simulate n rounds of random simulation and create classes - Cec4_ManSimAlloc( pMapped, 1 ); + assert( pPars->bitwidthSim > 0); + pMapped->nSimWords = (int) pPars->bitwidthSim / 64 + ((pPars->bitwidthSim % 64) > 0); + vSimPisSave = Vec_PtrAlloc( Gia_ManCiNum(pMapped) ); + for ( i = 0; i < Gia_ManCiNum(pMapped); i++ ){ + Vec_Wrd_t * vSim = Vec_WrdAlloc( pMapped->nSimWords ); + Vec_PtrPush( vSimPisSave, vSim ); + } + // simulate n rounds of random simulation and create classes + Cec4_ManSimAlloc( pMapped, pMapped->nSimWords ); if(pPars->nMaxIter >= 0){ - executeRandomSim( pMapped, pManSim, 0, pPars->nMaxIter, pPars->bitwidthSim , pPars->fVeryVerbose); + executeRandomSim( pMapped, pManSim, 0, pPars->nMaxIter, pPars->bitwidthSim , vSimPisSave, pPars->fVeryVerbose); } else if (pPars->nMaxIter == -1){ - executeRandomSim( pMapped, pManSim, 1, pPars->nMaxIter, pPars->bitwidthSim , pPars->fVeryVerbose); + executeRandomSim( pMapped, pManSim, 1, pPars->nMaxIter, pPars->bitwidthSim , vSimPisSave, pPars->fVeryVerbose); } else { printf("Invalid number of iterations %d\n", pPars->nMaxIter); return NULL; } + // extra data to compact multiple pi values in single words + pMapped->iData = ((Vec_Wrd_t *)Vec_PtrEntry( vSimPisSave, 0 ))->nSize; // [0:15] number of words filled + // [16:31] number of bits filled in the iData word + assert(pMapped->iData > 0); + Cec_RemoveNonLutNodes( pMapped ); // remove all the non-LUT nodes from the equivalence classes if(pPars->fVerbose || pPars->fVeryVerbose){ @@ -4369,7 +4437,7 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ //Cec4_ManPrintClasses2(pMapped); clock_t begin = clock(); assert(pPars->expId > 0); - executeControlledSim( pMapped, pManSim, pPars, -1 , pPars->expId ); + executeControlledSim( pMapped, pManSim, pPars, -1 , vSimPisSave, pPars->expId ); float implicationSuccessRate = (float)pPars->nImplicationSuccess / (float)pPars->nImplicationExecution; float implicationSuccessCheckRate = (float)pPars->nImplicationSuccessChecks / (float)pPars->nImplicationTotalChecks; @@ -4382,11 +4450,35 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ evaluate_equiv_classes(pMapped, 1); } + // save random and controlled sim pis values + if(p->vSimsPi != NULL){ + Vec_WrdFree( p->vSimsPi ); + } + nWordsPerCi = ((Vec_Wrd_t *)Vec_PtrEntry( vSimPisSave, 0 ))->nSize; + assert( nWordsPerCi > 0 ); + p->vSimsPi = Vec_WrdStart( Gia_ManCiNum(p) * nWordsPerCi ); + // copy the sim pis + assert( Gia_ManCiNum(p) == Vec_PtrSize(vSimPisSave) ); + for (i = 0; i < Gia_ManCiNum(p); i++){ + Vec_Wrd_t * vSim = (Vec_Wrd_t *)Vec_PtrEntry( vSimPisSave, i ); + assert( vSim->nSize == nWordsPerCi ); + word * pSim = Vec_WrdEntryP( p->vSimsPi, i * nWordsPerCi ); + for ( k = 0; k < nWordsPerCi; k++ ) + pSim[k] = Vec_WrdEntry( vSim, k ); + } + p->nSimWords = nWordsPerCi; + + //Vec_WrdDumpHex( "sim_vec.out", p->vSimsPi, nWordsPerCi , 1 ); // call SAT solver + /* Cec4_CallSATsolver(pMapped, pManSim, pPars->pCECPars); - + Gia_Man_t * ppNew; Gia_Obj_t * pObj; + Gia_ManForEachCo( pMapped, pObj, i ) + pObj->Value = Gia_ManAppendCo( pManSim->pNew, Gia_ObjFanin0Copy(pObj) ); + ppNew = Gia_ManCleanup( pManSim->pNew ); + */ if (pPars->fVerbose || pPars->fVeryVerbose){ pManSim->pPars->fVerbose = 1; // print the ending stats of sat calls } From 1a89f7ff63d7ce6349b9ef4eb7edf6c9a4b7fb2c Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Tue, 24 Dec 2024 11:43:18 +0100 Subject: [PATCH 058/133] [CEC][SimGen][CLI] Changed function name and help message. Added new option to specify file where to dump simulation vectors. Commented out too verbose information --- src/base/abci/abc.c | 30 ++++++++++++++++++++---------- src/proof/cec/cec.h | 1 + src/proof/cec/cecSatG2.c | 7 ++++++- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 426f90fd5..c4cdfa202 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -477,7 +477,7 @@ static int Abc_CommandAbc9Scorr ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Choice ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Sat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SatEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc9SimGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9AdvGenSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Fraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9CFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Srm ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1277,7 +1277,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&choice", Abc_CommandAbc9Choice, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sat", Abc_CommandAbc9Sat, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&satenum", Abc_CommandAbc9SatEnum, 0 ); - Cmd_CommandAdd( pAbc, "ABC9", "&fraigSimGen", Abc_CommandAbc9SimGen, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&adv_sim_gen", Abc_CommandAbc9AdvGenSim, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&fraig", Abc_CommandAbc9Fraig, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cfraig", Abc_CommandAbc9CFraig, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&srm", Abc_CommandAbc9Srm, 0 ); @@ -39179,7 +39179,7 @@ usage: /**Function************************************************************* - Synopsis [Abc_CommandAbc9SimGen] + Synopsis [Abc_CommandAbc9AdvGenSim] Description [This function calls SimGen tool] @@ -39189,7 +39189,7 @@ usage: ***********************************************************************/ -int Abc_CommandAbc9SimGen( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandAbc9AdvGenSim( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Cec_SimGenSetParDefault( Cec_ParSimGen_t * pPars ); extern Gia_Man_t * Cec_SimGenRun( Gia_Man_t * pAig, Cec_ParSimGen_t * pPars ); @@ -39198,7 +39198,7 @@ int Abc_CommandAbc9SimGen( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; Cec_SimGenSetParDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "EOStiwvV" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "EOStiFwvV" ) ) != EOF ) { switch ( c ) { @@ -39257,6 +39257,15 @@ int Abc_CommandAbc9SimGen( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nMaxIter <= -2 ) goto usage; break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by a string.\n" ); + goto usage; + } + pPars->pFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'w': pPars->fUseWatchlist = 1; break; @@ -39287,13 +39296,14 @@ int Abc_CommandAbc9SimGen( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &fraigSimGen [-EOSsivV ] [-v] \n" ); - Abc_Print( -2, "\t performs combinational SAT sweeping applying SimGen\n" ); - Abc_Print( -2, "\t-E num : the experiment ID for SimGen [default = %d]\n", pPars->expId ); + Abc_Print( -2, "usage: &adv_sim_gen [-EOSsivV ] [-v] \n" ); + Abc_Print( -2, "\t generates simulation patterns for combinational SAT sweeping\n" ); + Abc_Print( -2, "\t-E num : the experiment ID for different techniques [default = %d]\n", pPars->expId ); Abc_Print( -2, "\t-O num : the bitwidth of the output gold [default = %d]\n", pPars->bitwidthOutgold ); - Abc_Print( -2, "\t-S num : the bitwidth of the simulation vectors [default = %d]\n", pPars->bitwidthSim ); - Abc_Print( -2, "\t-t num : the timeout value after which Smart Simulation Pattern Generation terminates [default = %.0f]\n", pPars->timeOutSim); + Abc_Print( -2, "\t-S num : the bitwidth of the simulation vectors for random simulation [default = %d]\n", pPars->bitwidthSim ); + Abc_Print( -2, "\t-t num : the timeout value [default = %.0f]\n", pPars->timeOutSim); Abc_Print( -2, "\t-i num : the maximum number of iterations [default = %d]\n", pPars->nMaxIter ); + Abc_Print( -2, "\t-F file: the file name to dump the generated patterns [default = none]\n"); Abc_Print( -2, "\t-w : activates the watchlist feature [default = %d]\n", pPars->fUseWatchlist); Abc_Print( -2, "\t-v : verbose [default = %d]\n", pPars->fVerbose ); Abc_Print( -2, "\t-V : very verbose [default = %d]\n", pPars->fVeryVerbose ); diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index 4db2df726..3ef5454e1 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -220,6 +220,7 @@ struct Cec_ParSimGen_t_ int nImplicationTotalChecks; // number of times implication was checked int nImplicationSuccessChecks; // number of times implication was successful Cec_ParFra_t * pCECPars; // parameters of CEC + char * pFileName; // file name to dump simulation vectors }; //////////////////////////////////////////////////////////////////////// diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 1a27162ee..2e25ff249 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -254,6 +254,7 @@ void Cec_SimGenSetParDefault( Cec_ParSimGen_t * pPars ) pPars->nImplicationSuccessChecks = 0; // the number of implication successful checks pPars->pCECPars = (Cec_ParFra_t *) malloc(sizeof( Cec_ParFra_t )); // parameters of CEC Cec4_ManSetParams( pPars->pCECPars ); + pPars->pFileName = NULL; // file name to dump simulation vectors } /**Function************************************************************* @@ -4380,6 +4381,7 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ Cec_DeriveSOPs( pMapped ); + /* if (pPars->fVeryVerbose) { printf("**Printing LUTs information**\n"); @@ -4391,6 +4393,7 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ printISOPLUT( pMapped, i ); } } + */ // compute MFFCs Gia_ManLevelNum( pMapped); // compute levels @@ -4469,7 +4472,9 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ } p->nSimWords = nWordsPerCi; - //Vec_WrdDumpHex( "sim_vec.out", p->vSimsPi, nWordsPerCi , 1 ); + if (pPars->pFileName != NULL){ + Vec_WrdDumpHex( pPars->pFileName, p->vSimsPi, nWordsPerCi , 1 ); + } // call SAT solver /* From 0ba2b7dae903318f046e7e2aae8c014550152fe7 Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Tue, 24 Dec 2024 11:49:17 +0100 Subject: [PATCH 059/133] [CEC][SimGen][Clean codes] Removing unused parameters. --- src/proof/cec/cec.h | 1 - src/proof/cec/cecSatG2.c | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index 3ef5454e1..fe1a2d518 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -219,7 +219,6 @@ struct Cec_ParSimGen_t_ int nImplicationSuccess; // number of times implication was successful int nImplicationTotalChecks; // number of times implication was checked int nImplicationSuccessChecks; // number of times implication was successful - Cec_ParFra_t * pCECPars; // parameters of CEC char * pFileName; // file name to dump simulation vectors }; diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 2e25ff249..fab871f4a 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -252,8 +252,6 @@ void Cec_SimGenSetParDefault( Cec_ParSimGen_t * pPars ) pPars->nImplicationSuccess = 0; // the number of implication successes pPars->nImplicationTotalChecks = 0; // the number of implication checks pPars->nImplicationSuccessChecks = 0; // the number of implication successful checks - pPars->pCECPars = (Cec_ParFra_t *) malloc(sizeof( Cec_ParFra_t )); // parameters of CEC - Cec4_ManSetParams( pPars->pCECPars ); pPars->pFileName = NULL; // file name to dump simulation vectors } @@ -4362,6 +4360,7 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ int i, k, iFan, nWordsPerCi; Gia_Man_t * pMapped; Vec_Ptr_t * vSimPisSave; + Cec_ParFra_t * pCECPars; if (!Gia_ManHasMapping(p)){ // apply technology mapping if not already done @@ -4377,7 +4376,8 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ if(pPars->fVerbose) printf("Using already mapped network\n"); } - pManSim = Cec4_ManCreate( pMapped, pPars->pCECPars ); + pCECPars = (Cec_ParFra_t *) malloc(sizeof( Cec_ParFra_t )); // parameters of CEC + pManSim = Cec4_ManCreate( pMapped, pCECPars ); Cec_DeriveSOPs( pMapped ); From 699c8c4c889a0cc1f9b7c31ad017995b80d77dd0 Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Tue, 24 Dec 2024 11:50:11 +0100 Subject: [PATCH 060/133] [CEC][SimGen][Clean codes] Removing commented SAT calls operations. --- src/proof/cec/cecSatG2.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index fab871f4a..0d265f23d 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -4476,14 +4476,6 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ Vec_WrdDumpHex( pPars->pFileName, p->vSimsPi, nWordsPerCi , 1 ); } - // call SAT solver - /* - Cec4_CallSATsolver(pMapped, pManSim, pPars->pCECPars); - Gia_Man_t * ppNew; Gia_Obj_t * pObj; - Gia_ManForEachCo( pMapped, pObj, i ) - pObj->Value = Gia_ManAppendCo( pManSim->pNew, Gia_ObjFanin0Copy(pObj) ); - ppNew = Gia_ManCleanup( pManSim->pNew ); - */ if (pPars->fVerbose || pPars->fVeryVerbose){ pManSim->pPars->fVerbose = 1; // print the ending stats of sat calls } From 37979dbd94fdd86107c399c6cc842ebfe56ce147 Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Tue, 24 Dec 2024 11:50:47 +0100 Subject: [PATCH 061/133] [CEC][SimGen][Clean codes] Removing commented SAT calls operations. --- src/proof/cec/cecSatG2.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 0d265f23d..acbb15cbd 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -4476,9 +4476,6 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ Vec_WrdDumpHex( pPars->pFileName, p->vSimsPi, nWordsPerCi , 1 ); } - if (pPars->fVerbose || pPars->fVeryVerbose){ - pManSim->pPars->fVerbose = 1; // print the ending stats of sat calls - } // free memory Vec_IntFree( pMapped->vTTLut ); Vec_StrFree( pMapped->vTTISOPs ); From 7c6d1ffd2ddc89b402b5e3a484cb47ed289e957b Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Tue, 24 Dec 2024 11:59:23 +0100 Subject: [PATCH 062/133] [CEC][SimGen][Bugs] Fixing bugs and removing unused var. --- src/proof/cec/cecSatG2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index acbb15cbd..3305f9e90 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -2959,7 +2959,7 @@ void saveSimVectors( Gia_Man_t * p, Vec_Ptr_t * pValues, int bitLength, int jth_ int nWords = bitLength / 64; assert(nWords == 0); // Not considering case with large outgold values Gia_ManForEachCiId( p, Id, i ){ - Vec_Wrd_t * pValuesPi = Vec_PtrEntry( pValues, i ); + Vec_Wrd_t * pValuesPi = (Vec_Wrd_t *) Vec_PtrEntry( pValues, i ); word pValuePiJWord = 0; if(kth_bit == 0){ Vec_WrdPush( pValuesPi, 0 ); @@ -3002,7 +3002,7 @@ void executeRandomSim( Gia_Man_t * p, Cec4_Man_t * pMan , int dynSim, int nMaxIt numClass = totalNumClasses(p); iNumber++; Gia_ManForEachCiId( p, Id, j ){ - Vec_Wrd_t * vSimPI = Vec_PtrEntry( vSimSave, j ); + Vec_Wrd_t * vSimPI = (Vec_Wrd_t *) Vec_PtrEntry( vSimSave, j ); word * pSim = Cec4_ObjSim( p, Id ); for( k = 0; k < p->nSimWords; k++ ){ Vec_WrdPush( vSimPI, pSim[k] ); @@ -3020,7 +3020,7 @@ void executeRandomSim( Gia_Man_t * p, Cec4_Man_t * pMan , int dynSim, int nMaxIt if (verbose) printf("Time elapsed: %f (classes size: %d)\n", (float)(clock() - start_time)/CLOCKS_PER_SEC, quality); Gia_ManForEachCiId( p, Id, j ){ - Vec_Wrd_t * vSimPI = Vec_PtrEntry( vSimSave, j ); + Vec_Wrd_t * vSimPI = (Vec_Wrd_t *) Vec_PtrEntry( vSimSave, j ); word * pSim = Cec4_ObjSim( p, Id ); for( k = 0; k < p->nSimWords; k++ ){ Vec_WrdPush( vSimPI, pSim[k] ); @@ -4357,7 +4357,7 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ extern void Gia_ManDupMapping( Gia_Man_t * pNew, Gia_Man_t * p ); Cec4_Man_t * pManSim; - int i, k, iFan, nWordsPerCi; + int i, k, nWordsPerCi; Gia_Man_t * pMapped; Vec_Ptr_t * vSimPisSave; Cec_ParFra_t * pCECPars; From 5961231ed19846599d3c450f215c448b5a2f846e Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Tue, 24 Dec 2024 12:27:09 +0100 Subject: [PATCH 063/133] [CEC][SimGen][Clean codes] Disabling verbose. --- src/proof/cec/cecSatG2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 3305f9e90..45148cebc 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -4377,6 +4377,7 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ printf("Using already mapped network\n"); } pCECPars = (Cec_ParFra_t *) malloc(sizeof( Cec_ParFra_t )); // parameters of CEC + pManSim->pPars->fVerbose = 0; // disabling verbose sat solver pManSim = Cec4_ManCreate( pMapped, pCECPars ); Cec_DeriveSOPs( pMapped ); From 64e8bb02b9a7c28456c1d0a560e614c9086e7374 Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Tue, 24 Dec 2024 14:48:57 +0100 Subject: [PATCH 064/133] [CEC][SimGen][Bits to Words] Changing the units of measure for random simulation from number bits to number words --- src/base/abci/abc.c | 8 +++---- src/proof/cec/cec.h | 4 ++-- src/proof/cec/cecSatG2.c | 49 ++++++++-------------------------------- 3 files changed, 15 insertions(+), 46 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index c4cdfa202..d33db9428 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -39230,9 +39230,9 @@ int Abc_CommandAbc9AdvGenSim( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } - pPars->bitwidthSim = atoi(argv[globalUtilOptind]); + pPars->nSimWords = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( pPars->bitwidthSim <= 0 ) + if ( pPars->nSimWords <= 0 ) goto usage; break; case 't': @@ -39300,9 +39300,9 @@ usage: Abc_Print( -2, "\t generates simulation patterns for combinational SAT sweeping\n" ); Abc_Print( -2, "\t-E num : the experiment ID for different techniques [default = %d]\n", pPars->expId ); Abc_Print( -2, "\t-O num : the bitwidth of the output gold [default = %d]\n", pPars->bitwidthOutgold ); - Abc_Print( -2, "\t-S num : the bitwidth of the simulation vectors for random simulation [default = %d]\n", pPars->bitwidthSim ); + Abc_Print( -2, "\t-S num : the number of words in a round for random simulation [default = %d]\n", pPars->nSimWords ); Abc_Print( -2, "\t-t num : the timeout value [default = %.0f]\n", pPars->timeOutSim); - Abc_Print( -2, "\t-i num : the maximum number of iterations [default = %d]\n", pPars->nMaxIter ); + Abc_Print( -2, "\t-i num : the number of rounds of random simulation [default = %d]\n", pPars->nMaxIter ); Abc_Print( -2, "\t-F file: the file name to dump the generated patterns [default = none]\n"); Abc_Print( -2, "\t-w : activates the watchlist feature [default = %d]\n", pPars->fUseWatchlist); Abc_Print( -2, "\t-v : verbose [default = %d]\n", pPars->fVerbose ); diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index fe1a2d518..ca7eed5a7 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -209,8 +209,8 @@ struct Cec_ParSimGen_t_ int fVeryVerbose; // verbose flag int expId; // experiment ID for SimGen int bitwidthOutgold; // bitwidth of the output gold - int bitwidthSim; // bitwidth of the simulation vectors - int nMaxIter; // maximum number of iterations + int nSimWords; // number of words in a round of random simulation + int nMaxIter; // maximum number of rounds of random simulation char * outGold; // data containing outgold float timeOutSim; // timeout for simulation int fUseWatchlist; // use watchlist diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 45148cebc..20da24865 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -242,9 +242,9 @@ void Cec_SimGenSetParDefault( Cec_ParSimGen_t * pPars ) pPars->fVerbose = 0; // verbose output pPars->fVeryVerbose = 0; // verbose output and outputs files pPars->bitwidthOutgold = 2; // bitwidth of the output golden model - pPars->bitwidthSim = 31; // bitwidth of the simulation vectors + pPars->nSimWords = 4; // number of words in a round of random simulation pPars->expId = 1; // experiment ID - pPars->nMaxIter = -1; // the maximum number of iterations + pPars->nMaxIter = -1; // the maximum number of rounds of random simulation pPars->timeOutSim = 1000.0; // the timeout for simulation in sec pPars->fUseWatchlist = 0; // use watchlist pPars->fImplicationTime = 0.0; // time spent in implication @@ -2860,36 +2860,6 @@ void Cec_RemoveNonLutNodes( Gia_Man_t * p){ Vec_IntFree( vLutIds ); } -/**Function************************************************************* - - Synopsis [Simulate the CIs with random values with specific bitwidth.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -static inline void Cec_ObjSimCiSimGen( Gia_Man_t * p, int iObj , int bitwidth) -{ - int w; - word * pSim = Cec4_ObjSim( p, iObj ); - word wMask = (1 << bitwidth) -1; - for ( w = 0; w < p->nSimWords; w++ ) - pSim[w] = Abc_RandomW( 0 ) & wMask; - pSim[0] <<= 1; -} - -void Cec_ManSimulateCisSimGen( Gia_Man_t * p, int bitwidth ) -{ - int i, Id; - Gia_ManForEachCiId( p, Id, i ) - Cec_ObjSimCiSimGen( p, Id , bitwidth); - p->iPatsPi = 0; -} - /**Function************************************************************* Synopsis [Evaluate equivalence classes.] @@ -2984,7 +2954,7 @@ void saveSimVectors( Gia_Man_t * p, Vec_Ptr_t * pValues, int bitLength, int jth_ ************************************************************************/ -void executeRandomSim( Gia_Man_t * p, Cec4_Man_t * pMan , int dynSim, int nMaxIter , int bitwidthSim , Vec_Ptr_t * vSimSave, int verbose ){ +void executeRandomSim( Gia_Man_t * p, Cec4_Man_t * pMan , int dynSim, int nMaxIter , Vec_Ptr_t * vSimSave, int verbose ){ clock_t start_time = clock(); int i, j, k, Id; @@ -2994,7 +2964,7 @@ void executeRandomSim( Gia_Man_t * p, Cec4_Man_t * pMan , int dynSim, int nMaxIt while (numClass != oldNumClass && iNumber < iMaxNumber) { oldNumClass = numClass; - Cec_ManSimulateCisSimGen( p, bitwidthSim ); + Cec4_ManSimulateCis( p ); Cec4_ManSimulate( p, pMan ); int quality = evaluate_equiv_classes(p, 0); if (verbose) @@ -3013,7 +2983,7 @@ void executeRandomSim( Gia_Man_t * p, Cec4_Man_t * pMan , int dynSim, int nMaxIt } else { for(i = 0; i < nMaxIter; i++){ - Cec_ManSimulateCisSimGen( p, bitwidthSim ); + Cec4_ManSimulateCis( p ); Cec4_ManSimulate( p, pMan ); int quality = evaluate_equiv_classes(p, 0); Cec_RemoveNonLutNodes( p ); @@ -4377,8 +4347,8 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ printf("Using already mapped network\n"); } pCECPars = (Cec_ParFra_t *) malloc(sizeof( Cec_ParFra_t )); // parameters of CEC - pManSim->pPars->fVerbose = 0; // disabling verbose sat solver pManSim = Cec4_ManCreate( pMapped, pCECPars ); + pManSim->pPars->fVerbose = 0; // disabling verbose sat solver Cec_DeriveSOPs( pMapped ); @@ -4407,8 +4377,7 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ // generate vectors of fanouts Gia_generateFanoutMapping( pMapped ); - assert( pPars->bitwidthSim > 0); - pMapped->nSimWords = (int) pPars->bitwidthSim / 64 + ((pPars->bitwidthSim % 64) > 0); + pMapped->nSimWords = (int) pPars->nSimWords ; vSimPisSave = Vec_PtrAlloc( Gia_ManCiNum(pMapped) ); for ( i = 0; i < Gia_ManCiNum(pMapped); i++ ){ Vec_Wrd_t * vSim = Vec_WrdAlloc( pMapped->nSimWords ); @@ -4417,9 +4386,9 @@ Gia_Man_t * Cec_SimGenRun( Gia_Man_t * p, Cec_ParSimGen_t * pPars ){ // simulate n rounds of random simulation and create classes Cec4_ManSimAlloc( pMapped, pMapped->nSimWords ); if(pPars->nMaxIter >= 0){ - executeRandomSim( pMapped, pManSim, 0, pPars->nMaxIter, pPars->bitwidthSim , vSimPisSave, pPars->fVeryVerbose); + executeRandomSim( pMapped, pManSim, 0, pPars->nMaxIter, vSimPisSave, pPars->fVeryVerbose); } else if (pPars->nMaxIter == -1){ - executeRandomSim( pMapped, pManSim, 1, pPars->nMaxIter, pPars->bitwidthSim , vSimPisSave, pPars->fVeryVerbose); + executeRandomSim( pMapped, pManSim, 1, pPars->nMaxIter, vSimPisSave, pPars->fVeryVerbose); } else { printf("Invalid number of iterations %d\n", pPars->nMaxIter); return NULL; From a74da1c50bab5835b8b350305842861d308c7480 Mon Sep 17 00:00:00 2001 From: Carmine50 Date: Tue, 24 Dec 2024 14:54:59 +0100 Subject: [PATCH 065/133] [CEC][SAT Sweeping] Added new functionality in SAT sweeping function to use for simulation the PI vector present in vSimsPi data structure. --- src/proof/cec/cecSatG2.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 20da24865..1b0948de1 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -1863,7 +1863,7 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p Cec4_Man_t * pMan = Cec4_ManCreate( p, pPars ); Gia_Obj_t * pObj, * pRepr; - int i, fSimulate = 1; + int i, fSimulate = 1, Id; if ( pPars->fVerbose ) printf( "Solver type = %d. Simulate %d words in %d rounds. SAT with %d confs. Recycle after %d SAT calls.\n", pPars->jType, pPars->nWords, pPars->nRounds, pPars->nBTLimit, pPars->nCallsRecycle ); @@ -1888,6 +1888,22 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p } } + if( p->vSimsPi && p->nSimWords > 0){ // if the simulation pis are already set, do not generate new ones + pPars->nWords = p->nSimWords; + Vec_WrdFreeP( &p->vSims ); + p->vSims = Vec_WrdStart( Gia_ManObjNum(p) * pPars->nWords); + assert( Vec_WrdSize(p->vSimsPi) == Gia_ManCiNum(p) * p->nSimWords ); + Gia_ManForEachCiId(p, Id, i){ + memmove( Vec_WrdEntryP(p->vSims, Id*p->nSimWords), Vec_WrdEntryP(p->vSimsPi, i*p->nSimWords), sizeof(word)*p->nSimWords ); + } + Cec4_ManSimulate( p, pMan ); + if ( pPars->fCheckMiter && !Cec4_ManSimulateCos(p) ) // cex detected + goto finalize; + if ( fSimOnly ) + goto finalize; + goto execute_sat; + } + // simulate one round and create classes Cec4_ManSimAlloc( p, pPars->nWords ); Cec4_ManSimulateCis( p ); @@ -1922,6 +1938,7 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p if ( i && i % 5 == 0 && pPars->fVerbose ) Cec4_ManPrintStats( p, pPars, pMan, 1 ); } + execute_sat: if ( i && i % 5 && pPars->fVerbose ) Cec4_ManPrintStats( p, pPars, pMan, 1 ); From 17652cfda6fa1802e95d53bf5efe0f74feda7451 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Wed, 25 Dec 2024 15:37:36 +0800 Subject: [PATCH 066/133] Feat(write_hmetis): Write out hMetis file format --- src/base/io/io.c | 69 ++++++++++++++++++++++++ src/base/io/ioAbc.h | 5 +- src/base/io/ioWriteHMetis.c | 101 ++++++++++++++++++++++++++++++++++++ src/base/io/module.make | 1 + 4 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 src/base/io/ioWriteHMetis.c diff --git a/src/base/io/io.c b/src/base/io/io.c index 3327a9dfd..97d30c1b8 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -79,6 +79,7 @@ static int IoCommandWriteCex ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteDot ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteGml ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteHMetis ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteList ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWritePla ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ); @@ -155,6 +156,7 @@ void Io_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "I/O", "write_edgelist",IoCommandWriteEdgelist, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_gml", IoCommandWriteGml, 0 ); // Cmd_CommandAdd( pAbc, "I/O", "write_list", IoCommandWriteList, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_hmetis", IoCommandWriteHMetis, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_pla", IoCommandWritePla, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_verilog", IoCommandWriteVerilog, 0 ); // Cmd_CommandAdd( pAbc, "I/O", "write_verlib", IoCommandWriteVerLib, 0 ); @@ -3398,6 +3400,73 @@ usage: } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteHMetis( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int fVerbose; + int fSkipPo; + int c; + + fSkipPo = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fSkipPo ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + if ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) + { + fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" ); + return 1; + } + //Io_WriteAiger( pAbc->pNtkCur, pFileName, fWriteSymbols, fCompact, fUnique ); + Io_WriteHMetis( pAbc->pNtkCur, pFileName, fSkipPo, fVerbose ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_hmetis \n" ); + fprintf( pAbc->Err, "\t writes the network in the hMetis format (https://karypis.github.io/glaros/files/sw/hmetis/manual.pdf)\n" ); + fprintf( pAbc->Err, "\t-s : skip PO as sink explictly [default = %s]\n", fSkipPo? "yes" : "no" ); + fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes" : "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + + /**Function************************************************************* diff --git a/src/base/io/ioAbc.h b/src/base/io/ioAbc.h index cf30196f2..0f3034882 100644 --- a/src/base/io/ioAbc.h +++ b/src/base/io/ioAbc.h @@ -57,7 +57,8 @@ typedef enum { IO_FILE_DOT, IO_FILE_EDIF, IO_FILE_EQN, - IO_FILE_GML, + IO_FILE_GML, + IO_FILE_HMETIS, IO_FILE_JSON, IO_FILE_LIST, IO_FILE_PLA, @@ -129,6 +130,8 @@ extern void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ); extern void Io_WriteEdgelist( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches, int fBb2Wb, int fSeq , int fName); /*=== abcWriteGml.c ===========================================================*/ extern void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWriteHMetis.c ===========================================================*/ +extern void Io_WriteHMetis( Abc_Ntk_t * pNtk, char * pFileName, int fSkipPo, int fVerbose ); /*=== abcWriteList.c ==========================================================*/ extern void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ); /*=== abcWritePla.c ===========================================================*/ diff --git a/src/base/io/ioWriteHMetis.c b/src/base/io/ioWriteHMetis.c new file mode 100644 index 000000000..ebe322e81 --- /dev/null +++ b/src/base/io/ioWriteHMetis.c @@ -0,0 +1,101 @@ +/**CFile**************************************************************** + + FileName [ioWriteHMetis.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write hMetis format developed by + George Karypis and Vipin Kumar from the University of +Minnesota(https://karypis.github.io/glaros/files/sw/hmetis/manual.pdf)] + + Author [Jingren Wang] + + Affiliation [] + + Date [Ver. 1.0. Started - December 16, 2006.] + + Revision [] + +***********************************************************************/ +#include "base/abc/abc.h" +#include "ioAbc.h" +#include "misc/vec/vecInt.h" +#include "misc/vec/vecPtr.h" + + +ABC_NAMESPACE_IMPL_START + +void Io_WriteHMetis( Abc_Ntk_t * pNtk, char * pFileName, int fSkipPo, int fVerbose) +{ + Abc_Obj_t * pObj; + Abc_Obj_t * pFanout; + int i, j; + Vec_Int_t * vHyperEdgeEachWrite; + int Entry; + // check that the network is valid + assert( Abc_NtkIsStrash( pNtk ) && Abc_NtkIsComb( pNtk )); + + FILE * pFHMetis = fopen( pFileName, "wb" ); + Vec_Ptr_t * vHyperEdges = Vec_PtrAlloc(1000); + if ( pFHMetis == NULL ) + { + fprintf( stdout, "Io_WriteHMetis(): Cannot open the output file \"%s\".\n", pFileName ); + ABC_FREE(pFHMetis); + return; + } + + //show pi/po/and number + if ( fVerbose ) + { + Abc_Print( 1, "Writing hMetis file \"%s\" with %d nodes (%d pi, %d po, %d and nodes).\n", pFileName, Abc_NtkObjNum(pNtk), Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkNodeNum(pNtk) ); + } + + Abc_NtkForEachObj( pNtk, pObj, i ) + { + Vec_Int_t * vHyperEdgeEach = Vec_IntAlloc(20); + //push the node itself, which is a source node + Vec_IntPush(vHyperEdgeEach, Abc_ObjId(pObj)); + //iterate through all the fanouts(sink) of the node + if( !Abc_ObjIsCo(pObj) ) + { + Abc_ObjForEachFanout(pObj, pFanout, j) + { + Vec_IntPush(vHyperEdgeEach, Abc_ObjId(pFanout)); + } + } + else{ + if ( fSkipPo ) + { + continue; + } + Vec_IntPush(vHyperEdgeEach, Abc_ObjId(Abc_ObjFanin0(pObj))); + } + Vec_PtrPush(vHyperEdges, vHyperEdgeEach); + } + + //write the number of hyperedges and the number of vertices + fprintf(pFHMetis, "%d %d\n", Vec_PtrSize(vHyperEdges), Abc_NtkObjNum(pNtk)); + //write the hyperedges + Vec_PtrForEachEntry(Vec_Int_t *, vHyperEdges, vHyperEdgeEachWrite, i) + { + Vec_IntForEachEntry(vHyperEdgeEachWrite, Entry, j) + { + if (j == Vec_IntSize(vHyperEdgeEachWrite) - 1) + { + fprintf(pFHMetis, "%d", Entry); + } + else + { + fprintf(pFHMetis, "%d ", Entry); + } + } + fprintf(pFHMetis, "\n"); + } + fprintf( pFHMetis, "\nThis file was written by ABC on %s\n", Extra_TimeStamp() ); + fprintf( pFHMetis, "For information about hMetis format, refer to %s\n", "https://karypis.github.io/glaros/files/sw/hmetis/manual.pdf" ); + Vec_PtrFreeFree(vHyperEdges); +} + +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/base/io/module.make b/src/base/io/module.make index d80642134..19f9fa2d2 100644 --- a/src/base/io/module.make +++ b/src/base/io/module.make @@ -26,6 +26,7 @@ SRC += src/base/io/io.c \ src/base/io/ioWriteEqn.c \ src/base/io/ioWriteEdgelist.c \ src/base/io/ioWriteGml.c \ + src/base/io/ioWriteHMetis.c \ src/base/io/ioWriteList.c \ src/base/io/ioWritePla.c \ src/base/io/ioWriteVerilog.c \ From 47e4e23bc55141c66ba01cae11be03aab642ca42 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Wed, 25 Dec 2024 15:43:50 +0800 Subject: [PATCH 067/133] Fix(write_hmetis): Comments should be start with % --- src/base/io/ioWriteHMetis.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/base/io/ioWriteHMetis.c b/src/base/io/ioWriteHMetis.c index ebe322e81..293dc7207 100644 --- a/src/base/io/ioWriteHMetis.c +++ b/src/base/io/ioWriteHMetis.c @@ -93,8 +93,9 @@ void Io_WriteHMetis( Abc_Ntk_t * pNtk, char * pFileName, int fSkipPo, int fVerbo } fprintf(pFHMetis, "\n"); } - fprintf( pFHMetis, "\nThis file was written by ABC on %s\n", Extra_TimeStamp() ); - fprintf( pFHMetis, "For information about hMetis format, refer to %s\n", "https://karypis.github.io/glaros/files/sw/hmetis/manual.pdf" ); + //comments should be started with "%" in hMetis format + fprintf( pFHMetis, "\n%%This file was written by ABC on %s\n", Extra_TimeStamp() ); + fprintf( pFHMetis, "%%For information about hMetis format, refer to %s\n", "https://karypis.github.io/glaros/files/sw/hmetis/manual.pdf" ); Vec_PtrFreeFree(vHyperEdges); } From 7a5a0ad8b3c1a6284524e032dacf23784518e10e Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Thu, 26 Dec 2024 11:27:24 +0800 Subject: [PATCH 068/133] Refactor(Compile): For MSVS build --- abclib.dsp | 4 ++++ src/base/io/ioWriteHMetis.c | 6 +----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/abclib.dsp b/abclib.dsp index 559d59d2a..88e5e87f6 100644 --- a/abclib.dsp +++ b/abclib.dsp @@ -691,6 +691,10 @@ SOURCE=.\src\base\io\ioWriteGml.c # End Source File # Begin Source File +SOURCE=.\src\base\io\ioWriteHMetis.c +# End Source File +# Begin Source File + SOURCE=.\src\base\io\ioWriteList.c # End Source File # Begin Source File diff --git a/src/base/io/ioWriteHMetis.c b/src/base/io/ioWriteHMetis.c index 293dc7207..fa4d3d76d 100644 --- a/src/base/io/ioWriteHMetis.c +++ b/src/base/io/ioWriteHMetis.c @@ -19,15 +19,11 @@ Minnesota(https://karypis.github.io/glaros/files/sw/hmetis/manual.pdf)] Revision [] ***********************************************************************/ -#include "base/abc/abc.h" #include "ioAbc.h" -#include "misc/vec/vecInt.h" -#include "misc/vec/vecPtr.h" - ABC_NAMESPACE_IMPL_START -void Io_WriteHMetis( Abc_Ntk_t * pNtk, char * pFileName, int fSkipPo, int fVerbose) +void Io_WriteHMetis( Abc_Ntk_t * pNtk, char * pFileName, int fSkipPo, int fVerbose ) { Abc_Obj_t * pObj; Abc_Obj_t * pFanout; From 0dff4dbc4b919817ef6c29b05cf2902330f687b7 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Thu, 26 Dec 2024 13:54:55 +0800 Subject: [PATCH 069/133] Feat(write_hmetis): Add weight on hyperedges and format --- src/base/io/io.c | 11 +++-- src/base/io/ioAbc.h | 2 +- src/base/io/ioWriteHMetis.c | 99 +++++++++++++++++++++---------------- 3 files changed, 65 insertions(+), 47 deletions(-) diff --git a/src/base/io/io.c b/src/base/io/io.c index 97d30c1b8..364d82d0b 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -3416,18 +3416,23 @@ int IoCommandWriteHMetis( Abc_Frame_t * pAbc, int argc, char **argv ) char * pFileName; int fVerbose; int fSkipPo; + int fWeightEdges; int c; fSkipPo = 1; + fWeightEdges = 0; fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "swvh" ) ) != EOF ) { switch ( c ) { case 's': fSkipPo ^= 1; break; + case 'w': + fWeightEdges ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -3452,14 +3457,14 @@ int IoCommandWriteHMetis( Abc_Frame_t * pAbc, int argc, char **argv ) fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" ); return 1; } - //Io_WriteAiger( pAbc->pNtkCur, pFileName, fWriteSymbols, fCompact, fUnique ); - Io_WriteHMetis( pAbc->pNtkCur, pFileName, fSkipPo, fVerbose ); + Io_WriteHMetis( pAbc->pNtkCur, pFileName, fSkipPo, fWeightEdges, fVerbose ); return 0; usage: fprintf( pAbc->Err, "usage: write_hmetis \n" ); fprintf( pAbc->Err, "\t writes the network in the hMetis format (https://karypis.github.io/glaros/files/sw/hmetis/manual.pdf)\n" ); fprintf( pAbc->Err, "\t-s : skip PO as sink explictly [default = %s]\n", fSkipPo? "yes" : "no" ); + fprintf( pAbc->Err, "\t-w : simulate weight on hyperedges [default = %s]\n", fWeightEdges? "yes" : "no" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes" : "no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); diff --git a/src/base/io/ioAbc.h b/src/base/io/ioAbc.h index 0f3034882..77c7dc292 100644 --- a/src/base/io/ioAbc.h +++ b/src/base/io/ioAbc.h @@ -131,7 +131,7 @@ extern void Io_WriteEdgelist( Abc_Ntk_t * pNtk, char * pFileName, /*=== abcWriteGml.c ===========================================================*/ extern void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ); /*=== abcWriteHMetis.c ===========================================================*/ -extern void Io_WriteHMetis( Abc_Ntk_t * pNtk, char * pFileName, int fSkipPo, int fVerbose ); +extern void Io_WriteHMetis( Abc_Ntk_t * pNtk, char * pFileName, int fSkipPo, int fWeightEdges, int fVerbose ); /*=== abcWriteList.c ==========================================================*/ extern void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ); /*=== abcWritePla.c ===========================================================*/ diff --git a/src/base/io/ioWriteHMetis.c b/src/base/io/ioWriteHMetis.c index fa4d3d76d..5bb28783b 100644 --- a/src/base/io/ioWriteHMetis.c +++ b/src/base/io/ioWriteHMetis.c @@ -23,76 +23,89 @@ Minnesota(https://karypis.github.io/glaros/files/sw/hmetis/manual.pdf)] ABC_NAMESPACE_IMPL_START -void Io_WriteHMetis( Abc_Ntk_t * pNtk, char * pFileName, int fSkipPo, int fVerbose ) +void Io_WriteHMetis( Abc_Ntk_t *pNtk, char *pFileName, int fSkipPo, int fWeightEdges, int fVerbose ) { - Abc_Obj_t * pObj; - Abc_Obj_t * pFanout; + Abc_Obj_t *pObj; + Abc_Obj_t *pFanout; int i, j; - Vec_Int_t * vHyperEdgeEachWrite; - int Entry; + Vec_Int_t *vHyperEdgeEachWrite; + int iEntry; + int nHyperNodesNum = 0; // check that the network is valid - assert( Abc_NtkIsStrash( pNtk ) && Abc_NtkIsComb( pNtk )); - - FILE * pFHMetis = fopen( pFileName, "wb" ); - Vec_Ptr_t * vHyperEdges = Vec_PtrAlloc(1000); + assert( Abc_NtkIsStrash( pNtk ) && Abc_NtkIsComb( pNtk ) ); + + FILE *pFHMetis = fopen( pFileName, "wb" ); + Vec_Ptr_t *vHyperEdges = Vec_PtrAlloc( 1000 ); if ( pFHMetis == NULL ) { fprintf( stdout, "Io_WriteHMetis(): Cannot open the output file \"%s\".\n", pFileName ); - ABC_FREE(pFHMetis); + ABC_FREE( pFHMetis ); return; } - - //show pi/po/and number + + // show pi/po/and number if ( fVerbose ) { - Abc_Print( 1, "Writing hMetis file \"%s\" with %d nodes (%d pi, %d po, %d and nodes).\n", pFileName, Abc_NtkObjNum(pNtk), Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkNodeNum(pNtk) ); + Abc_Print( 1, "Writing hMetis file \"%s\" with %d nodes (%d pi, %d po, %d and nodes).\n", pFileName, Abc_NtkObjNum( pNtk ), Abc_NtkPiNum( pNtk ), Abc_NtkPoNum( pNtk ), Abc_NtkNodeNum( pNtk ) ); } - + Abc_NtkForEachObj( pNtk, pObj, i ) { - Vec_Int_t * vHyperEdgeEach = Vec_IntAlloc(20); - //push the node itself, which is a source node - Vec_IntPush(vHyperEdgeEach, Abc_ObjId(pObj)); - //iterate through all the fanouts(sink) of the node - if( !Abc_ObjIsCo(pObj) ) + Vec_Int_t *vHyperEdgeEach = Vec_IntAlloc( 20 ); + // push the node itself, which is a source node + Vec_IntPush( vHyperEdgeEach, Abc_ObjId( pObj ) ); + // iterate through all the fanouts(sink) of the node + if ( !Abc_ObjIsCo( pObj ) ) { - Abc_ObjForEachFanout(pObj, pFanout, j) + Abc_ObjForEachFanout( pObj, pFanout, j ) { - Vec_IntPush(vHyperEdgeEach, Abc_ObjId(pFanout)); + Vec_IntPush( vHyperEdgeEach, Abc_ObjId( pFanout ) ); } - } - else{ + } else + { if ( fSkipPo ) { continue; } - Vec_IntPush(vHyperEdgeEach, Abc_ObjId(Abc_ObjFanin0(pObj))); + Vec_IntPush( vHyperEdgeEach, Abc_ObjId( Abc_ObjFanin0( pObj ) ) ); } - Vec_PtrPush(vHyperEdges, vHyperEdgeEach); + Vec_PtrPush( vHyperEdges, vHyperEdgeEach ); } - //write the number of hyperedges and the number of vertices - fprintf(pFHMetis, "%d %d\n", Vec_PtrSize(vHyperEdges), Abc_NtkObjNum(pNtk)); - //write the hyperedges - Vec_PtrForEachEntry(Vec_Int_t *, vHyperEdges, vHyperEdgeEachWrite, i) + nHyperNodesNum = fSkipPo ? Abc_NtkObjNum( pNtk ) - Abc_NtkPoNum( pNtk ) : Abc_NtkObjNum( pNtk ); + + // write the number of hyperedges and the number of vertices + if ( fWeightEdges ) { - Vec_IntForEachEntry(vHyperEdgeEachWrite, Entry, j) - { - if (j == Vec_IntSize(vHyperEdgeEachWrite) - 1) - { - fprintf(pFHMetis, "%d", Entry); - } - else - { - fprintf(pFHMetis, "%d ", Entry); - } - } - fprintf(pFHMetis, "\n"); + fprintf( pFHMetis, "%d %d 1\n", Vec_PtrSize( vHyperEdges ), nHyperNodesNum ); + } else + { + fprintf( pFHMetis, "%d %d\n", Vec_PtrSize( vHyperEdges ), nHyperNodesNum ); } - //comments should be started with "%" in hMetis format + // write the hyperedges + Vec_PtrForEachEntry( Vec_Int_t *, vHyperEdges, vHyperEdgeEachWrite, i ) + { + if ( fWeightEdges ) + { + fprintf( pFHMetis, "%d ", Vec_IntSize( vHyperEdgeEachWrite ) ); + } + + Vec_IntForEachEntry( vHyperEdgeEachWrite, iEntry, j ) + { + if ( j == Vec_IntSize( vHyperEdgeEachWrite ) - 1 ) + { + fprintf( pFHMetis, "%d", iEntry ); + } else + { + fprintf( pFHMetis, "%d ", iEntry ); + } + } + fprintf( pFHMetis, "\n" ); + } + // comments should be started with "%" in hMetis format fprintf( pFHMetis, "\n%%This file was written by ABC on %s\n", Extra_TimeStamp() ); fprintf( pFHMetis, "%%For information about hMetis format, refer to %s\n", "https://karypis.github.io/glaros/files/sw/hmetis/manual.pdf" ); - Vec_PtrFreeFree(vHyperEdges); + Vec_PtrFreeFree( vHyperEdges ); } ABC_NAMESPACE_IMPL_END \ No newline at end of file From 7d247a08f7ece422d6a7df77c483a14f1dff4e12 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 26 Dec 2024 00:37:37 -0800 Subject: [PATCH 070/133] Experiments with bound-set evaluation. --- src/base/abci/abc.c | 126 +++++++++ src/misc/util/module.make | 1 + src/misc/util/utilBSet.c | 562 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 689 insertions(+) create mode 100644 src/misc/util/utilBSet.c diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 824c09003..140b2db4e 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -156,6 +156,7 @@ static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLutCasDec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLutCas ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBsEval ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandVarMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFaultClasses ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -958,6 +959,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "lutcasdec", Abc_CommandLutCasDec, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "lutcas", Abc_CommandLutCas, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "bseval", Abc_CommandBsEval, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "extract", Abc_CommandExtract, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "varmin", Abc_CommandVarMin, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "faultclasses", Abc_CommandFaultClasses, 0 ); @@ -9155,6 +9157,130 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBsEval( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_BSEvalOneTest( word * pT, int nVars, int nBVars, int fVerbose ); + extern void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fVerbose ); + extern void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryAll, int fVerbose ); + int c, nVars = 0, nBVars = 0, nFuncs = 0, nMints = 0, fTryAll = 0, fVerbose = 0; char * pTtStr = NULL; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IBRMavh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 2 || nVars > 16 ) + goto usage; + break; + case 'B': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + nBVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nBVars < 1 || nBVars > 16 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nFuncs = atoi(argv[globalUtilOptind]); + if ( nFuncs < 1 ) + goto usage; + globalUtilOptind++; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMints = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'a': + fTryAll ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind + 1 ) + pTtStr = argv[globalUtilOptind]; + if ( pTtStr ) + { + nVars = Abc_Base2Log((int)strlen(pTtStr)) + 2; + if ( (1 << (nVars-2)) != (int)strlen(pTtStr) ) + { + Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (nVars-2)), strlen(pTtStr) ); + return 1; + } + } + if ( nVars == 0 ) + { + Abc_Print( -1, "The number of variables should be specified on the command line.\n" ); + return 1; + } + if ( nBVars == 0 ) + { + Abc_Print( -1, "The bound set size should be specified on the command line.\n" ); + return 1; + } + if ( nFuncs ) + Abc_BSEvalBestGen( nVars, nBVars, nFuncs, nMints, fTryAll, fVerbose ); + else if ( pTtStr ) + { + word pTruth[1024] = {0}; + Abc_TtReadHex( pTruth, pTtStr ); + if ( fTryAll ) + Abc_BSEvalBestTest( pTruth, nVars, nBVars, fVerbose ); + else + Abc_BSEvalOneTest( pTruth, nVars, nBVars, fVerbose ); + } + return 0; + +usage: + Abc_Print( -2, "usage: bseval [-IBRM ] [-avh] \n" ); + Abc_Print( -2, "\t bound set evaluation\n" ); + Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", nVars ); + Abc_Print( -2, "\t-B : the number of bound set variables [default = %d]\n", nBVars ); + Abc_Print( -2, "\t-R : 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-a : toggle trying all bound sets of this size [default = %s]\n", fTryAll ? "yes" : "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t : truth table in hex notation\n" ); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/misc/util/module.make b/src/misc/util/module.make index 66e87653f..bf3538360 100644 --- a/src/misc/util/module.make +++ b/src/misc/util/module.make @@ -1,4 +1,5 @@ SRC += src/misc/util/utilBridge.c \ + src/misc/util/utilBSet.c \ src/misc/util/utilCex.c \ src/misc/util/utilColor.c \ src/misc/util/utilFile.c \ diff --git a/src/misc/util/utilBSet.c b/src/misc/util/utilBSet.c new file mode 100644 index 000000000..7f95e97d0 --- /dev/null +++ b/src/misc/util/utilBSet.c @@ -0,0 +1,562 @@ +/**CFile**************************************************************** + + FileName [utilBSet.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Bound set evaluation.] + + Synopsis [Bound set evaluation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 25, 2024.] + + Revision [$Id: utilBSet.c,v 1.00 2024/12/25 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include +#include + +#include "misc/vec/vec.h" +#include "misc/extra/extra.h" +#include "misc/util/utilTruth.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Abc_BSEval_t_ Abc_BSEval_t; +struct Abc_BSEval_t_ +{ + int nVars; + int nBVars; + Vec_Int_t * vPairs; // perm pairs + Vec_Int_t * vCounts; // cofactor counts + Vec_Int_t * vTable; // hash table + Vec_Int_t * vUsed; // used entries + Vec_Wrd_t * vStore; // cofactors +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Bound-set evalution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_TtGetCM1( word * p, int nVars ) +{ + int Counts[4] = {0}; + int i, Res = 0, nDigits = 1 << (nVars - 1); + for ( i = 0; i < nDigits; i++ ) + Counts[Abc_TtGetQua(p, i)]++; + for ( i = 0; i < 4; i++ ) + Res += Counts[i] > 0; + return Res; +} +int Abc_TtGetCM2( word * p, int nVars ) +{ + int Counts[16] = {0}; + int i, Res = 0, nDigits = 1 << (nVars - 2); + for ( i = 0; i < nDigits; i++ ) + Counts[Abc_TtGetHex(p, i)]++; + for ( i = 0; i < 16; i++ ) + Res += Counts[i] > 0; + return Res; +} +int Abc_TtGetCM3( word * p, int nVars, int * pCounts, Vec_Int_t * vUsed ) +{ + unsigned char * q = (unsigned char *)p; + int i, Digit, nDigits = 1 << (nVars - 3); + Vec_IntClear( vUsed ); + for ( i = 0; i < nDigits; i++ ) { + if ( pCounts[q[i]] ) + continue; + pCounts[q[i]] = 1; + Vec_IntPush(vUsed, q[i]); + } + Vec_IntForEachEntry( vUsed, Digit, i ) + pCounts[Digit] = 0; + return Vec_IntSize(vUsed); +} +int Abc_TtGetCM4( word * p, int nVars, int * pCounts, Vec_Int_t * vUsed ) +{ + unsigned short * q = (unsigned short *)p; + int i, Digit, nDigits = 1 << (nVars - 4); + Vec_IntClear( vUsed ); + for ( i = 0; i < nDigits; i++ ) { + if ( pCounts[q[i]] ) + continue; + pCounts[q[i]] = 1; + Vec_IntPush(vUsed, q[i]); + } + Vec_IntForEachEntry( vUsed, Digit, i ) + pCounts[Digit] = 0; + return Vec_IntSize(vUsed); +} + +// https://en.wikipedia.org/wiki/Jenkins_hash_function +int Abc_TtGetKey( unsigned char * p, int nSize, int nTableSize ) +{ + int i = 0; unsigned hash = 0; + while ( i != nSize ) + { + hash += p[i++]; + hash += hash << 10; + hash ^= hash >> 6; + } + hash += hash << 3; + hash ^= hash >> 11; + hash += hash << 15; + return (int)(hash % nTableSize); +} +int Abc_TtHashLookup5( int Entry, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +{ + int Key = Abc_TtGetKey( (unsigned char*)&Entry, 4, Vec_IntSize(vTable) ); + int * pTable = Vec_IntArray(vTable); + for ( ; pTable[Key]; Key = (Key + 1) % Vec_IntSize(vTable) ) + if ( Entry == (int)Vec_WrdEntry(vStore, pTable[Key]) ) + return 0; + assert( pTable[Key] == -1 ); + pTable[Key] = Vec_WrdSize(vStore); + Vec_WrdPush( vStore, (word)Entry ); + Vec_IntPush( vUsed, Key ); + return 1; +} +int Abc_TtGetCM5( word * p, int nVars, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +{ + unsigned * q = (unsigned *)p; + int i, Item, nDigits = 1 << (nVars - 5); + Vec_WrdClear( vStore ); + Vec_IntClear( vUsed ); + for ( i = 0; i < nDigits; i++ ) + Abc_TtHashLookup5( q[i], vTable, vStore, vUsed ); + Vec_IntForEachEntry( vUsed, Item, i ) + Vec_IntWriteEntry( vTable, Item, -1 ); + return Vec_IntSize(vUsed); +} +int Abc_TtHashLookup6( word * pEntry, int nWords, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +{ + int i, Key = Abc_TtGetKey( (unsigned char*)&pEntry, 8*nWords, Vec_IntSize(vTable) ); + int * pTable = Vec_IntArray(vTable); + for ( ; pTable[Key]; Key = (Key + 1) % Vec_IntSize(vTable) ) + if ( !memcmp(pEntry, Vec_WrdEntryP(vStore, pTable[Key]), 8*nWords) ) + return 0; + assert( pTable[Key] == -1 ); + pTable[Key] = Vec_WrdSize(vStore); + for ( i = 0; i < nWords; i++ ) + Vec_WrdPush( vStore, pEntry[i] ); + Vec_IntPush( vUsed, Key ); + return 1; +} +int Abc_TtGetCM6( word * p, int nVars, int nFVars, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +{ + assert( nFVars >= 6 && nFVars < nVars ); + int i, Item, nDigits = 1 << (nVars - nFVars), nWords = 1 << (nFVars - 6); + Vec_WrdClear( vStore ); + Vec_IntClear( vUsed ); + for ( i = 0; i < nDigits; i++ ) + Abc_TtHashLookup6( p + i*nWords, nWords, vTable, vStore, vUsed ); + Vec_IntForEachEntry( vUsed, Item, i ) + Vec_IntWriteEntry( vTable, Item, -1 ); + return Vec_IntSize(vUsed); +} +int Abc_TtGetCM( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +{ + if ( nFVars == 1 ) + return Abc_TtGetCM1( p, nVars ); + if ( nFVars == 2 ) + return Abc_TtGetCM2( p, nVars ); + if ( nFVars == 3 ) + return Abc_TtGetCM3( p, nVars, Vec_IntArray(vCounts), vUsed ); + if ( nFVars == 4 ) + return Abc_TtGetCM4( p, nVars, Vec_IntArray(vCounts), vUsed ); + if ( nFVars == 5 ) + return Abc_TtGetCM5( p, nVars, vTable, vStore, vUsed ); + if ( nFVars == 6 ) + return Abc_TtGetCM6( p, nVars, nFVars, vTable, vStore, vUsed ); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Permutation generation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Abc_TtPermGen( int * currPerm, int nVars, word * pT, int nTtVars ) +{ + int i = nVars - 1; + while ( i >= 0 && currPerm[i - 1] >= currPerm[i] ) + i--; + if (i >= 0) + { + int j = nVars; + while ( j > i && currPerm[j - 1] <= currPerm[i - 1 ]) + j--; + ABC_SWAP( int, currPerm[i - 1], currPerm[j - 1] ) + if ( pT ) Abc_TtSwapVars( pT, nTtVars, i-1, j-1 ); + i++; + j = nVars; + while ( i < j ) + { + ABC_SWAP( int, currPerm[i - 1], currPerm[j - 1] ) + if ( pT ) Abc_TtSwapVars( pT, nTtVars, i-1, j-1 ); + i++; + j--; + } + } +} +static int Abc_TtFactorial(int nVars) +{ + int i, Res = 1; + for ( i = 1; i <= nVars; i++ ) + Res *= i; + return Res; +} +void Abc_TtPermGenTest() +{ + int i, k, nVars = 5, currPerm[5] = {0}; + for ( i = 0; i < nVars; i++ ) + currPerm[i] = i; + int fact = Abc_TtFactorial( nVars ); + for ( i = 0; i < fact; i++ ) + { + printf( "%3d :", i ); + for ( k = 0; k < nVars; k++ ) + printf( " %d", currPerm[k] ); + printf( "\n" ); + Abc_TtPermGen( currPerm, nVars, NULL, 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Combination generation.] + + Description [https://stackoverflow.com/questions/22650522/how-to-generate-chases-sequence] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_GenChaseNext(int a[], int w[], int *r) +{ + int found_r = 0; + int j; + for (j = *r; !w[j]; j++) { + int b = a[j] + 1; + int n = a[j + 1]; + if (b < (w[j + 1] ? n - (2 - (n & 1)) : n)) { + if ((b & 1) == 0 && b + 1 < n) b++; + a[j] = b; + if (!found_r) *r = j > 1 ? j - 1 : 0; + return; + } + w[j] = a[j] - 1 >= j; + if (w[j] && !found_r) { + *r = j; + found_r = 1; + } + } + int b = a[j] - 1; + if ((b & 1) != 0 && b - 1 >= j) b--; + a[j] = b; + w[j] = b - 1 >= j; + if (!found_r) *r = j; +} +Vec_Int_t * Abc_GenChasePairs( int N, int T ) +{ + Vec_Int_t * vPairs = Vec_IntAlloc( 100 ); + int j, z, r = 0, Count = 0, a[32], b[32], w[32]; + for ( j = 0; j < T + 1; j++ ) { + a[j] = N - (T - j); + w[j] = 1; + } + do { + for ( z = 0; z <= T; z++ ) + b[z] = a[z]; + Abc_GenChaseNext( a, w, &r ); + for ( z = 0; z < T; z++ ) { + if ( a[z] == b[z] ) + continue; + Vec_IntPushTwo( vPairs, b[z], a[z] ); + if ( 0 ) { + printf( "%3d : ", Count++ ); + for (j = T - 1; j > -1; j--) printf("%x", b[j]); + printf( " %d <-> %d ", b[z], a[z] ); + for (j = T - 1; j > -1; j--) printf("%x", a[j]); + printf( "\n" ); + } + break; + } + } while (a[T] == N); + Vec_IntPushTwo( vPairs, 0, 0 ); + return vPairs; +} +void Abc_GenChasePrint( int Count, int * pPerm, int nVars, int nFVars, int Var0, int Var1 ) +{ + int k; + printf( "%3d : ", Count++ ); + for ( k = nVars-1; k >= nFVars; k-- ) + printf( "%d", pPerm[k] ); + printf( " " ); + for ( k = nFVars-1; k >= 0; k-- ) + printf( "%d", pPerm[k] ); + printf( " %d <-> %d\n", Var0, Var1 ); +} +void Abc_GenChaseTest() +{ + int nVars = 4; + int nFVars = 2; + Vec_Int_t * vPairs = Abc_GenChasePairs( nVars, nVars-nFVars ); + int i, Var0, Var1, Pla2Var[32], Var2Pla[32]; + for ( i = 0; i < nVars; i++ ) + Pla2Var[i] = Var2Pla[i] = i; + int Count = 0; + Vec_IntForEachEntryDouble( vPairs, Var0, Var1, i ) { + Abc_GenChasePrint( Count++, Pla2Var, nVars, nFVars, Var0, Var1 ); + int iPlace0 = Var2Pla[Var0]; + int iPlace1 = Var2Pla[Var1]; + //Abc_TtSwapVars( pTruth, nVars, iPlace0, iPlace1 ); + Var2Pla[Pla2Var[iPlace0]] = iPlace1; + Var2Pla[Pla2Var[iPlace1]] = iPlace0; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; + Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; + } + Vec_IntFree( vPairs ); +} + + +/**Function************************************************************* + + Synopsis [Bound-set evalution for one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_BSEval_t * Abc_BSEvalAlloc() +{ + Abc_BSEval_t * p = ABC_CALLOC( Abc_BSEval_t, 1 ); + p->vCounts = Vec_IntStart( 1 << 16 ); + p->vTable = Vec_IntStartFull( 997 ); + p->vUsed = Vec_IntAlloc(100); + p->vStore = Vec_WrdAlloc(1000); + return p; +} +void Abc_BSEvalFree( Abc_BSEval_t * p ) +{ + Vec_IntFreeP( &p->vPairs ); + Vec_IntFree( p->vCounts ); + Vec_IntFree( p->vTable ); + Vec_IntFree( p->vUsed ); + Vec_WrdFree( p->vStore ); + ABC_FREE( p ); +} +void Abc_BSEvalOneTest( word * pT, int nVars, int nBVars, int fVerbose ) +{ + assert( nVars > nBVars ); + Abc_BSEval_t * p = Abc_BSEvalAlloc(); + if ( p->nVars != nVars || p->nBVars != nBVars ) { + Vec_IntFreeP( &p->vPairs ); + p->vPairs = Abc_GenChasePairs( nVars, nBVars ); + p->nVars = nVars; + p->nBVars = nBVars; + } + int Best = Abc_TtGetCM( pT, nVars, nVars-nBVars, p->vCounts, p->vTable, p->vStore, p->vUsed ); + printf( "Function: " ); Extra_PrintHex( stdout, (unsigned *)pT, nVars ); printf( "\n" ); + printf( "The column multiplicity of the %d-var function with bound-sets of size %d is %d.\n", nVars, nBVars, Best ); + Abc_BSEvalFree(p); +} +int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int nCVars, int nFVars, int fVerbose, int * pPermBest ) +{ + int i, k, Var0, Var1, Pla2Var[32], Var2Pla[32]; + int nPermVars = nVars-nCVars; + assert( p->nVars == nPermVars && p->nBVars == nPermVars-nFVars ); + for ( i = 0; i < nVars; i++ ) + Pla2Var[i] = Var2Pla[i] = i; + if ( pPermBest ) + for ( i = 0; i < nVars; i++ ) + pPermBest[i] = i; + int CostBest = 1 << nVars; + //int Count = 0; + Vec_IntForEachEntryDouble( p->vPairs, Var0, Var1, i ) { + //Abc_GenChasePrint( Count++, Pla2Var, nVars, nFVars, Var0, Var1 ); + int CostThis = Abc_TtGetCM( pIn, nVars, nFVars, p->vCounts, p->vTable, p->vStore, p->vUsed ); + if ( CostBest > CostThis ) { + CostBest = CostThis; + if ( pBest ) Abc_TtCopy( pBest, pIn, Abc_Truth6WordNum(nVars), 0 ); + if ( pPermBest ) memcpy( pPermBest, Pla2Var, sizeof(int)*nPermVars ); + } + if ( fVerbose ) + { + printf( "%3d : ", i/2 ); + for ( k = nCVars-1; k >= 0; k-- ) + printf( " %d", nVars-nCVars+k ); + printf( " " ); + for ( k = nPermVars-1; k >= nFVars; k-- ) + printf( " %d", Pla2Var[k] ); + printf( " " ); + for ( k = nFVars-1; k >= 0; k-- ) + printf( " %d", Pla2Var[k] ); + printf( " : Myu = %3d", CostThis ); + printf( "\n" ); + } + int iPlace0 = Var2Pla[Var0]; + int iPlace1 = Var2Pla[Var1]; + if ( iPlace0 == iPlace1 ) + continue; + Abc_TtSwapVars( pIn, nVars, iPlace0, iPlace1 ); + Var2Pla[Pla2Var[iPlace0]] = iPlace1; + Var2Pla[Pla2Var[iPlace1]] = iPlace0; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; + Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; + } + for ( i = 0; i < nPermVars; i++ ) + { + int iPlace0 = i; + int iPlace1 = Var2Pla[i]; + if ( iPlace0 == iPlace1 ) + continue; + Abc_TtSwapVars( pIn, nVars, iPlace0, iPlace1 ); + Var2Pla[Pla2Var[iPlace0]] = iPlace1; + Var2Pla[Pla2Var[iPlace1]] = iPlace0; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; + Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; + } + return CostBest; +} +void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fVerbose ) +{ + assert( nVars > nBVars ); + Abc_BSEval_t * p = Abc_BSEvalAlloc(); int i, pPerm[32] = {0}; + if ( p->nVars != nVars || p->nBVars != nBVars ) { + Vec_IntFreeP( &p->vPairs ); + p->vPairs = Abc_GenChasePairs( nVars, nBVars ); + p->nVars = nVars; + p->nBVars = nBVars; + } + word * pFun = ABC_ALLOC( word, Abc_TtWordNum(nVars) ); + int Best = Abc_BSEvalBest( p, pIn, pFun, nVars, 0, nVars-nBVars, fVerbose, pPerm ); + printf( "The minimum column multiplicity of the %d-var function with bound-sets of size %d is %d.\n", nVars, nBVars, Best ); + printf( "Original: " ); Extra_PrintHex( stdout, (unsigned *)pIn, nVars ); printf( "\n" ); + printf( "Permuted: " ); Extra_PrintHex( stdout, (unsigned *)pFun, nVars ); printf( "\n" ); + printf( "Permutation is " ); + for ( i = 0; i < nVars; i++ ) + printf( "%d ", pPerm[i] ); + printf( "\n" ); + ABC_FREE( pFun ); + Abc_BSEvalFree(p); +} + +/**Function************************************************************* + + Synopsis [Testing on random functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryAll, int fVerbose ) +{ + assert( nVars > nBVars ); + abctime clkTotal = Abc_Clock(); + Abc_BSEval_t * p = Abc_BSEvalAlloc(); + Vec_Int_t * vCounts = Vec_IntStart( 1 << nVars ); + int i, k, Count, nWords = Abc_TtWordNum(nVars); + word * pFun = ABC_ALLOC( word, nWords ); + if ( p->nVars != nVars || p->nBVars != nBVars ) { + Vec_IntFreeP( &p->vPairs ); + p->vPairs = Abc_GenChasePairs( nVars, nBVars ); + p->nVars = nVars; + p->nBVars = nBVars; + } + Abc_Random(1); + //printf( "\n" ); + for ( i = 0; i < nFuncs; i++ ) { + if ( nMints == 0 ) + for ( k = 0; k < nWords; k++ ) + pFun[k] = Abc_RandomW(0); + else { + Abc_TtClear( pFun, nWords ); + for ( k = 0; k < nMints; k++ ) { + int iMint = 0; + do iMint = Abc_Random(0) % (1 << nVars); + while ( Abc_TtGetBit(pFun, iMint) ); + Abc_TtSetBit( pFun, iMint ); + } + } + if ( fVerbose ) { + printf( "Function %5d ", i ); + if ( nMints ) + printf( "with %d positive minterms ", nMints ); + if ( nVars <= 8 ) { + printf( "has truth table: " ); + Extra_PrintHex( stdout, (unsigned *)pFun, nVars ); + } + if ( fTryAll ) + printf( "\n" ); + else + printf( " " ); + } + if ( fTryAll ) + Count = Abc_BSEvalBest( p, pFun, NULL, nVars, 0, nVars-nBVars, fVerbose, NULL ); + else + Count = Abc_TtGetCM( pFun, nVars, nVars-nBVars, p->vCounts, p->vTable, p->vStore, p->vUsed ); + if ( fVerbose ) + printf( "Myu = %d\n", Count ); + Vec_IntAddToEntry( vCounts, Count, 1 ); + } + ABC_FREE( pFun ); + Abc_BSEvalFree(p); + if ( nMints ) + printf( "Generated %d random %d-var functions with %d positive minterms.\n", nFuncs, nVars, nMints ); + else + printf( "Generated %d random %d-var functions.\n", nFuncs, nVars ); + printf( "Distribution of the %s column multiplicity for bound set size %d is as follows:\n", fTryAll ? "MINIMUM": "ORIGINAL", nBVars ); + assert( Vec_IntSum(vCounts) == nFuncs ); + Vec_IntForEachEntry( vCounts, Count, i ) + if ( Count ) printf( "%d=%d (%.2f %%) ", i, Count, 100.0*Count/nFuncs ); + printf( "\n" ); + Vec_IntFree( vCounts ); + Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + From b59b475d6a2b9a2664e86a47a959bcbcc3d59a35 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 26 Dec 2024 00:56:18 -0800 Subject: [PATCH 071/133] Compiler error. --- src/misc/util/utilBSet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/misc/util/utilBSet.c b/src/misc/util/utilBSet.c index 7f95e97d0..f323febca 100644 --- a/src/misc/util/utilBSet.c +++ b/src/misc/util/utilBSet.c @@ -27,6 +27,8 @@ #include "misc/extra/extra.h" #include "misc/util/utilTruth.h" +ABC_NAMESPACE_IMPL_START + //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// From 73742a7ec281435bf105c4af039f80f07d3aadaa Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 26 Dec 2024 01:10:02 -0800 Subject: [PATCH 072/133] Adding new file to windows makefile. --- abclib.dsp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/abclib.dsp b/abclib.dsp index 559d59d2a..4e027c495 100644 --- a/abclib.dsp +++ b/abclib.dsp @@ -4111,6 +4111,10 @@ SOURCE=.\src\misc\util\utilBridge.c # End Source File # Begin Source File +SOURCE=.\src\misc\util\utilBSet.c +# End Source File +# Begin Source File + SOURCE=.\src\misc\util\utilCex.c # End Source File # Begin Source File From 350dcd3ea4cfb1859576c8cf20e64361279909fb Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 28 Dec 2024 00:05:00 -0800 Subject: [PATCH 073/133] Enabling shared variables in bound set evaluation. --- src/base/abci/abc.c | 26 ++-- src/misc/util/utilBSet.c | 257 +++++++++++++++++++++++++++++++++----- src/misc/util/utilTruth.h | 20 +++ 3 files changed, 263 insertions(+), 40 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 140b2db4e..cc28e1803 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -9171,11 +9171,11 @@ usage: int Abc_CommandBsEval( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_BSEvalOneTest( word * pT, int nVars, int nBVars, int fVerbose ); - extern void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fVerbose ); - extern void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryAll, int fVerbose ); - int c, nVars = 0, nBVars = 0, nFuncs = 0, nMints = 0, fTryAll = 0, fVerbose = 0; char * pTtStr = NULL; + extern void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fShared, int fVerbose ); + extern void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryAll, int fShared, int fVerbose ); + int c, nVars = 0, nBVars = 0, nSVars = 0, nFuncs = 0, nMints = 0, fTryAll = 0, fVerbose = 0; char * pTtStr = NULL; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "IBRMavh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "IBSRMavh" ) ) != EOF ) { switch ( c ) { @@ -9201,6 +9201,17 @@ int Abc_CommandBsEval( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nBVars < 1 || nBVars > 16 ) goto usage; break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + nSVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSVars < 0 || nSVars > 16 ) + goto usage; + break; case 'R': if ( globalUtilOptind >= argc ) { @@ -9255,23 +9266,24 @@ int Abc_CommandBsEval( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } if ( nFuncs ) - Abc_BSEvalBestGen( nVars, nBVars, nFuncs, nMints, fTryAll, fVerbose ); + Abc_BSEvalBestGen( nVars, nBVars, nFuncs, nMints, fTryAll, nSVars == 1, fVerbose ); else if ( pTtStr ) { word pTruth[1024] = {0}; Abc_TtReadHex( pTruth, pTtStr ); if ( fTryAll ) - Abc_BSEvalBestTest( pTruth, nVars, nBVars, fVerbose ); + Abc_BSEvalBestTest( pTruth, nVars, nBVars, nSVars == 1, fVerbose ); else Abc_BSEvalOneTest( pTruth, nVars, nBVars, fVerbose ); } return 0; usage: - Abc_Print( -2, "usage: bseval [-IBRM ] [-avh] \n" ); + Abc_Print( -2, "usage: bseval [-IBSRM ] [-avh] \n" ); Abc_Print( -2, "\t bound set evaluation\n" ); Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", nVars ); Abc_Print( -2, "\t-B : the number of bound set variables [default = %d]\n", nBVars ); + Abc_Print( -2, "\t-S : the number of shared variables [default = %d]\n", nSVars ); Abc_Print( -2, "\t-R : 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-a : toggle trying all bound sets of this size [default = %s]\n", fTryAll ? "yes" : "no" ); diff --git a/src/misc/util/utilBSet.c b/src/misc/util/utilBSet.c index f323febca..03faf51b7 100644 --- a/src/misc/util/utilBSet.c +++ b/src/misc/util/utilBSet.c @@ -86,13 +86,13 @@ int Abc_TtGetCM3( word * p, int nVars, int * pCounts, Vec_Int_t * vUsed ) int i, Digit, nDigits = 1 << (nVars - 3); Vec_IntClear( vUsed ); for ( i = 0; i < nDigits; i++ ) { - if ( pCounts[q[i]] ) + if ( pCounts[q[i]] == 1 ) continue; pCounts[q[i]] = 1; Vec_IntPush(vUsed, q[i]); } Vec_IntForEachEntry( vUsed, Digit, i ) - pCounts[Digit] = 0; + pCounts[Digit] = -1; return Vec_IntSize(vUsed); } int Abc_TtGetCM4( word * p, int nVars, int * pCounts, Vec_Int_t * vUsed ) @@ -101,13 +101,13 @@ int Abc_TtGetCM4( word * p, int nVars, int * pCounts, Vec_Int_t * vUsed ) int i, Digit, nDigits = 1 << (nVars - 4); Vec_IntClear( vUsed ); for ( i = 0; i < nDigits; i++ ) { - if ( pCounts[q[i]] ) + if ( pCounts[q[i]] == 1 ) continue; pCounts[q[i]] = 1; Vec_IntPush(vUsed, q[i]); } Vec_IntForEachEntry( vUsed, Digit, i ) - pCounts[Digit] = 0; + pCounts[Digit] = -1; return Vec_IntSize(vUsed); } @@ -130,14 +130,14 @@ int Abc_TtHashLookup5( int Entry, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_In { int Key = Abc_TtGetKey( (unsigned char*)&Entry, 4, Vec_IntSize(vTable) ); int * pTable = Vec_IntArray(vTable); - for ( ; pTable[Key]; Key = (Key + 1) % Vec_IntSize(vTable) ) + for ( ; pTable[Key] >= 0; Key = (Key + 1) % Vec_IntSize(vTable) ) if ( Entry == (int)Vec_WrdEntry(vStore, pTable[Key]) ) - return 0; + return pTable[Key]; assert( pTable[Key] == -1 ); pTable[Key] = Vec_WrdSize(vStore); Vec_WrdPush( vStore, (word)Entry ); Vec_IntPush( vUsed, Key ); - return 1; + return pTable[Key]; } int Abc_TtGetCM5( word * p, int nVars, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) { @@ -153,17 +153,17 @@ int Abc_TtGetCM5( word * p, int nVars, Vec_Int_t * vTable, Vec_Wrd_t * vStore, V } int Abc_TtHashLookup6( word * pEntry, int nWords, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) { - int i, Key = Abc_TtGetKey( (unsigned char*)&pEntry, 8*nWords, Vec_IntSize(vTable) ); + int i, Key = Abc_TtGetKey( (unsigned char*)pEntry, 8*nWords, Vec_IntSize(vTable) ); int * pTable = Vec_IntArray(vTable); - for ( ; pTable[Key]; Key = (Key + 1) % Vec_IntSize(vTable) ) - if ( !memcmp(pEntry, Vec_WrdEntryP(vStore, pTable[Key]), 8*nWords) ) - return 0; + for ( ; pTable[Key] >= 0; Key = (Key + 1) % Vec_IntSize(vTable) ) + if ( !memcmp(pEntry, Vec_WrdEntryP(vStore, nWords*pTable[Key]), 8*nWords) ) + return pTable[Key]; assert( pTable[Key] == -1 ); - pTable[Key] = Vec_WrdSize(vStore); + pTable[Key] = Vec_WrdSize(vStore)/nWords; for ( i = 0; i < nWords; i++ ) Vec_WrdPush( vStore, pEntry[i] ); Vec_IntPush( vUsed, Key ); - return 1; + return pTable[Key]; } int Abc_TtGetCM6( word * p, int nVars, int nFVars, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) { @@ -171,13 +171,14 @@ int Abc_TtGetCM6( word * p, int nVars, int nFVars, Vec_Int_t * vTable, Vec_Wrd_t int i, Item, nDigits = 1 << (nVars - nFVars), nWords = 1 << (nFVars - 6); Vec_WrdClear( vStore ); Vec_IntClear( vUsed ); + //assert( Vec_IntSum(vTable) == -Vec_IntSize(vTable) ); for ( i = 0; i < nDigits; i++ ) Abc_TtHashLookup6( p + i*nWords, nWords, vTable, vStore, vUsed ); Vec_IntForEachEntry( vUsed, Item, i ) Vec_IntWriteEntry( vTable, Item, -1 ); return Vec_IntSize(vUsed); } -int Abc_TtGetCM( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +int Abc_TtGetCMCount( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) { if ( nFVars == 1 ) return Abc_TtGetCM1( p, nVars ); @@ -195,6 +196,179 @@ int Abc_TtGetCM( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t return 0; } +/**Function************************************************************* + + Synopsis [Bound-set evalution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_TtGetCM1Pat( word * p, int nVars, word * pPat ) +{ + int nUsed = 0, pUsed[4], pMap[4]; + int i, nDigits = 1 << (nVars - 1), nWordsBS = Abc_TtWordNum(nVars - 1); + memset( pMap, 0xFF, 16 ); + for ( i = 0; i < nDigits; i++ ) { + int Digit = Abc_TtGetQua(p, i); + if ( pMap[Digit] == -1 ) { + pMap[Digit] = nUsed; + pUsed[nUsed++] = Digit; + } + if ( pPat ) Abc_TtSetBit( pPat + nWordsBS*pMap[Digit], i ); + } + return nUsed; +} +int Abc_TtGetCM2Pat( word * p, int nVars, word * pPat ) +{ + int nUsed = 0, pUsed[16], pMap[16]; + int i, nDigits = 1 << (nVars - 2), nWordsBS = Abc_TtWordNum(nVars - 2); + memset( pMap, 0xFF, 64 ); + for ( i = 0; i < nDigits; i++ ) { + int Digit = Abc_TtGetHex(p, i); + if ( pMap[Digit] == -1 ) { + pMap[Digit] = nUsed; + pUsed[nUsed++] = Digit; + } + if ( pPat ) Abc_TtSetBit( pPat + nWordsBS*pMap[Digit], i ); + } + return nUsed; +} +int Abc_TtGetCM3Pat( word * p, int nVars, int * pMap, Vec_Int_t * vUsed, word * pPat ) +{ + unsigned char * q = (unsigned char *)p; + int i, Digit, nDigits = 1 << (nVars - 3), nWordsBS = Abc_TtWordNum(nVars - 3); + Vec_IntClear( vUsed ); + for ( i = 0; i < nDigits; i++ ) { + if ( pMap[q[i]] == -1 ) { + pMap[q[i]] = Vec_IntSize(vUsed); + Vec_IntPush(vUsed, q[i]); + } + if ( pPat ) Abc_TtSetBit( pPat + nWordsBS*pMap[q[i]], i ); + } + Vec_IntForEachEntry( vUsed, Digit, i ) + pMap[Digit] = -1; + return Vec_IntSize(vUsed); +} +int Abc_TtGetCM4Pat( word * p, int nVars, int * pMap, Vec_Int_t * vUsed, word * pPat ) +{ + unsigned short * q = (unsigned short *)p; + int i, Digit, nDigits = 1 << (nVars - 4), nWordsBS = Abc_TtWordNum(nVars - 4); + Vec_IntClear( vUsed ); + for ( i = 0; i < nDigits; i++ ) { + if ( pMap[q[i]] == -1 ) { + pMap[q[i]] = Vec_IntSize(vUsed); + Vec_IntPush(vUsed, q[i]); + } + if ( pPat ) Abc_TtSetBit( pPat + nWordsBS*pMap[q[i]], i ); + } + Vec_IntForEachEntry( vUsed, Digit, i ) + pMap[Digit] = -1; + return Vec_IntSize(vUsed); +} +int Abc_TtGetCM5Pat( word * p, int nVars, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed, word * pPat ) +{ + unsigned * q = (unsigned *)p; + int i, Item, nDigits = 1 << (nVars - 5), nWordsBS = Abc_TtWordNum(nVars - 5); + Vec_WrdClear( vStore ); + Vec_IntClear( vUsed ); + if ( pPat ) + for ( i = 0; i < nDigits; i++ ) + Abc_TtSetBit( pPat + nWordsBS*Abc_TtHashLookup5(q[i], vTable, vStore, vUsed), i ); + else + for ( i = 0; i < nDigits; i++ ) + Abc_TtHashLookup5( q[i], vTable, vStore, vUsed ); + Vec_IntForEachEntry( vUsed, Item, i ) + Vec_IntWriteEntry( vTable, Item, -1 ); + return Vec_IntSize(vUsed); +} +int Abc_TtGetCM6Pat( word * p, int nVars, int nFVars, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed, word * pPat ) +{ + assert( nFVars >= 6 && nFVars < nVars ); + int i, Item, nDigits = 1 << (nVars - nFVars), nWords = 1 << (nFVars - 6), nWordsBS = Abc_TtWordNum(nVars - nFVars); + Vec_WrdClear( vStore ); + Vec_IntClear( vUsed ); + if ( pPat ) + for ( i = 0; i < nDigits; i++ ) + Abc_TtSetBit( pPat + nWordsBS*Abc_TtHashLookup6(p + i*nWords, nWords, vTable, vStore, vUsed), i ); + else + for ( i = 0; i < nDigits; i++ ) + Abc_TtHashLookup6( p + i*nWords, nWords, vTable, vStore, vUsed ); + Vec_IntForEachEntry( vUsed, Item, i ) + Vec_IntWriteEntry( vTable, Item, -1 ); + return Vec_IntSize(vUsed); +} + +void Abc_TtPrintPat( word * pPat, int nVars, int nMyu ) +{ + printf( "ACD i-sets with %d variables and column multiplicity %d:\n", nVars, nMyu ); + for ( int m = 0; m < nMyu; m++ ) + Extra_PrintBinary( stdout, (unsigned *)&pPat[m], (1 << nVars) ), printf("\n"); +} +int Abc_TtCheck1Shared( word * pPat, int nVars, int nFVars, int nMyu ) +{ + int fVerbose = 0; + if ( fVerbose ) Abc_TtPrintPat( pPat, nVars-nFVars, nMyu ); + assert( nMyu > 2 ); + int nRails = Abc_Base2Log(nMyu); + int nMyuMax = 1 << (nRails - 1); + for ( int v = 0; v < nVars - nFVars; v++ ) { + int m, n, Counts[2] = {0}; + for ( n = 0; n < 2; n++ ) { + for ( m = 0; m < nMyu; m++ ) + if ( (Counts[n] += ((s_Truth26[n][v] & pPat[m]) != 0)) > nMyuMax ) + break; + if ( m < nMyu ) + break; + } + if ( fVerbose ) printf( "%d : %2d %2d %2d\n", v, Counts[0], Counts[1], nMyuMax ); + if ( n == 2 ) { + //Abc_TtPrintPat( pPat, nVars-nFVars, nMyu ); + //printf( "%d : %2d %2d %2d\n", v, Counts[0], Counts[1], nMyuMax ); + return nRails - 1; + } + } + if ( fVerbose ) printf( "Not found\n" ); + return nRails; +} +int Abc_TtGetCMPat( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +{ + word pPat[1024]; + int nMintsBS = 1 << (nVars - nFVars); + int nWordsBS = Abc_TtWordNum(nVars - nFVars); + assert( nMintsBS * nWordsBS <= 1024 ); + memset( pPat, 0, 8 * nMintsBS * nWordsBS ); + int nMyu = 0, nRails; + if ( nFVars == 1 ) + nMyu = Abc_TtGetCM1Pat( p, nVars, pPat ); + else if ( nFVars == 2 ) + nMyu = Abc_TtGetCM2Pat( p, nVars, pPat ); + else if ( nFVars == 3 ) + nMyu = Abc_TtGetCM3Pat( p, nVars, Vec_IntArray(vCounts), vUsed, pPat ); + else if ( nFVars == 4 ) + nMyu = Abc_TtGetCM4Pat( p, nVars, Vec_IntArray(vCounts), vUsed, pPat ); + else if ( nFVars == 5 ) + nMyu = Abc_TtGetCM5Pat( p, nVars, vTable, vStore, vUsed, pPat ); + else if ( nFVars == 6 ) + nMyu = Abc_TtGetCM6Pat( p, nVars, nFVars, vTable, vStore, vUsed, pPat ); + else assert( 0 ); + if ( nMyu <= 2 ) + nRails = 1; + else + nRails = Abc_TtCheck1Shared( pPat, nVars, nFVars, nMyu ); + return nRails; +} +int Abc_TtGetCM( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed, int fShared ) +{ + if ( fShared ) + return Abc_TtGetCMPat( p, nVars, nFVars, vCounts, vTable, vStore, vUsed ); + return Abc_TtGetCMCount( p, nVars, nFVars, vCounts, vTable, vStore, vUsed ); +} + + /**Function************************************************************* Synopsis [Permutation generation.] @@ -366,7 +540,7 @@ void Abc_GenChaseTest() Abc_BSEval_t * Abc_BSEvalAlloc() { Abc_BSEval_t * p = ABC_CALLOC( Abc_BSEval_t, 1 ); - p->vCounts = Vec_IntStart( 1 << 16 ); + p->vCounts = Vec_IntStartFull( 1 << 16 ); p->vTable = Vec_IntStartFull( 997 ); p->vUsed = Vec_IntAlloc(100); p->vStore = Vec_WrdAlloc(1000); @@ -391,12 +565,12 @@ void Abc_BSEvalOneTest( word * pT, int nVars, int nBVars, int fVerbose ) p->nVars = nVars; p->nBVars = nBVars; } - int Best = Abc_TtGetCM( pT, nVars, nVars-nBVars, p->vCounts, p->vTable, p->vStore, p->vUsed ); + int Best = Abc_TtGetCM( pT, nVars, nVars-nBVars, p->vCounts, p->vTable, p->vStore, p->vUsed, 0 ); printf( "Function: " ); Extra_PrintHex( stdout, (unsigned *)pT, nVars ); printf( "\n" ); printf( "The column multiplicity of the %d-var function with bound-sets of size %d is %d.\n", nVars, nBVars, Best ); Abc_BSEvalFree(p); } -int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int nCVars, int nFVars, int fVerbose, int * pPermBest ) +int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int nCVars, int nFVars, int fVerbose, int * pPermBest, int fShared ) { int i, k, Var0, Var1, Pla2Var[32], Var2Pla[32]; int nPermVars = nVars-nCVars; @@ -410,7 +584,7 @@ int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int n //int Count = 0; Vec_IntForEachEntryDouble( p->vPairs, Var0, Var1, i ) { //Abc_GenChasePrint( Count++, Pla2Var, nVars, nFVars, Var0, Var1 ); - int CostThis = Abc_TtGetCM( pIn, nVars, nFVars, p->vCounts, p->vTable, p->vStore, p->vUsed ); + int CostThis = Abc_TtGetCM( pIn, nVars, nFVars, p->vCounts, p->vTable, p->vStore, p->vUsed, fShared ); if ( CostBest > CostThis ) { CostBest = CostThis; if ( pBest ) Abc_TtCopy( pBest, pIn, Abc_Truth6WordNum(nVars), 0 ); @@ -456,7 +630,7 @@ int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int n } return CostBest; } -void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fVerbose ) +void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fShared, int fVerbose ) { assert( nVars > nBVars ); Abc_BSEval_t * p = Abc_BSEvalAlloc(); int i, pPerm[32] = {0}; @@ -467,8 +641,9 @@ void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fVerbose ) p->nBVars = nBVars; } word * pFun = ABC_ALLOC( word, Abc_TtWordNum(nVars) ); - int Best = Abc_BSEvalBest( p, pIn, pFun, nVars, 0, nVars-nBVars, fVerbose, pPerm ); - printf( "The minimum column multiplicity of the %d-var function with bound-sets of size %d is %d.\n", nVars, nBVars, Best ); + int Best = Abc_BSEvalBest( p, pIn, pFun, nVars, 0, nVars-nBVars, fVerbose, pPerm, fShared ); + printf( "The minimum %s of the %d-var function with bound-sets of size %d is %d.\n", + fShared ? "number of rails" : "column multiplicity", nVars, nBVars, Best ); printf( "Original: " ); Extra_PrintHex( stdout, (unsigned *)pIn, nVars ); printf( "\n" ); printf( "Permuted: " ); Extra_PrintHex( stdout, (unsigned *)pFun, nVars ); printf( "\n" ); printf( "Permutation is " ); @@ -490,12 +665,12 @@ void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fVerbose ) SeeAlso [] ***********************************************************************/ -void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryAll, int fVerbose ) +void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryAll, int fShared, int fVerbose ) { assert( nVars > nBVars ); abctime clkTotal = Abc_Clock(); Abc_BSEval_t * p = Abc_BSEvalAlloc(); - Vec_Int_t * vCounts = Vec_IntStart( 1 << nVars ); + Vec_Int_t * vCounts[2] = { Vec_IntStart(1 << nVars), Vec_IntStart(1 << nVars) }; int i, k, Count, nWords = Abc_TtWordNum(nVars); word * pFun = ABC_ALLOC( word, nWords ); if ( p->nVars != nVars || p->nBVars != nBVars ) { @@ -505,7 +680,6 @@ void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryA p->nBVars = nBVars; } Abc_Random(1); - //printf( "\n" ); for ( i = 0; i < nFuncs; i++ ) { if ( nMints == 0 ) for ( k = 0; k < nWords; k++ ) @@ -532,13 +706,15 @@ void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryA else printf( " " ); } + if ( fTryAll ) - Count = Abc_BSEvalBest( p, pFun, NULL, nVars, 0, nVars-nBVars, fVerbose, NULL ); + Count = Abc_BSEvalBest( p, pFun, NULL, nVars, 0, nVars-nBVars, fVerbose, NULL, fShared ); else - Count = Abc_TtGetCM( pFun, nVars, nVars-nBVars, p->vCounts, p->vTable, p->vStore, p->vUsed ); + Count = Abc_TtGetCM( pFun, nVars, nVars-nBVars, p->vCounts, p->vTable, p->vStore, p->vUsed, fShared ); if ( fVerbose ) printf( "Myu = %d\n", Count ); - Vec_IntAddToEntry( vCounts, Count, 1 ); + Vec_IntAddToEntry( vCounts[0], Count, 1 ); + Vec_IntAddToEntry( vCounts[1], Abc_Base2Log(Count), 1 ); } ABC_FREE( pFun ); Abc_BSEvalFree(p); @@ -546,12 +722,27 @@ void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryA printf( "Generated %d random %d-var functions with %d positive minterms.\n", nFuncs, nVars, nMints ); else printf( "Generated %d random %d-var functions.\n", nFuncs, nVars ); - printf( "Distribution of the %s column multiplicity for bound set size %d is as follows:\n", fTryAll ? "MINIMUM": "ORIGINAL", nBVars ); - assert( Vec_IntSum(vCounts) == nFuncs ); - Vec_IntForEachEntry( vCounts, Count, i ) - if ( Count ) printf( "%d=%d (%.2f %%) ", i, Count, 100.0*Count/nFuncs ); - printf( "\n" ); - Vec_IntFree( vCounts ); + if ( fShared ) { + printf( "Distribution of the %s number of rails for bound set size %d with one shared variable:\n", fTryAll ? "MINIMUM": "ORIGINAL", nBVars ); + assert( Vec_IntSum(vCounts[0]) == nFuncs ); + Vec_IntForEachEntry( vCounts[0], Count, i ) + if ( Count ) printf( "%d=%d (%.2f %%) ", i, Count, 100.0*Count/nFuncs ); + printf( "\n" ); + } + else { + printf( "Distribution of the %s column multiplicity for bound set size %d with no shared variables:\n", fTryAll ? "MINIMUM": "ORIGINAL", nBVars ); + assert( Vec_IntSum(vCounts[0]) == nFuncs ); + Vec_IntForEachEntry( vCounts[0], Count, i ) + if ( Count ) printf( "%d=%d (%.2f %%) ", i, Count, 100.0*Count/nFuncs ); + printf( "\n" ); + printf( "Distribution of the %s number of rails for bound set size %d with no shared variables:\n", fTryAll ? "MINIMUM": "ORIGINAL", nBVars ); + assert( Vec_IntSum(vCounts[1]) == nFuncs ); + Vec_IntForEachEntry( vCounts[1], Count, i ) + if ( Count ) printf( "%d=%d (%.2f %%) ", i, Count, 100.0*Count/nFuncs ); + printf( "\n" ); + } + Vec_IntFree( vCounts[0] ); + Vec_IntFree( vCounts[1] ); Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); } diff --git a/src/misc/util/utilTruth.h b/src/misc/util/utilTruth.h index 6cfab7109..6f96e8d47 100644 --- a/src/misc/util/utilTruth.h +++ b/src/misc/util/utilTruth.h @@ -74,6 +74,25 @@ static word s_Truths6Neg[6] = { ABC_CONST(0x00000000FFFFFFFF) }; +static word s_Truth26[2][6] = { + { + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00), + ABC_CONST(0xFFFF0000FFFF0000), + ABC_CONST(0xFFFFFFFF00000000) + }, + { + ABC_CONST(0x5555555555555555), + ABC_CONST(0x3333333333333333), + ABC_CONST(0x0F0F0F0F0F0F0F0F), + ABC_CONST(0x00FF00FF00FF00FF), + ABC_CONST(0x0000FFFF0000FFFF), + ABC_CONST(0x00000000FFFFFFFF) + } +}; + static word s_TruthXors[6] = { ABC_CONST(0x0000000000000000), ABC_CONST(0x6666666666666666), @@ -3663,6 +3682,7 @@ static inline void Abc_TtProcessBiDecExperiment() // Dau_DsdPrintFromTruth( &This, Abc_TtBitCount16(resThis) ); // Dau_DsdPrintFromTruth( &That, Abc_TtBitCount16(resThat) ); nVars = nSuppLim; + This = s_Truth26[0][0]; } /**Function************************************************************* From d5e1a5d445f68bdb4895bb735b9568e5f4738c13 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 2 Jan 2025 00:33:22 +0700 Subject: [PATCH 074/133] Bug fix in &gencex. --- src/aig/gia/giaPat2.c | 6 ++++++ src/base/abci/abc.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/aig/gia/giaPat2.c b/src/aig/gia/giaPat2.c index 93c4b1da9..b0839f5d4 100644 --- a/src/aig/gia/giaPat2.c +++ b/src/aig/gia/giaPat2.c @@ -965,6 +965,12 @@ Vec_Wec_t * Min_ManComputeCexes( Gia_Man_t * p, Vec_Int_t * vOuts0, int nMaxTrie if ( Vec_IntEntry(vStats[2], i) >= nMinCexes || Vec_IntEntry(vStats[1], i) > 10*Vec_IntEntry(vStats[2], i) ) continue; { + assert( Gia_ObjIsCo(pObj) ); + if ( Gia_ObjFaninId0p(p, pObj) == 0 ) { + if ( fVerbose ) + printf( "Output %d is driven by constant %d.\n", Gia_ObjCioId(pObj), Gia_ObjFaninC0(pObj) ); + continue; + } abctime clk = Abc_Clock(); int iObj = Min_ManCo(pNew, i); int Index = Gia_ObjCioId(pObj); diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index cc28e1803..dcfa8a501 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -54262,7 +54262,7 @@ int Abc_CommandAbc9GenCex( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: Abc_Print( -2, "usage: &gencex [-CM num] [-F file] [-stcbvh]\n" ); Abc_Print( -2, "\t generates satisfying assignments for each output of the miter\n" ); - Abc_Print( -2, "\t-C num : the number of timeframes [default = %d]\n", nMinCexes ); + Abc_Print( -2, "\t-C num : the number of satisfying assignments [default = %d]\n", nMinCexes ); Abc_Print( -2, "\t-M num : the max simulation runs before using SAT [default = %d]\n", nMaxTries ); Abc_Print( -2, "\t-F file : the output file name [default = %s]\n", pFileName ); Abc_Print( -2, "\t-s : toggles using reverse simulation [default = %s]\n", fUseSim ? "yes": "no" ); From 8c7c9d0ccf62c720472d1c0aff8a0a62a145741e Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Thu, 9 Jan 2025 22:21:32 +0800 Subject: [PATCH 075/133] Fix(&dch): choices bugs in &put --- src/aig/gia/gia.h | 2 ++ src/aig/gia/giaAig.c | 4 ++++ src/aig/gia/giaEquiv.c | 33 +++++++++++++++++++++++++++++++++ src/aig/gia/giaMan.c | 2 ++ 4 files changed, 41 insertions(+) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 015a1da22..1900d0c32 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -478,6 +478,7 @@ static inline int Gia_ManConstrNum( Gia_Man_t * p ) { return p->nCons static inline void Gia_ManFlipVerbose( Gia_Man_t * p ) { p->fVerbose ^= 1; } static inline int Gia_ManHasChoices( Gia_Man_t * p ) { return p->pSibls != NULL; } static inline int Gia_ManChoiceNum( Gia_Man_t * p ) { int c = 0; if (p->pSibls) { int i; for (i = 0; i < p->nObjs; i++) c += (int)(p->pSibls[i] > 0); } return c; } +static inline int Gia_ManHasChoicesOri( Gia_Man_t *p ){ return p->pReprs != NULL; } static inline Gia_Obj_t * Gia_ManConst0( Gia_Man_t * p ) { return p->pObjs; } static inline Gia_Obj_t * Gia_ManConst1( Gia_Man_t * p ) { return Gia_Not(Gia_ManConst0(p)); } @@ -1436,6 +1437,7 @@ extern void Gia_ManEquivFixOutputPairs( Gia_Man_t * p ); extern int Gia_ManCheckTopoOrder( Gia_Man_t * p ); extern int * Gia_ManDeriveNexts( Gia_Man_t * p ); extern void Gia_ManDeriveReprs( Gia_Man_t * p ); +extern void Gia_ManDeriveReprsFromSibls( Gia_Man_t *p ); extern int Gia_ManEquivCountLits( Gia_Man_t * p ); extern int Gia_ManEquivCountLitsAll( Gia_Man_t * p ); extern int Gia_ManEquivCountClasses( Gia_Man_t * p ); diff --git a/src/aig/gia/giaAig.c b/src/aig/gia/giaAig.c index c764a0993..07bab5fec 100644 --- a/src/aig/gia/giaAig.c +++ b/src/aig/gia/giaAig.c @@ -19,10 +19,12 @@ ***********************************************************************/ #include "giaAig.h" +#include "aig/gia/gia.h" #include "proof/fra/fra.h" #include "proof/dch/dch.h" #include "opt/dar/dar.h" #include "opt/dau/dau.h" +#include ABC_NAMESPACE_IMPL_START @@ -191,6 +193,8 @@ Gia_Man_t * Gia_ManFromAigChoices( Aig_Man_t * p ) Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) ); //assert( Gia_ManObjNum(pNew) == Aig_ManObjNum(p) ); //Gia_ManCheckChoices( pNew ); + if ( pNew->pSibls ) + Gia_ManDeriveReprsFromSibls( pNew ); return pNew; } diff --git a/src/aig/gia/giaEquiv.c b/src/aig/gia/giaEquiv.c index e4f5a0d25..36e604153 100644 --- a/src/aig/gia/giaEquiv.c +++ b/src/aig/gia/giaEquiv.c @@ -310,6 +310,39 @@ void Gia_ManDeriveReprs( Gia_Man_t * p ) } } +/**Function************************************************************* + + Synopsis [Given pSibls, derives original representitives and nexts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void Gia_ManDeriveReprsFromSibls( Gia_Man_t *p ) +{ + + int i, iObj; + assert( !p->pReprs && p->pSibls ); + p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Gia_ObjSetRepr( p, i, GIA_VOID ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + { + if ( p->pSibls[i] == 0 ) + continue; + if ( p->pReprs[i].iRepr != GIA_VOID ) + continue; + for ( iObj = p->pSibls[i]; iObj; iObj = p->pSibls[iObj] ) + p->pReprs[iObj].iRepr = i; + } + ABC_FREE( p->pNexts ); + p->pNexts = Gia_ManDeriveNexts( p ); +} + /**Function************************************************************* Synopsis [] diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index d0af551b0..413dda726 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -557,6 +557,8 @@ void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ) Abc_Print( 1, " mem =%5.2f MB", Gia_ManMemory(p)/(1<<20) ); if ( Gia_ManHasChoices(p) ) Abc_Print( 1, " ch =%5d", Gia_ManChoiceNum(p) ); + if ( Gia_ManHasChoicesOri(p)) + Abc_Print( 1, " chOri =%5d", Gia_ManEquivCountClasses(p) ); if ( p->pManTime ) Abc_Print( 1, " box = %d", Gia_ManNonRegBoxNum(p) ); if ( p->pManTime ) From c1ac7d81532400b4ef6351f80503eda2b2e96039 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Thu, 9 Jan 2025 23:04:00 +0800 Subject: [PATCH 076/133] Update(&ps): Revert two line since `cls` shows the same data --- src/aig/gia/giaMan.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index 413dda726..d0af551b0 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -557,8 +557,6 @@ void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ) Abc_Print( 1, " mem =%5.2f MB", Gia_ManMemory(p)/(1<<20) ); if ( Gia_ManHasChoices(p) ) Abc_Print( 1, " ch =%5d", Gia_ManChoiceNum(p) ); - if ( Gia_ManHasChoicesOri(p)) - Abc_Print( 1, " chOri =%5d", Gia_ManEquivCountClasses(p) ); if ( p->pManTime ) Abc_Print( 1, " box = %d", Gia_ManNonRegBoxNum(p) ); if ( p->pManTime ) From a03c126a13debcdabb74a5b3bb42ee19283bba4b Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Thu, 9 Jan 2025 23:39:02 +0800 Subject: [PATCH 077/133] Refactor(Redundant): Remove redundant code --- src/aig/gia/gia.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 1900d0c32..31761a735 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -478,7 +478,6 @@ static inline int Gia_ManConstrNum( Gia_Man_t * p ) { return p->nCons static inline void Gia_ManFlipVerbose( Gia_Man_t * p ) { p->fVerbose ^= 1; } static inline int Gia_ManHasChoices( Gia_Man_t * p ) { return p->pSibls != NULL; } static inline int Gia_ManChoiceNum( Gia_Man_t * p ) { int c = 0; if (p->pSibls) { int i; for (i = 0; i < p->nObjs; i++) c += (int)(p->pSibls[i] > 0); } return c; } -static inline int Gia_ManHasChoicesOri( Gia_Man_t *p ){ return p->pReprs != NULL; } static inline Gia_Obj_t * Gia_ManConst0( Gia_Man_t * p ) { return p->pObjs; } static inline Gia_Obj_t * Gia_ManConst1( Gia_Man_t * p ) { return Gia_Not(Gia_ManConst0(p)); } From 910a66a3723e7f3dedd798695c40e9b073296255 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Fri, 17 Jan 2025 18:26:53 +0800 Subject: [PATCH 078/133] Fix(print_mffc): Missing condition when single output linked to CO --- src/base/abci/abcPrint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index 636665249..35d5c1206 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -1083,7 +1083,7 @@ void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk ) int i; extern void Abc_NodeMffcConeSuppPrint( Abc_Obj_t * pNode ); Abc_NtkForEachNode( pNtk, pNode, i ) - if ( Abc_ObjFanoutNum(pNode) > 1 ) + if ( Abc_ObjFanoutNum(pNode) > 1 || (Abc_ObjFanoutNum(pNode) == 1 && Abc_ObjIsCo(Abc_ObjFanout0(pNode)))) Abc_NodeMffcConeSuppPrint( pNode ); } From a75d0cb0ad3f094f619c49aa383780a2f52e7ee3 Mon Sep 17 00:00:00 2001 From: letsintegreat <37345795+letsintegreat@users.noreply.github.com> Date: Sat, 18 Jan 2025 22:41:24 +0530 Subject: [PATCH 079/133] fix switching bug --- src/aig/gia/giaSwitch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aig/gia/giaSwitch.c b/src/aig/gia/giaSwitch.c index bf94ad72d..26e29591c 100644 --- a/src/aig/gia/giaSwitch.c +++ b/src/aig/gia/giaSwitch.c @@ -612,7 +612,7 @@ Vec_Int_t * Gia_ManSwiSimulate( Gia_Man_t * pAig, Gia_ParSwi_t * pPars ) else if ( pPars->fProbTrans ) { Gia_ManForEachObj( pAig, pObj, i ) - pSwitching[i] = Gia_ManSwiComputeProbOne( p->pData1[i], pPars->nWords*(pPars->nIters-pPars->nPref) ); + pSwitching[i] = Gia_ManSwiComputeSwitching( p->pData1[i], pPars->nWords*(pPars->nIters-pPars->nPref) ); } else { From adf9b4e7fbc3d9e262c3d6d04fdb045d9f45c2e2 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Tue, 21 Jan 2025 15:54:38 +0800 Subject: [PATCH 080/133] Feat(read_lib): Support .gz file --- src/map/scl/sclLiberty.c | 63 +++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/src/map/scl/sclLiberty.c b/src/map/scl/sclLiberty.c index 707a8c585..8015de8ad 100644 --- a/src/map/scl/sclLiberty.c +++ b/src/map/scl/sclLiberty.c @@ -25,6 +25,8 @@ #include #endif +#include "misc/zlib/zlib.h" +#include "misc/bzlib/bzlib.h" #include "sclLib.h" #include "misc/st/st.h" #include "map/mio/mio.h" @@ -552,14 +554,59 @@ long Scl_LibertyFileSize( char * pFileName ) fclose( pFile ); return nFileSize; } -char * Scl_LibertyFileContents( char * pFileName, long nContents ) + +static char * Io_LibLoadFileGz( char * pFileName, long * pnFileSize ) { - FILE * pFile = fopen( pFileName, "rb" ); - char * pContents = ABC_ALLOC( char, nContents+1 ); - long RetValue = 0; - RetValue = fread( pContents, nContents, 1, pFile ); - fclose( pFile ); - pContents[nContents] = 0; + const int READ_BLOCK_SIZE = 100000; + gzFile pFile; + char * pContents; + long amtRead, readBlock, nFileSize = READ_BLOCK_SIZE; + pFile = gzopen( pFileName, "rb" ); // if pFileName doesn't end in ".gz" then this acts as a passthrough to fopen + pContents = ABC_ALLOC( char, nFileSize ); + readBlock = 0; + while ((amtRead = gzread(pFile, pContents + readBlock * READ_BLOCK_SIZE, READ_BLOCK_SIZE)) == READ_BLOCK_SIZE) { + //Abc_Print( 1,"%d: read %d bytes\n", readBlock, amtRead); + nFileSize += READ_BLOCK_SIZE; + pContents = ABC_REALLOC(char, pContents, nFileSize); + ++readBlock; + } + //Abc_Print( 1,"%d: read %d bytes\n", readBlock, amtRead); + assert( amtRead != -1 ); // indicates a zlib error + nFileSize -= (READ_BLOCK_SIZE - amtRead); + gzclose(pFile); + *pnFileSize = nFileSize; + return pContents; +} + +char * Scl_LibertyFileContents( char * pFileName, long * nContents ) +{ + char * pContents = NULL; + //if file ends in ".gz" then use gzopen + if ( !strncmp(pFileName+strlen(pFileName)-3,".gz", 3) ) + { + FILE * pFile = fopen( pFileName, "rb" ); + //char * pContents; + long RetValue = 0; + pContents = Io_LibLoadFileGz( pFileName, nContents ); + if(pContents == NULL) { + printf( "Scl_LibertyFileContents(): The input file is unavailable (absent or open).\n" ); + return NULL; + } + else { + RetValue = 1; + } + fclose( pFile ); + } + // original .lib file + else + { + FILE * pFile = fopen( pFileName, "rb" ); + pContents = ABC_ALLOC( char, nContents+1 ); + long RetValue = 0; + RetValue = fread( pContents, *nContents, 1, pFile ); + fclose( pFile ); + pContents[*nContents] = 0; + } return pContents; } void Scl_LibertyStringDump( char * pFileName, Vec_Str_t * vStr ) @@ -600,7 +647,7 @@ Scl_Tree_t * Scl_LibertyStart( char * pFileName ) memset( p, 0, sizeof(Scl_Tree_t) ); p->clkStart = Abc_Clock(); p->nContents = RetValue; - p->pContents = Scl_LibertyFileContents( pFileName, p->nContents ); + p->pContents = Scl_LibertyFileContents( pFileName, &p->nContents ); // other p->pFileName = Abc_UtilStrsav( pFileName ); p->nItermAlloc = 10 + Scl_LibertyCountItems( p->pContents, p->pContents+p->nContents ); From 303907ec0ccbed60eb7f83b8b47238767ad7074f Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Tue, 21 Jan 2025 15:58:31 +0800 Subject: [PATCH 081/133] Update(read_lib): Remove redundant header --- src/map/scl/sclLiberty.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/map/scl/sclLiberty.c b/src/map/scl/sclLiberty.c index 8015de8ad..236e6ef24 100644 --- a/src/map/scl/sclLiberty.c +++ b/src/map/scl/sclLiberty.c @@ -26,7 +26,6 @@ #endif #include "misc/zlib/zlib.h" -#include "misc/bzlib/bzlib.h" #include "sclLib.h" #include "misc/st/st.h" #include "map/mio/mio.h" From 3e864445105c1ccdf58ac6917af83c91b2fce7b4 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 29 Jan 2025 17:37:24 -0800 Subject: [PATCH 082/133] Bug fix in reading truth tables. --- src/base/abc/abcNtk.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c index 3c8fd383e..c9eeb79c6 100644 --- a/src/base/abc/abcNtk.c +++ b/src/base/abc/abcNtk.c @@ -1344,10 +1344,11 @@ Abc_Ntk_t * Abc_NtkCreateWithNodes( Vec_Ptr_t * vSop ) Abc_NodeFreeNames( vNames ); // create the node, add PIs as fanins, set the function Vec_PtrForEachEntry( char *, vSop, pSop, i ) - { + { pNode = Abc_NtkCreateNode( pNtkNew ); - Abc_NtkForEachPi( pNtkNew, pFanin, k ) - Abc_ObjAddFanin( pNode, pFanin ); + if ( Abc_SopGetVarNum(pSop) > 0 ) + Abc_NtkForEachPi( pNtkNew, pFanin, k ) + Abc_ObjAddFanin( pNode, pFanin ); pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, pSop ); // create the only PO pNodePo = Abc_NtkCreatePo(pNtkNew); From 8912d3aabefa03b71259374984bfc34b67b0df0b Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 29 Jan 2025 17:40:17 -0800 Subject: [PATCH 083/133] Adding command &write_truth equivalent to &write_truths. --- src/base/io/io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/base/io/io.c b/src/base/io/io.c index 3327a9dfd..7a8bcdaf9 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -160,6 +160,7 @@ void Io_Init( Abc_Frame_t * pAbc ) // Cmd_CommandAdd( pAbc, "I/O", "write_verlib", IoCommandWriteVerLib, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_sorter_cnf", IoCommandWriteSortCnf, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_truth", IoCommandWriteTruth, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "&write_truth", IoCommandWriteTruths, 0 ); Cmd_CommandAdd( pAbc, "I/O", "&write_truths", IoCommandWriteTruths, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_status", IoCommandWriteStatus, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_smv", IoCommandWriteSmv, 0 ); @@ -3934,7 +3935,7 @@ int IoCommandWriteTruths( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; usage: - fprintf( pAbc->Err, "usage: &write_truths [-rxbh] \n" ); + fprintf( pAbc->Err, "usage: &write_truth [-rxbh] \n" ); fprintf( pAbc->Err, "\t writes truth tables of each PO of GIA manager into a file\n" ); fprintf( pAbc->Err, "\t-r : toggle reversing bits in the truth table [default = %s]\n", fReverse? "yes":"no" ); fprintf( pAbc->Err, "\t-x : toggle writing in the hex notation [default = %s]\n", fHex? "yes":"no" ); From 964170d8dc5d944d760ae3b3224361f1e4d05fe1 Mon Sep 17 00:00:00 2001 From: Ethan Mahintorabi Date: Mon, 10 Feb 2025 05:44:31 +0000 Subject: [PATCH 084/133] Fixes missing return in cec Signed-off-by: Ethan Mahintorabi --- src/proof/cec/cecSatG2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 1b0948de1..c95492e28 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -3468,7 +3468,9 @@ int check_implication( Gia_Man_t * p, int ObjId , int validBit , int fanoutValue } assert(0); - + // In C++ assert(0) doesn't count as a proper exit. + // needs to return a value to compile. + return -1; } From 2227d6d4e7bad4aca0871676df5926e51d69597e Mon Sep 17 00:00:00 2001 From: Ethan Mahintorabi Date: Tue, 11 Feb 2025 22:04:24 +0000 Subject: [PATCH 085/133] nf: Fix assert( pDp->F < FLT_MAX ); in nf This error was triggered by what appears to be a missing saturating float check in Nf_ManCutMatchOne. When opened in the debugger AreaF starts at FLT_MAX and in some cases can be added to itself which results in +Inf. I noticed the other if had a saturating condidtion. I took a flyer on it, and added it to the previous condition, and it resolved the error. I think this is a good fix. Signed-off-by: Ethan Mahintorabi --- src/aig/gia/giaNf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/aig/gia/giaNf.c b/src/aig/gia/giaNf.c index f41d8dd49..eca59120c 100644 --- a/src/aig/gia/giaNf.c +++ b/src/aig/gia/giaNf.c @@ -1172,7 +1172,10 @@ void Nf_ManCutMatchOne( Nf_Man_t * p, int iObj, int * pCut, int * pCutSet ) if ( ArrivalA + pC->iDelays[k] <= Required && Required != SCL_INFINITY ) { Delay = Abc_MaxInt( Delay, ArrivalA + pC->iDelays[k] ); - AreaF += pBestF[iFanin]->M[fComplF][1].F; + if ( AreaF >= (float)1e32 || pBestF[iFanin]->M[fComplF][1].F >= (float)1e32 ) + AreaF = (float)1e32; + else + AreaF += pBestF[iFanin]->M[fComplF][1].F; } else { From b7bf6c20b60ab6f218ce1a722054894a09ac2d48 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 11 Feb 2025 17:32:19 -0800 Subject: [PATCH 086/133] Improvements to LUT cascade mapping. --- src/base/abci/abc.c | 7 +- src/base/abci/abcCas.c | 18 ++- src/misc/util/utilBSet.c | 252 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 267 insertions(+), 10 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index dcfa8a501..ff1fa79fd 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -8905,6 +8905,7 @@ usage: int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; int c, nLutSize = 6, nLuts = 8, nRails = 1, nIters = 1, fVerbose = 0; Extra_UtilGetoptReset(); @@ -8987,7 +8988,7 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_NtkCiNum(pNtk), nRails, nLuts, nLutSize, nLutSize + (nLutSize - nRails) * (nLuts - 1) ); return 1; } - pNtkRes = Abc_NtkLutCascade( pNtk, nLutSize, nLuts, nRails, nIters, fVerbose ); + pNtkRes = Abc_NtkLutCascade2( pNtk, nLutSize, nLuts, nRails, nIters, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "LUT cascade mapping failed.\n" ); @@ -8997,8 +8998,8 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutcas [-KNRI ] [-vh]\n" ); - Abc_Print( -2, "\t derives single-rail LUT cascade for the primary output function\n" ); + Abc_Print( -2, "usage: lutcasdec [-KNRI ] [-vh]\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-N : the number of LUTs in the cascade [default = %d]\n", nLuts ); Abc_Print( -2, "\t-R : the number of direct connections (rails) [default = %d]\n", nRails ); diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index 7fea2b54a..c48e95c73 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -255,17 +255,29 @@ Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nR { 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 nLuts, int nRails, int nIters, int fVerbose ); Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk ); Mini_Aig_t * pM = Gia_ManToMiniAig( pGia ); - word * pLuts = Abc_LutCascade( pM, nLutSize, nLuts, nRails, nIters, fVerbose ); - //word * pLuts = Abc_LutCascadeTest( pM, nLutSize, 0 ); + //word * pLuts = Abc_LutCascade( pM, nLutSize, nLuts, nRails, nIters, fVerbose ); + word * pLuts = Abc_LutCascadeTest( pM, nLutSize, 0 ); Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, pNtk, nLutSize, fVerbose ) : NULL; ABC_FREE( pLuts ); Mini_AigStop( pM ); Gia_ManStop( pGia ); return pNew; } +Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) +{ + extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk ); + extern word * Abc_LutCascade2( word * p, int nVars, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); + Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk ); + word * pTruth = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, 0) ); + word * pLuts = Abc_LutCascade2( pTruth, Gia_ManCiNum(pGia), nLutSize, nLuts, nRails, nIters, fVerbose ); + Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, pNtk, nLutSize, fVerbose ) : NULL; + ABC_FREE( pLuts ); + Gia_ManStop( pGia ); + return pNew; +} /**Function************************************************************* diff --git a/src/misc/util/utilBSet.c b/src/misc/util/utilBSet.c index 03faf51b7..e9b5e8912 100644 --- a/src/misc/util/utilBSet.c +++ b/src/misc/util/utilBSet.c @@ -27,6 +27,11 @@ #include "misc/extra/extra.h" #include "misc/util/utilTruth.h" +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +#endif + ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// @@ -43,6 +48,8 @@ struct Abc_BSEval_t_ Vec_Int_t * vTable; // hash table Vec_Int_t * vUsed; // used entries Vec_Wrd_t * vStore; // cofactors + Vec_Wec_t * vSets; // sets + Vec_Wrd_t * vCofs; // cofactors }; //////////////////////////////////////////////////////////////////////// @@ -334,14 +341,13 @@ int Abc_TtCheck1Shared( word * pPat, int nVars, int nFVars, int nMyu ) if ( fVerbose ) printf( "Not found\n" ); return nRails; } -int Abc_TtGetCMPat( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +int Abc_TtGetCMInt( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed, word * pPat ) { - word pPat[1024]; int nMintsBS = 1 << (nVars - nFVars); int nWordsBS = Abc_TtWordNum(nVars - nFVars); assert( nMintsBS * nWordsBS <= 1024 ); memset( pPat, 0, 8 * nMintsBS * nWordsBS ); - int nMyu = 0, nRails; + int nMyu = 0; if ( nFVars == 1 ) nMyu = Abc_TtGetCM1Pat( p, nVars, pPat ); else if ( nFVars == 2 ) @@ -355,6 +361,13 @@ int Abc_TtGetCMPat( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_In else if ( nFVars == 6 ) nMyu = Abc_TtGetCM6Pat( p, nVars, nFVars, vTable, vStore, vUsed, pPat ); else assert( 0 ); + return nMyu; +} + +int Abc_TtGetCMPat( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +{ + word pPat[1024]; + int nRails, nMyu = Abc_TtGetCMInt( p, nVars, nFVars, vCounts, vTable, vStore, vUsed, pPat ); if ( nMyu <= 2 ) nRails = 1; else @@ -553,6 +566,8 @@ void Abc_BSEvalFree( Abc_BSEval_t * p ) Vec_IntFree( p->vTable ); Vec_IntFree( p->vUsed ); Vec_WrdFree( p->vStore ); + Vec_WecFreeP( &p->vSets ); + Vec_WrdFreeP( &p->vCofs ); ABC_FREE( p ); } void Abc_BSEvalOneTest( word * pT, int nVars, int nBVars, int fVerbose ) @@ -588,7 +603,7 @@ int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int n if ( CostBest > CostThis ) { CostBest = CostThis; if ( pBest ) Abc_TtCopy( pBest, pIn, Abc_Truth6WordNum(nVars), 0 ); - if ( pPermBest ) memcpy( pPermBest, Pla2Var, sizeof(int)*nPermVars ); + if ( pPermBest ) memcpy( pPermBest, Pla2Var, sizeof(int)*nVars ); } if ( fVerbose ) { @@ -746,6 +761,235 @@ void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryA Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); } + +/**Function************************************************************* + + Synopsis [Finds shared variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Wrd_t * Vec_WrdStartTruthTables6( int nVars ) +{ + Vec_Wrd_t * p; + word Masks[6] = { + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00), + ABC_CONST(0xFFFF0000FFFF0000), + ABC_CONST(0xFFFFFFFF00000000) + }; + int i, k, nWords = nVars <= 6 ? 1 : (1 << (nVars - 6)); + p = Vec_WrdStart( nWords * nVars ); + for ( i = 0; i < nVars; i++ ) + { + word * pTruth = p->pArray + nWords * i; + if ( i < 6 ) + { + for ( k = 0; k < nWords; k++ ) + pTruth[k] = Masks[i]; + } + else + { + for ( k = 0; k < nWords; k++ ) + if ( k & (1 << (i-6)) ) + pTruth[k] = ~(word)0; + else + pTruth[k] = 0; + } + } + return p; +} + +void Abc_BSEvalCreateCofs( int iSet, int nVars, Vec_Wrd_t * vCofs, Vec_Wrd_t * vElems ) +{ + int nWords = Abc_Truth6WordNum(nVars); + int m, i, nUsed = 0, pUsed[32], Start = Vec_WrdSize(vCofs); + for ( i = 0; i < nVars; i++ ) + if ( (iSet >> i) & 1 ) + pUsed[nUsed++] = i; + Vec_WrdFillExtra( vCofs, Start + nWords*(1 << nUsed), ~(word)0 ); + for ( m = 0; m < (1 << nUsed); m++ ) + { + word * pCof = Vec_WrdEntryP(vCofs, Start + m*nWords); + for ( i = 0; i < nUsed; i++ ) + Abc_TtAndSharp( pCof, pCof, Vec_WrdEntryP(vElems, nWords*pUsed[i]), nWords, ((m >> i) & 1) == 0 ); + } +} +Vec_Wrd_t * Abc_BSEvalCreateCofactorSets( int nVars, Vec_Wec_t ** pvSets ) +{ + Vec_Wrd_t * vElems = Vec_WrdStartTruthTables6( nVars ); + Vec_Wrd_t * vCofs = Vec_WrdAlloc( 1000 ); + Vec_Wec_t * vSets = Vec_WecStart( nVars+1 ); + int m, nMints = 1 << nVars; + for ( m = 0; m < nMints; m++ ) + { + int nOnes = __builtin_popcount(m); + Vec_WecPushTwo( vSets, nOnes, m, Vec_WrdSize(vCofs) ); + Abc_BSEvalCreateCofs( m, nVars, vCofs, vElems ); + } + Vec_WrdFree( vElems ); + *pvSets = vSets; + return vCofs; +} + +static inline int Abc_BSEvalCountUnique( word * pISets, int nISets, int nBSWords, word * pCof ) +{ + int i, Count = 0; + for ( i = 0; i < nISets; i++ ) + Count += Abc_TtIntersect(pISets + i*nBSWords, pCof, nBSWords, 0); + return Count; +} +static inline int Abc_BSEvalCountUniqueMax( word * pISets, int nISets, int nBSWords, word * pCofs, int nOnes, int nISetsMaxHave ) +{ + int m, nMints = (1 << nOnes), CountMax = 0; + assert( nOnes > 0 && nOnes < 5 ); + for ( m = 0; m < nMints; m++ ) + { + int Count = Abc_BSEvalCountUnique( pISets, nISets, nBSWords, pCofs + m * nBSWords ); + if ( Count > nISetsMaxHave ) + return 0; + CountMax = Abc_MaxInt( CountMax, Count ); + } + return CountMax; +} +int Abc_BSEvalFindShared( int nVars, word * pISets, int nISets, int nBSWords, Vec_Wec_t * vSets, Vec_Wrd_t * vCofs, int nSharedMax ) +{ + Vec_Int_t * vLevel; int i, k, iSet, iStart, nMinMyu = nISets, nMinRails = Abc_Base2Log(nISets), MinShared = 0, MinSet = -1; + Vec_WecForEachLevelStartStop( vSets, vLevel, i, 1, nSharedMax+1 ) { + Vec_IntForEachEntryDouble( vLevel, iSet, iStart, k ) { + int Count = Abc_BSEvalCountUniqueMax( pISets, nISets, nBSWords, Vec_WrdEntryP(vCofs, iStart), i, 1 << (nMinRails-1) ); + if ( Count == 0 ) + continue; + int CountRails = Abc_Base2Log(Count); + if ( nMinRails > CountRails || (nMinRails == CountRails && nMinMyu > Count && MinShared == i) ) { + nMinRails = CountRails; + nMinMyu = Count; + MinShared = i; + MinSet = iSet; + } + } + } + return (MinSet << 16) | nMinMyu; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SharedEvalBest( Abc_BSEval_t * p, word * pTruth, int nVars, int nCVars, int nFVars, int MyuMin, int nRails, int fVerbose, int * pSetShared, word * pPat ) +{ + int nBSWords = Abc_Truth6WordNum( nVars - nFVars ), CVarMask = Abc_InfoMask(nCVars) << (nVars - nFVars - nCVars); + int MyuCur, Myu = Abc_TtGetCMInt( pTruth, nVars, nFVars, p->vCounts, p->vTable, p->vStore, p->vUsed, pPat ); + int nRailsCur = Abc_Base2Log( Myu ); Vec_Int_t * vLevel; + assert( Myu == MyuMin && nRailsCur > nRails ); + int i, k, iSet, iStart, nSharedMax = nVars - nFVars - 1, nRailsMin = 100; + Vec_WecForEachLevelStartStop( p->vSets, vLevel, i, 1, nSharedMax+1 ) { + Vec_IntForEachEntryDouble( vLevel, iSet, iStart, k ) { + if ( iSet & CVarMask ) + continue; + MyuCur = Abc_BSEvalCountUniqueMax( pPat, Myu, nBSWords, Vec_WrdEntryP(p->vCofs, iStart), i, 1 << nRails ); + if ( MyuCur == 0 ) + continue; + nRailsCur = Abc_Base2Log(MyuCur); + if ( nRailsCur > nRails ) + continue; + if ( nRailsMin > nRailsCur ) { + nRailsMin = nRailsCur; + *pSetShared = iSet; + } + } + if ( nRailsMin <= nRails ) + break; + } + return nRailsMin; +} +int Abc_DeriveLutDec( word * pTruth, int nVars, int nCVars, int nFVars, int * pPerm, int nRails, int Shared, int fVerbose, Vec_Wrd_t * vRes ) +{ + return 0; +} + +/**Function************************************************************* + + Synopsis [Decomposing truth table into a K-LUT cascade with R rails.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word * Abc_LutCascade2( word * pFunc, int nVars, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) +{ + Abc_BSEval_t * p = Abc_BSEvalAlloc(); + Vec_Wrd_t * vRes = Vec_WrdStart( 1 ); word * pRes = NULL; + word * pTruth = ABC_ALLOC( word, Abc_TtWordNum(nVars) ); + word * pBest = ABC_ALLOC( word, Abc_TtWordNum(nVars) ); + Abc_TtCopy( pTruth, pFunc, Abc_TtWordNum(nVars), 0 ); + int i, nVarsCur = nVars, nOutVars = 0; word pPat[1024]; + while ( nVarsCur > nLutSize ) + { + int pPerm[32] = {0}; + if ( p->nVars != nVarsCur || p->nBVars != nLutSize ) { + Vec_IntFreeP( &p->vPairs ); + if ( p->nBVars != nLutSize ) { + Vec_WecFreeP( &p->vSets ); + Vec_WrdFreeP( &p->vCofs ); + p->vCofs = Abc_BSEvalCreateCofactorSets( nLutSize, &p->vSets ); + } + p->vPairs = Abc_GenChasePairs( nVarsCur, nLutSize ); + p->nVars = nVarsCur; + p->nBVars = nLutSize; + } + int MyuMin = Abc_BSEvalBest( p, pTruth, pBest, nVarsCur, nOutVars, nVarsCur-nLutSize, fVerbose, pPerm, 0 ); + int Shared = 0, nRailsMin = Abc_Base2Log( MyuMin ); + if ( nRailsMin > nRails ) + nRailsMin = Abc_SharedEvalBest( p, pBest, nVarsCur, nOutVars, nVarsCur-nLutSize, MyuMin, nRails, fVerbose, &Shared, pPat ); + if ( nRailsMin > nRails ) { + Vec_WrdFreeP( &vRes ); + break; + } + // update nVarsCur, pTruth, nOutVars, and vRes + nVarsCur = Abc_DeriveLutDec( pBest, nVarsCur, nOutVars, nVarsCur-nLutSize, pPerm, nRailsMin, Shared, fVerbose, vRes ); + Abc_TtCopy( pTruth, pBest, Abc_TtWordNum(nVarsCur), 0 ); + nOutVars = nRailsMin; + } + if ( vRes ) // decomposition succeeded + { + // create the last node + assert( nVarsCur <= nLutSize ); + Vec_WrdAddToEntry( vRes, 0, 1 ); + Vec_WrdPush( vRes, nVarsCur+4 ); + Vec_WrdPush( vRes, nVarsCur ); + for ( i = 0; i < nVarsCur; i++ ) + Vec_WrdPush( vRes, i ); + Vec_WrdPush( vRes, 0 ); + Vec_WrdPush( vRes, pTruth[0] ); + // extract the output array + pRes = Vec_WrdReleaseArray( vRes ); + Vec_WrdFree( vRes ); + } + // cleanup and return + Abc_BSEvalFree(p); + ABC_FREE( pTruth ); + ABC_FREE( pBest ); + return pRes; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// From 6e3b38c7d382602a7cfb44e8d0b7d127b9f3f141 Mon Sep 17 00:00:00 2001 From: MyskYko Date: Wed, 12 Feb 2025 03:49:32 -0800 Subject: [PATCH 087/133] add rrr --- src/aig/gia/gia.h | 3 + src/aig/gia/giaRrr.cpp | 31 + src/aig/gia/module.make | 3 +- src/base/abci/abc.c | 128 ++++ src/opt/rrr/rrr.h | 37 + src/opt/rrr/rrrAbc.h | 80 +++ src/opt/rrr/rrrAnalyzer.h | 105 +++ src/opt/rrr/rrrAndNetwork.h | 1132 ++++++++++++++++++++++++++++++ src/opt/rrr/rrrBddAnalyzer.h | 667 ++++++++++++++++++ src/opt/rrr/rrrBddMspfAnalyzer.h | 761 ++++++++++++++++++++ src/opt/rrr/rrrOptimizer.h | 869 +++++++++++++++++++++++ src/opt/rrr/rrrParameter.h | 26 + src/opt/rrr/rrrSatSolver.h | 546 ++++++++++++++ src/opt/rrr/rrrScheduler.h | 232 ++++++ src/opt/rrr/rrrSimulator.h | 812 +++++++++++++++++++++ src/opt/rrr/rrrTypes.h | 207 ++++++ 16 files changed, 5638 insertions(+), 1 deletion(-) create mode 100644 src/aig/gia/giaRrr.cpp create mode 100644 src/opt/rrr/rrr.h create mode 100644 src/opt/rrr/rrrAbc.h create mode 100644 src/opt/rrr/rrrAnalyzer.h create mode 100644 src/opt/rrr/rrrAndNetwork.h create mode 100644 src/opt/rrr/rrrBddAnalyzer.h create mode 100644 src/opt/rrr/rrrBddMspfAnalyzer.h create mode 100644 src/opt/rrr/rrrOptimizer.h create mode 100644 src/opt/rrr/rrrParameter.h create mode 100644 src/opt/rrr/rrrSatSolver.h create mode 100644 src/opt/rrr/rrrScheduler.h create mode 100644 src/opt/rrr/rrrSimulator.h create mode 100644 src/opt/rrr/rrrTypes.h diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 015a1da22..09e892160 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1806,6 +1806,9 @@ extern Gia_Man_t * Gia_ManTtoptCare( Gia_Man_t * p, int nIns, int nOuts, extern Gia_Man_t * Gia_ManTransductionBdd( Gia_Man_t * pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t * pExdc, int fNewLine, int nVerbose ); extern Gia_Man_t * Gia_ManTransductionTt( Gia_Man_t * pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t * pExdc, int fNewLine, int nVerbose ); +/*=== giaRrr.cpp ===========================================================*/ +extern Gia_Man_t * Gia_ManRrr( Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int nSchedulerVerbose, int nOptimizerVerbose, int nAnalyzerVerbose, int nSimulatorVerbose, int nSatSolverVerbose, int fUseBddCspf, int fUseBddMspf, int nConflictLimit, int nSortType, int nOptimizerFlow, int nSchedulerFlow ); + /*=== giaCTas.c ===========================================================*/ typedef struct Tas_Man_t_ Tas_Man_t; extern Tas_Man_t * Tas_ManAlloc( Gia_Man_t * pAig, int nBTLimit ); diff --git a/src/aig/gia/giaRrr.cpp b/src/aig/gia/giaRrr.cpp new file mode 100644 index 000000000..21e343337 --- /dev/null +++ b/src/aig/gia/giaRrr.cpp @@ -0,0 +1,31 @@ +#include "aig/gia/gia.h" + +#include "opt/rrr/rrr.h" +#include "opt/rrr/rrrAbc.h" + +ABC_NAMESPACE_IMPL_START + +Gia_Man_t *Gia_ManRrr(Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int nSchedulerVerbose, int nOptimizerVerbose, int nAnalyzerVerbose, int nSimulatorVerbose, int nSatSolverVerbose, int fUseBddCspf, int fUseBddMspf, int nConflictLimit, int nSortType, int nOptimizerFlow, int nSchedulerFlow) { + rrr::AndNetwork ntk; + ntk.Read(pGia, rrr::GiaReader); + rrr::Parameter Par; + Par.iSeed = iSeed; + Par.nWords = nWords; + Par.nTimeout = nTimeout; + Par.nSchedulerVerbose = nSchedulerVerbose; + Par.nOptimizerVerbose = nOptimizerVerbose; + Par.nAnalyzerVerbose = nAnalyzerVerbose; + Par.nSimulatorVerbose = nSimulatorVerbose; + Par.nSatSolverVerbose = nSatSolverVerbose; + Par.fUseBddCspf = fUseBddCspf; + Par.fUseBddMspf = fUseBddMspf; + Par.nConflictLimit = nConflictLimit; + Par.nSortType = nSortType; + Par.nOptimizerFlow = nOptimizerFlow; + Par.nSchedulerFlow = nSchedulerFlow; + rrr::Perform(&ntk, &Par); + Gia_Man_t *pNew = rrr::CreateGia(&ntk); + return pNew; +} + +ABC_NAMESPACE_IMPL_END diff --git a/src/aig/gia/module.make b/src/aig/gia/module.make index 27240f443..2e64d1d1b 100644 --- a/src/aig/gia/module.make +++ b/src/aig/gia/module.make @@ -73,6 +73,7 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaResub6.c \ src/aig/gia/giaRetime.c \ src/aig/gia/giaRex.c \ + src/aig/gia/giaRrr.cpp \ src/aig/gia/giaSatEdge.c \ src/aig/gia/giaSatLE.c \ src/aig/gia/giaSatLut.c \ @@ -111,4 +112,4 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaTtopt.cpp \ src/aig/gia/giaUnate.c \ src/aig/gia/giaUtil.c \ - src/aig/gia/giaBound.c \ No newline at end of file + src/aig/gia/giaBound.c diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index dcfa8a501..633679184 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -521,6 +521,7 @@ static int Abc_CommandAbc9LNetOpt ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Ttopt ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Transduction ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9TranStoch ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Rrr ( Abc_Frame_t * pAbc, int argc, char ** argv ); //#endif static int Abc_CommandAbc9LNetMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Unmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1323,6 +1324,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&ttopt", Abc_CommandAbc9Ttopt, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&transduction", Abc_CommandAbc9Transduction, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&transtoch" , Abc_CommandAbc9TranStoch, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&rrr", Abc_CommandAbc9Rrr, 0 ); //#endif Cmd_CommandAdd( pAbc, "ABC9", "&lnetmap", Abc_CommandAbc9LNetMap, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&unmap", Abc_CommandAbc9Unmap, 0 ); @@ -45111,6 +45113,132 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +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, nOptimizerVerbose = 0, nAnalyzerVerbose = 0, nSimulatorVerbose = 0, nSatSolverVerbose = 0, fUseBddCspf = 0, fUseBddMspf = 0, nConflictLimit = 0, nSortType = 0, nOptimizerFlow = 0, nSchedulerFlow = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "XYRWTCGSOAPQabh" ) ) != EOF ) + { + switch ( c ) + { + case 'X': + nOptimizerFlow = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'Y': + nSchedulerFlow = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'R': + iSeed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'W': + nWords = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'T': + nTimeout = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'C': + nConflictLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'G': + nSortType = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'S': + nSchedulerVerbose = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'O': + nOptimizerVerbose = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'A': + nAnalyzerVerbose = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'P': + nSimulatorVerbose = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'Q': + nSatSolverVerbose = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'a': + fUseBddCspf ^= 1; + break; + case 'b': + fUseBddMspf ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc > globalUtilOptind ) { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + + pNew = Gia_ManRrr( pAbc->pGia, iSeed, nWords, nTimeout, nSchedulerVerbose, nOptimizerVerbose, nAnalyzerVerbose, nSimulatorVerbose, nSatSolverVerbose, fUseBddCspf, fUseBddMspf, nConflictLimit, nSortType, nOptimizerFlow, nSchedulerFlow ); + + Abc_FrameUpdateGia( pAbc, pNew ); + + return 0; + +usage: + Abc_Print( -2, "usage: rrr [-XYRWTCGSOAPQ num] [-abh]\n" ); + Abc_Print( -2, "\t perform optimization\n" ); + Abc_Print( -2, "\t-X num : method [default = %d]\n", nOptimizerFlow ); + Abc_Print( -2, "\t 0: single-add resub\n" ); + Abc_Print( -2, "\t 1: multi-add resub\n" ); + Abc_Print( -2, "\t 2: repeat 0 and 1\n" ); + Abc_Print( -2, "\t-Y num : flow [default = %d]\n", nSchedulerFlow ); + Abc_Print( -2, "\t 0: apply method once\n" ); + Abc_Print( -2, "\t 1: iterate like transtoch\n" ); + Abc_Print( -2, "\t 2: iterate like deepsyn\n" ); + 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 ); + Abc_Print( -2, "\t-C num : conflict limit [default = %d]\n", nConflictLimit ); + Abc_Print( -2, "\t-G num : fanin cost function [default = %d]\n", nSortType ); + Abc_Print( -2, "\t-S num : scheduler verbosity level [default = %d]\n", nSchedulerVerbose ); + Abc_Print( -2, "\t-O num : optimizer verbosity level [default = %d]\n", nOptimizerVerbose ); + Abc_Print( -2, "\t-A num : analyzer verbosity level [default = %d]\n", nAnalyzerVerbose ); + Abc_Print( -2, "\t-P num : simulator verbosity level [default = %d]\n", nSimulatorVerbose ); + Abc_Print( -2, "\t-Q num : SAT solver verbosity level [default = %d]\n", nSatSolverVerbose ); + 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-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/opt/rrr/rrr.h b/src/opt/rrr/rrr.h new file mode 100644 index 000000000..d306da3af --- /dev/null +++ b/src/opt/rrr/rrr.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +#include "rrrParameter.h" +#include "rrrTypes.h" +#include "rrrAndNetwork.h" +#include "rrrScheduler.h" +#include "rrrOptimizer.h" +#include "rrrAnalyzer.h" +#include "rrrBddAnalyzer.h" +#include "rrrBddMspfAnalyzer.h" +#include "rrrSatSolver.h" +#include "rrrSimulator.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace rrr { + + template + void Perform(Ntk *pNtk, Parameter const *pPar) { + assert(!pPar->fUseBddCspf || !pPar->fUseBddMspf); + if(pPar->fUseBddCspf) { + Scheduler>> sch(pNtk, pPar); + sch.Run(); + } else if(pPar->fUseBddMspf) { + Scheduler>> sch(pNtk, pPar); + sch.Run(); + } else { + Scheduler, rrr::SatSolver>>> sch(pNtk, pPar); + sch.Run(); + } + } + +} + +ABC_NAMESPACE_CXX_HEADER_END diff --git a/src/opt/rrr/rrrAbc.h b/src/opt/rrr/rrrAbc.h new file mode 100644 index 000000000..5fc2e1ff5 --- /dev/null +++ b/src/opt/rrr/rrrAbc.h @@ -0,0 +1,80 @@ +#pragma once + +#include + +#include "aig/gia/gia.h" +#include "base/main/main.h" +#include "base/cmd/cmd.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace rrr { + + template + void GiaReader(Gia_Man_t *pGia, Ntk *pNtk) { + int i; + Gia_Obj_t *pObj; + pNtk->Reserve(Gia_ManObjNum(pGia)); + Gia_ManConst0(pGia)->Value = pNtk->GetConst0(); + Gia_ManForEachObj1(pGia, pObj, i) { + if(Gia_ObjIsCi(pObj)) { + pObj->Value = pNtk->AddPi(); + } else if(Gia_ObjIsCo(pObj)) { + pNtk->AddPo(Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj)); + } else { + // TODO: support XOR (and BUF and MUX?), maybe create another function + pObj->Value = pNtk->AddAnd(Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj)); + } + } + } + + template + Gia_Man_t *CreateGia(Ntk *pNtk) { + Gia_Man_t *pGia = Gia_ManStart(pNtk->GetNumNodes()); + Gia_ManHashStart(pGia); + std::vector v(pNtk->GetNumNodes()); + v[0] = Gia_ManConst0Lit(); + pNtk->ForEachPi([&](int id) { + v[id] = Gia_ManAppendCi(pGia); + }); + pNtk->ForEachInt([&](int id) { + assert(pNtk->GetNodeType(id) == rrr::AND); + int x = -1; + pNtk->ForEachFanin(id, [&](int fi, bool c) { + if(x == -1) { + x = Abc_LitNotCond(v[fi], c); + } else { + x = Gia_ManHashAnd(pGia, x, Abc_LitNotCond(v[fi], c)); + } + }); + if(x == -1) { + x = Abc_LitNot(v[0]); + } + v[id] = x; + }); + pNtk->ForEachPoDriver([&](int fi, bool c) { + Gia_ManAppendCo(pGia, Abc_LitNotCond(v[fi], c)); + }); + Gia_ManHashStop(pGia); + return pGia; + } + + template + void Abc9Execute(Ntk *pNtk, std::string Command) { + Abc_Frame_t *pAbc = Abc_FrameGetGlobalFrame(); + Abc_FrameUpdateGia(pAbc, CreateGia(pNtk)); + if(Abc_FrameIsBatchMode()) { + int r = Cmd_CommandExecute(pAbc, Command.c_str()); + assert(r == 0); + } else { + Abc_FrameSetBatchMode(1); + int r = Cmd_CommandExecute(pAbc, Command.c_str()); + assert(r == 0); + Abc_FrameSetBatchMode(0); + } + pNtk->Read(Abc_FrameReadGia(pAbc), GiaReader); + } + +} + +ABC_NAMESPACE_CXX_HEADER_END diff --git a/src/opt/rrr/rrrAnalyzer.h b/src/opt/rrr/rrrAnalyzer.h new file mode 100644 index 000000000..a01d811c7 --- /dev/null +++ b/src/opt/rrr/rrrAnalyzer.h @@ -0,0 +1,105 @@ +#pragma once + +#include + +#include "rrrParameter.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace rrr { + + template + class Analyzer { + private: + // pointer to network + Ntk *pNtk; + + // parameters + bool nVerbose; + + // data + Sim sim; + Sol sol; + + public: + // constructors + Analyzer(Ntk *pNtk, Parameter const *pPar); + void UpdateNetwork(Ntk *pNtk_, bool fSame); + + // checks + bool CheckRedundancy(int id, int idx); + bool CheckFeasibility(int id, int fi, bool c); + }; + + /* {{{ Constructors */ + + template + Analyzer::Analyzer(Ntk *pNtk, Parameter const *pPar) : + pNtk(pNtk), + nVerbose(pPar->nAnalyzerVerbose), + sim(pNtk, pPar), + sol(pNtk, pPar) { + } + + template + void Analyzer::UpdateNetwork(Ntk *pNtk_, bool fSame) { + pNtk = pNtk_; + sim.UpdateNetwork(pNtk, fSame); + sol.UpdateNetwork(pNtk, fSame); + } + + /* }}} */ + + /* {{{ Checks */ + + template + bool Analyzer::CheckRedundancy(int id, int idx) { + if(sim.CheckRedundancy(id, idx)) { + if(nVerbose) { + std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " seems redundant" << std::endl; + } + SatResult r = sol.CheckRedundancy(id, idx); + if(r == UNSAT) { + if(nVerbose) { + std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is redundant" << std::endl; + } + return true; + } + if(r == SAT) { + if(nVerbose) { + std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is NOT redundant" << std::endl; + } + sim.AddCex(sol.GetCex()); + } + } + return false; + } + + template + bool Analyzer::CheckFeasibility(int id, int fi, bool c) { + if(sim.CheckFeasibility(id, fi, c)) { + if(nVerbose) { + std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " seems feasible" << std::endl; + } + SatResult r = sol.CheckFeasibility(id, fi, c); + if(r == UNSAT) { + if(nVerbose) { + std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is feasible" << std::endl; + } + return true; + } + if(r == SAT) { + if(nVerbose) { + std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is NOT feasible" << std::endl; + } + sim.AddCex(sol.GetCex()); + } + } + return false; + } + + /* }}} */ + +} + +ABC_NAMESPACE_CXX_HEADER_END diff --git a/src/opt/rrr/rrrAndNetwork.h b/src/opt/rrr/rrrAndNetwork.h new file mode 100644 index 000000000..01a3b1412 --- /dev/null +++ b/src/opt/rrr/rrrAndNetwork.h @@ -0,0 +1,1132 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rrrParameter.h" +#include "rrrTypes.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace rrr { + + class AndNetwork { + private: + // aliases + using itr = std::list::iterator; + using citr = std::list::const_iterator; + using ritr = std::list::reverse_iterator; + using critr = std::list::const_reverse_iterator; + using Callback = std::function; + + // network data + int nNodes; // number of allocated nodes + std::vector vPis; + std::list lInts; // internal nodes in topological order + std::set sInts; // internal nodes as a set + std::vector vPos; + std::vector> vvFaninEdges; // complementable edges, no duplicated fanins allowed (including complements), and nodes without fanins are treated as const-1 + std::vector vRefs; // reference count (number of fanouts) + + // mark for network traversal + bool fLockTrav; + unsigned iTrav; + std::vector vTrav; + + // flag used during constant propagation + bool fPropagating; + + // callback functions + std::vector vCallbacks; + + // network backups + std::vector vBackups; + + // conversion between node and edge + int Node2Edge(int id, bool c) const { return (id << 1) + (int)c; } + int Edge2Node(int f) const { return f >> 1; } + bool EdgeIsCompl(int f) const { return f & 1; } + + // other private functions + int CreateNode(); + void SortInts(itr it); + void StartTraversal(); + void EndTraversal(); + void TakenAction(Action const &action) const; + + public: + // constructors + AndNetwork(); + AndNetwork(AndNetwork const &x); + AndNetwork &operator=(AndNetwork const &x); + + // initialization APIs (should not be called after optimization has started) + void Clear(); + void Reserve(int nReserve); + int AddPi(); + int AddPo(int id, bool c); + int AddAnd(int id0, int id1, bool c0, bool c1); + template + void Read(Ntk *pFrom, std::function const &Reader); + + // network properties + bool UseComplementedEdges() const; + int GetNumNodes() const; // number of allocated nodes (max id + 1) + int GetNumPis() const; + int GetNumInts() const; + int GetNumPos() const; + int GetConst0() const; + int GetPi(int idx) const; + std::vector GetPis() const; + std::vector GetInts() const; + std::vector GetPisInts() const; + std::vector GetPos() const; + + // node properties + bool IsPi(int id) const; + bool IsInt(int id) const; + bool IsPo(int id) const; + NodeType GetNodeType(int id) const; + bool IsPoDriver(int id) const; + int GetPiIndex(int id) const; + int GetIntIndex(int id) const; + int GetPoIndex(int id) const; + int GetNumFanins(int id) const; + int GetNumFanouts(int id) const; + int GetFanin(int id, int idx) const; + bool GetCompl(int id, int idx) const; + int FindFanin(int id, int fi) const; + bool IsReconvergent(int id); + + // network traversal + void ForEachPi(std::function const &func) const; + void ForEachInt(std::function const &func) const; + void ForEachIntReverse(std::function const &func) const; + void ForEachPo(std::function const &func) const; + void ForEachPoDriver(std::function const &func) const; + void ForEachFanin(int id, std::function const &func) const; + void ForEachFaninIdx(int id, std::function const &func) const; // func(fi, c, index of fi in fanin list of id) + void ForEachFanout(int id, bool fPos, std::function const &func) const; + void ForEachFanoutRidx(int id, bool fPos, std::function const &func) const; // func(fo, c, index of id in fanin list of fo) + void ForEachTfo(int id, bool fPos, std::function const &func); + void ForEachTfoReverse(int id, bool fPos, std::function const &func); + void ForEachTfoUpdate(int id, bool fPos, std::function const &func); + template