From 864f96b11e32c7b3c4d83fa03e90e692aeee0ad1 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 16 Apr 2024 17:40:47 +0200 Subject: [PATCH 1/5] Adding decomposition of mapping into LUT structures before returning the result --- src/base/abci/abc.c | 13 ++++++++++-- src/base/abci/abcIf.c | 10 ++++++--- src/map/if/acd/ac_wrapper.cpp | 40 +++++++++++++++++++++-------------- src/map/if/acd/ac_wrapper.h | 1 + src/map/if/acd/acdXX.hpp | 5 ++++- src/map/if/if.h | 1 + src/map/if/ifDec66.c | 2 +- 7 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 7c3201a1a..0cbdf1989 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -19541,7 +19541,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) If_ManSetDefaultPars( pPars ); pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYUZDEWSJqaflepmrsdbgxyuojiktncvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYUZDEWSJqaflepmrsdbgxyzuojiktncvh" ) ) != EOF ) { switch ( c ) { @@ -19812,6 +19812,9 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'v': pPars->fVerbose ^= 1; break; + case 'z': + pPars->fReturnDec ^= 1; + break; case 'h': default: goto usage; @@ -19929,6 +19932,11 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16; } pPars->fCutMin = 1; + pPars->nLutDecSize = pPars->pLutStruct[0] - '0'; + } + else + { + pPars->fReturnDec = 0; } if ( pPars->fUserLutDec || pPars->fUserLut2D ) @@ -20112,7 +20120,7 @@ usage: sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: if [-KCFAGRNTXYUZ num] [-DEW float] [-SJ str] [-qarlepmsdbgxyuojiktncvh]\n" ); + Abc_Print( -2, "usage: if [-KCFAGRNTXYUZ num] [-DEW float] [-SJ str] [-qarlepmsdbgxyuojiktnczvh]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -20152,6 +20160,7 @@ usage: Abc_Print( -2, "\t-t : toggles optimizing average rather than maximum level [default = %s]\n", pPars->fDoAverage? "yes": "no" ); Abc_Print( -2, "\t-n : toggles computing DSDs of the cut functions [default = %s]\n", pPars->fUseDsd? "yes": "no" ); Abc_Print( -2, "\t-c : toggles computing truth tables in a new way [default = %s]\n", pPars->fUseTtPerm? "yes": "no" ); + Abc_Print( -2, "\t-z : toggles decomposing LUT structure on the final network [default = %s]\n", pPars->fReturnDec? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index 8c4ac1448..db0da36f9 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -465,10 +465,14 @@ void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCut { val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); } - else + else if ( pIfMan->pPars->fUserLut2D ) { val = acd2_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); } + else + { + val = acdXX_decompose( pTruth, pIfMan->pPars->nLutDecSize, pCutBest->nLeaves, decompArray ); + } assert( val == 0 ); // convert the LUT-structure into a set of logic nodes in Abc_Ntk_t @@ -593,7 +597,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i ) Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); } - else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D ) + else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D || pIfMan->pPars->fReturnDec ) { If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover); @@ -651,7 +655,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj ); } - else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D ) + else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D || pIfMan->pPars->fReturnDec ) { extern void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vMemory, Abc_Obj_t * pNodeTop ); Abc_DecRecordToHop( pNtkNew, pIfMan, pCutBest, pIfObj, vCover, pNodeNew ); diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index ad923edd2..ed512961f 100644 --- a/src/map/if/acd/ac_wrapper.cpp +++ b/src/map/if/acd/ac_wrapper.cpp @@ -118,32 +118,25 @@ int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay return 0; } -inline int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition ) +inline int acd66_evaluate( word * pTruth, unsigned nVars ) { using namespace acd; + acd66_impl acd( nVars, true, false ); if ( acd.run( pTruth ) == 0 ) return 0; - if ( decomposition == NULL ) - return 1; - int val = acd.compute_decomposition(); - if ( val != 0 ) - { - return 0; - } - acd.get_decomposition( decomposition ); return 1; } -int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition ) +int acdXX_evaluate( word * pTruth, unsigned lutSize, unsigned nVars ) { using namespace acd; if ( lutSize == 6 ) { - return acd66_decompose( pTruth, nVars, decomposition ); + return acd66_evaluate( pTruth, nVars ); } acdXX_params ps; @@ -153,14 +146,29 @@ int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned c if ( acd.run( pTruth ) == 0 ) return 0; - if ( decomposition == NULL ) - return 1; - int val = acd.compute_decomposition(); - if ( val != 0 ) + + return 1; +} + +int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition ) +{ + using namespace acd; + + acdXX_params ps; + ps.lut_size = lutSize; + + for ( int i = 0; i <= lutSize - 2; ++i ) { + ps.max_shared_vars = i; + ps.min_shared_vars = i; + acdXX_impl acd( nVars, ps ); + + if ( acd.run( pTruth ) == 0 ) + continue; + acd.compute_decomposition(); + acd.get_decomposition( decomposition ); return 0; } - acd.get_decomposition( decomposition ); return 1; } diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h index edb45ca7f..47c9afe45 100644 --- a/src/map/if/acd/ac_wrapper.h +++ b/src/map/if/acd/ac_wrapper.h @@ -37,6 +37,7 @@ int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, int acd2_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); +int acdXX_evaluate( word * pTruth, unsigned lutSize, unsigned nVars ); int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition ); ABC_NAMESPACE_HEADER_END diff --git a/src/map/if/acd/acdXX.hpp b/src/map/if/acd/acdXX.hpp index e43404ea9..e57199ce7 100644 --- a/src/map/if/acd/acdXX.hpp +++ b/src/map/if/acd/acdXX.hpp @@ -52,6 +52,9 @@ struct acdXX_params /* Maximum number of variables in the shared set */ uint32_t max_shared_vars{ 4 }; + /* Minimum number of variables in the shared set */ + uint32_t min_shared_vars{ 0 }; + /* Run verification */ bool verify{ false }; }; @@ -795,7 +798,7 @@ private: uint32_t max_shared_vars = std::min( ps.lut_size - best_free_set - 1, ps.max_shared_vars ); /* search for a feasible shared set */ - for ( uint32_t i = target_num_ss; i <= max_shared_vars; ++i ) + for ( uint32_t i = std::max( target_num_ss, ps.min_shared_vars ); i <= max_shared_vars; ++i ) { for ( uint32_t i = 0; i < 6; ++i ) { diff --git a/src/map/if/if.h b/src/map/if/if.h index 723fda780..2efe979d1 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -149,6 +149,7 @@ struct If_Par_t_ int fHashMapping; // perform AIG hashing after mapping int fUserLutDec; // perform Boolean decomposition during mapping int fUserLut2D; // perform Boolean decomposition during mapping + int fReturnDec; // perform Boolean decomposition during mapping int fVerbose; // the verbosity flag int fVerboseTrace; // the verbosity flag char * pLutStruct; // LUT structure diff --git a/src/map/if/ifDec66.c b/src/map/if/ifDec66.c index 9c486685c..df29f5292 100644 --- a/src/map/if/ifDec66.c +++ b/src/map/if/ifDec66.c @@ -267,7 +267,7 @@ int If_CluCheckXX( If_Man_t * p, word * pTruth0, int lutSize, int nVars, int fHa /* new entry */ if ( G1.nVars == 0 ) { - G1.nVars = acdXX_decompose( pTruth0, lutSize, nVars, NULL ); + G1.nVars = acdXX_evaluate( pTruth0, lutSize, nVars ); } if ( pHashed ) From 043a2ffcc66b478cf2db1347e711e86f9ecf17dc Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 23 Apr 2024 11:10:16 +0200 Subject: [PATCH 2/5] Adding new XX decomposition to &if --- src/aig/gia/giaIf.c | 23 +++++++++++--- src/base/abci/abc.c | 30 ++++++++++++++++-- src/map/if/if.h | 2 ++ src/map/if/ifDec66.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 8 deletions(-) diff --git a/src/aig/gia/giaIf.c b/src/aig/gia/giaIf.c index 7c5e706e8..558ff4517 100644 --- a/src/aig/gia/giaIf.c +++ b/src/aig/gia/giaIf.c @@ -1308,12 +1308,25 @@ int Gia_ManFromIfLogicNode( void * pIfMan, Gia_Man_t * pNew, int iObj, Vec_Int_t { if ( Length == 2 ) { - if ( !If_CluCheckExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) ) + if ( ((If_Man_t *)pIfMan)->pPars->fEnableStructN ) { - Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); - Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); - printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); - return -1; + if ( !If_CluCheckXXExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) ) + { + Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); + Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); + return -1; + } + } + else + { + if ( !If_CluCheckExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) ) + { + Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); + Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); + return -1; + } } } else diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 0cbdf1989..d2701d52d 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -40402,7 +40402,7 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) } pPars->pLutLib = (If_LibLut_t *)pAbc->pLibLut; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRDEWSTXYqalepmrsdbgxyofuijkztncvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRDEWSJTXYqalepmrsdbgxyofuijkztncvwh" ) ) != EOF ) { switch ( c ) { @@ -40554,6 +40554,21 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } break; + case 'J': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by string.\n" ); + goto usage; + } + pPars->pLutStruct = argv[globalUtilOptind]; + pPars->fEnableStructN = 1; + globalUtilOptind++; + if ( strlen(pPars->pLutStruct) != 2 ) + { + Abc_Print( -1, "Command line switch \"-J\" should be followed by a 2-char string (e.g. \"44\" or \"55\").\n" ); + goto usage; + } + break; case 'q': pPars->fPreprocess ^= 1; break; @@ -40788,8 +40803,16 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "This feature only works for [6;16]-LUTs.\n" ); return 1; } - pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16; + if ( pPars->fEnableStructN ) + { + pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheckXX; + } + else + { + pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16; + } pPars->fCutMin = 1; + pPars->nLutDecSize = pPars->pLutStruct[0] - '0'; } if ( pPars->fUse34Spec ) @@ -40934,7 +40957,7 @@ usage: sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: &if [-KCFAGRTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyofuijkztnchvw]\n" ); + Abc_Print( -2, "usage: &if [-KCFAGRTXY num] [-DEW float] [-SJ str] [-qarlepmsdbgxyofuijkztnchvw]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -40949,6 +40972,7 @@ usage: Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); Abc_Print( -2, "\t-W float : sets wire delay between adjects LUTs [default = %f]\n", pPars->WireDelay ); Abc_Print( -2, "\t-S str : string representing the LUT structure [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" ); + Abc_Print( -2, "\t-J str : string representing the LUT structure [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" ); Abc_Print( -2, "\t-q : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" ); Abc_Print( -2, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" ); diff --git a/src/map/if/if.h b/src/map/if/if.h index 2efe979d1..cb288e99b 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -564,6 +564,8 @@ extern int If_CluCheckExt( void * p, word * pTruth, int nVars, int n char * pLut0, char * pLut1, word * pFunc0, word * pFunc1 ); extern int If_CluCheckExt3( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutLeaf2, int nLutRoot, char * pLut0, char * pLut1, char * pLut2, word * pFunc0, word * pFunc1, word * pFunc2 ); +extern int If_CluCheckXXExt( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutRoot, + char * pLut0, char * pLut1, word * pFunc0, word * pFunc1 ); extern int If_MatchCheck1( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_MatchCheck2( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); /*=== ifDelay.c =============================================================*/ diff --git a/src/map/if/ifDec66.c b/src/map/if/ifDec66.c index df29f5292..7ded4ad18 100644 --- a/src/map/if/ifDec66.c +++ b/src/map/if/ifDec66.c @@ -104,6 +104,27 @@ static inline int If_CluWordNum2( int nVars ) return nVars <= 6 ? 1 : 1 << (nVars-6); } +static inline word If_CluAdjust2( word t, int nVars ) +{ + assert( nVars >= 0 && nVars <= 6 ); + if ( nVars == 6 ) + return t; + t &= (((word)1) << (1 << nVars)) - 1; + if ( nVars == 0 ) + t |= t << (1< Date: Thu, 2 May 2024 10:06:40 +0200 Subject: [PATCH 3/5] Cleaning code --- src/map/if/acd/ac_decomposition.hpp | 2 +- src/map/if/acd/kitty_operations.hpp | 1 - src/map/if/acd/kitty_operators.hpp | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index d8a44b1d5..803f9ce59 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -459,7 +459,7 @@ private: if ( free_set_size == offset ) { best_cost = fn( tt ); - return { tt, permutations, best_cost }; + return std::make_tuple( tt, permutations, best_cost ); } /* works up to 16 input truth tables */ diff --git a/src/map/if/acd/kitty_operations.hpp b/src/map/if/acd/kitty_operations.hpp index e0292bc05..f1893144c 100644 --- a/src/map/if/acd/kitty_operations.hpp +++ b/src/map/if/acd/kitty_operations.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "kitty_algorithm.hpp" diff --git a/src/map/if/acd/kitty_operators.hpp b/src/map/if/acd/kitty_operators.hpp index 7ccab7ca1..ded73b002 100644 --- a/src/map/if/acd/kitty_operators.hpp +++ b/src/map/if/acd/kitty_operators.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include "kitty_constants.hpp" #include "kitty_dynamic_tt.hpp" From 714ab458b7519e5d4d8c723eb6622937f8f3588b Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 2 May 2024 10:23:11 +0200 Subject: [PATCH 4/5] Adding deriving LUTs to if --- src/base/abci/abc.c | 6 +++--- src/base/abci/abcIf.c | 4 ++-- src/map/if/if.h | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index d2701d52d..5ff1f3fd1 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -19813,7 +19813,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fVerbose ^= 1; break; case 'z': - pPars->fReturnDec ^= 1; + pPars->fDeriveLuts ^= 1; break; case 'h': default: @@ -19936,7 +19936,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) } else { - pPars->fReturnDec = 0; + pPars->fDeriveLuts = 0; } if ( pPars->fUserLutDec || pPars->fUserLut2D ) @@ -20160,7 +20160,7 @@ usage: Abc_Print( -2, "\t-t : toggles optimizing average rather than maximum level [default = %s]\n", pPars->fDoAverage? "yes": "no" ); Abc_Print( -2, "\t-n : toggles computing DSDs of the cut functions [default = %s]\n", pPars->fUseDsd? "yes": "no" ); Abc_Print( -2, "\t-c : toggles computing truth tables in a new way [default = %s]\n", pPars->fUseTtPerm? "yes": "no" ); - Abc_Print( -2, "\t-z : toggles decomposing LUT structure on the final network [default = %s]\n", pPars->fReturnDec? "yes": "no" ); + Abc_Print( -2, "\t-z : toggles deriving LUTs when mapping into LUT structures [default = %s]\n", pPars->fDeriveLuts? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index db0da36f9..6c71c9ec2 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -597,7 +597,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i ) Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); } - else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D || pIfMan->pPars->fReturnDec ) + else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D || pIfMan->pPars->fDeriveLuts ) { If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover); @@ -655,7 +655,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj ); } - else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D || pIfMan->pPars->fReturnDec ) + else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D || pIfMan->pPars->fDeriveLuts ) { extern void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vMemory, Abc_Obj_t * pNodeTop ); Abc_DecRecordToHop( pNtkNew, pIfMan, pCutBest, pIfObj, vCover, pNodeNew ); diff --git a/src/map/if/if.h b/src/map/if/if.h index cb288e99b..136e61573 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -149,7 +149,6 @@ struct If_Par_t_ int fHashMapping; // perform AIG hashing after mapping int fUserLutDec; // perform Boolean decomposition during mapping int fUserLut2D; // perform Boolean decomposition during mapping - int fReturnDec; // perform Boolean decomposition during mapping int fVerbose; // the verbosity flag int fVerboseTrace; // the verbosity flag char * pLutStruct; // LUT structure From d109372fb77ef52a5fdeb5e85f2b2563b5877df5 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 7 May 2024 11:03:24 +0200 Subject: [PATCH 5/5] Adding delay-driven LUT decomposition to &if --- src/aig/gia/giaIf.c | 90 ++++++++++++++++++++++++++++++++++++++++++++- src/base/abci/abc.c | 36 +++++++++++++++++- 2 files changed, 123 insertions(+), 3 deletions(-) diff --git a/src/aig/gia/giaIf.c b/src/aig/gia/giaIf.c index 558ff4517..8b29e79c0 100644 --- a/src/aig/gia/giaIf.c +++ b/src/aig/gia/giaIf.c @@ -1424,6 +1424,90 @@ int Gia_ManFromIfLogicNode( void * pIfMan, Gia_Man_t * pNew, int iObj, Vec_Int_t return iObjLit3; } +/**Function************************************************************* + + Synopsis [Implements delay-driven decomposition of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFromIfLogicHop( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 ) +{ + word * pTruth = If_CutTruthW(pIfMan, pCutBest); + unsigned char decompArray[92]; + int val; + + assert( pCutBest->nLeaves > pIfMan->pPars->nLutDecSize ); + + unsigned delayProfile = pCutBest->decDelay; + val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); + assert( val == 0 ); + + // convert the LUT-structure into a set of logic nodes in Gia_Man_t + unsigned char bytes_check = decompArray[0]; + assert( bytes_check <= 92 ); + + int byte_p = 2; + unsigned char i, j, k, num_fanins, num_words, num_bytes; + int iObjLits[5]; + int fanin; + word *tt; + + for ( i = 0; i < decompArray[1]; ++i ) + { + num_fanins = decompArray[byte_p++]; + Vec_IntClear( vLeavesTemp ); + for ( j = 0; j < num_fanins; ++j ) + { + fanin = (int)decompArray[byte_p++]; + if ( fanin < If_CutLeaveNum(pCutBest) ) + { + Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, fanin) ); + } + else + { + Vec_IntPush( vLeavesTemp, iObjLits[fanin - If_CutLeaveNum(pCutBest)] ); + } + } + + /* extract the truth table */ + tt = pIfMan->puTempW; + num_words = ( num_fanins <= 6 ) ? 1 : ( 1 << ( num_fanins - 6 ) ); + num_bytes = ( num_fanins <= 3 ) ? 1 : ( 1 << ( Abc_MinInt( (int)num_fanins, 6 ) - 3 ) ); + for ( j = 0; j < num_words; ++j ) + { + tt[j] = 0; + for ( k = 0; k < num_bytes; ++k ) + { + tt[j] |= ( (word)(decompArray[byte_p++]) ) << ( k << 3 ); + } + } + + /* extend truth table if size < 5 */ + assert( num_fanins != 1 ); + if ( num_fanins == 2 ) + { + tt[0] |= tt[0] << 4; + } + while ( num_bytes < 4 ) + { + tt[0] |= tt[0] << ( num_bytes << 3 ); + num_bytes <<= 1; + } + + iObjLits[i] = Gia_ManFromIfLogicCreateLut( pNew, tt, vLeavesTemp, vCover, vMapping, vMapping2 ); + } + + /* check correct read */ + assert( byte_p == decompArray[0] ); + + return iObjLits[i-1]; +} + /**Function************************************************************* Synopsis [Recursively derives the local AIG for the cut.] @@ -1907,7 +1991,7 @@ Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan ) if ( !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize && !pIfMan->pPars->fEnableCheck75 && !pIfMan->pPars->fEnableCheck75u && !pIfMan->pPars->fEnableCheck07 && !pIfMan->pPars->fUseDsdTune && - !pIfMan->pPars->fUseCofVars && !pIfMan->pPars->fUseAndVars && !pIfMan->pPars->fUseCheck1 && !pIfMan->pPars->fUseCheck2 ) + !pIfMan->pPars->fUseCofVars && !pIfMan->pPars->fUseAndVars && !pIfMan->pPars->fUseCheck1 && !pIfMan->pPars->fUseCheck2 && !pIfMan->pPars->fUserLutDec ) If_CutRotatePins( pIfMan, pCutBest ); // collect leaves of the best cut Vec_IntClear( vLeaves ); @@ -1959,6 +2043,10 @@ Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan ) { pIfObj->iCopy = Gia_ManFromIfLogicCofVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); } + else if ( pIfMan->pPars->fUserLutDec && (int)pCutBest->nLeaves > pIfMan->pPars->nLutDecSize ) + { + pIfObj->iCopy = Gia_ManFromIfLogicHop( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); + } else if ( (pIfMan->pPars->fDeriveLuts && pIfMan->pPars->fTruth) || pIfMan->pPars->fUseDsd || pIfMan->pPars->fUseTtPerm || pIfMan->pPars->pFuncCell2 ) { word * pTruth = If_CutTruthW(pIfMan, pCutBest); diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index eb2b7480d..c173ca371 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -40412,7 +40412,7 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) } pPars->pLutLib = (If_LibLut_t *)pAbc->pLibLut; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRDEWSJTXYqalepmrsdbgxyofuijkztncvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRDEWSJTXYZqalepmrsdbgxyofuijkztncvwh" ) ) != EOF ) { switch ( c ) { @@ -40579,6 +40579,18 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } break; + case 'Z': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Z\" should be followed by a positive integer 3, 4, 5, or 6.\n" ); + goto usage; + } + pPars->nLutDecSize = atoi(argv[globalUtilOptind]); + pPars->fUserLutDec = 1; + globalUtilOptind++; + if ( pPars->nLutDecSize < 3 || pPars->nLutDecSize > 6 ) + goto usage; + break; case 'q': pPars->fPreprocess ^= 1; break; @@ -40825,6 +40837,25 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->nLutDecSize = pPars->pLutStruct[0] - '0'; } + if ( pPars->fUserLutDec ) + { + if ( pPars->nLutDecSize == 0 ) + { + Abc_Print( -1, "LUT decomposition size (%d) must be set.\n", pPars->nLutDecSize ); + return 1; + } + if ( pPars->nLutDecSize >= pPars->nLutSize ) + { + Abc_Print( -1, "LUT size (%d) must be greater than the LUT decomposition size (%d).\n", pPars->nLutSize, pPars->nLutDecSize ); + return 1; + } + if ( pPars->nLutSize < 4 || pPars->nLutSize > 11 ) + { + Abc_Print( -1, "This feature only works for [4;11]-LUTs.\n" ); + return 1; + } + } + if ( pPars->fUse34Spec ) { pPars->fTruth = 1; @@ -40850,7 +40881,7 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pLutLib = NULL; } // modify for delay optimization - if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut ) + if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fUserLutDec ) { pPars->fTruth = 1; pPars->fCutMin = 1; @@ -40983,6 +41014,7 @@ usage: Abc_Print( -2, "\t-W float : sets wire delay between adjects LUTs [default = %f]\n", pPars->WireDelay ); Abc_Print( -2, "\t-S str : string representing the LUT structure [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" ); Abc_Print( -2, "\t-J str : string representing the LUT structure [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" ); + Abc_Print( -2, "\t-Z num : the number of LUT inputs for delay-driven LUT decomposition [default = not used]\n" ); Abc_Print( -2, "\t-q : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" ); Abc_Print( -2, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" );