diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 36c8f698b..778e7f319 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -19514,7 +19514,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, "KCFAGRNTXYZDEWSJqaflepmrsdbgxyuojiktncvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYUZDEWSJqaflepmrsdbgxyuojiktncvh" ) ) != EOF ) { switch ( c ) { @@ -19630,6 +19630,18 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nAndDelay < 0 ) goto usage; break; + case 'U': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-U\" should be followed by a positive integer 3, 4, 5, or 6.\n" ); + goto usage; + } + pPars->nLutDecSize = atoi(argv[globalUtilOptind]); + pPars->fUserLut2D = 1; + globalUtilOptind++; + if ( pPars->nLutDecSize < 3 || pPars->nLutDecSize > 6 ) + goto usage; + break; case 'Z': if ( globalUtilOptind >= argc ) { @@ -19892,7 +19904,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fCutMin = 1; } - if ( pPars->fUserLutDec ) + if ( pPars->fUserLutDec || pPars->fUserLut2D ) { if ( pPars->nLutDecSize == 0 ) { @@ -19927,7 +19939,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pLutLib = NULL; } // modify for delay optimization - if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fUserLutDec ) + if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fUserLutDec || pPars->fUserLut2D ) { pPars->fTruth = 1; pPars->fCutMin = 1; @@ -20073,7 +20085,7 @@ usage: sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: if [-KCFAGRNTXYZ num] [-DEW float] [-S str] [-qarlepmsdbgxyuojiktncvh]\n" ); + Abc_Print( -2, "usage: if [-KCFAGRNTXYUZ num] [-DEW float] [-SJ str] [-qarlepmsdbgxyuojiktncvh]\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 ); @@ -20085,6 +20097,7 @@ usage: Abc_Print( -2, "\t-T num : the type of LUT structures [default = any]\n" ); Abc_Print( -2, "\t-X num : delay of AND-gate in LUT library units [default = %d]\n", pPars->nAndDelay ); Abc_Print( -2, "\t-Y num : area of AND-gate in LUT library units [default = %d]\n", pPars->nAndArea ); + Abc_Print( -2, "\t-U num : the number of LUT inputs for delay-driven LUT decomposition [default = not used]\n" ); Abc_Print( -2, "\t-Z num : the number of LUT inputs for delay-driven LUT decomposition [default = not used]\n" ); Abc_Print( -2, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index 357d7d83f..8c4ac1448 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -116,7 +116,7 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk); // update timing info to reflect logic level - if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fUserLutDec) && pNtk->pManTime ) + if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fUserLutDec || pPars->fUserLut2D ) && pNtk->pManTime ) { int c; if ( pNtk->AndGateDelay == 0.0 ) @@ -433,8 +433,8 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC SideEffects [] SeeAlso [] ***********************************************************************/ - void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, If_Obj_t * pIfObj, Vec_Int_t * vCover, Abc_Obj_t * pNodeTop ) - { +void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, If_Obj_t * pIfObj, Vec_Int_t * vCover, Abc_Obj_t * pNodeTop ) +{ extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); assert( !pIfMan->pPars->fUseTtPerm ); @@ -460,7 +460,15 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC // perform LUT-decomposition and return the LUT-structure unsigned char decompArray[92]; - int val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); + int val; + if ( pIfMan->pPars->fUserLutDec ) + { + val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); + } + else + { + val = acd2_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); + } assert( val == 0 ); // convert the LUT-structure into a set of logic nodes in Abc_Ntk_t @@ -473,7 +481,7 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC word *tt; Abc_Obj_t *pNewNodes[5]; - /* create intermediate LUTs*/ + /* create intermediate LUTs */ assert( decompArray[1] <= 6 ); Abc_Obj_t * pFanin; for ( i = 0; i < decompArray[1]; ++i ) @@ -537,7 +545,7 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC /* check correct read */ assert( byte_p == decompArray[0] ); - } +} /**Function************************************************************* @@ -577,14 +585,15 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t pNodeNew = Abc_NtkCreateNode( pNtkNew ); // if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays ) if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm && - !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserLutDec && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize ) + !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserLutDec && !pIfMan->pPars->fUserLut2D && !pIfMan->pPars->fUserRecLib && + !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize ) If_CutRotatePins( pIfMan, pCutBest ); if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) { If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i ) Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); } - else if ( pIfMan->pPars->fUserLutDec ) + else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D ) { If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover); @@ -642,7 +651,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 ) + else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D ) { 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 47fe109ca..723fda780 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -147,7 +147,8 @@ struct If_Par_t_ int fDeriveLuts; // enables deriving LUT structures int fDoAverage; // optimize average rather than maximum level int fHashMapping; // perform AIG hashing after mapping - int fUserLutDec; // perform AIG hashing after mapping + int fUserLutDec; // perform Boolean decomposition during mapping + int fUserLut2D; // perform Boolean decomposition during mapping int fVerbose; // the verbosity flag int fVerboseTrace; // the verbosity flag char * pLutStruct; // LUT structure @@ -573,6 +574,7 @@ extern int If_CutSopBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, extern int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ); extern int If_CutLutBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); extern int If_LutDecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ); +extern int If_Lut2DecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ); extern int If_LutDecReEval( If_Man_t * p, If_Cut_t * pCut ); extern float If_LutDecPinRequired( If_Man_t * p, If_Cut_t * pCut, int i, float required ); /*=== ifDsd.c =============================================================*/ @@ -704,6 +706,8 @@ extern void If_ObjPrint( If_Obj_t * pObj ); extern int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); extern int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); +extern int acd2_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); +extern int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); ABC_NAMESPACE_HEADER_END diff --git a/src/map/if/ifCore.c b/src/map/if/ifCore.c index f7fcbca66..eed6a55e8 100644 --- a/src/map/if/ifCore.c +++ b/src/map/if/ifCore.c @@ -63,6 +63,7 @@ void If_ManSetDefaultPars( If_Par_t * pPars ) pPars->fCutMin = 0; pPars->fBidec = 0; pPars->fUserLutDec = 0; + pPars->fUserLut2D = 0; pPars->fVerbose = 0; } diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c index 49850d313..c9354b339 100644 --- a/src/map/if/ifCut.c +++ b/src/map/if/ifCut.c @@ -761,7 +761,7 @@ void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut ) if ( !pCut->fUseless && (p->pPars->fUseDsd || p->pPars->pFuncCell2 || p->pPars->fUseBat || - p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || + p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fUserLut2D || p->pPars->fEnableCheck07 || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->fUseDsdTune || p->pPars->fEnableCheck75 || p->pPars->fEnableCheck75u || p->pPars->fUseCheck1 || p->pPars->fUseCheck2) ) { diff --git a/src/map/if/ifDelay.c b/src/map/if/ifDelay.c index 3514327c1..0f94de49a 100644 --- a/src/map/if/ifDelay.c +++ b/src/map/if/ifDelay.c @@ -505,6 +505,95 @@ int If_LutDecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, return DelayMax + val; } +int If_Lut2DecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ) +{ + pCut->fUser = 1; + pCut->Cost = pCut->nLeaves > 1 ? 1 : 0; + pCut->decDelay = 0; + if ( pCut->nLeaves == 0 ) // const + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 ); + return 0; + } + if ( pCut->nLeaves == 1 ) // variable + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 ); + return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; + } + + int LutSize = p->pPars->nLutDecSize; + int i, leaf_delay; + int DelayMax = -1, nLeafMax = 0; + unsigned uLeafMask = 0; + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + { + leaf_delay = If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; + + if ( DelayMax < leaf_delay ) + { + DelayMax = leaf_delay; + nLeafMax = 1; + uLeafMask = (1 << i); + } + else if ( DelayMax == leaf_delay ) + { + nLeafMax++; + uLeafMask |= (1 << i); + } + } + if ( If_CutLeaveNum(pCut) <= LutSize ) + { + pCut->decDelay = ( 1 << LutSize ) - 1; + return DelayMax + 1; + } + + /* compute the decomposition */ + int use_late_arrival = 0; + unsigned cost = 1; + + if ( !fFirst ) + { + if ( optDelay ) + { + /* checks based on delay: must be better than the previous best cut */ + use_late_arrival = DelayMax + 2 >= If_ObjCutBest(pObj)->Delay; + } + else + { + /* checks based on delay: look at the required time */ + use_late_arrival = DelayMax + 2 > pObj->Required + p->fEpsilon; + } + } + + /* Too many late-arriving signals */ + if ( nLeafMax == LutSize && use_late_arrival ) + { + /* unfeasible decomposition */ + pCut->Cost = IF_COST_MAX; + return ABC_INFINITY; + } + + if ( !use_late_arrival ) + { + uLeafMask = 0; + } + + /* returns the delay of the decomposition */ + word *pTruth = If_CutTruthW( p, pCut ); + int val = acd2_evaluate( pTruth, pCut->nLeaves, LutSize, &uLeafMask, &cost, !use_late_arrival ); + + /* not feasible decomposition */ + pCut->decDelay = uLeafMask; + if ( val < 0 ) + { + pCut->Cost = IF_COST_MAX; + return ABC_INFINITY; + } + + pCut->Cost = 2; + return DelayMax + val; +} + int If_LutDecReEval( If_Man_t * p, If_Cut_t * pCut ) { // pCut->fUser = 1; diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index bdd3ae439..0ad63f050 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -166,7 +166,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep If_Cut_t * pCut0R, * pCut1R; int fFunc0R, fFunc1R; int i, k, v, iCutDsd, fChange; - int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || + int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fUserLut2D || p->pPars->fUseDsdTune || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->pLutStruct || p->pPars->pFuncCell2 || p->pPars->fUseCheck1 || p->pPars->fUseCheck2; int fUseAndCut = (p->pPars->nAndDelay > 0) || (p->pPars->nAndArea > 0); assert( !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 0 ); @@ -208,7 +208,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->fUseless = 1; } } - else if ( p->pPars->fUserLutDec ) + else if ( p->pPars->fUserLutDec || p->pPars->fUserLut2D ) { pCut->Delay = If_LutDecReEval( p, pCut ); } @@ -434,6 +434,11 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->Delay = If_LutDecEval( p, pCut, pObj, Mode == 0, fFirst ); pCut->fUseless = pCut->Delay == ABC_INFINITY; } + else if ( p->pPars->fUserLut2D ) + { + pCut->Delay = If_Lut2DecEval( p, pCut, pObj, Mode == 0, fFirst ); + pCut->fUseless = pCut->Delay == ABC_INFINITY; + } else if ( p->pPars->fUserSesLib ) { int Cost = 0; @@ -518,7 +523,7 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP If_Set_t * pCutSet; If_Obj_t * pTemp; If_Cut_t * pCutTemp, * pCut; - int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec || p->pPars->fUserLutDec; + int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec || p->pPars->fUserLutDec || p->pPars->fUserLut2D; assert( pObj->pEquiv != NULL ); // prepare diff --git a/src/map/if/ifTime.c b/src/map/if/ifTime.c index f20842384..a1b51d6ad 100644 --- a/src/map/if/ifTime.c +++ b/src/map/if/ifTime.c @@ -211,7 +211,7 @@ void If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, fl pLeaf->Required = IF_MIN( pLeaf->Required, Required - pLutDelays[0] ); } } - else if ( p->pPars->fUserLutDec ) + else if ( p->pPars->fUserLutDec || p->pPars->fUserLut2D ) { Required = ObjRequired; If_CutForEachLeaf( p, pCut, pLeaf, i )