From d109372fb77ef52a5fdeb5e85f2b2563b5877df5 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 7 May 2024 11:03:24 +0200 Subject: [PATCH] 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" );