diff options
49 files changed, 5006 insertions, 566 deletions
@@ -391,6 +391,10 @@ SOURCE=.\src\base\abci\abcRec2.c # End Source File # Begin Source File +SOURCE=.\src\base\abci\abcRec3.c +# End Source File +# Begin Source File + SOURCE=.\src\base\abci\abcReconv.c # End Source File # Begin Source File @@ -1979,6 +1983,10 @@ SOURCE=.\src\opt\dau\dauDsd.c # End Source File # Begin Source File +SOURCE=.\src\opt\dau\dauEnum.c +# End Source File +# Begin Source File + SOURCE=.\src\opt\dau\dauInt.h # End Source File # End Group @@ -2705,6 +2713,10 @@ SOURCE=.\src\misc\util\utilSignal.h SOURCE=.\src\misc\util\utilSort.c # End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilTruth.h +# End Source File # End Group # Begin Group "nm" diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index b3efa455..35d80047 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -117,6 +117,7 @@ struct Gia_Man_t_ int * pReprsOld; // representatives (for CIs and ANDs) Gia_Rpr_t * pReprs; // representatives (for CIs and ANDs) int * pNexts; // next nodes in the equivalence classes + int * pSibls; // next nodes in the choice nodes int * pIso; // pairs of structurally isomorphic nodes int nTerLoop; // the state where loop begins int nTerStates; // the total number of ternary states @@ -481,6 +482,13 @@ static inline int Gia_ManAppendXor( Gia_Man_t * p, int iLit0, int iLit1 ) { return Gia_ManAppendMux( p, iLit0, Abc_LitNot(iLit1), iLit1 ); } +static inline void Gia_ManPatchCoDriver( Gia_Man_t * p, int iCoIndex, int iLit0 ) +{ + Gia_Obj_t * pObjCo = Gia_ManCo( p, iCoIndex ); + assert( Gia_ObjId(p, pObjCo) > Abc_Lit2Var(iLit0) ); + pObjCo->iDiff0 = Gia_ObjId(p, pObjCo) - Abc_Lit2Var(iLit0); + pObjCo->fCompl0 = Abc_LitIsCompl(iLit0); +} #define GIA_ZER 1 #define GIA_ONE 2 @@ -570,6 +578,8 @@ static inline void Gia_ObjSetReprRev( Gia_Man_t * p, int Id, int Num ){ a static inline void Gia_ObjUnsetRepr( Gia_Man_t * p, int Id ) { p->pReprs[Id].iRepr = GIA_VOID; } static inline int Gia_ObjHasRepr( Gia_Man_t * p, int Id ) { return p->pReprs[Id].iRepr != GIA_VOID; } static inline int Gia_ObjReprSelf( Gia_Man_t * p, int Id ) { return Gia_ObjHasRepr(p, Id) ? Gia_ObjRepr(p, Id) : Id; } +static inline int Gia_ObjSibl( Gia_Man_t * p, int Id ) { return p->pSibls ? p->pSibls[Id] : 0; } +static inline Gia_Obj_t * Gia_ObjSiblObj( Gia_Man_t * p, int Id ) { return (p->pSibls && p->pSibls[Id]) ? Gia_ManObj(p, p->pSibls[Id]) : NULL; } static inline int Gia_ObjProved( Gia_Man_t * p, int Id ) { return p->pReprs[Id].fProved; } static inline void Gia_ObjSetProved( Gia_Man_t * p, int Id ) { p->pReprs[Id].fProved = 1; } @@ -697,6 +707,7 @@ extern int Gia_ManCounterExampleValueLookup( Gia_Man_t * pGia, i extern void Gia_ManVerifyChoices( Gia_Man_t * p ); extern void Gia_ManReverseClasses( Gia_Man_t * p, int fNowIncreasing ); extern int Gia_ManHasChoices( Gia_Man_t * p ); +extern int Gia_ManChoiceLevel( Gia_Man_t * p ); /*=== giaCsatOld.c ============================================================*/ extern Vec_Int_t * Cbs_ManSolveMiter( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ); /*=== giaCsat.c ============================================================*/ @@ -807,7 +818,14 @@ extern Gia_Man_t * Gia_ManRehash( Gia_Man_t * p, int fAddStrash ); extern void Gia_ManHashProfile( Gia_Man_t * p ); extern int Gia_ManHashLookup( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 ); /*=== giaIf.c ===========================================================*/ -extern void Gia_ManPrintNpnClasses( Gia_Man_t * p ); +extern void Gia_ManPrintMappingStats( Gia_Man_t * p ); +extern int Gia_ManLutFaninCount( Gia_Man_t * p ); +extern int Gia_ManLutSizeMax( Gia_Man_t * p ); +extern int Gia_ManLutNum( Gia_Man_t * p ); +extern int Gia_ManLutLevel( Gia_Man_t * p ); +extern void Gia_ManSetRefsMapped( Gia_Man_t * p ); +extern void Gia_ManSetIfParsDefault( void * pIfPars ); +extern Gia_Man_t * Gia_ManPerformMapping( Gia_Man_t * p, void * pIfPars ); /*=== giaIso.c ===========================================================*/ extern Gia_Man_t * Gia_ManIsoCanonicize( Gia_Man_t * p, int fVerbose ); extern Gia_Man_t * Gia_ManIsoReduce( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, int fDualOut, int fVerbose ); @@ -823,12 +841,7 @@ extern void Gia_ManPrintStatsShort( Gia_Man_t * p ); extern void Gia_ManPrintMiterStatus( Gia_Man_t * p ); extern void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs ); extern void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew ); -/*=== giaMap.c ===========================================================*/ -extern void Gia_ManPrintMappingStats( Gia_Man_t * p ); -extern int Gia_ManLutFaninCount( Gia_Man_t * p ); -extern int Gia_ManLutSizeMax( Gia_Man_t * p ); -extern int Gia_ManLutNum( Gia_Man_t * p ); -extern int Gia_ManLutLevel( Gia_Man_t * p ); +extern void Gia_ManPrintNpnClasses( Gia_Man_t * p ); /*=== giaMem.c ===========================================================*/ extern Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax ); extern void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose ); @@ -857,6 +870,7 @@ extern int Sat_ManTest( Gia_Man_t * pGia, Gia_Obj_t * pObj, int extern int Gia_ManSeqMarkUsed( Gia_Man_t * p ); extern int Gia_ManCombMarkUsed( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManCleanup( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManCleanupOutputs( Gia_Man_t * p, int nOutputs ); extern Gia_Man_t * Gia_ManSeqCleanup( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManSeqStructSweep( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose ); /*=== giaShrink.c ===========================================================*/ @@ -906,7 +920,7 @@ extern int Gia_ManLevelNum( Gia_Man_t * p ); extern void Gia_ManCreateValueRefs( Gia_Man_t * p ); extern void Gia_ManCreateRefs( Gia_Man_t * p ); extern int * Gia_ManCreateMuxRefs( Gia_Man_t * p ); -extern int Gia_ManCrossCut( Gia_Man_t * p ); +extern int Gia_ManCrossCut( Gia_Man_t * p, int fReverse ); extern int Gia_ManIsNormalized( Gia_Man_t * p ); extern Vec_Int_t * Gia_ManCollectPoIds( Gia_Man_t * p ); extern int Gia_ObjIsMuxType( Gia_Obj_t * pNode ); @@ -920,6 +934,7 @@ extern void Gia_ObjPrint( Gia_Man_t * p, Gia_Obj_t * pObj ); extern void Gia_ManPrint( Gia_Man_t * p ); extern void Gia_ManInvertConstraints( Gia_Man_t * pAig ); extern int Gia_ManCompare( Gia_Man_t * p1, Gia_Man_t * p2 ); +extern void Gia_ManMarkFanoutDrivers( Gia_Man_t * p ); /*=== giaCTas.c ===========================================================*/ typedef struct Tas_Man_t_ Tas_Man_t; diff --git a/src/aig/gia/giaAig.c b/src/aig/gia/giaAig.c index 224d3bda..5dcc6038 100644 --- a/src/aig/gia/giaAig.c +++ b/src/aig/gia/giaAig.c @@ -42,7 +42,7 @@ static inline Aig_Obj_t * Gia_ObjChild1Copy2( Aig_Obj_t ** ppNodes, Gia_Obj_t * /**Function************************************************************* - Synopsis [Derives combinational miter of the two AIGs.] + Synopsis [Duplicates AIG in the DFS order.] Description [] @@ -70,6 +70,34 @@ void Gia_ManFromAig_rec( Gia_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) pNew->pNexts[iObjNew] = iNextNew; } } +Gia_Man_t * Gia_ManFromAig( Aig_Man_t * p ) +{ + Gia_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // create the new manager + pNew = Gia_ManStart( Aig_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + // create room to store equivalences + if ( p->pEquivs ) + pNew->pNexts = ABC_CALLOC( int, Aig_ManObjNum(p) ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->iData = 1; + Aig_ManForEachCi( p, pObj, i ) + pObj->iData = Gia_ManAppendCi( pNew ); + // add logic for the POs + Aig_ManForEachCo( p, pObj, i ) + Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin0(pObj) ); + Aig_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + if ( pNew->pNexts ) + Gia_ManDeriveReprs( pNew ); + return pNew; +} /**Function************************************************************* @@ -82,19 +110,38 @@ void Gia_ManFromAig_rec( Gia_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) SeeAlso [] ***********************************************************************/ -Gia_Man_t * Gia_ManFromAig( Aig_Man_t * p ) +void Gia_ManFromAigChoices_rec( Gia_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( pObj == NULL || pObj->iData ) + return; + assert( Aig_ObjIsNode(pObj) ); + Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin0(pObj) ); + Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin1(pObj) ); + Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjEquiv(p, pObj) ); + pObj->iData = Gia_ManAppendAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) ); + if ( Aig_ObjEquiv(p, pObj) ) + { + int iObjNew, iNextNew; + iObjNew = Abc_Lit2Var(pObj->iData); + iNextNew = Abc_Lit2Var(Aig_ObjEquiv(p, pObj)->iData); + assert( iObjNew > iNextNew ); + assert( Gia_ObjIsAnd(Gia_ManObj(pNew, iNextNew)) ); + pNew->pSibls[iObjNew] = iNextNew; + } +} +Gia_Man_t * Gia_ManFromAigChoices( Aig_Man_t * p ) { Gia_Man_t * pNew; Aig_Obj_t * pObj; int i; + assert( p->pEquivs != NULL ); // create the new manager pNew = Gia_ManStart( Aig_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; // create room to store equivalences - if ( p->pEquivs ) - pNew->pNexts = ABC_CALLOC( int, Aig_ManObjNum(p) ); + pNew->pSibls = ABC_CALLOC( int, Aig_ManObjNum(p) ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->iData = 1; @@ -102,12 +149,11 @@ Gia_Man_t * Gia_ManFromAig( Aig_Man_t * p ) pObj->iData = Gia_ManAppendCi( pNew ); // add logic for the POs Aig_ManForEachCo( p, pObj, i ) - Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin0(pObj) ); + Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin0(pObj) ); Aig_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) ); Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) ); - if ( pNew->pNexts ) - Gia_ManDeriveReprs( pNew ); + assert( Gia_ManObjNum(pNew) == Aig_ManObjNum(p) ); return pNew; } @@ -195,7 +241,7 @@ Gia_Man_t * Gia_ManFromAigSwitch( Aig_Man_t * p ) /**Function************************************************************* - Synopsis [Derives combinational miter of the two AIGs.] + Synopsis [Duplicates AIG in the DFS order.] Description [] @@ -228,18 +274,6 @@ void Gia_ManToAig_rec( Aig_Man_t * pNew, Aig_Obj_t ** ppNodes, Gia_Man_t * p, Gi pNew->pEquivs[Aig_Regular(pObjNew)->Id] = Aig_Regular(pNextNew); } } - -/**Function************************************************************* - - Synopsis [Duplicates AIG in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ Aig_Man_t * Gia_ManToAig( Gia_Man_t * p, int fChoices ) { Aig_Man_t * pNew; @@ -541,7 +575,8 @@ Gia_Man_t * Gia_ManPerformDch( Gia_Man_t * p, void * pPars ) Aig_Man_t * pNew; pNew = Gia_ManToAig( p, 0 ); pNew = Dar_ManChoiceNew( pNew, (Dch_Pars_t *)pPars ); - pGia = Gia_ManFromAig( pNew ); +// pGia = Gia_ManFromAig( pNew ); + pGia = Gia_ManFromAigChoices( pNew ); Aig_ManStop( pNew ); return pGia; } diff --git a/src/aig/gia/giaAig.h b/src/aig/gia/giaAig.h index b72f6415..6498ec52 100644 --- a/src/aig/gia/giaAig.h +++ b/src/aig/gia/giaAig.h @@ -51,6 +51,7 @@ ABC_NAMESPACE_HEADER_START /*=== giaAig.c =============================================================*/ extern Gia_Man_t * Gia_ManFromAig( Aig_Man_t * p ); +extern Gia_Man_t * Gia_ManFromAigChoices( Aig_Man_t * p ); extern Gia_Man_t * Gia_ManFromAigSimple( Aig_Man_t * p ); extern Gia_Man_t * Gia_ManFromAigSwitch( Aig_Man_t * p ); extern Aig_Man_t * Gia_ManToAig( Gia_Man_t * p, int fChoices ); diff --git a/src/aig/gia/giaChoice.c b/src/aig/gia/giaChoice.c index 85f0a372..ca2acb28 100644 --- a/src/aig/gia/giaChoice.c +++ b/src/aig/gia/giaChoice.c @@ -20,6 +20,7 @@ #include "gia.h" #include "giaAig.h" +#include "misc/tim/tim.h" ABC_NAMESPACE_IMPL_START @@ -261,6 +262,108 @@ int Gia_ManHasChoices( Gia_Man_t * p ) return 1; } + +/**Function************************************************************* + + Synopsis [Computes levels for AIG with choices and white boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManChoiceLevel_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + Gia_Obj_t * pNext; + int i, iBox, iTerm1, nTerms, LevelMax = 0; + if ( Gia_ObjIsTravIdCurrent( p, pObj ) ) + return; + Gia_ObjSetTravIdCurrent( p, pObj ); + if ( Gia_ObjIsCi(pObj) ) + { + if ( pManTime ) + { + iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) ); + if ( iBox >= 0 ) // this is not a true PI + { + iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox ); + nTerms = Tim_ManBoxInputNum( pManTime, iBox ); + for ( i = 0; i < nTerms; i++ ) + { + pNext = Gia_ManCo( p, iTerm1 + i ); + Gia_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Gia_ObjLevel(p, pNext) ) + LevelMax = Gia_ObjLevel(p, pNext); + } + LevelMax++; + } + } +// Abc_Print( 1, "%d ", pObj->Level ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + pNext = Gia_ObjFanin0(pObj); + Gia_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Gia_ObjLevel(p, pNext) ) + LevelMax = Gia_ObjLevel(p, pNext); + } + else if ( Gia_ObjIsAnd(pObj) ) + { + // get the maximum level of the two fanins + pNext = Gia_ObjFanin0(pObj); + Gia_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Gia_ObjLevel(p, pNext) ) + LevelMax = Gia_ObjLevel(p, pNext); + pNext = Gia_ObjFanin1(pObj); + Gia_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Gia_ObjLevel(p, pNext) ) + LevelMax = Gia_ObjLevel(p, pNext); + LevelMax++; + + // get the level of the nodes in the choice node + if ( p->pSibls && (pNext = Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))) ) + { + Gia_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Gia_ObjLevel(p, pNext) ) + LevelMax = Gia_ObjLevel(p, pNext); + } + } + else if ( !Gia_ObjIsConst0(pObj) ) + assert( 0 ); + Gia_ObjSetLevel( p, pObj, LevelMax ); +} +int Gia_ManChoiceLevel( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, LevelMax = 0; +// assert( Gia_ManRegNum(p) == 0 ); + Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + { + Gia_ManChoiceLevel_rec( p, pObj ); + if ( LevelMax < Gia_ObjLevel(p, pObj) ) + LevelMax = Gia_ObjLevel(p, pObj); + } + // account for dangling boxes + Gia_ManForEachCi( p, pObj, i ) + { + Gia_ManChoiceLevel_rec( p, pObj ); + if ( LevelMax < Gia_ObjLevel(p, pObj) ) + LevelMax = Gia_ObjLevel(p, pObj); +// Abc_Print( 1, "%d ", Gia_ObjLevel(p, pObj) ); + } +// Abc_Print( 1, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + assert( Gia_ObjLevel(p, pObj) > 0 ); +// printf( "Max level %d\n", LevelMax ); + return LevelMax; +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaFront.c b/src/aig/gia/giaFront.c index 322da785..fc99cfe9 100644 --- a/src/aig/gia/giaFront.c +++ b/src/aig/gia/giaFront.c @@ -103,13 +103,54 @@ void Gia_ManFrontTransform( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ +int Gia_ManCrossCutSimple( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, nCutCur = 0, nCutMax = 0; + Gia_ManCreateValueRefs( p ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( pObj->Value ) + nCutCur++; + if ( nCutMax < nCutCur ) + nCutMax = nCutCur; + if ( Gia_ObjIsAnd(pObj) ) + { + if ( --Gia_ObjFanin0(pObj)->Value == 0 ) + nCutCur--; + if ( --Gia_ObjFanin1(pObj)->Value == 0 ) + nCutCur--; + } + else if ( Gia_ObjIsCo(pObj) ) + { + if ( --Gia_ObjFanin0(pObj)->Value == 0 ) + nCutCur--; + } + } +// Gia_ManForEachObj( p, pObj, i ) +// assert( pObj->Value == 0 ); + return nCutMax; +} + + +/**Function************************************************************* + + Synopsis [Determine the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ Gia_Man_t * Gia_ManFront( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj, * pFanin0New, * pFanin1New, * pObjNew; char * pFront; // places used for the frontier int i, iLit, nCrossCut = 0, nCrossCutMax = 0; - int nCrossCutMaxInit = Gia_ManCrossCut( p ); + int nCrossCutMaxInit = Gia_ManCrossCutSimple( p ); int iFront = 0;//, clk = clock(); // set references for all objects Gia_ManCreateValueRefs( p ); diff --git a/src/aig/gia/giaIf.c b/src/aig/gia/giaIf.c index 13e4f429..deab1a60 100644 --- a/src/aig/gia/giaIf.c +++ b/src/aig/gia/giaIf.c @@ -21,7 +21,7 @@ #include "gia.h" #include "aig/aig/aig.h" #include "map/if/if.h" -#include "opt/dar/dar.h" +#include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START @@ -30,6 +30,9 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); +extern int Abc_RecToGia2( Gia_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vLeaves, int fHash ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -45,44 +48,48 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ -void Gia_ManSetIfParsDefault( If_Par_t * pPars ) +void Gia_ManSetIfParsDefault( void * pp ) { + If_Par_t * pPars = (If_Par_t *)pp; // extern void * Abc_FrameReadLibLut(); + If_Par_t * p = (If_Par_t *)pPars; // set defaults - memset( pPars, 0, sizeof(If_Par_t) ); + memset( p, 0, sizeof(If_Par_t) ); // user-controlable paramters -// pPars->nLutSize = -1; - pPars->nLutSize = 6; - pPars->nCutsMax = 8; - pPars->nFlowIters = 1; - pPars->nAreaIters = 2; - pPars->DelayTarget = -1; - pPars->Epsilon = (float)0.005; - pPars->fPreprocess = 1; - pPars->fArea = 0; - pPars->fFancy = 0; - pPars->fExpRed = 1; //// - pPars->fLatchPaths = 0; - pPars->fEdge = 1; - pPars->fPower = 0; - pPars->fCutMin = 0; - pPars->fSeqMap = 0; - pPars->fVerbose = 0; + p->nLutSize = -1; +// p->nLutSize = 6; + p->nCutsMax = 8; + p->nFlowIters = 1; + p->nAreaIters = 2; + p->DelayTarget = -1; + p->Epsilon = (float)0.005; + p->fPreprocess = 1; + p->fArea = 0; + p->fFancy = 0; + p->fExpRed = 0; //// + p->fLatchPaths = 0; + p->fEdge = 1; + p->fPower = 0; + p->fCutMin = 0; + p->fSeqMap = 0; + p->fVerbose = 0; + p->pLutStruct = NULL; // internal parameters - pPars->fTruth = 0; - pPars->nLatchesCi = 0; - pPars->nLatchesCo = 0; - pPars->fLiftLeaves = 0; -// pPars->pLutLib = Abc_FrameReadLibLut(); - pPars->pLutLib = NULL; - pPars->pTimesArr = NULL; - pPars->pTimesArr = NULL; - pPars->pFuncCost = NULL; + p->fTruth = 0; + p->nLatchesCi = 0; + p->nLatchesCo = 0; + p->fLiftLeaves = 0; + p->fUseCoAttrs = 1; // use CO attributes + p->pLutLib = NULL; + p->pTimesArr = NULL; + p->pTimesArr = NULL; + p->pFuncCost = NULL; } + /**Function************************************************************* - Synopsis [Load the network into FPGA manager.] + Synopsis [Prints mapping statistics.] Description [] @@ -91,97 +98,17 @@ void Gia_ManSetIfParsDefault( If_Par_t * pPars ) SeeAlso [] ***********************************************************************/ -If_Man_t * Gia_ManToIf( Gia_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf ) +int Gia_ManLutFaninCount( Gia_Man_t * p ) { -// extern Vec_Int_t * SGia_ManComputeSwitchProbs( Gia_Man_t * p, int nFrames, int nPref, int fProbOne ); -// Vec_Int_t * vSwitching = NULL, * vSwitching2 = NULL; -// float * pSwitching, * pSwitching2; - If_Man_t * pIfMan; - If_Obj_t * pIfObj; - Gia_Obj_t * pNode; - int i;//, clk = clock(); - Gia_ManLevelNum( p ); -// assert( p->pReprs == NULL ); -/* - // set the number of registers (switch activity will be combinational) - Gia_ManSetRegNum( p, 0 ); - if ( pPars->fPower ) - { - vSwitching = SGia_ManComputeSwitchProbs( p, 48, 16, 0 ); - if ( pPars->fVerbose ) - { - ABC_PRT( "Computing switching activity", clock() - clk ); - } - pSwitching = (float *)vSwitching->pArray; - vSwitching2 = Vec_IntStart( Gia_ManObjNumMax(p) ); - pSwitching2 = (float *)vSwitching2->pArray; - } -*/ - // start the mapping manager and set its parameters - pIfMan = If_ManStart( pPars ); -// pIfMan->vSwitching = vSwitching2; - // load the AIG into the mapper - Gia_ManCreateRefs( p ); - Gia_ManForEachObj( p, pNode, i ) - { - if ( Gia_ObjIsAnd(pNode) ) - pIfObj = If_ManCreateAnd( pIfMan, - If_NotCond( (If_Obj_t *)Vec_PtrEntry(vAigToIf, Gia_ObjFaninId0(pNode, i)), Gia_ObjFaninC0(pNode) ), - If_NotCond( (If_Obj_t *)Vec_PtrEntry(vAigToIf, Gia_ObjFaninId1(pNode, i)), Gia_ObjFaninC1(pNode) ) ); - else if ( Gia_ObjIsCi(pNode) ) - { - pIfObj = If_ManCreateCi( pIfMan ); - If_ObjSetLevel( pIfObj, Gia_ObjLevel(p,pNode) ); -// Abc_Print( 1, "pi=%d ", pIfObj->Level ); - if ( pIfMan->nLevelMax < (int)pIfObj->Level ) - pIfMan->nLevelMax = (int)pIfObj->Level; - } - else if ( Gia_ObjIsCo(pNode) ) - { - pIfObj = If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Vec_PtrEntry(vAigToIf, Gia_ObjFaninId0(pNode, i)), Gia_ObjFaninC0(pNode) ) ); -// Abc_Print( 1, "po=%d ", pIfObj->Level ); - } - else if ( Gia_ObjIsConst0(pNode) ) - pIfObj = If_Not(If_ManConst1( pIfMan )); - else // add the node to the mapper - assert( 0 ); - // save the result - assert( Vec_PtrEntry(vAigToIf, i) == NULL ); - Vec_PtrWriteEntry( vAigToIf, i, pIfObj ); -// if ( vSwitching2 ) -// pSwitching2[pIfObj->Id] = pSwitching[pNode->Id]; - // set up the choice node -/* -// if ( p->pReprs && p->pNexts && Gia_ObjIsHead( p, i ) ) - if ( p->pNexts && Gia_ObjNext(p, i) && Gia_ObjRefNumId(p, i) ) - { - int iPrev, iFanin; - pIfMan->nChoices++; - for ( iPrev = i, iFanin = Gia_ObjNext(p, i); iFanin; iPrev = iFanin, iFanin = Gia_ObjNext(p, iFanin) ) - If_ObjSetChoice( Vec_PtrEntry(vAigToIf,iPrev), Vec_PtrEntry(vAigToIf,iFanin) ); - If_ManCreateChoice( pIfMan, Vec_PtrEntry(vAigToIf,i) ); - } -*/ -/* // set up the choice node - if ( Gia_ObjIsChoice( p, pNode ) ) - { - pIfMan->nChoices++; - for ( pPrev = pNode, pFanin = Gia_ObjEquiv(p, pNode); pFanin; pPrev = pFanin, pFanin = Gia_ObjEquiv(p, pFanin) ) - If_ObjSetChoice( pPrev->pData, pFanin->pData ); - If_ManCreateChoice( pIfMan, pNode->pData ); - } -// assert( If_ObjLevel(pIfObj) == Gia_ObjLevel(pNode) ); -*/ - } -// if ( vSwitching ) -// Vec_IntFree( vSwitching ); - return pIfMan; + int i, Counter = 0; + Gia_ManForEachLut( p, i ) + Counter += Gia_ObjLutSize(p, i); + return Counter; } - /**Function************************************************************* - Synopsis [] + Synopsis [Prints mapping statistics.] Description [] @@ -190,60 +117,17 @@ If_Man_t * Gia_ManToIf( Gia_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf ) SeeAlso [] ***********************************************************************/ -int * Gia_ManFromIf( If_Man_t * pIfMan, Gia_Man_t * p, Vec_Ptr_t * vAigToIf ) +int Gia_ManLutSizeMax( Gia_Man_t * p ) { - int * pMapping, iOffset; - Vec_Ptr_t * vIfToAig; - Gia_Obj_t * pObj, * pObjRepr; - If_Obj_t * pIfObj; - If_Cut_t * pCutBest; - int i, k, j, nLeaves, * ppLeaves; - int nItems = 0; - assert( Gia_ManCiNum(p) == If_ManCiNum(pIfMan) ); - assert( Gia_ManCoNum(p) == If_ManCoNum(pIfMan) ); - assert( Gia_ManAndNum(p) == If_ManAndNum(pIfMan) ); - // create mapping of IF to AIG - vIfToAig = Vec_PtrStart( If_ManObjNum(pIfMan) ); - Gia_ManForEachObj( p, pObj, i ) - { - pIfObj = (If_Obj_t *)Vec_PtrEntry( vAigToIf, i ); - Vec_PtrWriteEntry( vIfToAig, pIfObj->Id, pObj ); - if ( !Gia_ObjIsAnd(pObj) || pIfObj->nRefs == 0 ) - continue; - nItems += 2 + If_CutLeaveNum( If_ObjCutBest(pIfObj) ); - } - // construct the network - pMapping = ABC_CALLOC( int, Gia_ManObjNum(p) + nItems ); - iOffset = Gia_ManObjNum(p); - Gia_ManForEachObj( p, pObj, i ) - { - pIfObj = (If_Obj_t *)Vec_PtrEntry( vAigToIf, i ); - if ( !Gia_ObjIsAnd(pObj) || pIfObj->nRefs == 0 ) - continue; - pCutBest = If_ObjCutBest( pIfObj ); - nLeaves = If_CutLeaveNum( pCutBest ); - ppLeaves = If_CutLeaves( pCutBest ); - // create node - k = iOffset; - pMapping[k++] = nLeaves; - for ( j = 0; j < nLeaves; j++ ) - { - pObjRepr = (Gia_Obj_t *)Vec_PtrEntry( vIfToAig, ppLeaves[j] ); - pMapping[k++] = Gia_ObjId( p, pObjRepr ); - } - pMapping[k++] = i; - pMapping[i] = iOffset; - iOffset = k; - } - assert( iOffset <= Gia_ManObjNum(p) + nItems ); - Vec_PtrFree( vIfToAig ); -// pNtk->pManTime = Tim_ManDup( pIfMan->pManTim, 0 ); - return pMapping; + int i, nSizeMax = -1; + Gia_ManForEachLut( p, i ) + nSizeMax = Abc_MaxInt( nSizeMax, Gia_ObjLutSize(p, i) ); + return nSizeMax; } /**Function************************************************************* - Synopsis [Interface with the FPGA mapping package.] + Synopsis [Prints mapping statistics.] Description [] @@ -252,39 +136,14 @@ int * Gia_ManFromIf( If_Man_t * pIfMan, Gia_Man_t * p, Vec_Ptr_t * vAigToIf ) SeeAlso [] ***********************************************************************/ -int Gia_MappingIf( Gia_Man_t * p, If_Par_t * pPars ) +int Gia_ManLutNum( Gia_Man_t * p ) { - If_Man_t * pIfMan; - Vec_Ptr_t * vAigToIf; - // set the arrival times - pPars->pTimesArr = ABC_ALLOC( float, Gia_ManCiNum(p) ); - memset( pPars->pTimesArr, 0, sizeof(float) * Gia_ManCiNum(p) ); - // translate into the mapper - vAigToIf = Vec_PtrStart( Gia_ManObjNum(p) ); - pIfMan = Gia_ManToIf( p, pPars, vAigToIf ); - if ( pIfMan == NULL ) - { - Vec_PtrFree( vAigToIf ); - return 0; - } -// pIfMan->pManTim = Tim_ManDup( pManTime, 0 ); - if ( !If_ManPerformMapping( pIfMan ) ) - { - Vec_PtrFree( vAigToIf ); - If_ManStop( pIfMan ); - return 0; - } - // transform the result of mapping into the new network - ABC_FREE( p->pMapping ); - p->pMapping = Gia_ManFromIf( pIfMan, p, vAigToIf ); -// if ( pPars->fBidec && pPars->nLutSize <= 8 ) -// Gia_ManBidecResyn( pNtk, 0 ); - If_ManStop( pIfMan ); - Vec_PtrFree( vAigToIf ); - return 1; + int i, Counter = 0; + Gia_ManForEachLut( p, i ) + Counter ++; + return Counter; } - /**Function************************************************************* Synopsis [Prints mapping statistics.] @@ -296,35 +155,30 @@ int Gia_MappingIf( Gia_Man_t * p, If_Par_t * pPars ) SeeAlso [] ***********************************************************************/ -void Gia_ManPrintMappingStats( Gia_Man_t * p ) +int Gia_ManLutLevel( Gia_Man_t * p ) { - int * pLevels; - int i, k, iFan, nLutSize = 0, nLuts = 0, nFanins = 0, LevelMax = 0; - if ( !p->pMapping ) - return; - pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; + int i, k, iFan, Level; + int * pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachLut( p, i ) { - nLuts++; - nFanins += Gia_ObjLutSize(p, i); - nLutSize = Abc_MaxInt( nLutSize, Gia_ObjLutSize(p, i) ); + Level = 0; Gia_LutForEachFanin( p, i, iFan, k ) - pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[iFan] ); - pLevels[i]++; - LevelMax = Abc_MaxInt( LevelMax, pLevels[i] ); + if ( Level < pLevels[iFan] ) + Level = pLevels[iFan]; + pLevels[i] = Level + 1; } + Level = 0; + Gia_ManForEachCo( p, pObj, k ) + if ( Level < pLevels[Gia_ObjFaninId0p(p, pObj)] ) + Level = pLevels[Gia_ObjFaninId0p(p, pObj)]; ABC_FREE( pLevels ); - Abc_Print( 1, "mapping (K=%d) : ", nLutSize ); - Abc_Print( 1, "lut =%7d ", nLuts ); - Abc_Print( 1, "edge =%8d ", nFanins ); - Abc_Print( 1, "lev =%5d ", LevelMax ); - Abc_Print( 1, "mem =%5.2f MB", 4.0*(Gia_ManObjNum(p) + 2*nLuts + nFanins)/(1<<20) ); - Abc_Print( 1, "\n" ); + return Level; } /**Function************************************************************* - Synopsis [Prints mapping statistics.] + Synopsis [Assigns levels.] Description [] @@ -333,12 +187,17 @@ void Gia_ManPrintMappingStats( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -int Gia_ManLutFaninCount( Gia_Man_t * p ) +void Gia_ManSetRefsMapped( Gia_Man_t * p ) { - int i, Counter = 0; + Gia_Obj_t * pObj; + int i, k, iFan; + ABC_FREE( p->pRefs ); + p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ObjRefInc( p, Gia_ObjFanin0(pObj) ); Gia_ManForEachLut( p, i ) - Counter += Gia_ObjLutSize(p, i); - return Counter; + Gia_LutForEachFanin( p, i, iFan, k ) + Gia_ObjRefInc( p, Gia_ManObj(p, iFan) ); } /**Function************************************************************* @@ -352,17 +211,37 @@ int Gia_ManLutFaninCount( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -int Gia_ManLutSizeMax( Gia_Man_t * p ) +void Gia_ManPrintMappingStats( Gia_Man_t * p ) { - int i, nSizeMax = -1; + int * pLevels; + int i, k, iFan, nLutSize = 0, nLuts = 0, nFanins = 0, LevelMax = 0; + if ( !p->pMapping ) + return; + pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachLut( p, i ) - nSizeMax = Abc_MaxInt( nSizeMax, Gia_ObjLutSize(p, i) ); - return nSizeMax; + { + nLuts++; + nFanins += Gia_ObjLutSize(p, i); + nLutSize = Abc_MaxInt( nLutSize, Gia_ObjLutSize(p, i) ); + Gia_LutForEachFanin( p, i, iFan, k ) + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[iFan] ); + pLevels[i]++; + LevelMax = Abc_MaxInt( LevelMax, pLevels[i] ); + } + ABC_FREE( pLevels ); + Abc_Print( 1, "mapping (K=%d) : ", nLutSize ); + Abc_Print( 1, "lut =%7d ", nLuts ); + Abc_Print( 1, "edge =%8d ", nFanins ); + Abc_Print( 1, "lev =%5d ", LevelMax ); + Abc_Print( 1, "mem =%5.2f MB", 4.0*(Gia_ManObjNum(p) + 2*nLuts + nFanins)/(1<<20) ); + Abc_Print( 1, "\n" ); } + + /**Function************************************************************* - Synopsis [Prints mapping statistics.] + Synopsis [Converts GIA into IF manager.] Description [] @@ -371,17 +250,66 @@ int Gia_ManLutSizeMax( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -int Gia_ManLutNum( Gia_Man_t * p ) +static inline If_Obj_t * If_ManFanin0Copy( If_Man_t * pIfMan, Gia_Obj_t * pObj ) { return If_NotCond( If_ManObj(pIfMan, Gia_ObjValue(Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj) ); } +static inline If_Obj_t * If_ManFanin1Copy( If_Man_t * pIfMan, Gia_Obj_t * pObj ) { return If_NotCond( If_ManObj(pIfMan, Gia_ObjValue(Gia_ObjFanin1(pObj))), Gia_ObjFaninC1(pObj) ); } +If_Man_t * Gia_ManToIf( Gia_Man_t * p, If_Par_t * pPars ) { - int i, Counter = 0; - Gia_ManForEachLut( p, i ) - Counter ++; - return Counter; + If_Man_t * pIfMan; + If_Obj_t * pIfObj; + Gia_Obj_t * pObj; + int i; + // create levels with choices + Gia_ManChoiceLevel( p ); + // mark representative nodes + Gia_ManMarkFanoutDrivers( p ); + // start the mapping manager and set its parameters + pIfMan = If_ManStart( pPars ); + pIfMan->pName = Abc_UtilStrsav( Gia_ManName(p) ); + // print warning about excessive memory usage + if ( 1.0 * Gia_ManObjNum(p) * pIfMan->nObjBytes / (1<<30) > 1.0 ) + printf( "Warning: The mapper will allocate %.1f GB for to represent the subject graph with %d AIG nodes.\n", + 1.0 * Gia_ManObjNum(p) * pIfMan->nObjBytes / (1<<30), Gia_ManObjNum(p) ); + // load the AIG into the mapper + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = If_ObjId( If_ManConst1(pIfMan) ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pIfObj = If_ManCreateAnd( pIfMan, If_ManFanin0Copy(pIfMan, pObj), If_ManFanin1Copy(pIfMan, pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + { + pIfObj = If_ManCreateCi( pIfMan ); + If_ObjSetLevel( pIfObj, Gia_ObjLevel(p, pObj) ); +// Abc_Print( 1, "pi%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); + if ( pIfMan->nLevelMax < (int)pIfObj->Level ) + pIfMan->nLevelMax = (int)pIfObj->Level; + } + else if ( Gia_ObjIsCo(pObj) ) + { + pIfObj = If_ManCreateCo( pIfMan, If_NotCond( If_ManFanin0Copy(pIfMan, pObj), Gia_ObjIsConst0(Gia_ObjFanin0(pObj))) ); +// Abc_Print( 1, "po%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); + } + else assert( 0 ); + assert( i == If_ObjId(pIfObj) ); + Gia_ObjSetValue( pObj, If_ObjId(pIfObj) ); + // set up the choice node + if ( Gia_ObjSibl(p, i) && pObj->fMark0 ) + { + Gia_Obj_t * pSibl, * pPrev; + for ( pPrev = pObj, pSibl = Gia_ObjSiblObj(p, i); pSibl; pPrev = pSibl, pSibl = Gia_ObjSiblObj(p, Gia_ObjId(p, pSibl)) ) + If_ObjSetChoice( If_ManObj(pIfMan, Gia_ObjValue(pObj)), If_ManObj(pIfMan, Gia_ObjValue(pSibl)) ); + If_ManCreateChoice( pIfMan, If_ManObj(pIfMan, Gia_ObjValue(pObj)) ); + } +// assert( If_ObjLevel(pIfObj) == Gia_ObjLevel(pNode) ); + } + Gia_ManCleanMark0( p ); + return pIfMan; } + /**Function************************************************************* - Synopsis [Prints mapping statistics.] + Synopsis [Derives node's AIG after SOP balancing] Description [] @@ -390,30 +318,47 @@ int Gia_ManLutNum( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -int Gia_ManLutLevel( Gia_Man_t * p ) +int Gia_ManNodeIfSopToGiaInt( Gia_Man_t * pNew, Vec_Wrd_t * vAnds, int nVars, Vec_Int_t * vLeaves, int fHash ) { - Gia_Obj_t * pObj; - int i, k, iFan, Level; - int * pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); - Gia_ManForEachLut( p, i ) + Vec_Int_t * vResults; + int iRes0, iRes1, iRes = -1; + If_And_t This; + word Entry; + int i; + if ( Vec_WrdSize(vAnds) == 0 ) + return 0; + if ( Vec_WrdSize(vAnds) == 1 && Vec_WrdEntry(vAnds,0) == 0 ) + return 1; + vResults = Vec_IntAlloc( Vec_WrdSize(vAnds) ); + for ( i = 0; i < nVars; i++ ) + Vec_IntPush( vResults, Vec_IntEntry(vLeaves, i) ); + Vec_WrdForEachEntryStart( vAnds, Entry, i, nVars ) { - Level = 0; - Gia_LutForEachFanin( p, i, iFan, k ) - if ( Level < pLevels[iFan] ) - Level = pLevels[iFan]; - pLevels[i] = Level + 1; + This = If_WrdToAnd( Entry ); + iRes0 = Abc_LitNotCond( Vec_IntEntry(vResults, This.iFan0), This.fCompl0 ); + iRes1 = Abc_LitNotCond( Vec_IntEntry(vResults, This.iFan1), This.fCompl1 ); + if ( fHash ) + iRes = Gia_ManHashAnd( pNew, iRes0, iRes1 ); + else + iRes = Gia_ManAppendAnd( pNew, iRes0, iRes1 ); + Vec_IntPush( vResults, iRes ); } - Level = 0; - Gia_ManForEachCo( p, pObj, k ) - if ( Level < pLevels[Gia_ObjFaninId0p(p, pObj)] ) - Level = pLevels[Gia_ObjFaninId0p(p, pObj)]; - ABC_FREE( pLevels ); - return Level; + Vec_IntFree( vResults ); + return Abc_LitNotCond( iRes, This.fCompl ); +} +int Gia_ManNodeIfSopToGia( Gia_Man_t * pNew, If_Man_t * p, If_Cut_t * pCut, Vec_Int_t * vLeaves, int fHash ) +{ + int iResult; + Vec_Wrd_t * vArray; + vArray = If_CutDelaySopArray( p, pCut ); + iResult = Gia_ManNodeIfSopToGiaInt( pNew, vArray, If_CutLeaveNum(pCut), vLeaves, fHash ); +// Vec_WrdFree( vArray ); + return iResult; } /**Function************************************************************* - Synopsis [Assigns levels.] + Synopsis [Recursively derives the local AIG for the cut.] Description [] @@ -422,22 +367,74 @@ int Gia_ManLutLevel( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -void Gia_ManSetRefsMapped( Gia_Man_t * p ) +int Gia_ManNodeIfToGia_rec( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited, int fHash ) { - Gia_Obj_t * pObj; - int i, k, iFan; - ABC_FREE( p->pRefs ); - p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); - Gia_ManForEachCo( p, pObj, i ) - Gia_ObjRefInc( p, Gia_ObjFanin0(pObj) ); - Gia_ManForEachLut( p, i ) - Gia_LutForEachFanin( p, i, iFan, k ) - Gia_ObjRefInc( p, Gia_ManObj(p, iFan) ); + If_Cut_t * pCut; + If_Obj_t * pTemp; + int iFunc, iFunc0, iFunc1; + // get the best cut + pCut = If_ObjCutBest(pIfObj); + // if the cut is visited, return the result + if ( If_CutDataInt(pCut) ) + return If_CutDataInt(pCut); + // mark the node as visited + Vec_PtrPush( vVisited, pCut ); + // insert the worst case + If_CutSetDataInt( pCut, ~0 ); + // skip in case of primary input + if ( If_ObjIsCi(pIfObj) ) + return If_CutDataInt(pCut); + // compute the functions of the children + for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv ) + { + iFunc0 = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pTemp->pFanin0, vVisited, fHash ); + if ( iFunc0 == ~0 ) + continue; + iFunc1 = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pTemp->pFanin1, vVisited, fHash ); + if ( iFunc1 == ~0 ) + continue; + // both branches are solved + if ( fHash ) + iFunc = Gia_ManHashAnd( pNew, Abc_LitNotCond(iFunc0, pTemp->fCompl0), Abc_LitNotCond(iFunc1, pTemp->fCompl1) ); + else + iFunc = Gia_ManAppendAnd( pNew, Abc_LitNotCond(iFunc0, pTemp->fCompl0), Abc_LitNotCond(iFunc1, pTemp->fCompl1) ); + if ( pTemp->fPhase != pIfObj->fPhase ) + iFunc = Abc_LitNot(iFunc); + If_CutSetDataInt( pCut, iFunc ); + break; + } + return If_CutDataInt(pCut); +} +int Gia_ManNodeIfToGia( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vLeaves, int fHash ) +{ + If_Cut_t * pCut; + If_Obj_t * pLeaf; + int i, iRes; + // get the best cut + pCut = If_ObjCutBest(pIfObj); + assert( pCut->nLeaves > 1 ); + // set the leaf variables + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + If_CutSetDataInt( If_ObjCutBest(pLeaf), Vec_IntEntry(vLeaves, i) ); + // recursively compute the function while collecting visited cuts + Vec_PtrClear( pIfMan->vTemp ); + iRes = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pIfObj, pIfMan->vTemp, fHash ); + if ( iRes == ~0 ) + { + Abc_Print( -1, "Gia_ManNodeIfToGia(): Computing local AIG has failed.\n" ); + return ~0; + } + // clean the cuts + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + If_CutSetDataInt( If_ObjCutBest(pLeaf), 0 ); + Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i ) + If_CutSetDataInt( pCut, 0 ); + return iRes; } /**Function************************************************************* - Synopsis [Prints NPN class statistics.] + Synopsis [Converts IF into GIA manager.] Description [] @@ -446,83 +443,212 @@ void Gia_ManSetRefsMapped( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -void Gia_ManPrintNpnClasses( Gia_Man_t * p ) +Gia_Man_t * Gia_ManFromIf( If_Man_t * pIfMan ) { - extern char ** Kit_DsdNpn4ClassNames(); - char ** pNames = Kit_DsdNpn4ClassNames(); - Vec_Int_t * vLeaves, * vTruth, * vVisited; - int * pLutClass, ClassCounts[222] = {0}; - int i, k, iFan, Class, OtherClasses, OtherClasses2, nTotal, Counter, Counter2; + int fHash = 0; + Gia_Man_t * pNew; + If_Obj_t * pIfObj, * pIfLeaf; + If_Cut_t * pCutBest; + Vec_Int_t * vLeaves; + Vec_Int_t * vCover; unsigned * pTruth; - assert( p->pMapping != NULL ); - assert( Gia_ManLutSizeMax( p ) <= 4 ); - vLeaves = Vec_IntAlloc( 100 ); - vVisited = Vec_IntAlloc( 100 ); - vTruth = Vec_IntAlloc( (1<<16) ); - pLutClass = ABC_CALLOC( int, Gia_ManObjNum(p) ); - Gia_ManCleanTruth( p ); - Gia_ManForEachLut( p, i ) + int Counter, iOffset, nItems = 0; + int i, k, w, GiaId; + // create new manager + pNew = Gia_ManStart( If_ManObjNum(pIfMan) ); + Gia_ManHashAlloc( pNew ); + // iterate through nodes used in the mapping + vCover = Vec_IntAlloc( 1 << 16 ); + vLeaves = Vec_IntAlloc( 16 ); + If_ManCleanCutData( pIfMan ); + If_ManForEachObj( pIfMan, pIfObj, i ) { - if ( Gia_ObjLutSize(p,i) > 4 ) + if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) ) continue; - Vec_IntClear( vLeaves ); - Gia_LutForEachFanin( p, i, iFan, k ) - Vec_IntPush( vLeaves, iFan ); - for ( ; k < 4; k++ ) - Vec_IntPush( vLeaves, 0 ); - pTruth = Gia_ManConvertAigToTruth( p, Gia_ManObj(p, i), vLeaves, vTruth, vVisited ); - Class = Dar_LibReturnClass( *pTruth ); - ClassCounts[ Class ]++; - pLutClass[i] = Class; + if ( If_ObjIsAnd(pIfObj) ) + { + pCutBest = If_ObjCutBest( pIfObj ); + // collect leaves of the best cut + Vec_IntClear( vLeaves ); + If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, k ) + Vec_IntPush( vLeaves, pIfLeaf->iCopy ); + // get the functionality + if ( pIfMan->pPars->pLutStruct ) + pIfObj->iCopy = Kit_TruthToGia( pNew, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), vCover, vLeaves, fHash ); + else if ( pIfMan->pPars->fDelayOpt ) + pIfObj->iCopy = Gia_ManNodeIfSopToGia( pNew, pIfMan, pCutBest, vLeaves, fHash ); + else if ( pIfMan->pPars->fUserRecLib ) + pIfObj->iCopy = Abc_RecToGia2( pNew, pIfMan, pCutBest, pIfObj, vLeaves, fHash ); + else + pIfObj->iCopy = Gia_ManNodeIfToGia( pNew, pIfMan, pIfObj, vLeaves, fHash ); + // complement the node if the TT was used and the cut was complemented + if ( pIfMan->pPars->pLutStruct ) + pIfObj->iCopy = Abc_LitNotCond( pIfObj->iCopy, pCutBest->fCompl ); + // count entries in the mapping array + nItems += 2 + If_CutLeaveNum( pCutBest ); + } + else if ( If_ObjIsCi(pIfObj) ) + pIfObj->iCopy = Gia_ManAppendCi(pNew); + else if ( If_ObjIsCo(pIfObj) ) + pIfObj->iCopy = Gia_ManAppendCo( pNew, Abc_LitNotCond(If_ObjFanin0(pIfObj)->iCopy, If_ObjFaninC0(pIfObj)) ); + else if ( If_ObjIsConst1(pIfObj) ) + { + pIfObj->iCopy = 1; + nItems += 2; + } + else assert( 0 ); } + Vec_IntFree( vCover ); Vec_IntFree( vLeaves ); - Vec_IntFree( vTruth ); - Vec_IntFree( vVisited ); - Vec_IntFreeP( &p->vTruths ); - nTotal = 0; - for ( i = 0; i < 222; i++ ) - nTotal += ClassCounts[i]; - Abc_Print( 1, "NPN CLASS STATISTICS (for %d LUT4 present in the current mapping):\n", nTotal ); - OtherClasses = 0; - for ( i = 0; i < 222; i++ ) + Gia_ManHashStop( pNew ); + + // GIA after mapping with choices may end up with dangling nodes + // which participate as leaves of some cuts used in the mapping + // such nodes are marked here and skipped when mapping is derived + Counter = Gia_ManMarkDangling(pNew); +// if ( pIfMan->pPars->fVerbose && Counter ) + if ( Counter ) + printf( "GIA after mapping has %d dangling nodes.\n", Counter ); + + // create mapping + iOffset = Gia_ManObjNum(pNew); + pNew->pMapping = ABC_CALLOC( int, iOffset + nItems ); + assert( pNew->vTruths == NULL ); + if ( pIfMan->pPars->pLutStruct ) + pNew->vTruths = Vec_IntAlloc( 1000 ); + If_ManForEachObj( pIfMan, pIfObj, i ) { - if ( ClassCounts[i] == 0 ) + if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) ) continue; - if ( 100.0 * ClassCounts[i] / (nTotal+1) < 0.1 ) // do not show anything below 0.1 percent - continue; - OtherClasses += ClassCounts[i]; - Abc_Print( 1, "Class %3d : Count = %6d (%7.2f %%) %s\n", - i, ClassCounts[i], 100.0 * ClassCounts[i] / (nTotal+1), pNames[i] ); + if ( If_ObjIsAnd(pIfObj) ) + { + GiaId = Abc_Lit2Var( pIfObj->iCopy ); + if ( !Gia_ObjIsAnd(Gia_ManObj(pNew, GiaId)) ) // skip trivial node + continue; + assert( Gia_ObjIsAnd(Gia_ManObj(pNew, GiaId)) ); + if ( !Gia_ManObj(pNew, GiaId)->fMark0 ) // skip dangling node + continue; + // get the best cut + pCutBest = If_ObjCutBest( pIfObj ); + // copy the truth tables + pTruth = NULL; + if ( pNew->vTruths ) + { + // copy truth table + for ( w = 0; w < pIfMan->nTruthWords; w++ ) + Vec_IntPush( pNew->vTruths, If_CutTruth(pCutBest)[w] ); + pTruth = (unsigned *)(Vec_IntArray(pNew->vTruths) + Vec_IntSize(pNew->vTruths) - pIfMan->nTruthWords); + // complement + if ( pCutBest->fCompl ^ Abc_LitIsCompl(pIfObj->iCopy) ) + for ( w = 0; w < pIfMan->nTruthWords; w++ ) + pTruth[w] = ~pTruth[w]; + } + // create node + pNew->pMapping[GiaId] = iOffset; + pNew->pMapping[iOffset++] = If_CutLeaveNum(pCutBest); + If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, k ) + { + int FaninId = Abc_Lit2Var(pIfLeaf->iCopy); + if ( pTruth && Abc_LitIsCompl(pIfLeaf->iCopy) ) + Kit_TruthChangePhase( pTruth, If_CutLeaveNum(pCutBest), k ); + if ( !Gia_ManObj(pNew, FaninId)->fMark0 ) // skip dangling node + { + // update truth table + if ( pTruth ) + { + extern void If_CluSwapVars( word * pTruth, int nVars, int * V2P, int * P2V, int iVar, int jVar ); + if ( If_CutLeaveNum(pCutBest) >= 6 ) + If_CluSwapVars( (word*)pTruth, If_CutLeaveNum(pCutBest), NULL, NULL, k, If_CutLeaveNum(pCutBest)-1 ); + else + { + word Truth = ((word)pTruth[0] << 32) | (word)pTruth[0]; + If_CluSwapVars( &Truth, 6, NULL, NULL, k, If_CutLeaveNum(pCutBest)-1 ); + pTruth[0] = (Truth & 0xFFFFFFFF); + } + } + pNew->pMapping[iOffset-k-1]--; + continue; + } + assert( FaninId < GiaId ); + pNew->pMapping[iOffset++] = FaninId; + } + pNew->pMapping[iOffset++] = GiaId; + } + else if ( If_ObjIsConst1(pIfObj) ) + { + // create node + pNew->pMapping[0] = iOffset; + pNew->pMapping[iOffset++] = 0; + pNew->pMapping[iOffset++] = 0; +/* + if ( pNew->vTruths ) + { + printf( "%d ", nLeaves ); + for ( w = 0; w < pIfMan->nTruthWords; w++ ) + Vec_IntPush( pNew->vTruths, 0 ); + } +*/ + } } - OtherClasses = nTotal - OtherClasses; - Abc_Print( 1, "Other : Count = %6d (%7.2f %%)\n", - OtherClasses, 100.0 * OtherClasses / (nTotal+1) ); - // count the number of LUTs that have MUX function and two fanins with MUX functions - OtherClasses = OtherClasses2 = 0; - ABC_FREE( p->pRefs ); - Gia_ManSetRefsMapped( p ); - Gia_ManForEachLut( p, i ) + Gia_ManCleanMark0( pNew ); +// assert( iOffset == Gia_ManObjNum(pNew) + nItems ); + if ( pIfMan->pManTim ) + pNew->pManTime = Tim_ManDup( pIfMan->pManTim, 0 ); + // verify that COs have mapping { - if ( pLutClass[i] != 109 ) - continue; - Counter = Counter2 = 0; - Gia_LutForEachFanin( p, i, iFan, k ) + Gia_Obj_t * pObj; + Gia_ManForEachCo( pNew, pObj, i ) { - Counter += (pLutClass[iFan] == 109); - Counter2 += (pLutClass[iFan] == 109) && (Gia_ObjRefNumId(p, iFan) == 1); + if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ) + assert( pNew->pMapping[Gia_ObjFaninId0p(pNew, pObj)] != 0 ); } - OtherClasses += (Counter > 1); - OtherClasses2 += (Counter2 > 1); -// Abc_Print( 1, "%d -- ", pLutClass[i] ); -// Gia_LutForEachFanin( p, i, iFan, k ) -// Abc_Print( 1, "%d ", pLutClass[iFan] ); -// Abc_Print( 1, "\n" ); } - ABC_FREE( p->pRefs ); - Abc_Print( 1, "Approximate number of 4:1 MUX structures: All = %6d (%7.2f %%) MFFC = %6d (%7.2f %%)\n", - OtherClasses, 100.0 * OtherClasses / (nTotal+1), - OtherClasses2, 100.0 * OtherClasses2 / (nTotal+1) ); - ABC_FREE( pLutClass ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Interface of LUT mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPerformMapping( Gia_Man_t * p, void * pp ) +{ + Gia_Man_t * pNew; + If_Man_t * pIfMan; + If_Par_t * pPars = (If_Par_t *)pp; + // set the arrival times + assert( pPars->pTimesArr == NULL ); + pPars->pTimesArr = ABC_ALLOC( float, Gia_ManCiNum(p) ); + memset( pPars->pTimesArr, 0, sizeof(float) * Gia_ManCiNum(p) ); + // translate into the mapper + pIfMan = Gia_ManToIf( p, pPars ); + if ( pIfMan == NULL ) + return NULL; + if ( p->pManTime ) + pIfMan->pManTim = Tim_ManDup( p->pManTime, 0 ); + if ( !If_ManPerformMapping( pIfMan ) ) + { + If_ManStop( pIfMan ); + return NULL; + } + // transform the result of mapping into the new network + pNew = Gia_ManFromIf( pIfMan ); + If_ManStop( pIfMan ); + // transfer name + assert( pNew->pName == NULL ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // unmap in case of SOP balancing +// if ( pIfMan->pPars->fDelayOpt ) +// Vec_IntFreeP( &pNew->vMapping ); + return pNew; } //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index f78ea847..0ae484fc 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -21,6 +21,7 @@ #include "gia.h" #include "misc/tim/tim.h" #include "proof/abs/abs.h" +#include "opt/dar/dar.h" ABC_NAMESPACE_IMPL_START @@ -107,6 +108,7 @@ void Gia_ManStop( Gia_Man_t * p ) ABC_FREE( p->pReprsOld ); ABC_FREE( p->pReprs ); ABC_FREE( p->pNexts ); + ABC_FREE( p->pSibls ); ABC_FREE( p->pRefs ); // ABC_FREE( p->pNodeRefs ); ABC_FREE( p->pHTable ); @@ -260,6 +262,36 @@ void Gia_ManPrintTents( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ +void Gia_ManPrintChoiceStats( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, nEquivs = 0, nChoices = 0; + Gia_ManMarkFanoutDrivers( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( !Gia_ObjSibl(p, i) ) + continue; + nEquivs++; + if ( pObj->fMark0 ) + nChoices++; + assert( !Gia_ObjSiblObj(p, i)->fMark0 ); + assert( Gia_ObjIsAnd(Gia_ObjSiblObj(p, i)) ); + } + Abc_Print( 1, "Choice stats: Equivs =%7d. Choices =%7d.\n", nEquivs, nChoices ); + Gia_ManCleanMark0( p ); +} + +/**Function************************************************************* + + Synopsis [Prints stats for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ void Gia_ManPrintStats( Gia_Man_t * p, int fTents, int fSwitch ) { if ( p->pName ) @@ -271,7 +303,7 @@ void Gia_ManPrintStats( Gia_Man_t * p, int fTents, int fSwitch ) printf( " ff =%7d", Gia_ManRegNum(p) ); printf( " and =%8d", Gia_ManAndNum(p) ); printf( " lev =%5d", Gia_ManLevelNum(p) ); Vec_IntFreeP( &p->vLevels ); - printf( " cut =%5d", Gia_ManCrossCut(p) ); + printf( " cut = %d(%d)", Gia_ManCrossCut(p, 0), Gia_ManCrossCut(p, 1) ); // printf( " mem =%5.2f MB", 1.0*(sizeof(Gia_Obj_t)*p->nObjs + sizeof(int)*(Vec_IntSize(p->vCis) + Vec_IntSize(p->vCos)))/(1<<20) ); printf( " mem =%5.2f MB", 1.0*(sizeof(Gia_Obj_t)*p->nObjsAlloc + sizeof(int)*(Vec_IntCap(p->vCis) + Vec_IntCap(p->vCos)))/(1<<20) ); if ( Gia_ManHasDangling(p) ) @@ -289,6 +321,8 @@ void Gia_ManPrintStats( Gia_Man_t * p, int fTents, int fSwitch ) // Gia_ManSatExperiment( p ); if ( p->pReprs && p->pNexts ) Gia_ManEquivPrintClasses( p, 0, 0.0 ); + if ( p->pSibls ) + Gia_ManPrintChoiceStats( p ); if ( p->pMapping ) Gia_ManPrintMappingStats( p ); if ( p->pPlacement ) @@ -427,6 +461,96 @@ void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew ) printf( "\n" ); } +/**Function************************************************************* + + Synopsis [Prints NPN class statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintNpnClasses( Gia_Man_t * p ) +{ + extern char ** Kit_DsdNpn4ClassNames(); + char ** pNames = Kit_DsdNpn4ClassNames(); + Vec_Int_t * vLeaves, * vTruth, * vVisited; + int * pLutClass, ClassCounts[222] = {0}; + int i, k, iFan, Class, OtherClasses, OtherClasses2, nTotal, Counter, Counter2; + unsigned * pTruth; + assert( p->pMapping != NULL ); + assert( Gia_ManLutSizeMax( p ) <= 4 ); + vLeaves = Vec_IntAlloc( 100 ); + vVisited = Vec_IntAlloc( 100 ); + vTruth = Vec_IntAlloc( (1<<16) ); + pLutClass = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManCleanTruth( p ); + Gia_ManForEachLut( p, i ) + { + if ( Gia_ObjLutSize(p,i) > 4 ) + continue; + Vec_IntClear( vLeaves ); + Gia_LutForEachFanin( p, i, iFan, k ) + Vec_IntPush( vLeaves, iFan ); + for ( ; k < 4; k++ ) + Vec_IntPush( vLeaves, 0 ); + pTruth = Gia_ManConvertAigToTruth( p, Gia_ManObj(p, i), vLeaves, vTruth, vVisited ); + Class = Dar_LibReturnClass( *pTruth ); + ClassCounts[ Class ]++; + pLutClass[i] = Class; + } + Vec_IntFree( vLeaves ); + Vec_IntFree( vTruth ); + Vec_IntFree( vVisited ); + Vec_IntFreeP( &p->vTruths ); + nTotal = 0; + for ( i = 0; i < 222; i++ ) + nTotal += ClassCounts[i]; + Abc_Print( 1, "NPN CLASS STATISTICS (for %d LUT4 present in the current mapping):\n", nTotal ); + OtherClasses = 0; + for ( i = 0; i < 222; i++ ) + { + if ( ClassCounts[i] == 0 ) + continue; + if ( 100.0 * ClassCounts[i] / (nTotal+1) < 0.1 ) // do not show anything below 0.1 percent + continue; + OtherClasses += ClassCounts[i]; + Abc_Print( 1, "Class %3d : Count = %6d (%7.2f %%) %s\n", + i, ClassCounts[i], 100.0 * ClassCounts[i] / (nTotal+1), pNames[i] ); + } + OtherClasses = nTotal - OtherClasses; + Abc_Print( 1, "Other : Count = %6d (%7.2f %%)\n", + OtherClasses, 100.0 * OtherClasses / (nTotal+1) ); + // count the number of LUTs that have MUX function and two fanins with MUX functions + OtherClasses = OtherClasses2 = 0; + ABC_FREE( p->pRefs ); + Gia_ManSetRefsMapped( p ); + Gia_ManForEachLut( p, i ) + { + if ( pLutClass[i] != 109 ) + continue; + Counter = Counter2 = 0; + Gia_LutForEachFanin( p, i, iFan, k ) + { + Counter += (pLutClass[iFan] == 109); + Counter2 += (pLutClass[iFan] == 109) && (Gia_ObjRefNumId(p, iFan) == 1); + } + OtherClasses += (Counter > 1); + OtherClasses2 += (Counter2 > 1); +// Abc_Print( 1, "%d -- ", pLutClass[i] ); +// Gia_LutForEachFanin( p, i, iFan, k ) +// Abc_Print( 1, "%d ", pLutClass[iFan] ); +// Abc_Print( 1, "\n" ); + } + ABC_FREE( p->pRefs ); + Abc_Print( 1, "Approximate number of 4:1 MUX structures: All = %6d (%7.2f %%) MFFC = %6d (%7.2f %%)\n", + OtherClasses, 100.0 * OtherClasses / (nTotal+1), + OtherClasses2, 100.0 * OtherClasses2 / (nTotal+1) ); + ABC_FREE( pLutClass ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaScl.c b/src/aig/gia/giaScl.c index 0aa255db..9b4c1c3e 100644 --- a/src/aig/gia/giaScl.c +++ b/src/aig/gia/giaScl.c @@ -94,6 +94,32 @@ Gia_Man_t * Gia_ManCleanup( Gia_Man_t * p ) return Gia_ManDupMarked( p ); } +/**Function************************************************************* + + Synopsis [Skip the first outputs during cleanup.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCleanupOutputs( Gia_Man_t * p, int nOutputs ) +{ + Gia_Obj_t * pObj; + int i; + assert( Gia_ManRegNum(p) == 0 ); + assert( nOutputs < Gia_ManCoNum(p) ); + Gia_ManCombMarkUsed( p ); + Gia_ManForEachCo( p, pObj, i ) + if ( i < nOutputs ) + pObj->fMark0 = 1; + else + break; + return Gia_ManDupMarked( p ); +} + /**Function************************************************************* diff --git a/src/aig/gia/giaUtil.c b/src/aig/gia/giaUtil.c index da713aa0..8389a9b0 100644 --- a/src/aig/gia/giaUtil.c +++ b/src/aig/gia/giaUtil.c @@ -550,12 +550,59 @@ int * Gia_ManCreateMuxRefs( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -int Gia_ManCrossCut( Gia_Man_t * p ) +void Gia_ManDfsForCrossCut_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) { + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + return; + } + if ( Gia_ObjIsCo(pObj) ) + { + Gia_ObjFanin0(pObj)->Value++; + Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin0(pObj), vNodes ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ObjFanin0(pObj)->Value++; + Gia_ObjFanin1(pObj)->Value++; + Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin0(pObj), vNodes ); + Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin1(pObj), vNodes ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); +} +Vec_Int_t * Gia_ManDfsForCrossCut( Gia_Man_t * p, int fReverse ) +{ + Vec_Int_t * vNodes; + Gia_Obj_t * pObj; + int i; + Gia_ManCleanValue( p ); + vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManIncrementTravId( p ); + if ( fReverse ) + { + Gia_ManForEachCoReverse( p, pObj, i ) + if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + Gia_ManDfsForCrossCut_rec( p, pObj, vNodes ); + } + else + { + Gia_ManForEachCo( p, pObj, i ) + if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + Gia_ManDfsForCrossCut_rec( p, pObj, vNodes ); + } + return vNodes; +} +int Gia_ManCrossCut( Gia_Man_t * p, int fReverse ) +{ + Vec_Int_t * vNodes; Gia_Obj_t * pObj; int i, nCutCur = 0, nCutMax = 0; - Gia_ManCreateValueRefs( p ); - Gia_ManForEachObj( p, pObj, i ) + vNodes = Gia_ManDfsForCrossCut( p, fReverse ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) { if ( pObj->Value ) nCutCur++; @@ -574,8 +621,9 @@ int Gia_ManCrossCut( Gia_Man_t * p ) nCutCur--; } } -// Gia_ManForEachObj( p, pObj, i ) -// assert( pObj->Value == 0 ); + Vec_IntFree( vNodes ); + Gia_ManForEachObj( p, pObj, i ) + assert( pObj->Value == 0 ); return nCutMax; } @@ -1195,6 +1243,31 @@ int Gia_ManCompare( Gia_Man_t * p1, Gia_Man_t * p2 ) return 1; } +/**Function************************************************************* + + Synopsis [Marks nodes that appear as faninis of other nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManMarkFanoutDrivers( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManCleanMark0( p ); + Gia_ManForEachObj( p, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ObjFanin1(pObj)->fMark0 = 1; + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ObjFanin0(pObj)->fMark0 = 1; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index f8e16cd6..e08e11d9 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -789,7 +789,7 @@ extern ABC_DLL int Abc_NtkRecVarNum(); extern ABC_DLL Vec_Int_t * Abc_NtkRecMemory(); extern ABC_DLL int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars ); /*=== abcRec2.c ==========================================================*/ -extern ABC_DLL void Abc_NtkRecStart2( Gia_Man_t *p, int nVars, int nCuts, int fTrim ); +extern ABC_DLL void Abc_NtkRecStart2( Gia_Man_t * p, int nVars, int nCuts, int fTrim ); extern ABC_DLL void Abc_NtkRecStop2(); extern ABC_DLL void Abc_NtkRecAdd2( Abc_Ntk_t * pNtk, int fUseSOPB ); extern ABC_DLL void Abc_NtkRecPs2(int fPrintLib); @@ -798,6 +798,15 @@ extern ABC_DLL void Abc_NtkRecLibMerge2(Gia_Man_t * pGia); extern ABC_DLL int Abc_NtkRecIsRunning2(); extern ABC_DLL int Abc_NtkRecIsInTrimMode2(); extern ABC_DLL void Abc_NtkRecFilter2(int nLimit); +/*=== abcRec3.c ==========================================================*/ +extern ABC_DLL void Abc_NtkRecStart3( Gia_Man_t * p, int nVars, int nCuts, int fFuncOnly, int fVerbose ); +extern ABC_DLL void Abc_NtkRecStop3(); +extern ABC_DLL void Abc_NtkRecAdd3( Abc_Ntk_t * pNtk, int fUseSOPB ); +extern ABC_DLL void Abc_NtkRecPs3(int fPrintLib); +extern ABC_DLL Gia_Man_t * Abc_NtkRecGetGia3(); +extern ABC_DLL int Abc_NtkRecIsRunning3(); +extern ABC_DLL void Abc_NtkRecLibMerge3(Gia_Man_t * pGia); +//extern ABC_DLL void Abc_NtkRecFilter3(int nLimit); /*=== abcReconv.c ==========================================================*/ extern ABC_DLL Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ); extern ABC_DLL void Abc_NtkManCutStop( Abc_ManCut_t * p ); diff --git a/src/base/abc/abcCheck.c b/src/base/abc/abcCheck.c index bc3399e0..6dc06f19 100644 --- a/src/base/abc/abcCheck.c +++ b/src/base/abc/abcCheck.c @@ -377,12 +377,12 @@ int Abc_NtkCheckPos( Abc_Ntk_t * pNtk ) } if ( Abc_ObjFaninNum(pObj) != 1 ) { - fprintf( stdout, "NetworkCheck: A PO \"%s\" does not have one fanin.\n", Abc_ObjName(pObj) ); + fprintf( stdout, "NetworkCheck: A PO \"%s\" does not have one fanin (but %d).\n", Abc_ObjName(pObj), Abc_ObjFaninNum(pObj) ); return 0; } if ( Abc_ObjFanoutNum(pObj) > 0 ) { - fprintf( stdout, "NetworkCheck: A PO \"%s\" has fanouts.\n", Abc_ObjName(pObj) ); + fprintf( stdout, "NetworkCheck: A PO \"%s\" has %d fanout(s).\n", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) ); return 0; } pObj->pCopy = (Abc_Obj_t *)1; diff --git a/src/base/abc/abcFanio.c b/src/base/abc/abcFanio.c index 5fb22d79..2669ae0c 100644 --- a/src/base/abc/abcFanio.c +++ b/src/base/abc/abcFanio.c @@ -87,20 +87,13 @@ void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) assert( !Abc_ObjIsComplement(pObj) ); assert( pObj->pNtk == pFaninR->pNtk ); assert( pObj->Id >= 0 && pFaninR->Id >= 0 ); + assert( !Abc_ObjIsPi(pObj) && !Abc_ObjIsPo(pFanin) ); // fanin of PI or fanout of PO + assert( !Abc_ObjIsCo(pObj) || !Abc_ObjFaninNum(pObj) ); // CO with two fanins + assert( !Abc_ObjIsNet(pObj) || !Abc_ObjFaninNum(pObj) ); // net with two fanins Vec_IntPushMem( pObj->pNtk->pMmStep, &pObj->vFanins, pFaninR->Id ); Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninR->vFanouts, pObj->Id ); if ( Abc_ObjIsComplement(pFanin) ) Abc_ObjSetFaninC( pObj, Abc_ObjFaninNum(pObj)-1 ); - if ( Abc_ObjIsNet(pObj) && Abc_ObjFaninNum(pObj) > 1 ) - { - printf( "Abc_ObjAddFanin(): Error! Creating net \"%s\" with two fanins.\n", Abc_ObjName(pObj) ); - } -/* - if ( Abc_ObjIsCo(pFanin) ) - { - printf( "Abc_ObjAddFanin(): Error! Creating fanout of a CO.\n", Abc_ObjName(pFanin) ); - } -*/ } diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index d1acef62..c6ec9d5b 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -169,6 +169,10 @@ static int Abc_CommandSenseInput ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandNpnLoad ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandNpnSave ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSendAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSendStatus ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSendCex ( Abc_Frame_t * pAbc, int argc, char ** argv ); + static int Abc_CommandIStrash ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandICut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandIRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -201,20 +205,27 @@ static int Abc_CommandFraigDress ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandRecStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecStop ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandRecAdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecAdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecUse ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecFilter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecStart2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecStop2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecPs2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecAdd2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandRecStop2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecDump2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecMerge2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecFilter2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecStart3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecStop3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecPs3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecAdd3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecDump3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecMerge3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); + static int Abc_CommandMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandUnmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -622,6 +633,10 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "npnload", Abc_CommandNpnLoad, 0 ); Cmd_CommandAdd( pAbc, "Various", "npnsave", Abc_CommandNpnSave, 0 ); + Cmd_CommandAdd( pAbc, "Various", "send_aig", Abc_CommandSendAig, 0 ); + Cmd_CommandAdd( pAbc, "Various", "send_status", Abc_CommandSendStatus, 0 ); + Cmd_CommandAdd( pAbc, "Various", "send_cex", Abc_CommandSendCex, 0 ); + Cmd_CommandAdd( pAbc, "New AIG", "istrash", Abc_CommandIStrash, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "icut", Abc_CommandICut, 0 ); Cmd_CommandAdd( pAbc, "New AIG", "irw", Abc_CommandIRewrite, 1 ); @@ -653,16 +668,23 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Choicing", "rec_add", Abc_CommandRecAdd, 0 ); Cmd_CommandAdd( pAbc, "Choicing", "rec_ps", Abc_CommandRecPs, 0 ); Cmd_CommandAdd( pAbc, "Choicing", "rec_use", Abc_CommandRecUse, 1 ); - Cmd_CommandAdd( pAbc, "Choicing", "rec_filter", Abc_CommandRecFilter, 1 ); - Cmd_CommandAdd( pAbc, "Choicing", "rec_merge", Abc_CommandRecMerge, 1 ); - - Cmd_CommandAdd( pAbc, "Choicing", "rec_start2", Abc_CommandRecStart2, 0 ); - Cmd_CommandAdd( pAbc, "Choicing", "rec_stop2", Abc_CommandRecStop2, 0 ); - Cmd_CommandAdd( pAbc, "Choicing", "rec_add2", Abc_CommandRecAdd2, 0 ); - Cmd_CommandAdd( pAbc, "Choicing", "rec_ps2", Abc_CommandRecPs2, 0 ); - Cmd_CommandAdd( pAbc, "Choicing", "rec_dump2", Abc_CommandRecDump2, 1 ); - Cmd_CommandAdd( pAbc, "Choicing", "rec_filter2", Abc_CommandRecFilter2, 1 ); - Cmd_CommandAdd( pAbc, "Choicing", "rec_merge2", Abc_CommandRecMerge2, 1 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_filter", Abc_CommandRecFilter, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_merge", Abc_CommandRecMerge, 0 ); + + Cmd_CommandAdd( pAbc, "Choicing", "rec_start2", Abc_CommandRecStart2, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_stop2", Abc_CommandRecStop2, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_ps2", Abc_CommandRecPs2, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_add2", Abc_CommandRecAdd2, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_dump2", Abc_CommandRecDump2, 1 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_filter2", Abc_CommandRecFilter2, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_merge2", Abc_CommandRecMerge2, 0 ); + + Cmd_CommandAdd( pAbc, "Choicing", "rec_start3", Abc_CommandRecStart3, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_stop3", Abc_CommandRecStop3, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_ps3", Abc_CommandRecPs3, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_add3", Abc_CommandRecAdd3, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_dump3", Abc_CommandRecDump3, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_merge3", Abc_CommandRecMerge3, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "map", Abc_CommandMap, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "amap", Abc_CommandAmap, 1 ); @@ -2628,10 +2650,10 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) pNtk = Abc_FrameReadNtk(pAbc); // set defaults - fVerbose = 1; + fVerbose = 0; fReorder = 1; fDualRail = 0; - fBddSizeMax = 50000000; + fBddSizeMax = ABC_INFINITY; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Brdvh" ) ) != EOF ) { @@ -4824,6 +4846,7 @@ usage: Abc_Print( -2, "\t 1: algebraic factoring applied to ISOP\n" ); Abc_Print( -2, "\t 2: bi-decomposition with cofactoring\n" ); Abc_Print( -2, "\t 3: disjoint-support decomposition with cofactoring\n" ); + Abc_Print( -2, "\t 4: updated disjoint-support decomposition with cofactoring\n" ); Abc_Print( -2, "\t-N <num> : the number of support variables (binary files only) [default = unused]\n" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -4846,15 +4869,16 @@ usage: ***********************************************************************/ int Abc_CommandTestNpn( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern int Abc_NpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, int fVerbose ); + extern int Abc_NpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, int fBinary, int fVerbose ); char * pFileName; int c; int fVerbose = 0; int NpnType = 0; int nVarNum = -1; int fDumpRes = 0; + int fBinary = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ANdvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ANdbvh" ) ) != EOF ) { switch ( c ) { @@ -4883,6 +4907,9 @@ int Abc_CommandTestNpn( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'd': fDumpRes ^= 1; break; + case 'b': + fBinary ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -4905,11 +4932,11 @@ int Abc_CommandTestNpn( Abc_Frame_t * pAbc, int argc, char ** argv ) // get the output file name pFileName = argv[globalUtilOptind]; // call the testbench - Abc_NpnTest( pFileName, NpnType, nVarNum, fDumpRes, fVerbose ); + Abc_NpnTest( pFileName, NpnType, nVarNum, fDumpRes, fBinary, fVerbose ); return 0; usage: - Abc_Print( -2, "usage: testnpn [-AN <num>] [-dvh] <file>\n" ); + Abc_Print( -2, "usage: testnpn [-AN <num>] [-dbvh] <file>\n" ); Abc_Print( -2, "\t testbench for computing (semi-)canonical forms\n" ); Abc_Print( -2, "\t of completely-specified Boolean functions up to 16 varibles\n" ); Abc_Print( -2, "\t-A <num> : semi-caninical form computation algorithm [default = %d]\n", NpnType ); @@ -4920,6 +4947,7 @@ usage: Abc_Print( -2, "\t 4: Jake's hybrid semi-canonical form (high-effort)\n" ); Abc_Print( -2, "\t-N <num> : the number of support variables (binary files only) [default = unused]\n" ); Abc_Print( -2, "\t-d : toggle dumping resulting functions into a file [default = %s]\n", fDumpRes? "yes": "no" ); + Abc_Print( -2, "\t-b : toggle dumping in binary format [default = %s]\n", fBinary? "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<file> : a text file with truth tables in hexadecimal, listed one per line,\n"); @@ -11602,6 +11630,171 @@ usage: return 1; } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSendAig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Gia_ManToBridgeAbsNetlist( FILE * pFile, Gia_Man_t * p ); + int c, fAndSpace = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "a" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fAndSpace ^= 1; + break; + default: + goto usage; + } + } + if ( !Abc_FrameIsBridgeMode() ) + { + Abc_Print( -1, "The bridge mode is not available.\n" ); + return 1; + } + if ( fAndSpace ) + { + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "There is no AIG in the &-space.\n" ); + return 1; + } + Gia_ManToBridgeAbsNetlist( stdout, pAbc->pGia ); + } + else + { + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); + Aig_Man_t * pAig; + Gia_Man_t * pGia; + if ( pAbc->pNtkCur == NULL ) + { + Abc_Print( -1, "There is no network in the main-space.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) + { + Abc_Print( -1, "The main-space network is not an AIG.\n" ); + return 1; + } + pAig = Abc_NtkToDar( pAbc->pNtkCur, 0, 1 ); + pGia = Gia_ManFromAig( pAig ); + Aig_ManStop( pAig ); + Gia_ManToBridgeAbsNetlist( stdout, pGia ); + Gia_ManStop( pGia ); + } + return 0; + +usage: + Abc_Print( -2, "usage: send_aig -a\n" ); + Abc_Print( -2, "\t sends current AIG to the bridge\n" ); + Abc_Print( -2, "\t-a : toggle sending AIG from &-space [default = %s]\n", fAndSpace? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSendStatus( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Gia_ManToBridgeResult( FILE * pFile, int Result, Abc_Cex_t * pCex ); + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_FrameIsBridgeMode() ) + { + Abc_Print( -1, "The bridge mode is not available.\n" ); + return 1; + } + if ( pAbc->Status == 0 && pAbc->pCex == NULL ) + { + Abc_Print( -1, "Status is \"sat\", but current CEX is not available.\n" ); + return 1; + } + Gia_ManToBridgeResult( stdout, pAbc->Status, pAbc->pCex ); + return 0; + +usage: + Abc_Print( -2, "usage: send_status\n" ); + Abc_Print( -2, "\t sends current status to the bridge\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSendCex( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManFromBridgeCex( FILE * pFile, Abc_Cex_t * pCex ); + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_FrameIsBridgeMode() ) + { + Abc_Print( -1, "The bridge mode is not available.\n" ); + return 1; + } + if ( pAbc->pCex == NULL ) + { + Abc_Print( -1, "Current CEX is not available.\n" ); + return 1; + } + Gia_ManFromBridgeCex( stdout, pAbc->pCex ); + return 0; + +usage: + Abc_Print( -2, "usage: send_cex\n" ); + Abc_Print( -2, "\t sends current CEX to the bridge\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* @@ -12312,19 +12505,18 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandRecAdd( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandRecPs( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - int c; - int fUseSOPB = 0; +// Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c, fPrintLib = 0; // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "gh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ph" ) ) != EOF ) { switch ( c ) { - case 'g': - fUseSOPB = 1; + case 'p': + fPrintLib ^= 1; break; case 'h': goto usage; @@ -12332,22 +12524,17 @@ int Abc_CommandRecAdd( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( !Abc_NtkIsStrash(pNtk) ) - { - Abc_Print( -1, "This command works for AIGs.\n" ); - return 0; - } if ( !Abc_NtkRecIsRunning() ) { - Abc_Print( -1, "This command works for AIGs after calling \"rec_start\".\n" ); + Abc_Print( -1, "This command works for AIGs only after calling \"rec_start\".\n" ); return 0; } - Abc_NtkRecAdd( pNtk, fUseSOPB); + Abc_NtkRecPs(fPrintLib); return 0; usage: - Abc_Print( -2, "usage: rec_add [-h]\n" ); - Abc_Print( -2, "\t adds subgraphs from the current network to the set\n" ); + Abc_Print( -2, "usage: rec_ps [-h]\n" ); + Abc_Print( -2, "\t prints statistics about the recorded AIG subgraphs\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -12363,18 +12550,19 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandRecPs( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandRecAdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { -// Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - int c, fPrintLib = 0; + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseSOPB = 0; // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ph" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "gh" ) ) != EOF ) { switch ( c ) { - case 'p': - fPrintLib ^= 1; + case 'g': + fUseSOPB = 1; break; case 'h': goto usage; @@ -12382,17 +12570,22 @@ int Abc_CommandRecPs( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works for AIGs.\n" ); + return 0; + } if ( !Abc_NtkRecIsRunning() ) { - Abc_Print( -1, "This command works for AIGs only after calling \"rec_start\".\n" ); + Abc_Print( -1, "This command works for AIGs after calling \"rec_start\".\n" ); return 0; } - Abc_NtkRecPs(fPrintLib); + Abc_NtkRecAdd( pNtk, fUseSOPB); return 0; usage: - Abc_Print( -2, "usage: rec_ps [-h]\n" ); - Abc_Print( -2, "\t prints statistics about the recorded AIG subgraphs\n" ); + Abc_Print( -2, "usage: rec_add [-h]\n" ); + Abc_Print( -2, "\t adds subgraphs from the current network to the set\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -12728,19 +12921,18 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandRecAdd2( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandRecPs2( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - int c; - int fUseSOPB = 0; +// Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c, fPrintLib = 0; // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "gh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ph" ) ) != EOF ) { switch ( c ) { - case 'g': - fUseSOPB = 1; + case 'p': + fPrintLib ^= 1; break; case 'h': goto usage; @@ -12748,22 +12940,17 @@ int Abc_CommandRecAdd2( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( !Abc_NtkIsStrash(pNtk) ) - { - Abc_Print( -1, "This command works for AIGs.\n" ); - return 0; - } if ( !Abc_NtkRecIsRunning2() ) { - Abc_Print( -1, "This command works for AIGs after calling \"rec_start2\".\n" ); + Abc_Print( -1, "This command works for AIGs only after calling \"rec_start2\".\n" ); return 0; } - Abc_NtkRecAdd2( pNtk, fUseSOPB); + Abc_NtkRecPs2(fPrintLib); return 0; usage: - Abc_Print( -2, "usage: rec_add2 [-h]\n" ); - Abc_Print( -2, "\t adds subgraphs from the current network to the set\n" ); + Abc_Print( -2, "usage: rec_ps2 [-h]\n" ); + Abc_Print( -2, "\t prints statistics about the recorded AIG subgraphs\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -12780,18 +12967,19 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandRecPs2( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandRecAdd2( Abc_Frame_t * pAbc, int argc, char ** argv ) { -// Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - int c, fPrintLib = 0; + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseSOPB = 0; // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ph" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "gh" ) ) != EOF ) { switch ( c ) { - case 'p': - fPrintLib ^= 1; + case 'g': + fUseSOPB = 1; break; case 'h': goto usage; @@ -12799,17 +12987,22 @@ int Abc_CommandRecPs2( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works for AIGs.\n" ); + return 0; + } if ( !Abc_NtkRecIsRunning2() ) { - Abc_Print( -1, "This command works for AIGs only after calling \"rec_start2\".\n" ); + Abc_Print( -1, "This command works for AIGs after calling \"rec_start2\".\n" ); return 0; } - Abc_NtkRecPs2(fPrintLib); + Abc_NtkRecAdd2( pNtk, fUseSOPB); return 0; usage: - Abc_Print( -2, "usage: rec_ps2 [-h]\n" ); - Abc_Print( -2, "\t prints statistics about the recorded AIG subgraphs\n" ); + Abc_Print( -2, "usage: rec_add2 [-h]\n" ); + Abc_Print( -2, "\t adds subgraphs from the current network to the set\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -13018,6 +13211,405 @@ usage: } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecStart3( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char * FileName, * pTemp; + char ** pArgvNew; + int c, nArgcNew; + FILE * pFile; + Gia_Man_t * pGia = NULL; + int nVars = 6; + int nCuts = 32; + int fFuncOnly = 0; + int fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KCfvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 1 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCuts < 1 ) + goto usage; + break; + case 'f': + fFuncOnly ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !(nVars >= 3 && nVars <= 16) ) + { + Abc_Print( -1, "The range of allowed values is 3 <= K <= 16.\n" ); + return 0; + } + if ( Abc_NtkRecIsRunning3() ) + { + Abc_Print( -1, "The AIG subgraph recording is already started.\n" ); + return 0; + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + Abc_Print( 1, "File name is not given on the command line. Starting a new record.\n" ); + else + { + // get the input file name + FileName = pArgvNew[0]; + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pGia = Gia_ReadAiger( FileName, 1, 0 ); + if ( pGia == NULL ) + { + Abc_Print( -1, "Reading AIGER has failed.\n" ); + return 0; + } + } + Abc_NtkRecStart3( pGia, nVars, nCuts, fFuncOnly, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: rec_start3 [-K num] [-C num] [-fvh] <file>\n" ); + Abc_Print( -2, "\t starts recording AIG subgraphs (should be called for\n" ); + Abc_Print( -2, "\t an empty network or after reading in a previous record)\n" ); + Abc_Print( -2, "\t-K num : the largest number of inputs [default = %d]\n", nVars ); + Abc_Print( -2, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCuts ); + Abc_Print( -2, "\t-f : toggles recording functions without AIG subgraphs [default = %s]\n", fFuncOnly? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t<file> : AIGER file with the library\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecStop3( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning3() ) + { + Abc_Print( -1, "This command works only after calling \"rec_start3\".\n" ); + return 0; + } + Abc_NtkRecStop3(); + return 0; + +usage: + Abc_Print( -2, "usage: rec_stop3 [-h]\n" ); + Abc_Print( -2, "\t cleans the internal storage for AIG subgraphs\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecPs3( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c, fPrintLib = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ph" ) ) != EOF ) + { + switch ( c ) + { + case 'p': + fPrintLib ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning3() ) + { + Abc_Print( -1, "This command works for AIGs only after calling \"rec_start2\".\n" ); + return 0; + } + Abc_NtkRecPs3(fPrintLib); + return 0; + +usage: + Abc_Print( -2, "usage: rec_ps3 [-h]\n" ); + Abc_Print( -2, "\t prints statistics about the recorded AIG subgraphs\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecAdd3( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseSOPB = 0; + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "gh" ) ) != EOF ) + { + switch ( c ) + { + case 'g': + fUseSOPB = 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works for AIGs.\n" ); + return 0; + } + if ( !Abc_NtkRecIsRunning3() ) + { + Abc_Print( -1, "This command works for AIGs after calling \"rec_start2\".\n" ); + return 0; + } + Abc_NtkRecAdd3( pNtk, fUseSOPB ); + return 0; + +usage: + Abc_Print( -2, "usage: rec_add3 [-h]\n" ); + Abc_Print( -2, "\t adds subgraphs from the current network to the set\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecDump3( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char * FileName; + char ** pArgvNew; + int nArgcNew; + Gia_Man_t * pGia; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning3() ) + { + Abc_Print( -1, "The AIG subgraph recording is not started.\n" ); + return 1; + } + + pGia = Abc_NtkRecGetGia3(); + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "File name is not given on the command line.\n" ); + return 1; + } + else if( Gia_ManPoNum(pGia) == 0 ) + { + Abc_Print( 0, "No structure in the library.\n" ); + return 1; + } + else + { + // get the input file name + FileName = pArgvNew[0]; + Gia_WriteAiger( pGia, FileName, 0, 0 ); + } + return 0; + +usage: + Abc_Print( -2, "usage: rec_dump3 [-h] <file>\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t<file> : AIGER file to write the library\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecMerge3( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c; + char * FileName, * pTemp; + char ** pArgvNew; + int nArgcNew; + FILE * pFile; + Gia_Man_t * pGia = NULL; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning3() ) + { + Abc_Print( -1, "This command works for AIGs only after calling \"rec_start3\".\n" ); + return 0; + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "File name is not given on the command line.\n" ); + return 1; + } + else + { + // get the input file name + FileName = pArgvNew[0]; + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pGia = Gia_ReadAiger( FileName, 1, 0 ); + if ( pGia == NULL ) + { + Abc_Print( -1, "Reading AIGER has failed.\n" ); + return 0; + } + } + Abc_NtkRecLibMerge3(pGia); + Gia_ManStop( pGia ); + return 0; + +usage: + Abc_Print( -2, "usage: rec_merge3 [-h] <file>\n" ); + Abc_Print( -2, "\t merge libraries\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t<file> : AIGER file with the library\n"); + return 1; +} + + /**Function************************************************************* Synopsis [] @@ -13052,7 +13644,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) DelayMulti = 0; fAreaOnly = 0; fRecovery = 1; - fSweep = 1; + fSweep = 0; fSwitching = 0; fVerbose = 0; Extra_UtilGetoptReset(); @@ -14392,7 +14984,7 @@ usage: Abc_Print( -2, "\t-d : toggles deriving local AIGs using bi-decomposition [default = %s]\n", pPars->fBidec? "yes": "no" ); Abc_Print( -2, "\t-b : toggles the use of one special feature [default = %s]\n", pPars->fUseBat? "yes": "no" ); Abc_Print( -2, "\t-u : toggles the use of MUXes along with LUTs [default = %s]\n", fLutMux? "yes": "no" ); - Abc_Print( -2, "\t-g : toggles global delay optimization [default = %s]\n", pPars->fDelayOpt? "yes": "no" ); + Abc_Print( -2, "\t-g : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" ); Abc_Print( -2, "\t-y : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" ); Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" ); Abc_Print( -2, "\t-j : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" ); @@ -16004,7 +16596,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, "PQFCLSIVMNcmplkofdsevwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLSIVMNcmplkofdseqvwh" ) ) != EOF ) { switch ( c ) { @@ -16148,6 +16740,9 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'e': pPars->fEquivDump ^= 1; break; + case 'q': + pPars->fStopWhenGone ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -16214,7 +16809,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: scorr [-PQFCLSIVMN <num>] [-cmplkodsevwh]\n" ); + Abc_Print( -2, "usage: scorr [-PQFCLSIVMN <num>] [-cmplkodseqvwh]\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 ); @@ -16237,6 +16832,7 @@ usage: Abc_Print( -2, "\t-d : toggle dynamic addition of constraints [default = %s]\n", pPars->fDynamic? "yes": "no" ); Abc_Print( -2, "\t-s : toggle local simulation in the cone of influence [default = %s]\n", pPars->fLocalSim? "yes": "no" ); Abc_Print( -2, "\t-e : toggle dumping disproved internal equivalences [default = %s]\n", pPars->fEquivDump? "yes": "no" ); + Abc_Print( -2, "\t-q : toggle quitting when PO is not a constant candidate [default = %s]\n", pPars->fStopWhenGone? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printout of flop equivalences [default = %s]\n", pPars->fFlopVerbose? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -22697,7 +23293,12 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Empty network.\n" ); return 1; } - if ( Gia_ManHasDangling(pAbc->pGia) == 0 ) + if ( pAbc->pGia->pMapping ) + { + extern Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p ); + pNtk = Abc_NtkFromMappedGia( pAbc->pGia ); + } + else if ( Gia_ManHasDangling(pAbc->pGia) == 0 ) { pMan = Gia_ManToAig( pAbc->pGia, 0 ); pNtk = Abc_NtkFromAigPhase( pMan ); @@ -25098,7 +25699,7 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; Cec_ManCorSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FCPkrecwvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "FCPkrecqwvh" ) ) != EOF ) { switch ( c ) { @@ -25147,6 +25748,9 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'c': pPars->fUseCSat ^= 1; break; + case 'q': + pPars->fStopWhenGone ^= 1; + break; case 'w': pPars->fVerboseFlops ^= 1; break; @@ -25172,7 +25776,7 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &scorr [-FCP num] [-krecwvh]\n" ); + Abc_Print( -2, "usage: &scorr [-FCP num] [-krecqwvh]\n" ); Abc_Print( -2, "\t performs signal correpondence computation\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-F num : the number of timeframes in inductive case [default = %d]\n", pPars->nFrames ); @@ -25181,6 +25785,7 @@ usage: Abc_Print( -2, "\t-r : toggle using implication rings during refinement [default = %s]\n", pPars->fUseRings? "yes": "no" ); Abc_Print( -2, "\t-e : toggle using equivalences as choices [default = %s]\n", pPars->fMakeChoices? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using circuit-based SAT solver [default = %s]\n", pPars->fUseCSat? "yes": "no" ); + Abc_Print( -2, "\t-q : toggle quitting when PO is not a constant candidate [default = %s]\n", pPars->fStopWhenGone? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing verbose info about equivalent flops [default = %s]\n", pPars->fVerboseFlops? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -26210,20 +26815,18 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) { char Buffer[200]; char LutSize[200]; + Gia_Man_t * pNew; If_Par_t Pars, * pPars = &Pars; int c; - extern void Gia_ManSetIfParsDefault( If_Par_t * pPars ); - extern int Gia_MappingIf( Gia_Man_t * p, If_Par_t * pPars ); // set defaults Gia_ManSetIfParsDefault( pPars ); -// if ( pAbc->pAbc8Lib == NULL ) -// { -// Abc_Print( -1, "LUT library is not given. Using default LUT library.\n" ); -// pAbc->pAbc8Lib = If_SetSimpleLutLib( 6 ); -// } -// pPars->pLutLib = pAbc->pAbc8Lib; + if ( pAbc->pLibLut == NULL ) + { + Abc_Print( -1, "LUT library is not given. Using default LUT library.\n" ); + pAbc->pLibLut = If_SetSimpleLutLib( 6 ); + } Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADEqaflepmrsdbvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGDEWSqaflepmrsdbgyojikcvh" ) ) != EOF ) { switch ( c ) { @@ -26273,6 +26876,17 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nAreaIters < 0 ) goto usage; break; + case 'G': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer no less than 3.\n" ); + goto usage; + } + pPars->nGateSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nGateSize < 2 ) + goto usage; + break; case 'D': if ( globalUtilOptind >= argc ) { @@ -26295,6 +26909,31 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->Epsilon < 0.0 || pPars->Epsilon > 1.0 ) goto usage; break; + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by a floating point number.\n" ); + goto usage; + } + pPars->WireDelay = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->WireDelay < 0.0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by string.\n" ); + goto usage; + } + pPars->pLutStruct = argv[globalUtilOptind]; + globalUtilOptind++; + if ( strlen(pPars->pLutStruct) != 2 && strlen(pPars->pLutStruct) != 3 ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by a 2- or 3-char string (e.g. \"44\" or \"555\").\n" ); + goto usage; + } + break; case 'q': pPars->fPreprocess ^= 1; break; @@ -26328,6 +26967,27 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'b': pPars->fUseBat ^= 1; break; + case 'g': + pPars->fDelayOpt ^= 1; + break; + case 'y': + pPars->fUserRecLib ^= 1; + break; + case 'o': + pPars->fUseBuffs ^= 1; + break; + case 'j': + pPars->fEnableCheck07 ^= 1; + break; + case 'i': + pPars->fEnableCheck08 ^= 1; + break; + case 'k': + pPars->fEnableCheck10 ^= 1; + break; + case 'c': + pPars->fEnableRealPos ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -26336,12 +26996,27 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( pAbc->pGia == NULL ) { - Abc_Print( -1, "Abc_CommandAbc9If(): There is no AIG to map.\n" ); + Abc_Print( -1, "Empty GIA network.\n" ); return 1; } + if ( pPars->nLutSize == -1 ) + { + if ( pPars->pLutLib == NULL ) + { + Abc_Print( -1, "The LUT library is not given.\n" ); + return 1; + } + // get LUT size from the library + pPars->nLutSize = pPars->pLutLib->LutMax; + // if variable pin delay, force truth table computation +// if ( pPars->pLutLib->fVarPinDelays ) +// pPars->fTruth = 1; + } + if ( pPars->nLutSize < 3 || pPars->nLutSize > IF_MAX_LUTSIZE ) { Abc_Print( -1, "Incorrect LUT size (%d).\n", pPars->nLutSize ); @@ -26355,9 +27030,10 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) } // enable truth table computation if choices are selected - if ( (c = Gia_ManCountChoiceNodes( pAbc->pGia )) ) + if ( Gia_ManHasChoices(pAbc->pGia) ) { - Abc_Print( 0, "Performing LUT mapping with %d choices.\n", c ); + if ( !Abc_FrameReadFlag("silentmode") ) + Abc_Print( 0, "Performing LUT mapping with choices.\n" ); pPars->fExpRed = 0; } @@ -26371,12 +27047,86 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fCutMin = 1; } + if ( pPars->fEnableCheck07 + pPars->fEnableCheck08 + pPars->fEnableCheck10 + (pPars->pLutStruct != NULL) > 1 ) + { + Abc_Print( -1, "Only one additional check can be performed at the same time.\n" ); + return 1; + } + if ( pPars->fEnableCheck07 ) + { + if ( pPars->nLutSize < 6 || pPars->nLutSize > 7 ) + { + Abc_Print( -1, "This feature only works for {6,7}-LUTs.\n" ); + return 1; + } + pPars->pFuncCell = If_CutPerformCheck07; + pPars->fCutMin = 1; + } + if ( pPars->fEnableCheck08 ) + { + if ( pPars->nLutSize < 6 || pPars->nLutSize > 8 ) + { + Abc_Print( -1, "This feature only works for {6,7,8}-LUTs.\n" ); + return 1; + } + pPars->pFuncCell = If_CutPerformCheck08; + pPars->fCutMin = 1; + } + if ( pPars->fEnableCheck10 ) + { + if ( pPars->nLutSize < 6 || pPars->nLutSize > 10 ) + { + Abc_Print( -1, "This feature only works for {6,7,8,9,10}-LUTs.\n" ); + return 1; + } + pPars->pFuncCell = If_CutPerformCheck10; + pPars->fCutMin = 1; + } + if ( pPars->pLutStruct ) + { + if ( pPars->nLutSize < 6 || pPars->nLutSize > 16 ) + { + Abc_Print( -1, "This feature only works for [6;16]-LUTs.\n" ); + return 1; + } + pPars->pFuncCell = If_CutPerformCheck16; + pPars->fCutMin = 1; + } + // enable truth table computation if cut minimization is selected if ( pPars->fCutMin ) { pPars->fTruth = 1; pPars->fExpRed = 0; } + // modify the subgraph recording + if ( pPars->fUserRecLib ) + { + pPars->fTruth = 1; + pPars->fCutMin = 1; + pPars->fExpRed = 0; + pPars->fUsePerm = 1; + pPars->pLutLib = NULL; + } + // modify for global delay optimization + if ( pPars->fDelayOpt ) + { + pPars->fTruth = 1; + pPars->fCutMin = 1; + pPars->fExpRed = 0; + pPars->fUsePerm = 1; + pPars->pLutLib = NULL; + } + // modify for global delay optimization + if ( pPars->nGateSize > 0 ) + { + pPars->fTruth = 1; + pPars->fCutMin = 1; + pPars->fExpRed = 0; + pPars->fUsePerm = 1; + pPars->pLutLib = NULL; + pPars->nLutSize = pPars->nGateSize; + } // complain if truth tables are requested but the cut size is too large if ( pPars->fTruth && pPars->nLutSize > IF_MAX_FUNC_LUTSIZE ) @@ -26385,11 +27135,14 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( !Gia_MappingIf( pAbc->pGia, pPars ) ) + // perform mapping + pNew = Gia_ManPerformMapping( pAbc->pGia, pPars ); + if ( pNew == NULL ) { Abc_Print( -1, "Abc_CommandAbc9If(): Mapping of the AIG has failed.\n" ); return 1; } + Abc_CommandUpdate9( pAbc, pNew ); return 0; usage: @@ -26401,14 +27154,17 @@ usage: sprintf( LutSize, "library" ); else sprintf( LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: &if [-KCFA num] [-DE float] [-qarlepmdbvh]\n" ); + Abc_Print( -2, "usage: &if [-KCFAG num] [-DEW float] [-S str] [-qarlepmsdbgyojikcvh]\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 ); Abc_Print( -2, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters ); Abc_Print( -2, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters ); + Abc_Print( -2, "\t-G num : the max AND/OR gate size for mapping (0 = unused) [default = %d]\n", pPars->nGateSize ); 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 ); + 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-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-f : toggles one fancy feature [default = %s]\n", pPars->fFancy? "yes": "no" ); @@ -26417,9 +27173,16 @@ usage: Abc_Print( -2, "\t-e : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" ); Abc_Print( -2, "\t-p : uses power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" ); Abc_Print( -2, "\t-m : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" ); -// Abc_Print( -2, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeqMap? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeqMap? "yes": "no" ); Abc_Print( -2, "\t-d : toggles deriving local AIGs using bi-decomposition [default = %s]\n", pPars->fBidec? "yes": "no" ); Abc_Print( -2, "\t-b : toggles the use of one special feature [default = %s]\n", pPars->fUseBat? "yes": "no" ); + Abc_Print( -2, "\t-g : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" ); + Abc_Print( -2, "\t-y : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" ); + Abc_Print( -2, "\t-j : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" ); + Abc_Print( -2, "\t-i : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck08? "yes": "no" ); + Abc_Print( -2, "\t-k : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck10? "yes": "no" ); + Abc_Print( -2, "\t-c : toggles enabling additional feature [default = %s]\n", pPars->fEnableRealPos? "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/abcDar.c b/src/base/abci/abcDar.c index 6072a9db..dbb75f59 100644 --- a/src/base/abci/abcDar.c +++ b/src/base/abci/abcDar.c @@ -620,6 +620,150 @@ Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ) return pNtkNew; } + + +/**Function************************************************************* + + Synopsis [Creates local function of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_ObjHopFromGia_rec( Hop_Man_t * pHopMan, Gia_Man_t * p, int Id, Vec_Ptr_t * vCopies ) +{ + Gia_Obj_t * pObj; + Hop_Obj_t * gFunc, * gFunc0, * gFunc1; + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + return (Hop_Obj_t *)Vec_PtrEntry( vCopies, Id ); + Gia_ObjSetTravIdCurrentId(p, Id); + pObj = Gia_ManObj(p, Id); + assert( Gia_ObjIsAnd(pObj) ); + // compute the functions of the children + gFunc0 = Abc_ObjHopFromGia_rec( pHopMan, p, Gia_ObjFaninId0(pObj, Id), vCopies ); + gFunc1 = Abc_ObjHopFromGia_rec( pHopMan, p, Gia_ObjFaninId1(pObj, Id), vCopies ); + // get the function of the cut + gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, Gia_ObjFaninC0(pObj)), Hop_NotCond(gFunc1, Gia_ObjFaninC1(pObj)) ); + Vec_PtrWriteEntry( vCopies, Id, gFunc ); + return gFunc; +} +Hop_Obj_t * Abc_ObjHopFromGia( Hop_Man_t * pHopMan, Gia_Man_t * p, int GiaId, Vec_Ptr_t * vCopies ) +{ + int k, iFan; + assert( Gia_ObjIsLut(p, GiaId) ); + assert( Gia_ObjLutSize(p, GiaId) > 0 ); + Gia_ManIncrementTravId( p ); + Gia_LutForEachFanin( p, GiaId, iFan, k ) + { + Gia_ObjSetTravIdCurrentId(p, iFan); + Vec_PtrWriteEntry( vCopies, iFan, Hop_IthVar(pHopMan, k) ); + } + return Abc_ObjHopFromGia_rec( pHopMan, p, GiaId, vCopies ); +} + +/**Function************************************************************* + + Synopsis [Converts the network from the mapped GIA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p ) +{ + int fVerbose = 0; + int fDuplicate = 0; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjNew, * pObjNewLi, * pObjNewLo, * pConst0 = NULL; + Gia_Obj_t * pObj, * pObjLi, * pObjLo; + Vec_Ptr_t * vReflect; + int i, k, iFan, nDupGates; + assert( p->pMapping != NULL ); + 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 ); + } + // rebuild the AIG + vReflect = Vec_PtrStart( Gia_ManObjNum(p) ); + 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( pNtkNew->pManFunc, p, i, vReflect ); + pObj->Value = Abc_ObjId( pObjNew ); + } + Vec_PtrFree( vReflect ); + // connect the PO nodes + Gia_ManForEachCo( p, pObj, i ) + { + pObjNew = Abc_NtkObj( pNtkNew, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), Abc_ObjNotCond( pObjNew, Gia_ObjFaninC0(pObj) ) ); + } + // create names + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_NtkAddDummyPoNames( pNtkNew ); + Abc_NtkAddDummyBoxNames( pNtkNew ); + + // decouple the PO driver nodes to reduce the number of levels + nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, fDuplicate ); + if ( fVerbose && nDupGates && !Abc_FrameReadFlag("silentmode") ) + { + if ( !fDuplicate ) + printf( "Added %d buffers/inverters to decouple the CO drivers.\n", nDupGates ); + else + printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); + } + // remove const node if it is not used + if ( Abc_ObjFanoutNum(pConst0) == 0 ) + Abc_NtkDeleteObj( pConst0 ); + + assert( Gia_ManPiNum(p) == Abc_NtkPiNum(pNtkNew) ); + assert( Gia_ManPoNum(p) == Abc_NtkPoNum(pNtkNew) ); + assert( Gia_ManRegNum(p) == Abc_NtkLatchNum(pNtkNew) ); + + // check the resulting AIG + if ( !Abc_NtkCheck( pNtkNew ) ) + Abc_Print( 1, "Abc_NtkFromMappedGia(): Network check has failed.\n" ); + return pNtkNew; +} + + /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] diff --git a/src/base/abci/abcDec.c b/src/base/abci/abcDec.c index 309c6a50..f5dce96e 100644 --- a/src/base/abci/abcDec.c +++ b/src/base/abci/abcDec.c @@ -353,10 +353,10 @@ void Abc_TruthStoreRead( char * pFileName, Abc_TtStore_t * p ) SeeAlso [] ***********************************************************************/ -void Abc_TtStoreWrite( char * pFileName, Abc_TtStore_t * p ) +void Abc_TtStoreWrite( char * pFileName, Abc_TtStore_t * p, int fBinary ) { FILE * pFile; - int i; + int i, nBytes = 8 * Abc_Truth6WordNum( p->nVars ); pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { @@ -365,8 +365,10 @@ void Abc_TtStoreWrite( char * pFileName, Abc_TtStore_t * p ) } for ( i = 0; i < p->nFuncs; i++ ) { - Abc_TruthWriteHex( pFile, p->pFuncs[i], p->nVars ); - fprintf( pFile, "\n" ); + if ( fBinary ) + fwrite( p->pFuncs[i], nBytes, 1, pFile ); + else + Abc_TruthWriteHex( pFile, p->pFuncs[i], p->nVars ), fprintf( pFile, "\n" ); } fclose( pFile ); } @@ -441,7 +443,7 @@ void Abc_TtStoreTest( char * pFileName ) return; // write into another file - Abc_TtStoreWrite( pFileOutput, p ); + Abc_TtStoreWrite( pFileOutput, p, 0 ); // delete data-structure Abc_TtStoreFree( p, -1 ); @@ -471,6 +473,8 @@ void Abc_TruthDecPerform( Abc_TtStore_t * p, int DecType, int fVerbose ) pAlgoName = "bi-decomp"; else if ( DecType == 3 ) pAlgoName = "DSD"; + else if ( DecType == 4 ) + pAlgoName = "fast DSD"; if ( pAlgoName ) printf( "Applying %-10s to %8d func%s of %2d vars... ", @@ -535,6 +539,24 @@ void Abc_TruthDecPerform( Abc_TtStore_t * p, int DecType, int fVerbose ) Kit_DsdNtkFree( pNtk ); } } + else if ( DecType == 4 ) + { + extern void Dau_DsdTestOne( word t, int i ); + if ( p->nVars != 6 ) + { + printf( "Currently only works for 6 variables.\n" ); + return; + } + // perform disjoint-support decomposition and count AIG nodes + // (non-DSD blocks are decomposed into 2:1 MUXes, each counting as 3 AIG nodes) + assert( p->nVars == 6 ); + for ( i = 0; i < p->nFuncs; i++ ) + { + if ( fVerbose ) + printf( "%7d : ", i ); + Dau_DsdTestOne( *p->pFuncs[i], i ); + } + } else assert( 0 ); printf( "AIG nodes =%9d ", nNodes ); @@ -585,7 +607,7 @@ int Abc_DecTest( char * pFileName, int DecType, int nVarNum, int fVerbose ) printf( "Using truth tables from file \"%s\"...\n", pFileName ); if ( DecType == 0 ) { if ( nVarNum < 0 ) Abc_TtStoreTest( pFileName ); } - else if ( DecType >= 1 && DecType <= 3 ) + else if ( DecType >= 1 && DecType <= 4 ) Abc_TruthDecTest( pFileName, DecType, nVarNum, fVerbose ); else printf( "Unknown decomposition type value (%d).\n", DecType ); diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index 362f0e46..76171eee 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -228,7 +228,6 @@ If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) // set up the choice node if ( Abc_AigNodeIsChoice( pNode ) ) { - pIfMan->nChoices++; for ( pPrev = pNode, pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pPrev = pFanin, pFanin = (Abc_Obj_t *)pFanin->pData ) If_ObjSetChoice( (If_Obj_t *)pPrev->pCopy, (If_Obj_t *)pFanin->pCopy ); If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pCopy ); @@ -495,10 +494,13 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t { extern Hop_Obj_t * Abc_RecToHop( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); extern Hop_Obj_t * Abc_RecToHop2( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); - if(Abc_NtkRecIsRunning()) - pNodeNew->pData = Abc_RecToHop( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj); - else + extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); + if(Abc_NtkRecIsRunning3()) + pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj); + else if(Abc_NtkRecIsRunning2()) pNodeNew->pData = Abc_RecToHop2( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj); + else + pNodeNew->pData = Abc_RecToHop( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj); } else diff --git a/src/base/abci/abcNpn.c b/src/base/abci/abcNpn.c index 9494cba2..0e3f41f9 100644 --- a/src/base/abci/abcNpn.c +++ b/src/base/abci/abcNpn.c @@ -49,7 +49,7 @@ struct Abc_TtStore_t_ extern Abc_TtStore_t * Abc_TtStoreLoad( char * pFileName, int nVarNum ); extern void Abc_TtStoreFree( Abc_TtStore_t * p, int nVarNum ); -extern void Abc_TtStoreWrite( char * pFileName, Abc_TtStore_t * p ); +extern void Abc_TtStoreWrite( char * pFileName, Abc_TtStore_t * p, int fBinary ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -276,7 +276,7 @@ void Abc_TruthNpnPerform( Abc_TtStore_t * p, int NpnType, int fVerbose ) SeeAlso [] ***********************************************************************/ -void Abc_TruthNpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, int fVerbose ) +void Abc_TruthNpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, int fBinary, int fVerbose ) { Abc_TtStore_t * p; char * pFileNameOut; @@ -292,8 +292,11 @@ void Abc_TruthNpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, // write the result if ( fDumpRes ) { - pFileNameOut = Extra_FileNameGenericAppend( pFileName, "_out.txt" ); - Abc_TtStoreWrite( pFileNameOut, p ); + if ( fBinary ) + pFileNameOut = Extra_FileNameGenericAppend( pFileName, "_out.tt" ); + else + pFileNameOut = Extra_FileNameGenericAppend( pFileName, "_out.txt" ); + Abc_TtStoreWrite( pFileNameOut, p, fBinary ); if ( fVerbose ) printf( "The resulting functions are written into file \"%s\".\n", pFileNameOut ); } @@ -315,12 +318,12 @@ void Abc_TruthNpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, SeeAlso [] ***********************************************************************/ -int Abc_NpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, int fVerbose ) +int Abc_NpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, int fBinary, int fVerbose ) { if ( fVerbose ) printf( "Using truth tables from file \"%s\"...\n", pFileName ); if ( NpnType >= 0 && NpnType <= 4 ) - Abc_TruthNpnTest( pFileName, NpnType, nVarNum, fDumpRes, fVerbose ); + Abc_TruthNpnTest( pFileName, NpnType, nVarNum, fDumpRes, fBinary, fVerbose ); else printf( "Unknown canonical form value (%d).\n", NpnType ); fflush( stdout ); diff --git a/src/base/abci/abcRec2.c b/src/base/abci/abcRec2.c index 12e444e8..0eb843bf 100644 --- a/src/base/abci/abcRec2.c +++ b/src/base/abci/abcRec2.c @@ -86,6 +86,7 @@ struct Abc_ManRec_t_2 Vec_Ptr_t * vNodes; // the temporary nodes Vec_Ptr_t * vTtTemps; // the truth tables for the internal nodes of the cut Vec_Ptr_t * vLabels; // temporary storage for AIG node labels + Vec_Int_t * vLabelsInt; // temporary storage for AIG node labels Vec_Int_t * vUselessPos; // statistics int nTried; // the number of cuts tried @@ -1144,6 +1145,7 @@ p->timeInsert += clock() - timeInsert; p->vNodes = Vec_PtrAlloc( 100 ); p->vTtTemps = Vec_PtrAllocSimInfo( 1024, p->nWords ); p->vLabels = Vec_PtrStart( 1000 ); + p->vLabelsInt = Vec_IntStart( 1000 ); p->timeTotal += clock() - clkTotal; @@ -2065,6 +2067,105 @@ Hop_Obj_t * Abc_RecToHop2( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, /**Function************************************************************* + Synopsis [Derive the final network from the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_RecToGia2( Gia_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vLeaves, int fHash ) +{ + Rec_Obj_t2 * pCandMin; + int pHopObj, pFan0, pFan1; + Gia_Obj_t* pGiaObj, *pGiaTemp; + Gia_Man_t * pAig = s_pMan->pGia; + int nLeaves, i;// DelayMin = ABC_INFINITY , Delay = -ABC_INFINITY + unsigned uCanonPhase; + int nVars = s_pMan->nVars; + char pCanonPerm[16]; + unsigned *pInOut = s_pMan->pTemp1; + unsigned *pTemp = s_pMan->pTemp2; + int time = clock(); + int fCompl; + int * pCompl = &fCompl; + nLeaves = If_CutLeaveNum(pCut); +// if (nLeaves < 3) +// return Abc_NodeTruthToHop(pMan, pIfMan, pCut); + Kit_TruthCopy(pInOut, If_CutTruth(pCut), pCut->nLimit); + //special cases when cut-minimization return 2, that means there is only one leaf in the cut. + if ((Kit_TruthIsConst0(pInOut, nLeaves) && pCut->fCompl == 0) || (Kit_TruthIsConst1(pInOut, nLeaves) && pCut->fCompl == 1)) + return 0; + if ((Kit_TruthIsConst0(pInOut, nLeaves) && pCut->fCompl == 1) || (Kit_TruthIsConst1(pInOut, nLeaves) && pCut->fCompl == 0)) + return 1; + if (Kit_TruthSupport(pInOut, nLeaves) != Kit_BitMask(nLeaves)) + { + for (i = 0; i < nLeaves; i++) + if(Kit_TruthVarInSupport( pInOut, nLeaves, i )) + return Abc_LitNotCond( Vec_IntEntry(vLeaves, i), (pCut->fCompl ^ ((*pInOut & 0x01) > 0)) ); + } + + for (i = 0; i < nLeaves; i++) + pCanonPerm[i] = i; + uCanonPhase = Kit_TruthSemiCanonicize_new(pInOut, pTemp, nLeaves, pCanonPerm); + If_CutTruthStretch(pInOut, nLeaves, nVars); + pCandMin = Abc_NtkRecLookUpBest(pIfMan, pCut, pInOut, pCanonPerm, pCompl,NULL); + + // get the top-most GIA node + pGiaObj = Abc_NtkRecGetObj( Rec_ObjID(s_pMan, pCandMin) ); + assert( Gia_ObjIsAnd(pGiaObj) || Gia_ObjIsPi(pAig, pGiaObj) ); + // collect internal nodes into pAig->vTtNodes + if ( pAig->vTtNodes == NULL ) + pAig->vTtNodes = Vec_IntAlloc( 256 ); + Gia_ObjCollectInternal( pAig, pGiaObj ); + // collect HOP nodes for leaves + Vec_IntClear( s_pMan->vLabelsInt ); + for (i = 0; i < nLeaves; i++) + { + pHopObj = Vec_IntEntry(vLeaves, pCanonPerm[i]); + pHopObj = Abc_LitNotCond(pHopObj, ((uCanonPhase & (1 << i)) > 0)); + Vec_IntPush(s_pMan->vLabelsInt, pHopObj); + } + // compute HOP nodes for internal nodes + Gia_ManForEachObjVec( pAig->vTtNodes, pAig, pGiaTemp, i ) + { + pGiaTemp->fMark0 = 0; // unmark node marked by Gia_ObjCollectInternal() + + if ( Gia_ObjIsAnd(Gia_ObjFanin0(pGiaTemp)) ) + pFan0 = Vec_IntEntry(s_pMan->vLabelsInt, Gia_ObjNum(pAig, Gia_ObjFanin0(pGiaTemp)) + nLeaves); + else + pFan0 = Vec_IntEntry(s_pMan->vLabelsInt, Gia_ObjCioId(Gia_ObjFanin0(pGiaTemp))); + pFan0 = Abc_LitNotCond(pFan0, Gia_ObjFaninC0(pGiaTemp)); + + if ( Gia_ObjIsAnd(Gia_ObjFanin1(pGiaTemp)) ) + pFan1 = Vec_IntEntry(s_pMan->vLabelsInt, Gia_ObjNum(pAig, Gia_ObjFanin1(pGiaTemp)) + nLeaves); + else + pFan1 = Vec_IntEntry(s_pMan->vLabelsInt, Gia_ObjCioId(Gia_ObjFanin1(pGiaTemp))); + pFan1 = Abc_LitNotCond(pFan1, Gia_ObjFaninC1(pGiaTemp)); + + if ( fHash ) + pHopObj = Gia_ManHashAnd(pMan, pFan0, pFan1); + else + pHopObj = Gia_ManAppendAnd(pMan, pFan0, pFan1); + Vec_IntPush(s_pMan->vLabelsInt, pHopObj); + } + // get the final result + if ( Gia_ObjIsAnd(pGiaObj) ) + pHopObj = Vec_IntEntry(s_pMan->vLabelsInt, Gia_ObjNum(pAig, pGiaObj) + nLeaves); + else if ( Gia_ObjIsPi(pAig, pGiaObj) ) + pHopObj = Vec_IntEntry(s_pMan->vLabelsInt, Gia_ObjCioId(pGiaObj)); + else assert( 0 ); + + s_pMan->timeIfDerive += clock() - time; + s_pMan->timeIfTotal += clock() - time; + // complement the result if needed + return Abc_LitNotCond(pHopObj, (pCut->fCompl)^(((uCanonPhase & (1 << nLeaves)) > 0)) ^ fCompl); +} + +/**Function************************************************************* + Synopsis [Returns the given record.] Description [] @@ -2097,8 +2198,8 @@ void Abc_NtkRecStop2() ABC_FREE( s_pMan->pTemp2 ); Vec_PtrFree( s_pMan->vNodes ); Vec_PtrFree( s_pMan->vTtTemps ); - if ( s_pMan->vLabels ) - Vec_PtrFree( s_pMan->vLabels ); + Vec_PtrFree( s_pMan->vLabels ); + Vec_IntFree( s_pMan->vLabelsInt ); //if(s_pMan->pMemObj) // Mem_FixedStop(s_pMan->pMemObj, 0); Vec_IntFree( s_pMan->vUselessPos); diff --git a/src/base/abci/abcRec3.c b/src/base/abci/abcRec3.c new file mode 100644 index 00000000..ed6148ab --- /dev/null +++ b/src/base/abci/abcRec3.c @@ -0,0 +1,1097 @@ +/**CFile**************************************************************** + + FileName [abcRec2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Record of semi-canonical AIG subgraphs.] + + Author [Allan Yang, Alan Mishchenko] + + Affiliation [Fudan University in Shanghai, UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "base/abc/abc.h" +#include "map/if/if.h" +#include "bool/kit/kit.h" +#include "aig/gia/giaAig.h" +#include "misc/vec/vecMem.h" +#include "bool/lucky/lucky.h" +#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + This LMS manager can be used in two modes: + - library constuction + - AIG level minimization + + It is not OK to switch from library construction to AIG level minimization + without restarting LSM manager. To restart the LSM manager, GIA has to be written out + (rec_dump3 <file>.aig) and LMS manager started again (rec_start3 <file>.aig). +*/ + +typedef struct Lms_Man_t_ Lms_Man_t; +struct Lms_Man_t_ +{ + // parameters + int nVars; // the number of variables + int nWords; // the number of TT words + int nCuts; // the max number of cuts to use + int fFuncOnly; // record only functions + int fLibConstr; // this manager is used for library construction + // internal data for library construction + Gia_Man_t * pGia; // the record + Vec_Mem_t * vTtMem; // truth table memory and hash table + Vec_Int_t * vTruthIds; // truth table IDs of each PO + // internal data for AIG level minimization (allocated the first time it is called) + Vec_Int_t * vTruthPo; // first PO where this canonicized truth table was seen + Vec_Wrd_t * vDelays; // pin-to-pin delays of each PO + Vec_Str_t * vAreas; // number of AND gates in each PO + Vec_Int_t * vFreqs; // subgraph usage frequencies + // temporaries + Vec_Ptr_t * vNodes; // the temporary nodes + Vec_Ptr_t * vLabelsP; // temporary storage for HOP node labels + Vec_Int_t * vLabels; // temporary storage for AIG node labels + word pTemp1[1024]; // copy of the truth table + word pTemp2[1024]; // copy of the truth table + // statistics + int nTried; + int nFilterSize; + int nFilterRedund; + int nFilterVolume; + int nFilterTruth; + int nFilterError; + int nFilterSame; + int nAdded; + int nAddedFuncs; + int nHoleInTheWall; + // runtime + clock_t timeCollect; + clock_t timeCanon; + clock_t timeBuild; + clock_t timeCheck; + clock_t timeInsert; + clock_t timeOther; + clock_t timeTotal; +}; + +static Lms_Man_t * s_pMan3 = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Lms_Man_t * Lms_ManStart( Gia_Man_t * pGia, int nVars, int nCuts, int fFuncOnly, int fVerbose ) +{ + Lms_Man_t * p; + // if GIA is given, use the number of variables from GIA + nVars = pGia ? Gia_ManCiNum(pGia) : nVars; + assert( nVars >= 6 && nVars <= 16 ); + // allocate manager + p = ABC_CALLOC( Lms_Man_t, 1 ); + // parameters + p->nVars = nVars; + p->nCuts = nCuts; + p->nWords = Abc_Truth6WordNum( nVars ); + p->fFuncOnly = fFuncOnly; + // internal data for library construction + p->vTtMem = Vec_MemAlloc( p->nWords, 12 ); // 32 KB/page for 6-var functions + Vec_MemHashAlloc( p->vTtMem, 10000 ); + p->vTruthIds = Vec_IntAlloc( 10000 ); + if ( pGia == NULL ) + { + int i; + p->pGia = Gia_ManStart( 10000 ); + p->pGia->pName = Abc_UtilStrsav( "record" ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCi( p->pGia ); + } + else + { + Gia_Obj_t * pObj; + unsigned * pTruth; + int i, Index, Prev = -1; + p->pGia = pGia; + // populate the manager with subgraphs present in GIA + p->nAdded = Gia_ManCoNum( p->pGia ); + Gia_ManForEachCo( p->pGia, pObj, i ) + { + pTruth = Gia_ObjComputeTruthTable( p->pGia, pObj ); + Index = Vec_MemHashInsert( p->vTtMem, (word *)pTruth ); + assert( Index == Prev || Index == Prev + 1 ); // GIA subgraphs should be ordered + Vec_IntPush( p->vTruthIds, Index ); + Prev = Index; + } + } + // temporaries + p->vNodes = Vec_PtrAlloc( 1000 ); + p->vLabelsP = Vec_PtrAlloc( 1000 ); + p->vLabels = Vec_IntAlloc( 1000 ); + return p; +} +void Lms_ManStop( Lms_Man_t * p ) +{ + // temporaries + Vec_IntFreeP( &p->vLabels ); + Vec_PtrFreeP( &p->vLabelsP ); + Vec_PtrFreeP( &p->vNodes ); + // internal data for AIG level minimization + Vec_IntFreeP( &p->vTruthPo ); + Vec_WrdFreeP( &p->vDelays ); + Vec_StrFreeP( &p->vAreas ); + Vec_IntFreeP( &p->vFreqs ); + // internal data for library construction + Vec_IntFreeP( &p->vTruthIds ); + Vec_MemHashFree( p->vTtMem ); + Vec_MemFree( p->vTtMem ); + Gia_ManStop( p->pGia ); + ABC_FREE( p ); +} +void Lms_ManPrint( Lms_Man_t * p ) +{ +// Gia_ManPrintStats( p->pGia, 0, 0 ); + printf( "Library with %d vars has %d classes and %d AIG subgraphs with %d AND nodes.\n", + Gia_ManCiNum(p->pGia), Vec_MemEntryNum(p->vTtMem), p->nAdded, Gia_ManAndNum(p->pGia) ); + + p->nAddedFuncs = Vec_MemEntryNum(p->vTtMem); + printf( "Subgraphs tried = %10d. (%6.2f %%)\n", p->nTried, !p->nTried? 0 : 100.0*p->nTried/p->nTried ); + printf( "Subgraphs filtered by support size = %10d. (%6.2f %%)\n", p->nFilterSize, !p->nTried? 0 : 100.0*p->nFilterSize/p->nTried ); + printf( "Subgraphs filtered by structural redundancy = %10d. (%6.2f %%)\n", p->nFilterRedund, !p->nTried? 0 : 100.0*p->nFilterRedund/p->nTried ); + printf( "Subgraphs filtered by volume = %10d. (%6.2f %%)\n", p->nFilterVolume, !p->nTried? 0 : 100.0*p->nFilterVolume/p->nTried ); + printf( "Subgraphs filtered by TT redundancy = %10d. (%6.2f %%)\n", p->nFilterTruth, !p->nTried? 0 : 100.0*p->nFilterTruth/p->nTried ); + printf( "Subgraphs filtered by error = %10d. (%6.2f %%)\n", p->nFilterError, !p->nTried? 0 : 100.0*p->nFilterError/p->nTried ); + printf( "Subgraphs filtered by isomorphism = %10d. (%6.2f %%)\n", p->nFilterSame, !p->nTried? 0 : 100.0*p->nFilterSame/p->nTried ); + printf( "Subgraphs added = %10d. (%6.2f %%)\n", p->nAdded, !p->nTried? 0 : 100.0*p->nAdded/p->nTried ); + printf( "Functions added = %10d. (%6.2f %%)\n", p->nAddedFuncs, !p->nTried? 0 : 100.0*p->nAddedFuncs/p->nTried ); + if ( p->nHoleInTheWall ) + printf( "Cuts whose logic structure has a hole = %10d. (%6.2f %%)\n", p->nHoleInTheWall, !p->nTried? 0 : 100.0*p->nHoleInTheWall/p->nTried ); + + p->timeOther = p->timeTotal - p->timeCollect - p->timeCanon - p->timeBuild - p->timeCheck - p->timeInsert; + ABC_PRTP( "Runtime: Collect", p->timeCollect, p->timeTotal ); + ABC_PRTP( "Runtime: Canon ", p->timeCanon, p->timeTotal ); + ABC_PRTP( "Runtime: Build ", p->timeBuild, p->timeTotal ); + ABC_PRTP( "Runtime: Check ", p->timeCheck, p->timeTotal ); + ABC_PRTP( "Runtime: Insert ", p->timeInsert, p->timeTotal ); + ABC_PRTP( "Runtime: Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "Runtime: TOTAL ", p->timeTotal, p->timeTotal ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecStart3( Gia_Man_t * p, int nVars, int nCuts, int fFuncOnly, int fVerbose ) +{ + assert( s_pMan3 == NULL ); + s_pMan3 = Lms_ManStart( p, nVars, nCuts, fFuncOnly, fVerbose ); +} + +void Abc_NtkRecStop3() +{ + assert( s_pMan3 != NULL ); + Lms_ManStop( s_pMan3 ); + s_pMan3 = NULL; +} + + +/**Function************************************************************* + + Synopsis [Compute delay/area profiles of POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Lms_DelayGet( word D, int v ) { assert(v >= 0 && v < 16); return (int)((D >> (v << 2)) & 0xF); } +static inline void Lms_DelaySet( word * pD, int v, int d ) { assert(v >= 0 && v < 16); assert(d >= 0 && d < 16); *pD |= ((word)d << (v << 2)); } +static inline word Lms_DelayInit( int v ) { assert(v >= 0 && v < 16); return (word)1 << (v << 2); } +static inline word Lms_DelayMax( word D1, word D2, int nVars ) +{ + int v, Max; + word D = 0; + for ( v = 0; v < nVars; v++ ) + if ( (Max = Abc_MaxInt(Lms_DelayGet(D1, v), Lms_DelayGet(D2, v))) ) + Lms_DelaySet( &D, v, Abc_MinInt(Max + 1, 15) ); + return D; +} +static inline word Lms_DelayDecrement( word D1, int nVars ) +{ + int v; + word D = 0; + for ( v = 0; v < nVars; v++ ) + if ( Lms_DelayGet(D1, v) ) + Lms_DelaySet( &D, v, Lms_DelayGet(D1, v) - 1 ); + return D; +} +static inline int Lms_DelayEqual( word D1, word D2, int nVars ) // returns 1 if D1 has the same delays than D2 +{ + int v; + for ( v = 0; v < nVars; v++ ) + if ( Lms_DelayGet(D1, v) != Lms_DelayGet(D2, v) ) + return 0; + return 1; +} +static inline int Lms_DelayDom( word D1, word D2, int nVars ) // returns 1 if D1 has the same or smaller delays than D2 +{ + int v; + for ( v = 0; v < nVars; v++ ) + if ( Lms_DelayGet(D1, v) > Lms_DelayGet(D2, v) ) + return 0; + return 1; +} +static inline void Lms_DelayPrint( word D, int nVars ) +{ + int v; + printf( "Delay profile = {" ); + for ( v = 0; v < nVars; v++ ) + printf( " %d", Lms_DelayGet(D, v) ); + printf( " }\n" ); +} +Vec_Wrd_t * Lms_GiaDelays( Gia_Man_t * p ) +{ + Vec_Wrd_t * vDelays, * vResult; + Gia_Obj_t * pObj; + int i; + // compute delay profiles of all objects + vDelays = Vec_WrdAlloc( Gia_ManObjNum(p) ); + Vec_WrdPush( vDelays, 0 ); // const 0 + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + Vec_WrdPush( vDelays, Lms_DelayMax( Vec_WrdEntry(vDelays, Gia_ObjFaninId0(pObj, i)), Vec_WrdEntry(vDelays, Gia_ObjFaninId1(pObj, i)), Gia_ManCiNum(p) ) ); + else if ( Gia_ObjIsCo(pObj) ) + Vec_WrdPush( vDelays, Lms_DelayDecrement( Vec_WrdEntry(vDelays, Gia_ObjFaninId0(pObj, i)), Gia_ManCiNum(p) ) ); + else if ( Gia_ObjIsCi(pObj) ) + Vec_WrdPush( vDelays, Lms_DelayInit( Gia_ObjCioId(pObj) ) ); + else assert( 0 ); + } + // collect delay profiles of COs only + vResult = Vec_WrdAlloc( Gia_ManCoNum(p) ); + Gia_ManForEachCo( p, pObj, i ) + Vec_WrdPush( vResult, Vec_WrdEntry(vDelays, Gia_ObjId(p, pObj)) ); + Vec_WrdFree( vDelays ); + return vResult; +} +void Lms_ObjAreaMark_rec( Gia_Obj_t * pObj ) +{ + if ( pObj->fMark0 || Gia_ObjIsCi(pObj) ) + return; + pObj->fMark0 = 1; + Lms_ObjAreaMark_rec( Gia_ObjFanin0(pObj) ); + Lms_ObjAreaMark_rec( Gia_ObjFanin1(pObj) ); +} +int Lms_ObjAreaUnmark_rec( Gia_Obj_t * pObj ) +{ + if ( !pObj->fMark0 || Gia_ObjIsCi(pObj) ) + return 0; + pObj->fMark0 = 0; + return 1 + Lms_ObjAreaUnmark_rec( Gia_ObjFanin0(pObj) ) + + Lms_ObjAreaUnmark_rec( Gia_ObjFanin1(pObj) ); +} +int Lms_ObjArea( Gia_Obj_t * pObj ) +{ + assert( Gia_ObjIsAnd(pObj) ); + Lms_ObjAreaMark_rec( pObj ); + return Lms_ObjAreaUnmark_rec( pObj ); +} +Vec_Str_t * Lms_GiaAreas( Gia_Man_t * p ) +{ + Vec_Str_t * vAreas; + Gia_Obj_t * pObj; + int i; + vAreas = Vec_StrAlloc( Gia_ManCoNum(p) ); + Gia_ManForEachCo( p, pObj, i ) + Vec_StrPush( vAreas, (char)(Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ? Lms_ObjArea(Gia_ObjFanin0(pObj)) : 0) ); + return vAreas; +} + +/**Function************************************************************* + + Synopsis [Prints one GIA subgraph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lms_GiaPrintSubgraph_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( !pObj->fMark0 || Gia_ObjIsCi(pObj) ) + return; + pObj->fMark0 = 0; + assert( Gia_ObjIsAnd(pObj) ); + Lms_GiaPrintSubgraph_rec( p, Gia_ObjFanin0(pObj) ); + Lms_GiaPrintSubgraph_rec( p, Gia_ObjFanin1(pObj) ); + Gia_ObjPrint( p, pObj ); +} +void Lms_GiaPrintSubgraph( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + assert( Gia_ObjIsCo(pObj) ); + if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ) + { + Lms_ObjAreaMark_rec( Gia_ObjFanin0(pObj) ); + Lms_GiaPrintSubgraph_rec( p, Gia_ObjFanin0(pObj) ); + } + else + Gia_ObjPrint( p, Gia_ObjFanin0(pObj) ); + Gia_ObjPrint( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Prints delay/area profiles of the GIA subgraphs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lms_GiaProfilesPrint( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Vec_Wrd_t * vDelays; + Vec_Str_t * vAreas; + vDelays = Lms_GiaDelays( p ); + vAreas = Lms_GiaAreas( p ); + + Gia_ManForEachPo( p, pObj, i ) + { + printf( "%6d : ", i ); + printf( "A = %2d ", Vec_StrEntry(vAreas, i) ); + Lms_DelayPrint( Vec_WrdEntry(vDelays, i), Gia_ManPiNum(p) ); +// Lms_GiaPrintSubgraph( p, pObj ); +// printf( "\n" ); + } + + Vec_WrdFree( vDelays ); + Vec_StrFree( vAreas ); +} + +/**Function************************************************************* + + Synopsis [Compute support sizes for each CO.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Gia_ManSuppSizes( Gia_Man_t * p ) +{ + Vec_Str_t * vResult; + Vec_Str_t * vSupps; + Gia_Obj_t * pObj; + int i; + vSupps = Vec_StrAlloc( Gia_ManObjNum(p) ); + Vec_StrPush( vSupps, 0 ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + Vec_StrPush( vSupps, (char)Abc_MaxInt( Vec_StrEntry(vSupps, Gia_ObjFaninId0(pObj, i)), Vec_StrEntry(vSupps, Gia_ObjFaninId1(pObj, i)) ) ); + else if ( Gia_ObjIsCo(pObj) ) + Vec_StrPush( vSupps, Vec_StrEntry(vSupps, Gia_ObjFaninId0(pObj, i)) ); + else if ( Gia_ObjIsCi(pObj) ) + Vec_StrPush( vSupps, (char)(Gia_ObjCioId(pObj)+1) ); + else assert( 0 ); + } + assert( Vec_StrSize(vSupps) == Gia_ManObjNum(p) ); + vResult = Vec_StrAlloc( Gia_ManCoNum(p) ); + Gia_ManForEachCo( p, pObj, i ) + Vec_StrPush( vResult, Vec_StrEntry(vSupps, Gia_ObjId(p, pObj)) ); + Vec_StrFree( vSupps ); + return vResult; +} + + +/**Function************************************************************* + + Synopsis [Recanonicizes the library and add it to the current library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecLibMerge3( Gia_Man_t * pLib ) +{ + int fCheck = 0; + Lms_Man_t * p = s_pMan3; + Gia_Man_t * pGia = p->pGia; + Vec_Str_t * vSupps; + char pCanonPerm[16]; + unsigned uCanonPhase; + unsigned * pTruth; + int i, k, Index, iFanin0, iFanin1, nLeaves; + Gia_Obj_t * pObjPo, * pDriver, * pTemp = NULL; + clock_t clk, clk2 = clock(); + + assert( Gia_ManCiNum(pLib) == Gia_ManCiNum(pGia) ); + + // create hash table if not available + if ( pGia->pHTable == NULL ) + Gia_ManHashStart( pGia ); + + // add AIG subgraphs + vSupps = Gia_ManSuppSizes( pLib ); + Gia_ManForEachCo( pLib, pObjPo, k ) + { + // get support size + nLeaves = Vec_StrEntry(vSupps, k); + assert( nLeaves > 1 ); + // compute the truth table +clk = clock(); + pTruth = Gia_ObjComputeTruthTable( pLib, Gia_ObjFanin0(pObjPo) ); +p->timeCollect += clock() - clk; + // semi-canonicize +clk = clock(); + memcpy( p->pTemp1, pTruth, p->nWords * sizeof(word) ); + // uCanonPhase = luckyCanonicizer_final_fast( p->pTemp1, nLeaves, pCanonPerm ); + uCanonPhase = Kit_TruthSemiCanonicize( (unsigned *)p->pTemp1, (unsigned *)p->pTemp2, nLeaves, pCanonPerm ); + Abc_TtStretch5( (unsigned *)p->pTemp1, nLeaves, p->nVars ); +p->timeCanon += clock() - clk; + // pCanonPerm and uCanonPhase show what was the variable corresponding to each var in the current truth + +clk = clock(); + // map cut leaves into elementary variables of GIA + for ( i = 0; i < nLeaves; i++ ) + Gia_ManCi( pLib, pCanonPerm[i] )->Value = Abc_Var2Lit( Gia_ObjId(pGia, Gia_ManPi(pGia, i)), (uCanonPhase >> i) & 1 ); + // build internal nodes + assert( Vec_IntSize(pLib->vTtNodes) > 0 ); + Gia_ManForEachObjVec( pLib->vTtNodes, pLib, pTemp, i ) + { + iFanin0 = Abc_LitNotCond( Gia_ObjFanin0(pTemp)->Value, Gia_ObjFaninC0(pTemp) ); + iFanin1 = Abc_LitNotCond( Gia_ObjFanin1(pTemp)->Value, Gia_ObjFaninC1(pTemp) ); + pTemp->Value = Gia_ManHashAnd( pGia, iFanin0, iFanin1 ); + } +p->timeBuild += clock() - clk; + + // check if this node is already driving a PO + assert( Gia_ObjIsAnd(pTemp) ); + pDriver = Gia_ManObj(pGia, Abc_Lit2Var(pTemp->Value)); + if ( pDriver->fMark1 ) + { + p->nFilterSame++; + continue; + } + pDriver->fMark1 = 1; + // create output + Gia_ManAppendCo( pGia, Abc_LitNotCond( pTemp->Value, (uCanonPhase >> nLeaves) & 1 ) ); + + // verify truth table + if ( fCheck ) + { +clk = clock(); + pTemp = Gia_ManCo(pGia, Gia_ManCoNum(pGia)-1); + pTruth = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, Gia_ManCoNum(pGia)-1) ); +p->timeCheck += clock() - clk; + if ( memcmp( p->pTemp1, pTruth, p->nWords * sizeof(word) ) != 0 ) + { + + Kit_DsdPrintFromTruth( pTruth, nLeaves ); printf( "\n" ); + Kit_DsdPrintFromTruth( (unsigned *)p->pTemp1, nLeaves ); printf( "\n" ); + printf( "Truth table verification has failed.\n" ); + + // drive PO with constant + Gia_ManPatchCoDriver( pGia, Gia_ManCoNum(pGia)-1, 0 ); + // save truth table ID + Vec_IntPush( p->vTruthIds, -1 ); + p->nFilterTruth++; + continue; + } + } + +clk = clock(); + // add the resulting truth table to the hash table + Index = Vec_MemHashInsert( p->vTtMem, p->pTemp1 ); + // save truth table ID + Vec_IntPush( p->vTruthIds, Index ); + assert( Gia_ManCoNum(pGia) == Vec_IntSize(p->vTruthIds) ); + p->nAdded++; +p->timeInsert += clock() - clk; + } + Vec_StrFree( vSupps ); +p->timeTotal += clock() - clk2; +} + + +/**Function************************************************************* + + Synopsis [Evaluates one cut during library construction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecAddCut3( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut ) +{ + Lms_Man_t * p = s_pMan3; + char pCanonPerm[16]; + unsigned uCanonPhase; + int i, Index, iFanin0, iFanin1, fHole; + int nLeaves = If_CutLeaveNum(pCut); + Vec_Ptr_t * vNodes = p->vNodes; + Gia_Man_t * pGia = p->pGia; + Gia_Obj_t * pDriver; + If_Obj_t * pIfObj = NULL; + unsigned * pTruth; + clock_t clk; + p->nTried++; + + // skip small cuts + assert( p->nVars == (int)pCut->nLimit ); + if ( nLeaves < 2 ) + { + p->nFilterSize++; + return 1; + } + + // collect internal nodes and skip redundant cuts +clk = clock(); + If_CutTraverse( pIfMan, pRoot, pCut, vNodes ); +p->timeCollect += clock() - clk; + + // semi-canonicize truth table +clk = clock(); + memcpy( p->pTemp1, If_CutTruthW(pCut), p->nWords * sizeof(word) ); +// uCanonPhase = luckyCanonicizer_final_fast( p->pTemp1, nLeaves, pCanonPerm ); + uCanonPhase = Kit_TruthSemiCanonicize( (unsigned *)p->pTemp1, (unsigned *)p->pTemp2, nLeaves, pCanonPerm ); + Abc_TtStretch5( (unsigned *)p->pTemp1, nLeaves, p->nVars ); +p->timeCanon += clock() - clk; + // pCanonPerm and uCanonPhase show what was the variable corresponding to each var in the current truth + +clk = clock(); + // map cut leaves into elementary variables of GIA + for ( i = 0; i < nLeaves; i++ ) + If_ManObj( pIfMan, pCut->pLeaves[(int)pCanonPerm[i]] )->iCopy = Abc_Var2Lit( Gia_ObjId(pGia, Gia_ManPi(pGia, i)), (uCanonPhase >> i) & 1 ); + // build internal nodes + fHole = 0; + assert( Vec_PtrSize(vNodes) > 0 ); + Vec_PtrForEachEntryStart( If_Obj_t *, vNodes, pIfObj, i, nLeaves ) + { + if ( If_ObjIsCi(pIfObj) ) + { + pIfObj->iCopy = 0; + fHole = 1; + continue; + } + iFanin0 = Abc_LitNotCond( If_ObjFanin0(pIfObj)->iCopy, If_ObjFaninC0(pIfObj) ); + iFanin1 = Abc_LitNotCond( If_ObjFanin1(pIfObj)->iCopy, If_ObjFaninC1(pIfObj) ); + pIfObj->iCopy = Gia_ManHashAnd( pGia, iFanin0, iFanin1 ); + } + p->nHoleInTheWall += fHole; +p->timeBuild += clock() - clk; + + // check if this node is already driving a PO + assert( If_ObjIsAnd(pIfObj) ); + pDriver = Gia_ManObj(pGia, Abc_Lit2Var(pIfObj->iCopy)); + if ( pDriver->fMark1 ) + { + p->nFilterSame++; + return 1; + } + pDriver->fMark1 = 1; + // create output + Gia_ManAppendCo( pGia, Abc_LitNotCond( pIfObj->iCopy, (uCanonPhase >> nLeaves) & 1 ) ); + + // verify truth table +clk = clock(); + pTruth = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, Gia_ManCoNum(pGia)-1) ); +p->timeCheck += clock() - clk; + if ( memcmp( p->pTemp1, pTruth, p->nWords * sizeof(word) ) != 0 ) + { +/* + Kit_DsdPrintFromTruth( pTruth, nLeaves ); printf( "\n" ); + Kit_DsdPrintFromTruth( (unsigned *)p->pTemp1, nLeaves ); printf( "\n" ); + printf( "Truth table verification has failed.\n" ); +*/ + // drive PO with constant + Gia_ManPatchCoDriver( pGia, Gia_ManCoNum(pGia)-1, 0 ); + // save truth table ID + Vec_IntPush( p->vTruthIds, -1 ); + p->nFilterTruth++; + return 1; + } + +clk = clock(); + // add the resulting truth table to the hash table + Index = Vec_MemHashInsert( p->vTtMem, p->pTemp1 ); + // save truth table ID + Vec_IntPush( p->vTruthIds, Index ); + assert( Gia_ManCoNum(pGia) == Vec_IntSize(p->vTruthIds) ); + p->nAdded++; +p->timeInsert += clock() - clk; + return 1; +} + +/**Function************************************************************* + + Synopsis [Top level procedure for library construction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecAdd3( Abc_Ntk_t * pNtk, int fUseSOPB ) +{ + extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); + If_Par_t Pars, * pPars = &Pars; + Abc_Ntk_t * pNtkNew; + int clk = clock(); + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Performing recoding structures with choices.\n" ); + // remember that the manager was used for library construction + s_pMan3->fLibConstr = 1; + // create hash table if not available + if ( s_pMan3->pGia->pHTable == NULL ) + Gia_ManHashStart( s_pMan3->pGia ); + + // set defaults + memset( pPars, 0, sizeof(If_Par_t) ); + // user-controlable paramters + pPars->nLutSize = s_pMan3->nVars; + pPars->nCutsMax = s_pMan3->nCuts; + pPars->DelayTarget = -1; + pPars->Epsilon = (float)0.005; + pPars->fArea = 1; + // internal parameters + if ( fUseSOPB ) + { + pPars->fTruth = 1; + pPars->fCutMin = 0; + pPars->fUsePerm = 1; + pPars->fDelayOpt = 1; + } + else + { + pPars->fTruth = 1; + pPars->fCutMin = 1; + pPars->fUsePerm = 0; + pPars->fDelayOpt = 0; + } + pPars->fSkipCutFilter = 0; + pPars->pFuncCost = NULL; + pPars->pFuncUser = Abc_NtkRecAddCut3; + // perform recording + pNtkNew = Abc_NtkIf( pNtk, pPars ); + Abc_NtkDelete( pNtkNew ); +s_pMan3->timeTotal += clock() - clk; +} + + /**Function************************************************************* + + Synopsis [Returns min AIG level at the output fo the cut using the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int If_CutComputeDelay( If_Man_t * p, If_Cut_t * pCut, char * pCanonPerm, word Delay ) +{ + If_Obj_t* pLeaf; + int nLeaves = If_CutLeaveNum(pCut); + int i, delayTemp, delayMax = -ABC_INFINITY; + for ( i = 0; i < nLeaves; i++ ) + { + pLeaf = If_ManObj(p, (pCut)->pLeaves[(int)pCanonPerm[i]]); + delayTemp = If_ObjCutBest(pLeaf)->Delay + Lms_DelayGet(Delay, i); + if(delayTemp > delayMax) + delayMax = delayTemp; + } + return delayMax; +} +static inline int If_CutFindBestStruct( If_Man_t * pIfMan, If_Cut_t * pCut, char * pCanonPerm, unsigned * puCanonPhase, int * pBestPo ) +{ + Lms_Man_t * p = s_pMan3; + int i, * pTruthId, iFirstPo, iFirstPoNext, iBestPo; + int BestDelay = ABC_INFINITY, BestArea = ABC_INFINITY, Delay, Area; + int nLeaves = If_CutLeaveNum( pCut ); + clock_t clk; + + // semicanonicize the function +clk = clock(); + memcpy( p->pTemp1, If_CutTruthW(pCut), p->nWords * sizeof(word) ); +// uCanonPhase = luckyCanonicizer_final_fast( p->pTemp1, nLeaves, pCanonPerm ); + *puCanonPhase = Kit_TruthSemiCanonicize( (unsigned *)p->pTemp1, (unsigned *)p->pTemp2, nLeaves, pCanonPerm ); + Abc_TtStretch5( (unsigned *)p->pTemp1, nLeaves, p->nVars ); +p->timeCanon += clock() - clk; + + // get TT ID for the given class + pTruthId = Vec_MemHashLookup( p->vTtMem, p->pTemp1 ); + if ( *pTruthId == -1 ) + return ABC_INFINITY; + + // note that array p->vTruthPo contains the first PO for the given truth table + // other POs belonging to the same equivalence class follow immediately after this one + // to iterate through the POs, we need to perform the following steps + + // find the first PO of this class + iFirstPo = Vec_IntEntry( p->vTruthPo, *pTruthId ); + // find the first PO of the next class + iFirstPoNext = Vec_IntEntry( p->vTruthPo, *pTruthId+1 ); + // iterate through the subgraphs of this class + iBestPo = -1; + for ( i = iFirstPo; i < iFirstPoNext; i++ ) + { + Delay = If_CutComputeDelay( pIfMan, pCut, pCanonPerm, Vec_WrdEntry(p->vDelays, i) ); + Area = Vec_StrEntry(p->vAreas, i); + if ( iBestPo == -1 || BestDelay > Delay || (BestDelay == Delay && BestArea > Area) ) + { + iBestPo = i; + BestDelay = Delay; + BestArea = Area; + } + } + if ( pBestPo ) + *pBestPo = iBestPo; + return BestDelay; +} +int If_CutDelayRecCost3( If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pObj ) +{ + Lms_Man_t * p = s_pMan3; + char pCanonPerm[16]; + unsigned uCanonPhase; + // make sure the cut functions match the library + assert( p->nVars == (int)pCut->nLimit ); + // if this assertion fires, it means that LMS manager was used for library construction + // in this case, GIA has to be written out and the manager restarted as described above + assert( !p->fLibConstr ); + if ( p->vTruthPo == NULL ) // the first time AIG level minimization is called + { + // compute the first PO for each semi-canonical form + int i, Entry; + p->vTruthPo = Vec_IntStartFull( Vec_MemEntryNum(p->vTtMem)+1 ); + assert( Vec_IntFindMin(p->vTruthIds) >= 0 ); + assert( Vec_IntFindMax(p->vTruthIds) < Vec_MemEntryNum(p->vTtMem) ); + Vec_IntForEachEntry( p->vTruthIds, Entry, i ) + if ( Vec_IntEntry(p->vTruthPo, Entry) == -1 ) + Vec_IntWriteEntry( p->vTruthPo, Entry, i ); + Vec_IntWriteEntry( p->vTruthPo, Vec_MemEntryNum(p->vTtMem), Gia_ManCoNum(p->pGia) ); + // compute delay/area and init frequency + assert( p->vDelays == NULL ); + assert( p->vAreas == NULL ); + assert( p->vFreqs == NULL ); + p->vDelays = Lms_GiaDelays( p->pGia ); + p->vAreas = Lms_GiaAreas( p->pGia ); + p->vFreqs = Vec_IntStart( Gia_ManCoNum(p->pGia) ); + } + // return the delay of the best structure + return If_CutFindBestStruct( pIfMan, pCut, pCanonPerm, &uCanonPhase, NULL ); +} + +/**Function************************************************************* + + Synopsis [Reexpresses the best structure of the cut in the HOP manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ) +{ + Lms_Man_t * p = s_pMan3; + char pCanonPerm[16]; + unsigned uCanonPhase; + Hop_Obj_t * pFan0, * pFan1, * pHopObj; + Gia_Man_t * pGia = p->pGia; + Gia_Obj_t * pGiaPo, * pGiaTemp = NULL; + int i, BestPo = -1, nLeaves = If_CutLeaveNum(pCut); + assert( pIfMan->pPars->fCutMin == 1 ); + assert( nLeaves > 1 ); + + // get the best output for this node + If_CutFindBestStruct( pIfMan, pCut, pCanonPerm, &uCanonPhase, &BestPo ); + assert( BestPo >= 0 ); + pGiaPo = Gia_ManCo( pGia, BestPo ); + + // collect internal nodes into pGia->vTtNodes + if ( pGia->vTtNodes == NULL ) + pGia->vTtNodes = Vec_IntAlloc( 256 ); + Gia_ObjCollectInternal( pGia, pGiaPo ); + // collect HOP nodes for leaves + Vec_PtrClear( p->vLabelsP ); + for ( i = 0; i < nLeaves; i++ ) + { + pHopObj = Hop_IthVar( pMan, pCanonPerm[i] ); + pHopObj = Hop_NotCond( pHopObj, (uCanonPhase >> i) & 1 ); + Vec_PtrPush(p->vLabelsP, pHopObj); + } + // compute HOP nodes for internal nodes + Gia_ManForEachObjVec( pGia->vTtNodes, pGia, pGiaTemp, i ) + { + pGiaTemp->fMark0 = 0; // unmark node marked by Gia_ObjCollectInternal() + + if ( Gia_ObjIsAnd(Gia_ObjFanin0(pGiaTemp)) ) + pFan0 = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjNum(pGia, Gia_ObjFanin0(pGiaTemp)) + nLeaves); + else + pFan0 = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjCioId(Gia_ObjFanin0(pGiaTemp))); + pFan0 = Hop_NotCond(pFan0, Gia_ObjFaninC0(pGiaTemp)); + + if ( Gia_ObjIsAnd(Gia_ObjFanin1(pGiaTemp)) ) + pFan1 = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjNum(pGia, Gia_ObjFanin1(pGiaTemp)) + nLeaves); + else + pFan1 = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjCioId(Gia_ObjFanin1(pGiaTemp))); + pFan1 = Hop_NotCond(pFan1, Gia_ObjFaninC1(pGiaTemp)); + + pHopObj = Hop_And(pMan, pFan0, pFan1); + Vec_PtrPush(p->vLabelsP, pHopObj); + } + // get the final result + assert( Gia_ObjIsAnd(pGiaTemp) ); + pHopObj = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjNum(pGia, pGiaTemp) + nLeaves); + // complement the result if needed + return Hop_NotCond( pHopObj, pCut->fCompl ^ Gia_ObjFaninC0(pGiaPo) ^ ((uCanonPhase >> nLeaves) & 1) ); +} + + +/**Function************************************************************* + + Synopsis [Reduces GIA to contain only useful COs and internal nodes.] + + Description [During library construction, redundant nodes are added. + Some COs are found to be useless because their TT does not match the + (semi-canonicized TT) of the cut, etc. This procedure reduces GIA + to contains only useful (non-redundant, non-dominated) COs and the + corresponding internal nodes. This procedure replaces GIA by a new GIA + and creates new vTruthIds. The COs with the same truth table have + adjacent IDs. This procedure does not change the truth tables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +// count how many times TT occurs +Vec_Int_t * Lms_GiaCountTruths( Lms_Man_t * p ) +{ + Vec_Int_t * vCounts = Vec_IntStart( Vec_MemEntryNum(p->vTtMem) ); + int i, Entry; + Vec_IntForEachEntry( p->vTruthIds, Entry, i ) + if ( Entry >= 0 ) + Vec_IntAddToEntry( vCounts, Entry, 1 ); + return vCounts; +} +// collect PO indexes worth visiting +Vec_Int_t * Lms_GiaCollectUsefulCos( Lms_Man_t * p ) +{ + Vec_Int_t * vBegins = Vec_IntAlloc( Vec_MemEntryNum(p->vTtMem) ); + Vec_Int_t * vUseful = Vec_IntStartFull( Gia_ManCoNum(p->pGia) + Vec_MemEntryNum(p->vTtMem) ); + Vec_Int_t * vCounts = Lms_GiaCountTruths( p ); + int i, Entry, * pPlace, SumTotal = 0; + // mark up the place for POs + Vec_IntForEachEntry( vCounts, Entry, i ) + { + assert( Entry > 0 ); + Vec_IntPush( vBegins, SumTotal ); + SumTotal += Entry + 1; +// printf( "%d ", Entry ); + } + Vec_IntPush( vBegins, SumTotal ); + // fill out POs in their places + Vec_IntFill( vCounts, Vec_IntSize(vCounts), 0 ); + Vec_IntForEachEntry( p->vTruthIds, Entry, i ) + { + if ( Entry < 0 ) + continue; + pPlace = Vec_IntEntryP( vUseful, Vec_IntEntry(vBegins, Entry) + Vec_IntEntry(vCounts, Entry) ); + assert( *pPlace == -1 ); + *pPlace = i; + Vec_IntAddToEntry( vCounts, Entry, 1 ); + } + Vec_IntFree( vBegins ); + Vec_IntFree( vCounts ); + return vUseful; +} +// collect non-dominated COs +Vec_Int_t * Lms_GiaFindNonRedundantCos( Lms_Man_t * p ) +{ + Vec_Int_t * vRemain; + Vec_Int_t * vUseful; + Vec_Wrd_t * vDelays; + int i, k, EntryI, EntryK; + word D1, D2; + vDelays = Lms_GiaDelays( p->pGia ); + vUseful = Lms_GiaCollectUsefulCos( p ); + Vec_IntForEachEntry( vUseful, EntryI, i ) + { + if ( EntryI < 0 ) + continue; + D1 = Vec_WrdEntry(vDelays, EntryI); + assert( D1 > 0 ); + Vec_IntForEachEntryStart( vUseful, EntryK, k, i+1 ) + { + if ( EntryK == -1 ) + break; + if ( EntryK == -2 ) + continue; + D2 = Vec_WrdEntry(vDelays, EntryK); + assert( D2 > 0 ); + if ( Lms_DelayDom(D1, D2, Gia_ManCiNum(p->pGia)) ) // D1 dominate D2 + { + Vec_IntWriteEntry( vUseful, k, -2 ); + continue; + } + if ( Lms_DelayDom(D2, D1, Gia_ManCiNum(p->pGia)) ) // D2 dominate D1 + { + Vec_IntWriteEntry( vUseful, i, -2 ); + break; + } + } + } + + vRemain = Vec_IntAlloc( 1000 ); + Vec_IntForEachEntry( vUseful, EntryI, i ) + if ( EntryI >= 0 ) + Vec_IntPush( vRemain, EntryI ); + Vec_IntFree( vUseful ); + Vec_WrdFree( vDelays ); + return vRemain; +} +// replace GIA and vTruthIds by filtered ones +void Lms_GiaNormalize( Lms_Man_t * p ) +{ + Gia_Man_t * pGiaNew; + Gia_Obj_t * pObj; + Vec_Int_t * vRemain; + Vec_Int_t * vTruthIdsNew; + int i, Entry, Prev = -1, Next; + clock_t clk = clock(); + // collect non-redundant COs + vRemain = Lms_GiaFindNonRedundantCos( p ); + // change these to be useful literals + vTruthIdsNew = Vec_IntAlloc( Vec_IntSize(vRemain) ); + Vec_IntForEachEntry( vRemain, Entry, i ) + { + pObj = Gia_ManCo(p->pGia, Entry); + assert( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ); + Vec_IntWriteEntry( vRemain, i, Gia_ObjFaninLit0p(p->pGia, pObj) ); + // create new truth IDs + Next = Vec_IntEntry(p->vTruthIds, Gia_ObjCioId(pObj)); + assert( Prev <= Next ); + Vec_IntPush( vTruthIdsNew, Next ); + Prev = Next; + } + // create a new GIA + Gia_ManForEachObj( p->pGia, pObj, i ) + assert( pObj->fMark0 == 0 ); + for ( i = 0; i < Gia_ManCoNum(p->pGia); i++ ) + Gia_ManPatchCoDriver( p->pGia, i, 0 ); + Vec_IntForEachEntry( vRemain, Entry, i ) + Gia_ManAppendCo( p->pGia, Entry ); +// pGiaNew = Gia_ManCleanup( p->pGia ); + pGiaNew = Gia_ManCleanupOutputs( p->pGia, Gia_ManCoNum(p->pGia) - Vec_IntSize(vRemain) ); + Gia_ManStop( p->pGia ); + p->pGia = pGiaNew; + Vec_IntFree( vRemain ); + // update truth IDs + Vec_IntFree( p->vTruthIds ); + p->vTruthIds = vTruthIdsNew; +// Vec_IntPrint( vTruthIdsNew ); + Abc_PrintTime( 1, "Normalization runtime", clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecPs3(int fPrintLib) +{ + Lms_ManPrint( s_pMan3 ); + + printf( "Before normalizing\n" ); + Gia_ManPrintStats( s_pMan3->pGia, 0, 0 ); + + Lms_GiaNormalize( s_pMan3 ); + + printf( "After normalizing\n" ); + Gia_ManPrintStats( s_pMan3->pGia, 0, 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecIsRunning3() +{ + return s_pMan3 != NULL; +} +Gia_Man_t * Abc_NtkRecGetGia3() +{ + Lms_GiaNormalize( s_pMan3 ); + return s_pMan3->pGia; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END
\ No newline at end of file diff --git a/src/base/abci/module.make b/src/base/abci/module.make index d96afbd1..90bdb419 100644 --- a/src/base/abci/module.make +++ b/src/base/abci/module.make @@ -46,6 +46,7 @@ SRC += src/base/abci/abc.c \ src/base/abci/abcQuant.c \ src/base/abci/abcRec.c \ src/base/abci/abcRec2.c \ + src/base/abci/abcRec3.c \ src/base/abci/abcReconv.c \ src/base/abci/abcReach.c \ src/base/abci/abcRefactor.c \ diff --git a/src/base/io/io.c b/src/base/io/io.c index b7c3234c..466a563a 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -1654,9 +1654,10 @@ int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv ) char * pFileName; char * pLutStruct = NULL; int c, fSpecial = 0; + int fUseHie = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Sjh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Sjah" ) ) != EOF ) { switch ( c ) { @@ -1677,6 +1678,9 @@ int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv ) case 'j': fSpecial ^= 1; break; + case 'a': + fUseHie ^= 1; + break; case 'h': goto usage; default: @@ -1694,16 +1698,17 @@ int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv ) pFileName = argv[globalUtilOptind]; // call the corresponding file writer if ( fSpecial || pLutStruct ) - Io_WriteBlifSpecial( pAbc->pNtkCur, pFileName, pLutStruct ); + Io_WriteBlifSpecial( pAbc->pNtkCur, pFileName, pLutStruct, fUseHie ); else Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIF ); return 0; usage: - fprintf( pAbc->Err, "usage: write_blif [-S str] [-jh] <file>\n" ); + fprintf( pAbc->Err, "usage: write_blif [-S str] [-jah] <file>\n" ); fprintf( pAbc->Err, "\t writes the network into a BLIF file\n" ); fprintf( pAbc->Err, "\t-S str : string representing the LUT structure [default = %s]\n", pLutStruct ? pLutStruct : "not used" ); fprintf( pAbc->Err, "\t-j : enables special BLIF writing [default = %s]\n", fSpecial? "yes" : "no" );; + fprintf( pAbc->Err, "\t-a : enables hierarchical BLIF writing for LUT structures [default = %s]\n", fUseHie? "yes" : "no" );; fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .blif)\n" ); return 1; @@ -2734,17 +2739,22 @@ int IoCommandWriteTruths( Abc_Frame_t * pAbc, int argc, char **argv ) char * pFileName; FILE * pFile; unsigned * pTruth; + int nBytes; int fReverse = 0; + int fBinary = 0; int c, i; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "rh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "rbh" ) ) != EOF ) { switch ( c ) { case 'r': fReverse ^= 1; break; + case 'b': + fBinary ^= 1; + break; case 'h': goto usage; default: @@ -2761,30 +2771,39 @@ int IoCommandWriteTruths( Abc_Frame_t * pAbc, int argc, char **argv ) Abc_Print( -1, "IoCommandWriteTruths(): Can write truth tables up to 16 inputs.\n" ); return 0; } + if ( Gia_ManPiNum(pAbc->pGia) < 3 ) + { + Abc_Print( -1, "IoCommandWriteTruths(): Can write truth tables for 3 inputs or more.\n" ); + return 0; + } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // convert to logic - pFile = fopen( pFileName, "w" ); + pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return 0; } + nBytes = 8 * Abc_Truth6WordNum( Gia_ManPiNum(pAbc->pGia) ); Gia_ManForEachCo( pAbc->pGia, pObj, i ) { pTruth = Gia_ObjComputeTruthTable( pAbc->pGia, pObj ); - Extra_PrintHex( pFile, pTruth, Gia_ManPiNum(pAbc->pGia) ); - fprintf( pFile, "\n" ); + if ( fBinary ) + fwrite( pTruth, nBytes, 1, pFile ); + else + Extra_PrintHex( pFile, pTruth, Gia_ManPiNum(pAbc->pGia) ), fprintf( pFile, "\n" ); } fclose( pFile ); return 0; usage: - fprintf( pAbc->Err, "usage: &write_truths [-rh] <file>\n" ); + fprintf( pAbc->Err, "usage: &write_truths [-rbh] <file>\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-b : toggle using binary format [default = %s]\n", fBinary? "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; diff --git a/src/base/io/ioAbc.h b/src/base/io/ioAbc.h index 039f53c0..efac1212 100644 --- a/src/base/io/ioAbc.h +++ b/src/base/io/ioAbc.h @@ -106,7 +106,7 @@ extern void Io_WriteBblif( Abc_Ntk_t * pNtk, char * pFileName ); extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); extern void Io_WriteBlif( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches, int fBb2Wb, int fSeq ); extern void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ); -extern void Io_WriteBlifSpecial( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct ); +extern void Io_WriteBlifSpecial( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct, int fUseHie ); /*=== abcWriteBlifMv.c ==========================================================*/ extern void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcWriteBench.c =========================================================*/ diff --git a/src/base/io/ioReadBlifMv.c b/src/base/io/ioReadBlifMv.c index bbaad423..ab40065e 100644 --- a/src/base/io/ioReadBlifMv.c +++ b/src/base/io/ioReadBlifMv.c @@ -1272,7 +1272,7 @@ static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ) return 0; } */ - if ( k == nEquals ) + if ( pName2 == NULL ) { Abc_Obj_t * pNode = Abc_NtkCreateNode( p->pNtk ); pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, " 0\n" ); @@ -1313,11 +1313,10 @@ static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ) return 0; } */ - assert( pName2 != NULL ); // create the BI with the actual name pTerm = Abc_NtkCreateBo( p->pNtk ); - pNet = Abc_NtkFindOrCreateNet( p->pNtk, k == nEquals ? Abc_ObjNameSuffix(pTerm, "abc") : pName2 ); + pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName2 == NULL ? Abc_ObjNameSuffix(pTerm, "abc") : pName2 ); Abc_ObjAddFanin( pNet, pTerm ); Abc_ObjAddFanin( pTerm, pBox ); } diff --git a/src/base/io/ioWriteBlif.c b/src/base/io/ioWriteBlif.c index e13037db..bd7d9819 100644 --- a/src/base/io/ioWriteBlif.c +++ b/src/base/io/ioWriteBlif.c @@ -514,6 +514,68 @@ void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode ) fprintf( pFile, " %s", pName ); } +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteSubcktFanins( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNet; + int LineLength; + int AddedLength; + int NameCounter; + char * pName; + int i; + + LineLength = 6; + NameCounter = 0; + + // get the output name + pName = Abc_ObjName(Abc_ObjFanout0(pNode)); + // get the line length after the output name is written + AddedLength = strlen(pName) + 1; + fprintf( pFile, " m%d", Abc_ObjId(pNode) ); + + // get the input names + Abc_ObjForEachFanin( pNode, pNet, i ) + { + // get the fanin name + pName = Abc_ObjName(pNet); + // get the line length after the fanin name is written + AddedLength = strlen(pName) + 3; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %c=%s", 'a'+i, pName ); + LineLength += AddedLength; + NameCounter++; + } + + // get the output name + pName = Abc_ObjName(Abc_ObjFanout0(pNode)); + // get the line length after the output name is written + AddedLength = strlen(pName) + 3; + if ( NameCounter && LineLength + AddedLength > 75 ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %c=%s", 'o', pName ); +} + /**Function************************************************************* @@ -586,6 +648,26 @@ int Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length ) /**Function************************************************************* + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_NtkWriteNodeSubckt( FILE * pFile, Abc_Obj_t * pNode, int Length ) +{ + int RetValue = 0; + fprintf( pFile, ".subckt" ); + Io_NtkWriteSubcktFanins( pFile, pNode ); + fprintf( pFile, "\n" ); + return RetValue; +} + +/**Function************************************************************* + Synopsis [Writes the timing info.] Description [] @@ -1022,6 +1104,182 @@ void Io_NtkWriteNodeIntStruct( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vCov /**Function************************************************************* + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteModelIntStruct( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vCover, char * pStr ) +{ + Abc_Obj_t * pNet; + int nLeaves = Abc_ObjFaninNum(pNode); + int i, nLutLeaf, nLutLeaf2, nLutRoot, Length; + + // write the header + fprintf( pFile, "\n" ); + fprintf( pFile, ".model m%d\n", Abc_ObjId(pNode) ); + fprintf( pFile, ".inputs" ); + for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) + fprintf( pFile, " %c", 'a' + i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".outputs o\n" ); + + // quit if parameters are wrong + Length = strlen(pStr); + if ( Length != 2 && Length != 3 ) + { + printf( "Wrong LUT struct (%s)\n", pStr ); + return; + } + for ( i = 0; i < Length; i++ ) + if ( pStr[i] - '0' < 3 || pStr[i] - '0' > 6 ) + { + printf( "The LUT size (%d) should belong to {3,4,5,6}.\n", pStr[i] - '0' ); + return; + } + + nLutLeaf = pStr[0] - '0'; + nLutLeaf2 = ( Length == 3 ) ? pStr[1] - '0' : 0; + nLutRoot = pStr[Length-1] - '0'; + if ( nLeaves > nLutLeaf - 1 + (nLutLeaf2 ? nLutLeaf2 - 1 : 0) + nLutRoot ) + { + printf( "The node size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr ); + return; + } + + // consider easy case + if ( nLeaves <= Abc_MaxInt( nLutLeaf2, Abc_MaxInt(nLutLeaf, nLutRoot) ) ) + { + // write the .names line + fprintf( pFile, ".names" ); + Abc_ObjForEachFanin( pNode, pNet, i ) + fprintf( pFile, " %c", 'a' + i ); + // get the output name + fprintf( pFile, " %s\n", "o" ); + // write the cubes + fprintf( pFile, "%s", (char*)Abc_ObjData(pNode) ); + fprintf( pFile, ".end\n" ); + return; + } + else + { + extern int If_CluMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars ); + + static word TruthStore[16][1<<10] = {{0}}, * pTruths[16]; + word pCube[1<<10], pRes[1<<10], Func0, Func1, Func2; + char pLut0[32], pLut1[32], pLut2[32] = {0}, * pSop; +// int nVarsMin[3], pVars[3][20]; + + if ( TruthStore[0][0] == 0 ) + { + static word Truth6[6] = { + 0xAAAAAAAAAAAAAAAA, + 0xCCCCCCCCCCCCCCCC, + 0xF0F0F0F0F0F0F0F0, + 0xFF00FF00FF00FF00, + 0xFFFF0000FFFF0000, + 0xFFFFFFFF00000000 + }; + int nVarsMax = 16; + int nWordsMax = (1 << 10); + int i, k; + assert( nVarsMax <= 16 ); + for ( i = 0; i < nVarsMax; i++ ) + pTruths[i] = TruthStore[i]; + for ( i = 0; i < 6; i++ ) + for ( k = 0; k < nWordsMax; k++ ) + pTruths[i][k] = Truth6[i]; + for ( i = 6; i < nVarsMax; i++ ) + for ( k = 0; k < nWordsMax; k++ ) + pTruths[i][k] = ((k >> (i-6)) & 1) ? ~(word)0 : 0; + } + + // collect variables +// Abc_ObjForEachFanin( pNode, pNet, i ) +// pVars[0][i] = pVars[1][i] = pVars[2][i] = i; + + // derive truth table + Abc_SopToTruthBig( (char*)Abc_ObjData(pNode), nLeaves, pTruths, pCube, pRes ); + if ( Kit_TruthIsConst0((unsigned *)pRes, nLeaves) || Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ) + { + fprintf( pFile, ".names %s\n %d\n", "o", Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ); + fprintf( pFile, ".end\n" ); + return; + } + +// Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); +// Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + + // perform decomposition + if ( Length == 2 ) + { + 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 \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return; + } + } + else + { + if ( !If_CluCheckExt3( NULL, pRes, nLeaves, nLutLeaf, nLutLeaf2, nLutRoot, pLut0, pLut1, pLut2, &Func0, &Func1, &Func2 ) ) + { + Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); + Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + printf( "Node \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return; + } + } + + // write leaf node + fprintf( pFile, ".names" ); + for ( i = 0; i < pLut1[0]; i++ ) + fprintf( pFile, " %c", 'a' + pLut1[2+i] ); + fprintf( pFile, " lut1\n" ); + // write SOP + pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func1, pLut1[0], vCover ); + fprintf( pFile, "%s", pSop ); + + if ( Length == 3 && pLut2[0] > 0 ) + { + // write leaf node + fprintf( pFile, ".names" ); + for ( i = 0; i < pLut2[0]; i++ ) + if ( pLut2[2+i] == nLeaves ) + fprintf( pFile, " lut1" ); + else + fprintf( pFile, " %c", 'a' + pLut2[2+i] ); + fprintf( pFile, " lut2\n" ); + // write SOP + pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func2, pLut2[0], vCover ); + fprintf( pFile, "%s", pSop ); + } + + // write root node + fprintf( pFile, ".names" ); + for ( i = 0; i < pLut0[0]; i++ ) + if ( pLut0[2+i] == nLeaves ) + fprintf( pFile, " lut1" ); + else if ( pLut0[2+i] == nLeaves+1 ) + fprintf( pFile, " lut2" ); + else + fprintf( pFile, " %c", 'a' + pLut0[2+i] ); + fprintf( pFile, " %s\n", "o" ); + // write SOP + pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func0, pLut0[0], vCover ); + fprintf( pFile, "%s", pSop ); + fprintf( pFile, ".end\n" ); + } +} + + +/**Function************************************************************* + Synopsis [Write the network into a BLIF file with the given name.] Description [] @@ -1031,7 +1289,7 @@ void Io_NtkWriteNodeIntStruct( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vCov SeeAlso [] ***********************************************************************/ -void Io_WriteBlifInt( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct ) +void Io_WriteBlifInt( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct, int fUseHie ) { FILE * pFile; Vec_Int_t * vCover; @@ -1063,18 +1321,33 @@ void Io_WriteBlifInt( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct ) Io_NtkWriteLatch( pFile, pLatch ); if ( Abc_NtkLatchNum(pNtk) ) fprintf( pFile, "\n" ); - // write each internal node + // write the hierarchy vCover = Vec_IntAlloc( (1<<16) ); - Abc_NtkForEachNode( pNtk, pNode, i ) + if ( fUseHie ) { - if ( pLutStruct ) - Io_NtkWriteNodeIntStruct( pFile, pNode, vCover, pLutStruct ); - else - Io_NtkWriteNodeInt( pFile, pNode, vCover ); + // write each internal node + fprintf( pFile, "\n" ); + Abc_NtkForEachNode( pNtk, pNode, i ) + Io_NtkWriteNodeSubckt( pFile, pNode, 0 ); + fprintf( pFile, ".end\n\n" ); + // write models + Abc_NtkForEachNode( pNtk, pNode, i ) + Io_NtkWriteModelIntStruct( pFile, pNode, vCover, pLutStruct ); + fprintf( pFile, "\n" ); + } + else + { + // write each internal node + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( pLutStruct ) + Io_NtkWriteNodeIntStruct( pFile, pNode, vCover, pLutStruct ); + else + Io_NtkWriteNodeInt( pFile, pNode, vCover ); + } + fprintf( pFile, ".end\n\n" ); } Vec_IntFree( vCover ); - // write the end - fprintf( pFile, ".end\n\n" ); fclose( pFile ); } @@ -1089,7 +1362,7 @@ void Io_WriteBlifInt( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct ) SeeAlso [] ***********************************************************************/ -void Io_WriteBlifSpecial( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct ) +void Io_WriteBlifSpecial( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct, int fUseHie ) { Abc_Ntk_t * pNtkTemp; assert( Abc_NtkIsLogic(pNtk) ); @@ -1101,7 +1374,10 @@ void Io_WriteBlifSpecial( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct ) fprintf( stdout, "Writing BLIF has failed.\n" ); return; } - Io_WriteBlifInt( pNtkTemp, FileName, pLutStruct ); + if ( pLutStruct && fUseHie ) + Io_WriteBlifInt( pNtkTemp, FileName, pLutStruct, 1 ); + else + Io_WriteBlifInt( pNtkTemp, FileName, pLutStruct, 0 ); Abc_NtkDelete( pNtkTemp ); } diff --git a/src/base/main/mainInt.h b/src/base/main/mainInt.h index 4db982f0..f30a13e5 100644 --- a/src/base/main/mainInt.h +++ b/src/base/main/mainInt.h @@ -111,7 +111,7 @@ struct Abc_Frame_t_ void * pAbc85Ntl2; void * pAbc85Best; void * pAbc85Delay; - If_Lib_t * pAbc85Lib; +// If_Lib_t * pAbc85Lib; EXT_ABC_FRAME // plugin for external functionality }; diff --git a/src/bool/kit/kit.h b/src/bool/kit/kit.h index 5ecb5581..cb1c1eb0 100644 --- a/src/bool/kit/kit.h +++ b/src/bool/kit/kit.h @@ -68,7 +68,8 @@ struct Kit_Node_t_ Kit_Edge_t eEdge0; // the left child of the node Kit_Edge_t eEdge1; // the right child of the node // other info - void * pFunc; // the function of the node (BDD or AIG) + union { int iFunc; // the function of the node (BDD or AIG) + void * pFunc; }; // the function of the node (BDD or AIG) unsigned Level : 14; // the level of this node in the global AIG // printing info unsigned fNodeOr : 1; // marks the original OR node @@ -561,6 +562,7 @@ extern unsigned Kit_GraphToTruth( Kit_Graph_t * pGraph ); extern Kit_Graph_t * Kit_TruthToGraph( unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); extern int Kit_GraphLeafDepth_rec( Kit_Graph_t * pGraph, Kit_Node_t * pNode, Kit_Node_t * pLeaf ); /*=== kitHop.c ==========================================================*/ +//extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); //extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ); //extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); //extern Hop_Obj_t * Kit_CoverToHop( Hop_Man_t * pMan, Vec_Int_t * vCover, int nVars, Vec_Int_t * vMemory ); diff --git a/src/bool/kit/kitHop.c b/src/bool/kit/kitHop.c index c7c855af..a4ce79f3 100644 --- a/src/bool/kit/kitHop.c +++ b/src/bool/kit/kitHop.c @@ -20,6 +20,7 @@ #include "kit.h" #include "aig/hop/hop.h" +#include "aig/gia/gia.h" ABC_NAMESPACE_IMPL_START @@ -43,31 +44,66 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ -Hop_Obj_t * Kit_GraphToHopInternal( Hop_Man_t * pMan, Kit_Graph_t * pGraph ) +int Kit_GraphToGiaInternal( Gia_Man_t * pMan, Kit_Graph_t * pGraph, int fHash ) { Kit_Node_t * pNode = NULL; - Hop_Obj_t * pAnd0, * pAnd1; - int i; + int i, pAnd0, pAnd1; // check for constant function if ( Kit_GraphIsConst(pGraph) ) - return Hop_NotCond( Hop_ManConst1(pMan), Kit_GraphIsComplement(pGraph) ); + return Abc_LitNotCond( 1, Kit_GraphIsComplement(pGraph) ); // check for a literal if ( Kit_GraphIsVar(pGraph) ) - return Hop_NotCond( (Hop_Obj_t *)Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) ); + return Abc_LitNotCond( Kit_GraphVar(pGraph)->iFunc, Kit_GraphIsComplement(pGraph) ); // build the AIG nodes corresponding to the AND gates of the graph Kit_GraphForEachNode( pGraph, pNode, i ) { - pAnd0 = Hop_NotCond( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Hop_NotCond( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 ); + pAnd0 = Abc_LitNotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->iFunc, pNode->eEdge0.fCompl ); + pAnd1 = Abc_LitNotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->iFunc, pNode->eEdge1.fCompl ); + if ( fHash ) + pNode->iFunc = Gia_ManHashAnd( pMan, pAnd0, pAnd1 ); + else + pNode->iFunc = Gia_ManAppendAnd( pMan, pAnd0, pAnd1 ); } // complement the result if necessary - return Hop_NotCond( (Hop_Obj_t *)pNode->pFunc, Kit_GraphIsComplement(pGraph) ); + return Abc_LitNotCond( pNode->iFunc, Kit_GraphIsComplement(pGraph) ); +} +int Kit_GraphToGia( Gia_Man_t * pMan, Kit_Graph_t * pGraph, Vec_Int_t * vLeaves, int fHash ) +{ + Kit_Node_t * pNode = NULL; + int i; + // collect the fanins + Kit_GraphForEachLeaf( pGraph, pNode, i ) + pNode->iFunc = Vec_IntEntry( vLeaves, i ); + // perform strashing + return Kit_GraphToGiaInternal( pMan, pGraph, fHash ); +} +int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ) +{ + int iLit; + Kit_Graph_t * pGraph; + // transform truth table into the decomposition tree + if ( vMemory == NULL ) + { + vMemory = Vec_IntAlloc( 0 ); + pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); + Vec_IntFree( vMemory ); + } + else + pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); + if ( pGraph == NULL ) + { + printf( "Kit_TruthToGia(): Converting truth table to AIG has failed for function:\n" ); + Kit_DsdPrintFromTruth( pTruth, nVars ); printf( "\n" ); + } + // derive the AIG for the decomposition tree + iLit = Kit_GraphToGia( pMan, pGraph, vLeaves, fHash ); + Kit_GraphFree( pGraph ); + return iLit; } /**Function************************************************************* - Synopsis [Strashes one logic node using its SOP.] + Synopsis [Transforms the decomposition graph into the AIG.] Description [] @@ -76,6 +112,27 @@ Hop_Obj_t * Kit_GraphToHopInternal( Hop_Man_t * pMan, Kit_Graph_t * pGraph ) SeeAlso [] ***********************************************************************/ +Hop_Obj_t * Kit_GraphToHopInternal( Hop_Man_t * pMan, Kit_Graph_t * pGraph ) +{ + Kit_Node_t * pNode = NULL; + Hop_Obj_t * pAnd0, * pAnd1; + int i; + // check for constant function + if ( Kit_GraphIsConst(pGraph) ) + return Hop_NotCond( Hop_ManConst1(pMan), Kit_GraphIsComplement(pGraph) ); + // check for a literal + if ( Kit_GraphIsVar(pGraph) ) + return Hop_NotCond( (Hop_Obj_t *)Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) ); + // build the AIG nodes corresponding to the AND gates of the graph + Kit_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Hop_NotCond( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Hop_NotCond( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 ); + } + // complement the result if necessary + return Hop_NotCond( (Hop_Obj_t *)pNode->pFunc, Kit_GraphIsComplement(pGraph) ); +} Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ) { Kit_Node_t * pNode = NULL; @@ -86,18 +143,6 @@ Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ) // perform strashing return Kit_GraphToHopInternal( pMan, pGraph ); } - -/**Function************************************************************* - - Synopsis [Strashed onen logic nodes using its truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ) { Hop_Obj_t * pObj; diff --git a/src/bool/kit/kitTruth.c b/src/bool/kit/kitTruth.c index a6951163..87b28135 100644 --- a/src/bool/kit/kitTruth.c +++ b/src/bool/kit/kitTruth.c @@ -1664,6 +1664,8 @@ unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, // canonicize output uCanonPhase = 0; + for ( i = 0; i < nVars; i++ ) + pCanonPerm[i] = i; nOnes = Kit_TruthCountOnes(pIn, nVars); //if(pIn[0] & 1) diff --git a/src/map/if/if.h b/src/map/if/if.h index f74a59da..9e649e0c 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -333,7 +333,7 @@ static inline void * If_ObjCopy( If_Obj_t * pObj ) { r static inline int If_ObjLevel( If_Obj_t * pObj ) { return pObj->Level; } static inline void If_ObjSetLevel( If_Obj_t * pObj, int Level ) { pObj->Level = Level; } static inline void If_ObjSetCopy( If_Obj_t * pObj, void * pCopy ) { pObj->pCopy = pCopy; } -static inline void If_ObjSetChoice( If_Obj_t * pObj, If_Obj_t * pEqu ) { pObj->pEquiv = pEqu; } +static inline void If_ObjSetChoice( If_Obj_t * pObj, If_Obj_t * pEqu ) { assert( pObj->Id > pEqu->Id ); pObj->pEquiv = pEqu; } static inline If_Cut_t * If_ObjCutBest( If_Obj_t * pObj ) { return &pObj->CutBest; } static inline unsigned If_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId % 31)); } @@ -353,8 +353,9 @@ static inline void If_CutSetDataInt( If_Cut_t * pCut, int Data ) { * static inline int If_CutLeaveNum( If_Cut_t * pCut ) { return pCut->nLeaves; } static inline int * If_CutLeaves( If_Cut_t * pCut ) { return pCut->pLeaves; } static inline unsigned * If_CutTruth( If_Cut_t * pCut ) { return pCut->pTruth; } +static inline word * If_CutTruthW( If_Cut_t * pCut ) { return (word *)pCut->pTruth; } static inline unsigned If_CutSuppMask( If_Cut_t * pCut ) { return (~(unsigned)0) >> (32-pCut->nLeaves); } -static inline int If_CutTruthWords( int nVarsMax ) { return nVarsMax <= 5 ? 1 : (1 << (nVarsMax - 5)); } +static inline int If_CutTruthWords( int nVarsMax ) { return nVarsMax <= 5 ? 2 : (1 << (nVarsMax - 5)); } static inline int If_CutPermWords( int nVarsMax ) { return nVarsMax / sizeof(int) + ((nVarsMax % sizeof(int)) > 0); } static inline float If_CutLutArea( If_Man_t * p, If_Cut_t * pCut ) { return pCut->fUser? (float)pCut->Cost : (p->pPars->pLutLib? p->pPars->pLutLib->pLutAreas[pCut->nLeaves] : (float)1.0); } @@ -505,8 +506,9 @@ extern void If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, I extern void If_CutRotatePins( If_Man_t * p, If_Cut_t * pCut ); /*=== ifTruth.c ===========================================================*/ extern int If_CutTruthMinimize( If_Man_t * p, If_Cut_t * pCut ); -extern int If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 ); extern void If_CutTruthPermute( unsigned * pOut, unsigned * pIn, int nVars, float * pDelays, int * pVars ); +extern int If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 ); +extern int If_CutComputeTruth2( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 ); /*=== ifUtil.c ============================================================*/ extern void If_ManCleanNodeCopy( If_Man_t * p ); extern void If_ManCleanCutData( If_Man_t * p ); @@ -525,13 +527,18 @@ extern Vec_Ptr_t * If_ManCollectMappingDirect( If_Man_t * p ); extern Vec_Int_t * If_ManCollectMappingInt( If_Man_t * p ); extern int If_ManCountSpecialPos( If_Man_t * p ); +extern void If_CutTraverse( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes ); +extern void If_ObjPrint( If_Obj_t * pObj ); /*=== abcRec.c ============================================================*/ +/*=== abcRec2.c ============================================================*/ +/*=== abcRec3.c ============================================================*/ extern int If_CutDelayRecCost(If_Man_t* p, If_Cut_t* pCut, If_Obj_t * pObj); extern int If_CutDelayRecCost2(If_Man_t* p, If_Cut_t* pCut, If_Obj_t * pObj); -/*=== abcRec2.c ============================================================*/ +extern int If_CutDelayRecCost3(If_Man_t* p, If_Cut_t* pCut, If_Obj_t * pObj); extern ABC_DLL int Abc_NtkRecIsRunning(); extern ABC_DLL int Abc_NtkRecIsRunning2(); +extern ABC_DLL int Abc_NtkRecIsRunning3(); // othe packages extern int Bat_ManCellFuncLookup( unsigned * pTruth, int nVars, int nLeaves ); diff --git a/src/map/if/ifMan.c b/src/map/if/ifMan.c index 3028e370..0ebdec1b 100644 --- a/src/map/if/ifMan.c +++ b/src/map/if/ifMan.c @@ -337,6 +337,7 @@ void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pObj ) // mark the largest level if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; + p->nChoices++; } /**Function************************************************************* @@ -410,8 +411,7 @@ void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId ) // set up elementary truth table of the unit cut if ( p->pPars->fTruth ) { - int i, nTruthWords; - nTruthWords = pCut->nLimit <= 5 ? 1 : (1 << (pCut->nLimit - 5)); + int i, nTruthWords = If_CutTruthWords(pCut->nLimit); for ( i = 0; i < nTruthWords; i++ ) If_CutTruth(pCut)[i] = 0xAAAAAAAA; } diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index 6fcb8799..1f7ba898 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -75,7 +75,8 @@ float If_CutDelaySpecial( If_Man_t * p, If_Cut_t * pCut, int fCarry ) Delay = IF_MAX( Delay, Pin2Pin[fCarry][i] + DelayCur ); } return Delay; - } +} + /**Function************************************************************* @@ -157,12 +158,13 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep /// pCut->Delay = If_CutDelayLutStruct( p, pCut, p->pPars->pLutStruct, p->pPars->WireDelay ); if ( p->pPars->fUserRecLib ) { - if((Abc_NtkRecIsRunning2()&& Abc_NtkRecIsRunning()) || (!Abc_NtkRecIsRunning2()&& !Abc_NtkRecIsRunning())) - assert(0); - else if(Abc_NtkRecIsRunning()) - pCut->Delay = If_CutDelayRecCost(p, pCut, pObj); + assert( Abc_NtkRecIsRunning() + Abc_NtkRecIsRunning2() + Abc_NtkRecIsRunning3() == 1 ); + if ( Abc_NtkRecIsRunning3() ) + pCut->Delay = If_CutDelayRecCost3(p, pCut, pObj); + else if( Abc_NtkRecIsRunning2() ) + pCut->Delay = If_CutDelayRecCost2(p, pCut, pObj); else - pCut->Delay = If_CutDelayRecCost2(p, pCut, pObj); + pCut->Delay = If_CutDelayRecCost(p, pCut, pObj); } else if(p->pPars->fDelayOpt) pCut->Delay = If_CutDelaySopCost(p,pCut); @@ -211,8 +213,10 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep if ( p->pPars->fTruth ) { // clock_t clk = clock(); - int RetValue = If_CutComputeTruth( p, pCut, pCut0, pCut1, pObj->fCompl0, pObj->fCompl1 ); +// int RetValue = If_CutComputeTruth( p, pCut, pCut0, pCut1, pObj->fCompl0, pObj->fCompl1 ); + int RetValue = If_CutComputeTruth2( p, pCut, pCut0, pCut1, pObj->fCompl0, pObj->fCompl1 ); // p->timeTruth += clock() - clk; + pCut->fUseless = 0; if ( p->pPars->pFuncCell && RetValue < 2 ) { @@ -236,12 +240,13 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep /// pCut->Delay = If_CutDelayLutStruct( p, pCut, p->pPars->pLutStruct, p->pPars->WireDelay ); if ( p->pPars->fUserRecLib ) { - if((Abc_NtkRecIsRunning2()&& Abc_NtkRecIsRunning()) || (!Abc_NtkRecIsRunning2()&& !Abc_NtkRecIsRunning())) - assert(0); - else if(Abc_NtkRecIsRunning()) - pCut->Delay = If_CutDelayRecCost(p, pCut, pObj); - else + assert( Abc_NtkRecIsRunning() + Abc_NtkRecIsRunning2() + Abc_NtkRecIsRunning3() == 1 ); + if ( Abc_NtkRecIsRunning3() ) + pCut->Delay = If_CutDelayRecCost3(p, pCut, pObj); + else if( Abc_NtkRecIsRunning2() ) pCut->Delay = If_CutDelayRecCost2(p, pCut, pObj); + else + pCut->Delay = If_CutDelayRecCost(p, pCut, pObj); } else if (p->pPars->fDelayOpt) pCut->Delay = If_CutDelaySopCost(p, pCut); @@ -263,6 +268,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut ); // insert the cut into storage If_CutSort( p, pCutSet, pCut ); +// If_CutTraverse( p, pObj, pCut ); } assert( pCutSet->nCuts > 0 ); diff --git a/src/map/if/ifTruth.c b/src/map/if/ifTruth.c index f0289695..4b0db8b4 100644 --- a/src/map/if/ifTruth.c +++ b/src/map/if/ifTruth.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "if.h" +#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START @@ -43,29 +44,28 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ -static inline int If_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } static inline void If_TruthNot( unsigned * pOut, unsigned * pIn, int nVars ) { int w; - for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- ) + for ( w = If_CutTruthWords(nVars)-1; w >= 0; w-- ) pOut[w] = ~pIn[w]; } static inline void If_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) { int w; - for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- ) + for ( w = If_CutTruthWords(nVars)-1; w >= 0; w-- ) pOut[w] = pIn[w]; } static inline void If_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; - for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- ) + for ( w = If_CutTruthWords(nVars)-1; w >= 0; w-- ) pOut[w] = ~(pIn0[w] & pIn1[w]); } static inline void If_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; - for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- ) + for ( w = If_CutTruthWords(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] & pIn1[w]; } @@ -89,7 +89,7 @@ void If_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int i { 0xF00FF00F, 0x00F000F0, 0x0F000F00 }, { 0xFF0000FF, 0x0000FF00, 0x00FF0000 } }; - int nWords = If_TruthWordNum( nVars ); + int nWords = If_CutTruthWords( nVars ); int i, k, Step, Shift; assert( iVar < nVars - 1 ); @@ -245,7 +245,7 @@ void If_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, u ***********************************************************************/ int If_CutTruthVarInSupport( unsigned * pTruth, int nVars, int iVar ) { - int nWords = If_TruthWordNum( nVars ); + int nWords = If_CutTruthWords( nVars ); int i, k, Step; assert( iVar < nVars ); @@ -449,6 +449,191 @@ int If_CutTruthMinimize( If_Man_t * p, If_Cut_t * pCut ) } + + +/**Function************************************************************* + + Synopsis [Performs truth table computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int If_CutTruthMinimize6( If_Man_t * p, If_Cut_t * pCut ) +{ + unsigned uSupport; + int i, k, nSuppSize; + int nVars = If_CutLeaveNum(pCut); + // compute the support of the cut's function + uSupport = Abc_Tt6SupportAndSize( *If_CutTruthW(pCut), nVars, &nSuppSize ); + if ( nSuppSize == If_CutLeaveNum(pCut) ) + return 0; +// TEMPORARY + if ( nSuppSize < 2 ) + { + p->nSmallSupp++; + return 2; + } + // update leaves and signature + pCut->uSign = 0; + for ( i = k = 0; i < nVars; i++ ) + { + if ( !(uSupport & (1 << i)) ) + continue; + pCut->uSign |= If_ObjCutSign( pCut->pLeaves[i] ); + if ( k < i ) + { + pCut->pLeaves[k] = pCut->pLeaves[i]; + Abc_TtSwapVars( If_CutTruthW(pCut), pCut->nLimit, k, i ); + } + k++; + } + assert( k == nSuppSize ); + pCut->nLeaves = nSuppSize; + // verify the result +// assert( nSuppSize == Abc_TtSupportSize(If_CutTruthW(pCut), nVars) ); + return 1; +} +static inline word If_TruthStretch6( word Truth, If_Cut_t * pCut, If_Cut_t * pCut0 ) +{ + int i, k; + for ( i = (int)pCut->nLeaves - 1, k = (int)pCut0->nLeaves - 1; i >= 0 && k >= 0; i-- ) + { + if ( pCut0->pLeaves[k] < pCut->pLeaves[i] ) + continue; + assert( pCut0->pLeaves[k] == pCut->pLeaves[i] ); + if ( k < i ) + Abc_TtSwapVars( &Truth, pCut->nLimit, k, i ); + k--; + } + return Truth; +} +static inline int If_CutComputeTruth6( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 ) +{ + word t0 = (fCompl0 ^ pCut0->fCompl) ? ~*If_CutTruthW(pCut0) : *If_CutTruthW(pCut0); + word t1 = (fCompl1 ^ pCut1->fCompl) ? ~*If_CutTruthW(pCut1) : *If_CutTruthW(pCut1); + assert( pCut->nLimit <= 6 ); + t0 = If_TruthStretch6( t0, pCut, pCut0 ); + t1 = If_TruthStretch6( t1, pCut, pCut1 ); + *If_CutTruthW(pCut) = t0 & t1; + if ( p->pPars->fCutMin ) + return If_CutTruthMinimize6( p, pCut ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Performs truth table computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +// this procedure handles special case reductions +static inline int If_CutTruthMinimize21( If_Man_t * p, If_Cut_t * pCut ) +{ + word * pTruth = If_CutTruthW(pCut); + int i, k, nVars = If_CutLeaveNum(pCut); + unsigned uSign = 0; + for ( i = k = 0; i < nVars; i++ ) + { + if ( !Abc_TtHasVar( pTruth, nVars, i ) ) + continue; + uSign |= If_ObjCutSign( pCut->pLeaves[i] ); + if ( k < i ) + { + pCut->pLeaves[k] = pCut->pLeaves[i]; + Abc_TtSwapVars( pTruth, nVars, k, i ); + } + k++; + } + if ( k == nVars ) + return 0; + assert( k < nVars ); + pCut->nLeaves = k; + pCut->uSign = uSign; +// TEMPORARY + if ( pCut->nLeaves < 2 ) + { + p->nSmallSupp++; + return 2; + } + // verify the result + assert( If_CutLeaveNum(pCut) == Abc_TtSupportSize(pTruth, nVars) ); + return 1; +} +static inline int If_CutTruthMinimize2( If_Man_t * p, If_Cut_t * pCut ) +{ + unsigned uSupport; + int i, k, nSuppSize; + int nVars = If_CutLeaveNum(pCut); + // compute the support of the cut's function + uSupport = Abc_TtSupportAndSize( If_CutTruthW(pCut), nVars, &nSuppSize ); + if ( nSuppSize == If_CutLeaveNum(pCut) ) + return 0; +// TEMPORARY + if ( nSuppSize < 2 ) + { + p->nSmallSupp++; + return 2; + } + // update leaves and signature + pCut->uSign = 0; + for ( i = k = 0; i < nVars; i++ ) + { + if ( !(uSupport & (1 << i)) ) + continue; + pCut->uSign |= If_ObjCutSign( pCut->pLeaves[i] ); + if ( k < i ) + { + pCut->pLeaves[k] = pCut->pLeaves[i]; + Abc_TtSwapVars( If_CutTruthW(pCut), pCut->nLimit, k, i ); + } + k++; + } + assert( k == nSuppSize ); + pCut->nLeaves = nSuppSize; + // verify the result +// assert( nSuppSize == Abc_TtSupportSize(If_CutTruthW(pCut), nVars) ); + return 1; +} +static inline void If_TruthStretch2( word * pTruth, If_Cut_t * pCut, If_Cut_t * pCut0 ) +{ + int i, k; + for ( i = (int)pCut->nLeaves - 1, k = (int)pCut0->nLeaves - 1; i >= 0 && k >= 0; i-- ) + { + if ( pCut0->pLeaves[k] < pCut->pLeaves[i] ) + continue; + assert( pCut0->pLeaves[k] == pCut->pLeaves[i] ); + if ( k < i ) + Abc_TtSwapVars( pTruth, pCut->nLimit, k, i ); + k--; + } +} +inline int If_CutComputeTruth2( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 ) +{ + int nWords; + if ( pCut->nLimit < 7 ) + return If_CutComputeTruth6( p, pCut, pCut0, pCut1, fCompl0, fCompl1 ); + nWords = Abc_TtWordNum( pCut->nLimit ); + Abc_TtCopy( (word *)p->puTemp[0], If_CutTruthW(pCut0), nWords, fCompl0 ^ pCut0->fCompl ); + Abc_TtCopy( (word *)p->puTemp[1], If_CutTruthW(pCut1), nWords, fCompl1 ^ pCut1->fCompl ); + If_TruthStretch2( (word *)p->puTemp[0], pCut, pCut0 ); + If_TruthStretch2( (word *)p->puTemp[1], pCut, pCut1 ); + Abc_TtAnd( If_CutTruthW(pCut), (word *)p->puTemp[0], (word *)p->puTemp[1], nWords, 0 ); + if ( p->pPars->fCutMin ) + return If_CutTruthMinimize2( p, pCut ); + return 0; +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/map/if/ifUtil.c b/src/map/if/ifUtil.c index 4d904613..b8b03d70 100644 --- a/src/map/if/ifUtil.c +++ b/src/map/if/ifUtil.c @@ -769,6 +769,90 @@ int If_ManCountSpecialPos( If_Man_t * p ) } +/**Function************************************************************* + + Synopsis [Traverse the cut and counts its volume.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void If_CutTraverse_rec( If_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + if ( pNode->fMark ) + return; + pNode->fMark = 1; +// assert( !If_ObjIsCi(pNode) ); // does not hold with cut minimization + if ( If_ObjIsAnd(pNode) ) + If_CutTraverse_rec( If_ObjFanin0(pNode), vNodes ); + if ( If_ObjIsAnd(pNode) ) + If_CutTraverse_rec( If_ObjFanin1(pNode), vNodes ); + Vec_PtrPush( vNodes, pNode ); +} +void If_CutTraverse( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes ) +{ + If_Obj_t * pLeaf; + int i; + // collect the internal nodes of the cut + Vec_PtrClear( vNodes ); + If_CutForEachLeaf( p, pCut, pLeaf, i ) + { + Vec_PtrPush( vNodes, pLeaf ); + assert( pLeaf->fMark == 0 ); + pLeaf->fMark = 1; + } + // collect other nodes + If_CutTraverse_rec( pRoot, vNodes ); + // clean the mark + Vec_PtrForEachEntry( If_Obj_t *, vNodes, pLeaf, i ) + pLeaf->fMark = 0; +} +void If_CutTraverseTest( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut ) +{ + Vec_Ptr_t * vNodes; + vNodes = Vec_PtrAlloc( 1000 ); + If_CutTraverse( p, pRoot, pCut, vNodes ); +//if ( Vec_PtrSize(vNodes) > 30 ) +//printf( "%d ", Vec_PtrSize(vNodes) ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ObjPrint( If_Obj_t * pObj ) +{ + if ( pObj == NULL ) + { + printf( "Object is NULL." ); + return; + } + printf( "Obj %4d : ", If_ObjId(pObj) ); + if ( If_ObjIsConst1(pObj) ) + printf( "constant 1" ); + else if ( If_ObjIsCi(pObj) ) + printf( "PI" ); + else if ( If_ObjIsCo(pObj) ) + printf( "PO( %4d%s )", If_ObjId(If_ObjFanin0(pObj)), (If_ObjFaninC0(pObj)? "\'" : " ") ); + else + printf( "AND( %4d%s, %4d%s )", + If_ObjId(If_ObjFanin0(pObj)), (If_ObjFaninC0(pObj)? "\'" : " "), + If_ObjId(If_ObjFanin1(pObj)), (If_ObjFaninC1(pObj)? "\'" : " ") ); + printf( " (refs = %3d)", pObj->nVisitsCopy ); + printf( "\n" ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/map/scl/sclTime.c b/src/map/scl/sclTime.c index 66a28b51..4e3b3de8 100644 --- a/src/map/scl/sclTime.c +++ b/src/map/scl/sclTime.c @@ -109,6 +109,7 @@ static inline void Abc_SclTimeNodePrint( SC_Man * p, Abc_Obj_t * pObj, int fRise { printf( "%7d : ", Abc_ObjId(pObj) ); printf( "%d ", Abc_ObjFaninNum(pObj) ); + printf( "%d ", Abc_ObjFanoutNum(pObj) ); printf( "%-*s ", Length, Abc_SclObjCell(p, pObj)->pName ); if ( fRise >= 0 ) printf( "(%s) ", fRise ? "rise" : "fall" ); diff --git a/src/misc/util/abc_global.h b/src/misc/util/abc_global.h index 03474a04..3259fa0d 100644 --- a/src/misc/util/abc_global.h +++ b/src/misc/util/abc_global.h @@ -52,9 +52,11 @@ #endif // catch memory leaks in Visual Studio -#ifdef _DEBUG -#define _CRTDBG_MAP_ALLOC -#include <crtdbg.h> +#ifdef WIN32 + #ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include <crtdbg.h> + #endif #endif #if !defined(___unused) diff --git a/src/misc/util/utilTruth.h b/src/misc/util/utilTruth.h new file mode 100644 index 00000000..6bfb5699 --- /dev/null +++ b/src/misc/util/utilTruth.h @@ -0,0 +1,422 @@ +/**CFile**************************************************************** + + FileName [utilTruth.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Truth table manipulation.] + + Synopsis [Truth table manipulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 28, 2012.] + + Revision [$Id: utilTruth.h,v 1.00 2012/10/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__misc__util__utilTruth_h +#define ABC__misc__util__utilTruth_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +static word s_Truths6[6] = { + 0xAAAAAAAAAAAAAAAA, + 0xCCCCCCCCCCCCCCCC, + 0xF0F0F0F0F0F0F0F0, + 0xFF00FF00FF00FF00, + 0xFFFF0000FFFF0000, + 0xFFFFFFFF00000000 +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_TtWordNum( int nVars ) { return nVars <= 6 ? 1 : 1 << (nVars-6); } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_TtCopy( word * pOut, word * pIn, int nWords, int fCompl ) +{ + int w; + if ( fCompl ) + for ( w = 0; w < nWords; w++ ) + pOut[w] = ~pIn[w]; + else + for ( w = 0; w < nWords; w++ ) + pOut[w] = pIn[w]; +} +static inline void Abc_TtAnd( word * pOut, word * pIn1, word * pIn2, int nWords, int fCompl ) +{ + int w; + if ( fCompl ) + for ( w = 0; w < nWords; w++ ) + pOut[w] = ~(pIn1[w] & pIn2[w]); + else + for ( w = 0; w < nWords; w++ ) + pOut[w] = pIn1[w] & pIn2[w]; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_TtSuppIsMinBase( int Supp ) +{ + return (Supp & (Supp+1)) == 0; +} +static inline int Abc_Tt6HasVar( word t, int iVar ) +{ + return ((t << (1<<iVar)) & s_Truths6[iVar]) != (t & s_Truths6[iVar]); +} +static inline int Abc_TtHasVar( word * t, int nVars, int iVar ) +{ + int nWords = Abc_TtWordNum( nVars ); + assert( iVar < nVars ); + if ( iVar < 6 ) + { + int i, Shift = (1 << iVar); + for ( i = 0; i < nWords; i++ ) + if ( ((t[i] << Shift) & s_Truths6[iVar]) != (t[i] & s_Truths6[iVar]) ) + return 1; + return 0; + } + else + { + int i, Step = (1 << (iVar - 6)); + word * tLimit = t + nWords; + for ( ; t < tLimit; t += 2*Step ) + for ( i = 0; i < Step; i++ ) + if ( t[i] != t[Step+i] ) + return 1; + return 0; + } +} +static inline int Abc_TtSupport( word * t, int nVars ) +{ + int v, Supp = 0; + for ( v = 0; v < nVars; v++ ) + if ( Abc_TtHasVar( t, nVars, v ) ) + Supp |= (1 << v); + return Supp; +} +static inline int Abc_TtSupportSize( word * t, int nVars ) +{ + int v, SuppSize = 0; + for ( v = 0; v < nVars; v++ ) + if ( Abc_TtHasVar( t, nVars, v ) ) + SuppSize++; + return SuppSize; +} +static inline int Abc_TtSupportAndSize( word * t, int nVars, int * pSuppSize ) +{ + int v, Supp = 0; + *pSuppSize = 0; + for ( v = 0; v < nVars; v++ ) + if ( Abc_TtHasVar( t, nVars, v ) ) + Supp |= (1 << v), (*pSuppSize)++; + return Supp; +} +static inline int Abc_Tt6SupportAndSize( word t, int nVars, int * pSuppSize ) +{ + int v, Supp = 0; + *pSuppSize = 0; + assert( nVars <= 6 ); + for ( v = 0; v < nVars; v++ ) + if ( Abc_Tt6HasVar( t, v ) ) + Supp |= (1 << v), (*pSuppSize)++; + return Supp; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_TtSwapVars( word * pTruth, int nVars, int iVar, int jVar ) +{ + static word PPMasks[5][6][3] = { + { + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 0 0 + { 0x9999999999999999, 0x2222222222222222, 0x4444444444444444 }, // 0 1 + { 0xA5A5A5A5A5A5A5A5, 0x0A0A0A0A0A0A0A0A, 0x5050505050505050 }, // 0 2 + { 0xAA55AA55AA55AA55, 0x00AA00AA00AA00AA, 0x5500550055005500 }, // 0 3 + { 0xAAAA5555AAAA5555, 0x0000AAAA0000AAAA, 0x5555000055550000 }, // 0 4 + { 0xAAAAAAAA55555555, 0x00000000AAAAAAAA, 0x5555555500000000 } // 0 5 + }, + { + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 1 0 + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 1 1 + { 0xC3C3C3C3C3C3C3C3, 0x0C0C0C0C0C0C0C0C, 0x3030303030303030 }, // 1 2 + { 0xCC33CC33CC33CC33, 0x00CC00CC00CC00CC, 0x3300330033003300 }, // 1 3 + { 0xCCCC3333CCCC3333, 0x0000CCCC0000CCCC, 0x3333000033330000 }, // 1 4 + { 0xCCCCCCCC33333333, 0x00000000CCCCCCCC, 0x3333333300000000 } // 1 5 + }, + { + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 2 0 + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 2 1 + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 2 2 + { 0xF00FF00FF00FF00F, 0x00F000F000F000F0, 0x0F000F000F000F00 }, // 2 3 + { 0xF0F00F0FF0F00F0F, 0x0000F0F00000F0F0, 0x0F0F00000F0F0000 }, // 2 4 + { 0xF0F0F0F00F0F0F0F, 0x00000000F0F0F0F0, 0x0F0F0F0F00000000 } // 2 5 + }, + { + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 3 0 + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 3 1 + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 3 2 + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 3 3 + { 0xFF0000FFFF0000FF, 0x0000FF000000FF00, 0x00FF000000FF0000 }, // 3 4 + { 0xFF00FF0000FF00FF, 0x00000000FF00FF00, 0x00FF00FF00000000 } // 3 5 + }, + { + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 4 0 + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 4 1 + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 4 2 + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 4 3 + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, // 4 4 + { 0xFFFF00000000FFFF, 0x00000000FFFF0000, 0x0000FFFF00000000 } // 4 5 + } + }; + if ( iVar == jVar ) + return; + if ( jVar < iVar ) + ABC_SWAP( int, iVar, jVar ); + assert( iVar < jVar && jVar < nVars ); + if ( nVars <= 6 ) + { + word * pMasks = PPMasks[iVar][jVar]; + int shift = (1 << jVar) - (1 << iVar); + pTruth[0] = (pTruth[0] & pMasks[0]) | ((pTruth[0] & pMasks[1]) << shift) | ((pTruth[0] & pMasks[2]) >> shift); + } + else + { + if ( jVar <= 5 ) + { + word * pMasks = PPMasks[iVar][jVar]; + int nWords = Abc_TtWordNum(nVars); + int w, shift = (1 << jVar) - (1 << iVar); + for ( w = 0; w < nWords; w++ ) + pTruth[w] = (pTruth[w] & pMasks[0]) | ((pTruth[w] & pMasks[1]) << shift) | ((pTruth[w] & pMasks[2]) >> shift); + } + else if ( iVar <= 5 && jVar > 5 ) + { + word low2High, high2Low; + word * pLimit = pTruth + Abc_TtWordNum(nVars); + int j, jStep = Abc_TtWordNum(jVar); + int shift = 1 << iVar; + for ( ; pTruth < pLimit; pTruth += 2*jStep ) + for ( j = 0; j < jStep; j++ ) + { + low2High = (pTruth[j] & s_Truths6[iVar]) >> shift; + high2Low = (pTruth[j+jStep] << shift) & s_Truths6[iVar]; + pTruth[j] = (pTruth[j] & ~s_Truths6[iVar]) | high2Low; + pTruth[j+jStep] = (pTruth[j+jStep] & s_Truths6[iVar]) | low2High; + } + } + else + { + word temp, * pLimit = pTruth + Abc_TtWordNum(nVars); + int i, iStep = Abc_TtWordNum(iVar); + int j, jStep = Abc_TtWordNum(jVar); + for ( ; pTruth < pLimit; pTruth += 2*jStep ) + for ( i = 0; i < jStep; i += 2*iStep ) + for ( j = 0; j < iStep; j++ ) + { + temp = pTruth[iStep + i + j]; + pTruth[iStep + i + j] = pTruth[jStep + i + j]; + pTruth[jStep + i + j] = temp; + } + } + } +} + +static inline void Abc_TtSwapVars_( word * pTruth, int nVars, int iVar, int jVar ) +{ + static word PPMasks[6][6] = { + { 0x2222222222222222, 0x0A0A0A0A0A0A0A0A, 0x00AA00AA00AA00AA, 0x0000AAAA0000AAAA, 0x00000000AAAAAAAA, 0xAAAAAAAAAAAAAAAA }, + { 0x0000000000000000, 0x0C0C0C0C0C0C0C0C, 0x00CC00CC00CC00CC, 0x0000CCCC0000CCCC, 0x00000000CCCCCCCC, 0xCCCCCCCCCCCCCCCC }, + { 0x0000000000000000, 0x0000000000000000, 0x00F000F000F000F0, 0x0000F0F00000F0F0, 0x00000000F0F0F0F0, 0xF0F0F0F0F0F0F0F0 }, + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000FF000000FF00, 0x00000000FF00FF00, 0xFF00FF00FF00FF00 }, + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x00000000FFFF0000, 0xFFFF0000FFFF0000 }, + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0xFFFFFFFF00000000 } + }; + if ( nVars <= 6 ) + { + int shift; + word low2High, high2Low; + assert( iVar <= 5 && jVar <= 5 && iVar < jVar ); + shift = (1 << jVar) - (1 << iVar); + low2High = (pTruth[0] & PPMasks[iVar][jVar - 1] ) << shift; + pTruth[0] &= ~PPMasks[iVar][jVar - 1]; + high2Low = (pTruth[0] & (PPMasks[iVar][jVar - 1] << shift )) >> shift; + pTruth[0] &= ~(PPMasks[iVar][jVar - 1] << shift); + pTruth[0] |= low2High | high2Low; + } + else + { + word low2High, high2Low, temp; + int nWords = Abc_TtWordNum(nVars); + int shift, step, iStep, jStep; + int w = 0, i = 0, j = 0; + if ( iVar == jVar ) + return; + if ( jVar < iVar ) + ABC_SWAP( int, iVar, jVar ); + if ( iVar <= 5 && jVar <= 5 ) + { + shift = (1 << jVar) - (1 << iVar); + for ( w = 0; w < nWords; w++ ) + { + low2High = (pTruth[w] & PPMasks[iVar][jVar - 1] ) << shift; + pTruth[w] &= ~PPMasks[iVar][jVar - 1]; + high2Low = (pTruth[w] & (PPMasks[iVar][jVar - 1] << shift )) >> shift; + pTruth[w] &= ~(PPMasks[iVar][jVar - 1] << shift); + pTruth[w] |= low2High | high2Low; + } + } + else if ( iVar <= 5 && jVar > 5 ) + { + step = Abc_TtWordNum(jVar + 1)/2; + shift = 1 << iVar; + for ( w = 0; w < nWords; w += 2*step ) + { + for (j = 0; j < step; j++) + { + low2High = (pTruth[w + j] & PPMasks[iVar][5]) >> shift; + pTruth[w + j] &= ~PPMasks[iVar][5]; + high2Low = (pTruth[w + step + j] & (PPMasks[iVar][5] >> shift)) << shift; + pTruth[w + step + j] &= ~(PPMasks[iVar][5] >> shift); + pTruth[w + j] |= high2Low; + pTruth[w + step + j] |= low2High; + } + } + } + else + { + iStep = Abc_TtWordNum(iVar + 1)/2; + jStep = Abc_TtWordNum(jVar + 1)/2; + for (w = 0; w < nWords; w += 2*jStep) + { + for (i = 0; i < jStep; i += 2*iStep) + { + for (j = 0; j < iStep; j++) + { + temp = pTruth[w + iStep + i + j]; + pTruth[w + iStep + i + j] = pTruth[w + jStep + i + j]; + pTruth[w + jStep + i + j] = temp; + } + } + } + } + } +} + + + +/**Function************************************************************* + + Synopsis [Stretch truthtable to have more input variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Abc_TtStretch5( unsigned * pInOut, int nVarS, int nVarB ) +{ + int w, i, step, nWords; + if ( nVarS == nVarB ) + return; + assert( nVarS < nVarB ); + step = Abc_TruthWordNum(nVarS); + nWords = Abc_TruthWordNum(nVarB); + if ( step == nWords ) + return; + assert( step < nWords ); + for ( w = 0; w < nWords; w += step ) + for ( i = 0; i < step; i++ ) + pInOut[w + i] = pInOut[i]; +} +static void Abc_TtStretch6( word * pInOut, int nVarS, int nVarB ) +{ + int w, i, step, nWords; + if ( nVarS == nVarB ) + return; + assert( nVarS < nVarB ); + step = Abc_Truth6WordNum(nVarS); + nWords = Abc_Truth6WordNum(nVarB); + if ( step == nWords ) + return; + assert( step < nWords ); + for ( w = 0; w < nWords; w += step ) + for ( i = 0; i < step; i++ ) + pInOut[w + i] = pInOut[i]; +} + +/*=== utilTruth.c ===========================================================*/ + + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/misc/vec/vecMem.h b/src/misc/vec/vecMem.h index 229c53a2..eaa9481f 100644 --- a/src/misc/vec/vecMem.h +++ b/src/misc/vec/vecMem.h @@ -57,14 +57,16 @@ struct Vec_Mem_t_ int nPageAlloc; // number of pages currently allocated int iPage; // the number of a page currently used word ** ppPages; // memory pages + Vec_Int_t * vTable; // hash table + Vec_Int_t * vNexts; // next pointers }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// -#define Vec_MemForEachEntry( vVec, pEntry, i ) \ - for ( i = 0; (i < Vec_MemEntryNum(vVec)) && ((pEntry) = Vec_MemReadEntry(vVec, i)); i++ ) +#define Vec_MemForEachEntry( p, pEntry, i ) \ + for ( i = 0; (i < Vec_MemEntryNum(p)) && ((pEntry) = Vec_MemReadEntry(p, i)); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -266,12 +268,12 @@ static inline void Vec_MemShrink( Vec_Mem_t * p, int nEntriesNew ) SeeAlso [] ***********************************************************************/ -static inline void Vec_MemPrint( Vec_Mem_t * vVec ) +static inline void Vec_MemPrint( Vec_Mem_t * p ) { word * pEntry; int i; - printf( "Memory vector has %d entries: ", Vec_MemEntryNum(vVec) ); - Vec_MemForEachEntry( vVec, pEntry, i ) + printf( "Memory vector has %d entries: ", Vec_MemEntryNum(p) ); + Vec_MemForEachEntry( p, pEntry, i ) { printf( "%3d : ", i ); // add printout here @@ -279,6 +281,76 @@ static inline void Vec_MemPrint( Vec_Mem_t * vVec ) } } +/**Function************************************************************* + + Synopsis [Hashing entries in the memory vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_MemHashAlloc( Vec_Mem_t * p, int nTableSize ) +{ + assert( p->vTable == NULL && p->vNexts == NULL ); + p->vTable = Vec_IntStartFull( Abc_PrimeCudd(nTableSize) ); + p->vNexts = Vec_IntAlloc( nTableSize ); +} +static inline void Vec_MemHashFree( Vec_Mem_t * p ) +{ + Vec_IntFreeP( &p->vTable ); + Vec_IntFreeP( &p->vNexts ); +} +static inline unsigned Vec_MemHashKey( Vec_Mem_t * p, word * pEntry ) +{ + static int s_Primes[8] = { 1699, 4177, 5147, 5647, 6343, 7103, 7873, 8147 }; + int i, nData = 2 * p->nEntrySize; + unsigned * pData = (unsigned *)pEntry; + unsigned uHash = 0; + for ( i = 0; i < nData; i++ ) + uHash += pData[i] * s_Primes[i & 0x7]; + return uHash % Vec_IntSize(p->vTable); +} +static int * Vec_MemHashLookup( Vec_Mem_t * p, word * pEntry ) +{ + int * pSpot = Vec_IntEntryP( p->vTable, Vec_MemHashKey(p, pEntry) ); + for ( ; *pSpot != -1; pSpot = Vec_IntEntryP(p->vNexts, *pSpot) ) + if ( !memcmp( Vec_MemReadEntry(p, *pSpot), pEntry, sizeof(word) * p->nEntrySize ) ) // equal + return pSpot; + return pSpot; +} +static void Vec_MemHashResize( Vec_Mem_t * p ) +{ + word * pEntry; + int i, * pSpot; + Vec_IntFill( p->vTable, Abc_PrimeCudd(2 * Vec_IntSize(p->vTable)), -1 ); + Vec_IntClear( p->vNexts ); + Vec_MemForEachEntry( p, pEntry, i ) + { + pSpot = Vec_MemHashLookup( p, pEntry ); + assert( *pSpot == -1 ); + *pSpot = Vec_IntSize(p->vNexts); + Vec_IntPush( p->vNexts, -1 ); + } + assert( p->nEntries == Vec_IntSize(p->vNexts) ); +} +static int Vec_MemHashInsert( Vec_Mem_t * p, word * pEntry ) +{ + int * pSpot; + if ( p->nEntries > Vec_IntSize(p->vTable) ) + Vec_MemHashResize( p ); + pSpot = Vec_MemHashLookup( p, pEntry ); + if ( *pSpot != -1 ) + return *pSpot; + *pSpot = Vec_IntSize(p->vNexts); + Vec_IntPush( p->vNexts, -1 ); + Vec_MemPush( p, pEntry ); + assert( p->nEntries == Vec_IntSize(p->vNexts) ); + return Vec_IntSize(p->vNexts) - 1; +} + ABC_NAMESPACE_HEADER_END diff --git a/src/opt/dau/dauDsd.c b/src/opt/dau/dauDsd.c index 6f970b62..f6367304 100644 --- a/src/opt/dau/dauDsd.c +++ b/src/opt/dau/dauDsd.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "dauInt.h" +#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START @@ -443,7 +444,7 @@ void Dau_DsdTestOne( word t, int i ) { word t2; char * p = Dau_DsdPerform( t ); -// return; + return; t2 = Dau_DsdToTruth( p ); if ( t != t2 ) { @@ -463,6 +464,344 @@ void Dau_DsdTestOne( word t, int i ) Dau_DsdTestOne( *p->pFuncs[i], i ); */ + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_TtTruthIsConst0( word * p, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( p[w] != 0 ) return 0; return 1; } +static inline int Abc_TtTruthIsConst1( word * p, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( p[w] != ~(word)0 ) return 0; return 1; } + +static inline int Abc_TtCof0IsConst0( word * t, int nWords, int iVar ) +{ + if ( iVar < 6 ) + { + int i; + for ( i = 0; i < nWords; i++ ) + if ( t[i] & ~s_Truths6[iVar] ) + return 0; + return 1; + } + else + { + int i, Step = (1 << (iVar - 6)); + word * tLimit = t + nWords; + for ( ; t < tLimit; t += 2*Step ) + for ( i = 0; i < Step; i++ ) + if ( t[i] ) + return 0; + return 1; + } +} +static inline int Abc_TtCof0IsConst1( word * t, int nWords, int iVar ) +{ + if ( iVar < 6 ) + { + int i; + for ( i = 0; i < nWords; i++ ) + if ( (t[i] & ~s_Truths6[iVar]) != ~s_Truths6[iVar] ) + return 0; + return 1; + } + else + { + int i, Step = (1 << (iVar - 6)); + word * tLimit = t + nWords; + for ( ; t < tLimit; t += 2*Step ) + for ( i = 0; i < Step; i++ ) + if ( t[i] != ~(word)0 ) + return 0; + return 1; + } +} +static inline int Abc_TtCof1IsConst0( word * t, int nWords, int iVar ) +{ + if ( iVar < 6 ) + { + int i; + for ( i = 0; i < nWords; i++ ) + if ( t[i] & s_Truths6[iVar] ) + return 0; + return 1; + } + else + { + int i, Step = (1 << (iVar - 6)); + word * tLimit = t + nWords; + for ( ; t < tLimit; t += 2*Step ) + for ( i = 0; i < Step; i++ ) + if ( t[i+Step] ) + return 0; + return 1; + } +} +static inline int Abc_TtCof1IsConst1( word * t, int nWords, int iVar ) +{ + if ( iVar < 6 ) + { + int i; + for ( i = 0; i < nWords; i++ ) + if ( (t[i] & s_Truths6[iVar]) != s_Truths6[iVar] ) + return 0; + return 1; + } + else + { + int i, Step = (1 << (iVar - 6)); + word * tLimit = t + nWords; + for ( ; t < tLimit; t += 2*Step ) + for ( i = 0; i < Step; i++ ) + if ( t[i+Step] != ~(word)0 ) + return 0; + return 1; + } +} +static inline int Abc_TtCofsOpposite( word * t, int nWords, int iVar ) +{ + if ( iVar < 6 ) + { + int i, Shift = (1 << iVar); + for ( i = 0; i < nWords; i++ ) + if ( ((t[i] << Shift) & s_Truths6[iVar]) != (~t[i] & s_Truths6[iVar]) ) + return 0; + return 1; + } + else + { + int i, Step = (1 << (iVar - 6)); + word * tLimit = t + nWords; + for ( ; t < tLimit; t += 2*Step ) + for ( i = 0; i < Step; i++ ) + if ( t[i] != ~t[i+Step] ) + return 0; + return 1; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_TtCof0HasVar( word * t, int nWords, int iVarI, int iVarJ ) +{ + assert( iVarI > iVarJ ); + if ( iVarI < 6 ) + { + int i, Shift = (1 << iVarJ); + for ( i = 0; i < nWords; i++ ) + if ( (((t[i] & ~s_Truths6[iVarI]) << Shift) & s_Truths6[iVarJ]) != ((t[i] & ~s_Truths6[iVarI]) & s_Truths6[iVarJ]) ) + return 0; + return 1; + } + else if ( iVarI == 6 ) + { + } + else + { + int i, Step = (1 << (iVarJ - 6)); + word * tLimit = t + nWords; + for ( ; t < tLimit; t += 2*Step ) + for ( i = 0; i < Step; i++ ) + if ( t[i] != t[i+Step] ) + return 0; + return 1; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dau_DsdMinimize( word * p, int * pVars, int nVars ) +{ + int i, k; + assert( nVars > 6 ); + for ( i = k = nVars - 1; i >= 0; i-- ) + { + if ( Abc_TtHasVar( p, nVars, i ) ) + continue; + if ( i < k ) + { + pVars[i] = pVars[k]; + Abc_TtSwapVars( p, nVars, i, k ); + } + k--; + nVars--; + } + return nVars; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dau_DsdRun6_rec( word * p, int * pVars, int nVars, char * pBuffer, int Pos, char pStore[16][16], int Func ) +{ + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dau_DsdRun_rec( word * p, int * pVars, int nVars, char * pBuffer, int Pos, char pStore[16][16], int Func ) +{ + int v, nWords = Abc_TtWordNum( nVars ); + nVars = Dau_DsdMinimize( p, pVars, nVars ); + if ( nVars <= 6 ) + return Dau_DsdRun6_rec( p, pVars, nVars, pBuffer, Pos, pStore, Func ); + if ( p[0] & 1 ) + { + // check for !(ax) + for ( v = 0; v < nVars; v++ ) + if ( Abc_TtCof0IsConst0( p, nWords, v ) ) + { + pBuffer[Pos++] = '('; + pBuffer[Pos++] = 'a' + pVars[v]; + Abc_TtSwapVars( p, nVars, v, nVars - 1 ); + pVars[v] = pVars[nVars-1]; + Pos = Dau_DsdRun_rec( p + nWords/2, pVars, nVars-1, pBuffer, Pos, pStore, Func ); + pBuffer[Pos++] = ')'; + return Pos; + } + } + else + { + // check for ax + for ( v = 0; v < nVars; v++ ) + if ( Abc_TtCof0IsConst1( p, nWords, v ) ) + { + pBuffer[Pos++] = '!'; + pBuffer[Pos++] = '('; + pBuffer[Pos++] = 'a' + pVars[v]; + Abc_TtSwapVars( p, nVars, v, nVars - 1 ); + pVars[v] = pVars[nVars-1]; + Pos = Dau_DsdRun_rec( p + nWords/2, pVars, nVars-1, pBuffer, Pos, pStore, Func ); + pBuffer[Pos++] = ')'; + return Pos; + } + } + if ( (p[nWords-1] >> 63) & 1 ) + { + // check for !(!ax) + for ( v = 0; v < nVars; v++ ) + if ( Abc_TtCof0IsConst1( p, nWords, v ) ) + { + pBuffer[Pos++] = '!'; + pBuffer[Pos++] = '('; + pBuffer[Pos++] = '!'; + pBuffer[Pos++] = 'a' + pVars[v]; + Abc_TtSwapVars( p, nVars, v, nVars - 1 ); + pVars[v] = pVars[nVars-1]; + Pos = Dau_DsdRun_rec( p, pVars, nVars-1, pBuffer, Pos, pStore, Func ); + pBuffer[Pos++] = ')'; + return Pos; + } + } + else + { + // check for !ax + for ( v = 0; v < nVars; v++ ) + if ( Abc_TtCof1IsConst0( p, nWords, v ) ) + { + pBuffer[Pos++] = '('; + pBuffer[Pos++] = '!'; + pBuffer[Pos++] = 'a' + pVars[v]; + Abc_TtSwapVars( p, nVars, v, nVars - 1 ); + pVars[v] = pVars[nVars-1]; + Pos = Dau_DsdRun_rec( p, pVars, nVars-1, pBuffer, Pos, pStore, Func ); + pBuffer[Pos++] = ')'; + return Pos; + } + } + // check for a^x + for ( v = 0; v < nVars; v++ ) + if ( Abc_TtCofsOpposite( p, nWords, v ) ) + { + pBuffer[Pos++] = '['; + pBuffer[Pos++] = 'a' + pVars[v]; + Abc_TtSwapVars( p, nVars, v, nVars - 1 ); + pVars[v] = pVars[nVars-1]; + Pos = Dau_DsdRun_rec( p, pVars, nVars-1, pBuffer, Pos, pStore, Func ); + pBuffer[Pos++] = ']'; + return Pos; + } + + return 0; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Dau_DsdRun( word * p, int nVars ) +{ + static char pBuffer[DAU_MAX_STR+20]; + static char pStore[16][16]; + int nWords = Abc_TtWordNum( nVars ); + int i, Pos = 0, Func = 0, pVars[16]; + assert( nVars <= 16 ); + for ( i = 0; i < nVars; i++ ) + pVars[i] = i; + if ( Abc_TtTruthIsConst0( p, nWords ) ) + pBuffer[Pos++] = '0'; + else if ( Abc_TtTruthIsConst1( p, nWords ) ) + pBuffer[Pos++] = '1'; + else if ( nVars <= 6 ) + Pos = Dau_DsdRun6_rec( p, pVars, nVars, pBuffer, Pos, pStore, Func ); + else + Pos = Dau_DsdRun_rec( p, pVars, nVars, pBuffer, Pos, pStore, Func ); + pBuffer[Pos++] = 0; + Dau_DsdCleanBraces( pBuffer ); + return pBuffer; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/dau/dauEnum.c b/src/opt/dau/dauEnum.c new file mode 100644 index 00000000..58e44c02 --- /dev/null +++ b/src/opt/dau/dauEnum.c @@ -0,0 +1,253 @@ +/**CFile**************************************************************** + + FileName [dauEnum.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware unmapping.] + + Synopsis [Enumeration of decompositions.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: dauEnum.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dauInt.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Dau_EnumLift( char * pName, int Shift ) +{ + static char pBuffer[64]; + char * pTemp; + for ( pTemp = pBuffer; *pName; pTemp++, pName++ ) + *pTemp = (*pName >= 'a' && *pName <= 'z') ? *pName + Shift : *pName; + *pTemp = 0; + return pBuffer; +} +char * Dau_EnumLift2( char * pName, int Shift ) +{ + static char pBuffer[64]; + char * pTemp; + for ( pTemp = pBuffer; *pName; pTemp++, pName++ ) + *pTemp = (*pName >= 'a' && *pName <= 'z') ? *pName + Shift : *pName; + *pTemp = 0; + return pBuffer; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dau_EnumCombineTwo( Vec_Ptr_t * vOne, int fStar, int fXor, char * pName1, char * pName2, int Shift2, int fCompl1, int fCompl2 ) +{ + static char pBuffer[256]; + pName2 = Dau_EnumLift( pName2, Shift2 ); + sprintf( pBuffer, "%s%c%s%s%s%s%c", + fStar?"*":"", + fXor?'[':'(', + fCompl1?"!":"", pName1[0] == '*' ? pName1 + 1 : pName1, + fCompl2?"!":"", pName2[0] == '*' ? pName2 + 1 : pName2, + fXor?']':')' ); +// printf( "%s ", pBuffer ); + Vec_PtrPush( vOne, Abc_UtilStrsav(pBuffer) ); +} +void Dau_EnumCombineThree( Vec_Ptr_t * vOne, int fStar, char * pNameC, char * pName1, char * pName2, int Shift1, int Shift2, int fComplC, int fCompl1, int fCompl2 ) +{ + static char pBuffer[256]; + pName1 = Dau_EnumLift( pName1, Shift1 ); + pName2 = Dau_EnumLift2( pName2, Shift2 ); + sprintf( pBuffer, "%s%c%s%s%s%s%s%s%c", + fStar?"*":"", + '<', + fComplC?"!":"", pNameC[0] == '*' ? pNameC + 1 : pNameC, + fCompl1?"!":"", pName1[0] == '*' ? pName1 + 1 : pName1, + fCompl2?"!":"", pName2[0] == '*' ? pName2 + 1 : pName2, + '>' ); +// printf( "%s ", pBuffer ); + Vec_PtrPush( vOne, Abc_UtilStrsav(pBuffer) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dau_EnumTestDump( Vec_Ptr_t * vSets, char * pFileName ) +{ + FILE * pFile; + Vec_Ptr_t * vOne; + char * pName; + int v, k; + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + return; + Vec_PtrForEachEntry( Vec_Ptr_t *, vSets, vOne, v ) + { + fprintf( pFile, "VARIABLE NUMBER %d:\n", v ); + Vec_PtrForEachEntry( char *, vOne, pName, k ) + fprintf( pFile, "%s\n", pName ); + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dau_EnumTest() +{ + int v, k, nVarMax = 10; + Vec_Ptr_t * vSets; + Vec_Ptr_t * vOne; + char * pName; + // 0 vars + vSets = Vec_PtrAlloc( 16 ); + Vec_PtrPush( vSets, Vec_PtrAlloc(0) ); + // 1 vars + vOne = Vec_PtrAlloc( 1 ); + Vec_PtrPush( vOne, Abc_UtilStrsav("*a") ); + Vec_PtrPush( vSets, vOne ); + // 2+ vars + for ( v = 2; v <= nVarMax; v++ ) + { + Vec_Ptr_t * vSetI, * vSetJ, * vSetK; + char * pNameI, * pNameJ, * pNameK; + int i, j, k, i1, j1, k1; + vOne = Vec_PtrAlloc( 100 ); + for ( i = 1; i < v; i++ ) + for ( j = i; j < v; j++ ) + { + if ( i + j != v ) + continue; + vSetI = (Vec_Ptr_t *)Vec_PtrEntry( vSets, i ); + vSetJ = (Vec_Ptr_t *)Vec_PtrEntry( vSets, j ); + Vec_PtrForEachEntry( char *, vSetI, pNameI, i1 ) + Vec_PtrForEachEntry( char *, vSetJ, pNameJ, j1 ) + { + // AND(a,b) + Dau_EnumCombineTwo( vOne, 0, 0, pNameI, pNameJ, i, 0, 0 ); + // AND(!a,b) + if ( pNameI[0] != '*' ) + Dau_EnumCombineTwo( vOne, 0, 0, pNameI, pNameJ, i, 1, 0 ); + // AND(a,!b) + if ( pNameJ[0] != '*' && !(i == j && i1 == j1) ) + Dau_EnumCombineTwo( vOne, 0, 0, pNameI, pNameJ, i, 0, 1 ); + // AND(!a,!b) + if ( pNameI[0] != '*' && pNameJ[0] != '*' ) + Dau_EnumCombineTwo( vOne, 0, 0, pNameI, pNameJ, i, 1, 1 ); + // XOR(a,b) + Dau_EnumCombineTwo( vOne, pNameI[0] == '*' || pNameJ[0] == '*', 1, pNameI, pNameJ, i, 0, 0 ); + } + } + for ( k = 1; k < v; k++ ) + for ( i = 1; i < v; i++ ) + for ( j = i; j < v; j++ ) + { + if ( k + i + j != v ) + continue; + vSetK = (Vec_Ptr_t *)Vec_PtrEntry( vSets, k ); + vSetI = (Vec_Ptr_t *)Vec_PtrEntry( vSets, i ); + vSetJ = (Vec_Ptr_t *)Vec_PtrEntry( vSets, j ); + Vec_PtrForEachEntry( char *, vSetK, pNameK, k1 ) + Vec_PtrForEachEntry( char *, vSetI, pNameI, i1 ) + Vec_PtrForEachEntry( char *, vSetJ, pNameJ, j1 ) + { + int fStar = pNameI[0] == '*' && pNameJ[0] == '*'; + + // MUX(c,a,b) + Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 0, 0, 0 ); + // MUX(c,!a,b) + if ( pNameI[0] != '*' ) + Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 0, 1, 0 ); + // MUX(c,a,!b) + if ( pNameJ[0] != '*' && !(i == j && i1 == j1) ) + Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 0, 0, 1 ); + + if ( pNameK[0] != '*' && !(i == j && i1 == j1) ) + { + // MUX(!c,a,b) + Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 1, 0, 0 ); + // MUX(!c,!a,b) + if ( pNameI[0] != '*' ) + Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 1, 1, 0 ); + // MUX(!c,a,!b) + if ( pNameJ[0] != '*' ) + Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 1, 0, 1 ); + } + } + } + Vec_PtrPush( vSets, vOne ); + } + Dau_EnumTestDump( vSets, "_npn/npn/dsd10.txt" ); + + Vec_PtrForEachEntry( Vec_Ptr_t *, vSets, vOne, v ) + { + printf( "VARIABLE NUMBER %d:\n", v ); + Vec_PtrForEachEntry( char *, vOne, pName, k ) + printf( "%s\n", pName ); + if ( v == 4 ) + break; + } + Vec_PtrForEachEntry( Vec_Ptr_t *, vSets, vOne, v ) + { + printf( "%d=%d ", v, Vec_PtrSize(vOne) ); + Vec_PtrFreeFree( vOne ); + } + Vec_PtrFree( vSets ); + printf( "\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/dau/module.make b/src/opt/dau/module.make index c58d8807..87a800e9 100644 --- a/src/opt/dau/module.make +++ b/src/opt/dau/module.make @@ -1,3 +1,4 @@ SRC += src/opt/dau/dau.c \ src/opt/dau/dauCore.c \ - src/opt/dau/dauDsd.c + src/opt/dau/dauDsd.c \ + src/opt/dau/dauEnum.c diff --git a/src/opt/nwk/nwkMap.c b/src/opt/nwk/nwkMap.c index e80c4c93..e8be5a2d 100644 --- a/src/opt/nwk/nwkMap.c +++ b/src/opt/nwk/nwkMap.c @@ -163,7 +163,6 @@ If_Man_t * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf ) // set up the choice node if ( Aig_ObjIsChoice( p, pNode ) ) { - pIfMan->nChoices++; for ( pPrev = pNode, pFanin = Aig_ObjEquiv(p, pNode); pFanin; pPrev = pFanin, pFanin = Aig_ObjEquiv(p, pFanin) ) If_ObjSetChoice( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData ); If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pData ); diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index 10b06c28..65d2e24e 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -144,6 +144,7 @@ struct Cec_ParCor_t_ int fUseCSat; // use circuit-based solver // int fFirstStop; // stop on the first sat output int fUseSmartCnf; // use smart CNF computation + int fStopWhenGone; // quit when PO is not a candidate constant int fVerboseFlops; // verbose stats int fVeryVerbose; // verbose stats int fVerbose; // verbose stats diff --git a/src/proof/cec/cecCorr.c b/src/proof/cec/cecCorr.c index f35cd952..f3a84d3a 100644 --- a/src/proof/cec/cecCorr.c +++ b/src/proof/cec/cecCorr.c @@ -753,6 +753,7 @@ void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIte nFail++; } Abc_Print( 1, "p =%6d d =%6d f =%6d ", nProve, nDispr, nFail ); + Abc_Print( 1, "%c ", Gia_ObjIsConst( p, Gia_ObjFaninId0p(p, Gia_ManPo(p, 0)) ) ? '+' : '-' ); Abc_PrintTime( 1, "T", Time ); } @@ -950,6 +951,14 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) //Gia_ManEquivPrintClasses( pAig, 1, 0 ); if ( pPars->pFunc ) ((int (*)(void *))pPars->pFunc)( pPars->pData ); + // quit if const is no longer there + if ( pPars->fStopWhenGone && Gia_ManPoNum(pAig) == 1 && !Gia_ObjIsConst( pAig, Gia_ObjFaninId0p(pAig, Gia_ManPo(pAig, 0)) ) ) + { + printf( "Iterative refinement is stopped after iteration %d\n", r ); + printf( "because the property output is no longer a candidate constant.\n" ); + Cec_ManSimStop( pSim ); + return 0; + } } if ( pPars->fVerbose ) Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, clock() - clk ); @@ -1071,7 +1080,11 @@ Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) ABC_FREE( pAig->pReprs ); ABC_FREE( pAig->pNexts ); if ( pPars->nPrefix == 0 ) + { RetValue = Cec_ManLSCorrespondenceClasses( pAig, pPars ); + if ( RetValue == 0 ) + return Gia_ManDup( pAig ); + } else { // compute the cycles AIG diff --git a/src/proof/dch/dchChoice.c b/src/proof/dch/dchChoice.c index 783202e2..3f097ecc 100644 --- a/src/proof/dch/dchChoice.c +++ b/src/proof/dch/dchChoice.c @@ -95,7 +95,7 @@ int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig ) pEquiv = Aig_ObjEquiv( pAig, pObj ); if ( pEquiv == NULL ) continue; - assert( pEquiv->Id > pObj->Id ); + assert( pEquiv->Id < pObj->Id ); nEquivs++; } return nEquivs; diff --git a/src/proof/dch/dchCore.c b/src/proof/dch/dchCore.c index 0d2e8c0d..b92de8a6 100644 --- a/src/proof/dch/dchCore.c +++ b/src/proof/dch/dchCore.c @@ -111,7 +111,9 @@ p->timeTotal = clock() - clkTotal; pResult = Dch_DeriveChoiceAig( pAig, pPars->fSkipRedSupp ); // count the number of representatives if ( pPars->fVerbose ) - Abc_Print( 1, "STATS: Reprs = %6d. Equivs = %6d. Choices = %6d.\n", + Abc_Print( 1, "STATS: Ands:%8d ->%8d. Reprs:%7d ->%7d. Choices =%7d.\n", + Aig_ManNodeNum(pAig), + Aig_ManNodeNum(pResult), Dch_DeriveChoiceCountReprs( pAig ), Dch_DeriveChoiceCountEquivs( pResult ), Aig_ManChoiceNum( pResult ) ); diff --git a/src/proof/llb/llb4Map.c b/src/proof/llb/llb4Map.c index 51f1fec6..4b46f308 100644 --- a/src/proof/llb/llb4Map.c +++ b/src/proof/llb/llb4Map.c @@ -48,7 +48,7 @@ Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin ) { extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); extern If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); - extern void Gia_ManSetIfParsDefault( If_Par_t * pPars ); + extern void Gia_ManSetIfParsDefault( void * pPars ); If_Par_t Pars, * pPars = &Pars; If_Man_t * pIfMan; If_Obj_t * pAnd; diff --git a/src/proof/ssw/ssw.h b/src/proof/ssw/ssw.h index 35d41a35..df73c357 100644 --- a/src/proof/ssw/ssw.h +++ b/src/proof/ssw/ssw.h @@ -70,6 +70,7 @@ struct Ssw_Pars_t_ int fVerbose; // verbose stats int fFlopVerbose; // verbose printout of redundant flops int fEquivDump; // enables dumping equivalences + int fStopWhenGone; // stop when PO output is not a candidate constant // 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/sswCore.c b/src/proof/ssw/sswCore.c index 7e2e66da..7a9d4b9f 100644 --- a/src/proof/ssw/sswCore.c +++ b/src/proof/ssw/sswCore.c @@ -346,6 +346,24 @@ clk = clock(); } // if ( p->pPars->fDynamic && p->nSatCallsSat-nSatCallsSat < 100 ) // p->pPars->nBTLimit = 10000; + + if ( p->pPars->fStopWhenGone && Saig_ManPoNum(p->pAig) == 1 && !Ssw_ObjIsConst1Cand(p->pAig,Aig_ObjFanin0(Aig_ManCo(p->pAig,0))) ) + { + printf( "Iterative refinement is stopped after iteration %d\n", nIter ); + printf( "because the property output is no longer a candidate constant.\n" ); + // prepare to quite + p->nLitsEnd = p->nLitsBeg; + p->nNodesEnd = p->nNodesBeg; + p->nRegsEnd = p->nRegsBeg; + // cleanup + Ssw_SatStop( p->pMSat ); + p->pMSat = NULL; + Ssw_ManCleanup( p ); + // cleanup + Aig_ManSetPhase( p->pAig ); + Aig_ManCleanMarkB( p->pAig ); + return Aig_ManDupSimple( p->pAig ); + } } nSatProof = p->nSatProof; nSatCallsSat = p->nSatCallsSat; |