diff options
Diffstat (limited to 'src/aig/gia/giaStr.c')
-rw-r--r-- | src/aig/gia/giaStr.c | 1812 |
1 files changed, 1809 insertions, 3 deletions
diff --git a/src/aig/gia/giaStr.c b/src/aig/gia/giaStr.c index 13ddb233..f3416683 100644 --- a/src/aig/gia/giaStr.c +++ b/src/aig/gia/giaStr.c @@ -6,7 +6,7 @@ PackageName [Scalable AIG package.] - Synopsis [Cut computation.] + Synopsis [AIG structuring.] Author [Alan Mishchenko] @@ -19,6 +19,9 @@ ***********************************************************************/ #include "gia.h" +#include "misc/util/utilNam.h" +#include "misc/vec/vecWec.h" +#include "misc/tim/tim.h" ABC_NAMESPACE_IMPL_START @@ -26,15 +29,1343 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +#define STR_SUPER 100 + +enum { + STR_NONE = 0, + STR_CONST0 = 1, + STR_PI = 2, + STR_AND = 3, + STR_XOR = 4, + STR_MUX = 5, + STR_BUF = 6, + STR_PO = 7, + STR_UNUSED = 8 +}; + +typedef struct Str_Obj_t_ Str_Obj_t; +struct Str_Obj_t_ +{ + unsigned Type : 4; // object type + unsigned nFanins : 28; // fanin count + int iOffset; // place where fanins are stored + int iTop; // top level MUX + int iCopy; // copy of this node +}; +typedef struct Str_Ntk_t_ Str_Ntk_t; +struct Str_Ntk_t_ +{ + int nObjs; // object count + int nObjsAlloc; // alloc objects + Str_Obj_t * pObjs; // objects + Vec_Int_t vFanins; // object fanins + int nObjCount[STR_UNUSED]; + int nTrees; + int nGroups; + int DelayGain; +}; +typedef struct Str_Man_t_ Str_Man_t; +struct Str_Man_t_ +{ + // user data + Gia_Man_t * pOld; // manager + int nLutSize; // LUT size + int fCutMin; // cut minimization + // internal data + Str_Ntk_t * pNtk; // balanced network + // AIG under construction + Gia_Man_t * pNew; // newly constructed + Vec_Int_t * vDelays; // delays of each object +}; + +static inline Str_Obj_t * Str_NtkObj( Str_Ntk_t * p, int i ) { assert( i < p->nObjs ); return p->pObjs + i; } +static inline int Str_ObjFaninId( Str_Ntk_t * p, Str_Obj_t * pObj, int i ) { return Abc_Lit2Var( Vec_IntEntry(&p->vFanins, pObj->iOffset + i) ); } +static inline Str_Obj_t * Str_ObjFanin( Str_Ntk_t * p, Str_Obj_t * pObj, int i ) { return Str_NtkObj( p, Str_ObjFaninId(p, pObj, i) ); } +static inline int Str_ObjFaninC( Str_Ntk_t * p, Str_Obj_t * pObj, int i ) { return Abc_LitIsCompl( Vec_IntEntry(&p->vFanins, pObj->iOffset + i) ); } +static inline int Str_ObjFaninCopy( Str_Ntk_t * p, Str_Obj_t * pObj, int i ) { return Abc_LitNotCond( Str_ObjFanin(p, pObj, i)->iCopy, Str_ObjFaninC(p, pObj, i) ); } +static inline int Str_ObjId( Str_Ntk_t * p, Str_Obj_t * pObj ) { return pObj - p->pObjs; } + +#define Str_NtkManForEachObj( p, pObj ) \ + for ( pObj = p->pObjs; Str_ObjId(p, pObj) < p->nObjs; pObj++ ) +#define Str_NtkManForEachObjVec( vVec, p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Str_NtkObj(p, Vec_IntEntry(vVec,i))); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [Logic network manipulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Str_ObjCreate( Str_Ntk_t * p, int Type, int nFanins, int * pFanins ) +{ + Str_Obj_t * pObj = p->pObjs + p->nObjs; int i; + assert( p->nObjs < p->nObjsAlloc ); + pObj->Type = Type; + pObj->nFanins = nFanins; + pObj->iOffset = Vec_IntSize(&p->vFanins); + pObj->iTop = pObj->iCopy = -1; + for ( i = 0; i < nFanins; i++ ) + { + Vec_IntPush( &p->vFanins, pFanins[i] ); + assert( pFanins[i] >= 0 ); + } + p->nObjCount[Type]++; + return Abc_Var2Lit( p->nObjs++, 0 ); +} +static inline Str_Ntk_t * Str_NtkCreate( int nObjsAlloc, int nFaninsAlloc ) +{ + Str_Ntk_t * p; + p = ABC_CALLOC( Str_Ntk_t, 1 ); + p->pObjs = ABC_ALLOC( Str_Obj_t, nObjsAlloc ); + p->nObjsAlloc = nObjsAlloc; + Str_ObjCreate( p, STR_CONST0, 0, NULL ); + Vec_IntGrow( &p->vFanins, nFaninsAlloc ); + return p; +} +static inline void Str_NtkDelete( Str_Ntk_t * p ) +{ +// printf( "Total delay gain = %d.\n", p->DelayGain ); + ABC_FREE( p->vFanins.pArray ); + ABC_FREE( p->pObjs ); + ABC_FREE( p ); +} +static inline void Str_NtkPs( Str_Ntk_t * p, abctime clk ) +{ + printf( "Network contains %d ands, %d xors, %d muxes (%d trees in %d groups). ", + p->nObjCount[STR_AND], p->nObjCount[STR_XOR], p->nObjCount[STR_MUX], p->nTrees, p->nGroups ); + Abc_PrintTime( 1, "Time", clk ); +} +static inline void Str_ObjReadGroup( Str_Ntk_t * p, Str_Obj_t * pObj, int * pnGroups, int * pnMuxes ) +{ + Str_Obj_t * pObj1, * pObj2; + *pnGroups = *pnMuxes = 0; + if ( pObj->iTop == 0 ) + return; + pObj1 = Str_NtkObj( p, pObj->iTop ); + pObj2 = Str_NtkObj( p, pObj1->iTop ); + *pnMuxes = pObj1 - pObj + 1; + *pnGroups = (pObj2 - pObj + 1) / *pnMuxes; +} +static inline void Str_NtkPrintGroups( Str_Ntk_t * p ) +{ + Str_Obj_t * pObj; + int nGroups, nMuxes; + Str_NtkManForEachObj( p, pObj ) + if ( pObj->Type == STR_MUX && pObj->iTop > 0 ) + { + Str_ObjReadGroup( p, pObj, &nGroups, &nMuxes ); + pObj += nGroups * nMuxes - 1; + printf( "%d x %d ", nGroups, nMuxes ); + } + printf( "\n" ); +} +Gia_Man_t * Str_NtkToGia( Gia_Man_t * pGia, Str_Ntk_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Str_Obj_t * pObj; int k; + assert( pGia->pMuxes == NULL ); + pNew = Gia_ManStart( 3 * Gia_ManObjNum(pGia) / 2 ); + pNew->pName = Abc_UtilStrsav( pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); + Gia_ManHashStart( pNew ); + Str_NtkManForEachObj( p, pObj ) + { + if ( pObj->Type == STR_PI ) + pObj->iCopy = Gia_ManAppendCi( pNew ); + else if ( pObj->Type == STR_AND ) + { + pObj->iCopy = 1; + for ( k = 0; k < (int)pObj->nFanins; k++ ) + pObj->iCopy = Gia_ManHashAnd( pNew, pObj->iCopy, Str_ObjFaninCopy(p, pObj, k) ); + } + else if ( pObj->Type == STR_XOR ) + { + pObj->iCopy = 0; + for ( k = 0; k < (int)pObj->nFanins; k++ ) + pObj->iCopy = Gia_ManHashXor( pNew, pObj->iCopy, Str_ObjFaninCopy(p, pObj, k) ); + } + else if ( pObj->Type == STR_MUX ) + pObj->iCopy = Gia_ManHashMux( pNew, Str_ObjFaninCopy(p, pObj, 2), Str_ObjFaninCopy(p, pObj, 1), Str_ObjFaninCopy(p, pObj, 0) ); + else if ( pObj->Type == STR_PO ) + pObj->iCopy = Gia_ManAppendCo( pNew, Str_ObjFaninCopy(p, pObj, 0) ); + else if ( pObj->Type == STR_CONST0 ) + pObj->iCopy = 0; + else assert( 0 ); + } + Gia_ManHashStop( pNew ); +// assert( Gia_ManObjNum(pNew) <= Gia_ManObjNum(pGia) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Constructs a normalized AIG without structural hashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupMuxesNoHash( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj, * pFan0, * pFan1, * pFanC; + int i, iLit0, iLit1, fCompl; + assert( p->pMuxes == NULL ); + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + // discount nodes with one fanout pointed to by MUX type + Gia_ManForEachAnd( p, pObj, i ) + { + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + Gia_ObjRefDec(p, Gia_ObjFanin0(pObj)); + Gia_ObjRefDec(p, Gia_ObjFanin1(pObj)); + } + // start the new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( !Gia_ObjRefNumId(p, i) ) + continue; + if ( !Gia_ObjIsMuxType(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) + { + iLit0 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)); + iLit1 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)); + fCompl = Abc_LitIsCompl(iLit0) ^ Abc_LitIsCompl(iLit1); + pObj->Value = fCompl ^ Gia_ManAppendXorReal( pNew, Abc_LitRegular(iLit0), Abc_LitRegular(iLit1) ); + } + else + { + pFanC = Gia_ObjRecognizeMux( pObj, &pFan1, &pFan0 ); + iLit0 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)); + iLit1 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)); + if ( iLit0 == iLit1 ) + pObj->Value = iLit0; + else if ( Abc_Lit2Var(iLit0) == Abc_Lit2Var(iLit1) ) + { + iLit1 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFanC)); + fCompl = Abc_LitIsCompl(iLit0) ^ Abc_LitIsCompl(iLit1); + pObj->Value = fCompl ^ Gia_ManAppendXorReal( pNew, Abc_LitRegular(iLit0), Abc_LitRegular(iLit1) ); + } + else + pObj->Value = Gia_ManAppendMuxReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFanC)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)) ); + } + } + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + assert( !Gia_ManHasDangling(pNew) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Constructs AIG ordered for balancing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Str_MuxInputsCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( !pObj->fMark0 ) + { + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + return; + } + Vec_IntPush( vNodes, Gia_ObjFaninId2p(p, pObj) ); + Str_MuxInputsCollect_rec( p, Gia_ObjFanin0(pObj), vNodes ); + Str_MuxInputsCollect_rec( p, Gia_ObjFanin1(pObj), vNodes ); +} +void Str_MuxInputsCollect( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + assert( !pObj->fMark0 ); + pObj->fMark0 = 1; + Vec_IntClear( vNodes ); + Str_MuxInputsCollect_rec( p, pObj, vNodes ); + pObj->fMark0 = 0; +} +void Str_MuxStructCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( !pObj->fMark0 ) + return; + Str_MuxStructCollect_rec( p, Gia_ObjFanin0(pObj), vNodes ); + Str_MuxStructCollect_rec( p, Gia_ObjFanin1(pObj), vNodes ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); +} +void Str_MuxStructCollect( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + assert( !pObj->fMark0 ); + pObj->fMark0 = 1; + Vec_IntClear( vNodes ); + Str_MuxStructCollect_rec( p, pObj, vNodes ); + pObj->fMark0 = 0; +} +void Str_MuxStructDump_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Str_t * vStr ) +{ + if ( !pObj->fMark0 ) + return; + Vec_StrPush( vStr, '[' ); + Vec_StrPush( vStr, '(' ); + Vec_StrPrintNum( vStr, Gia_ObjFaninId2p(p, pObj) ); + Vec_StrPush( vStr, ')' ); + Str_MuxStructDump_rec( p, Gia_ObjFaninC2(p, pObj) ? Gia_ObjFanin0(pObj) : Gia_ObjFanin1(pObj), vStr ); + Vec_StrPush( vStr, '|' ); + Str_MuxStructDump_rec( p, Gia_ObjFaninC2(p, pObj) ? Gia_ObjFanin1(pObj) : Gia_ObjFanin0(pObj), vStr ); + Vec_StrPush( vStr, ']' ); +} +void Str_MuxStructDump( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Str_t * vStr ) +{ + assert( !pObj->fMark0 ); + pObj->fMark0 = 1; + Vec_StrClear( vStr ); + Str_MuxStructDump_rec( p, pObj, vStr ); + Vec_StrPush( vStr, '\0' ); + pObj->fMark0 = 0; +} +int Str_ManMuxCountOne( char * p ) +{ + int Count = 0; + for ( ; *p; p++ ) + Count += (*p == '['); + return Count; +} +Vec_Wec_t * Str_ManDeriveTrees( Gia_Man_t * p ) +{ + int fPrintStructs = 0; + Abc_Nam_t * pNames; + Vec_Wec_t * vGroups; + Vec_Str_t * vStr; + Gia_Obj_t * pObj, * pFanin; + int i, iStructId, fFound; + assert( p->pMuxes != NULL ); + // mark MUXes whose only fanout is a MUX + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + Gia_ManForEachMuxId( p, i ) + { + pObj = Gia_ManObj(p, i); + pFanin = Gia_ObjFanin0(pObj); + if ( Gia_ObjIsMux(p, pFanin) && Gia_ObjRefNum(p, pFanin) == 1 ) + pFanin->fMark0 = 1; + pFanin = Gia_ObjFanin1(pObj); + if ( Gia_ObjIsMux(p, pFanin) && Gia_ObjRefNum(p, pFanin) == 1 ) + pFanin->fMark0 = 1; + } + // traverse for top level MUXes + vStr = Vec_StrAlloc( 1000 ); + pNames = Abc_NamStart( 10000, 50 ); + vGroups = Vec_WecAlloc( 1000 ); + Vec_WecPushLevel( vGroups ); + Gia_ManForEachMuxId( p, i ) + { + // skip internal + pObj = Gia_ManObj(p, i); + if ( pObj->fMark0 ) + continue; + // skip trees of size one + if ( !Gia_ObjFanin0(pObj)->fMark0 && !Gia_ObjFanin1(pObj)->fMark0 ) + continue; + // hash the tree + Str_MuxStructDump( p, pObj, vStr ); + iStructId = Abc_NamStrFindOrAdd( pNames, Vec_StrArray(vStr), &fFound ); + if ( !fFound ) Vec_WecPushLevel( vGroups ); + assert( Abc_NamObjNumMax(pNames) == Vec_WecSize(vGroups) ); + Vec_IntPush( Vec_WecEntry(vGroups, iStructId), i ); + } + if ( fPrintStructs ) + { + char * pTemp; + Abc_NamManForEachObj( pNames, pTemp, i ) + { + printf( "%5d : ", i ); + printf( "Occur = %4d ", Vec_IntSize(Vec_WecEntry(vGroups,i)) ); + printf( "Size = %4d ", Str_ManMuxCountOne(pTemp) ); + printf( "%s\n", pTemp ); + } + } + Abc_NamStop( pNames ); + Vec_StrFree( vStr ); + return vGroups; +} +Vec_Int_t * Str_ManCreateRoots( Vec_Wec_t * vGroups, int nObjs ) +{ // map tree MUXes into their classes + Vec_Int_t * vRoots; + Vec_Int_t * vGroup; + int i, k, Entry; + vRoots = Vec_IntStartFull( nObjs ); + Vec_WecForEachLevel( vGroups, vGroup, i ) + Vec_IntForEachEntry( vGroup, Entry, k ) + Vec_IntWriteEntry( vRoots, Entry, i ); + return vRoots; +} + +void Str_MuxTraverse_rec( Gia_Man_t * p, int i ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, i) ) + return; + Gia_ObjSetTravIdCurrentId(p, i); + pObj = Gia_ManObj(p, i); + if ( !Gia_ObjIsAnd(pObj) ) + return; + Str_MuxTraverse_rec(p, Gia_ObjFaninId0(pObj, i) ); + Str_MuxTraverse_rec(p, Gia_ObjFaninId1(pObj, i) ); + if ( Gia_ObjIsMux(p, pObj) ) + Str_MuxTraverse_rec(p, Gia_ObjFaninId2(p, i) ); +} +void Str_ManCheckOverlap( Gia_Man_t * p, Vec_Wec_t * vGroups ) +{ // check that members of each group are not in the TFI of each other + Vec_Int_t * vGroup, * vGroup2; + int i, k, n, iObj, iObj2; + +// vGroup = Vec_WecEntry(vGroups, 7); +// Vec_IntForEachEntry( vGroup, iObj, n ) +// Gia_ManPrintCone2( p, Gia_ManObj(p, iObj) ), printf( "\n" ); + + Vec_WecForEachLevel( vGroups, vGroup, i ) + Vec_IntForEachEntry( vGroup, iObj, k ) + { + if ( Vec_IntSize(vGroup) == 1 ) + continue; + // high light the cone + Gia_ManIncrementTravId( p ); + Str_MuxTraverse_rec( p, iObj ); + // check that none of the others are highlighted + Vec_IntForEachEntry( vGroup, iObj2, n ) + if ( iObj != iObj2 && Gia_ObjIsTravIdCurrentId(p, iObj2) ) + break; + if ( n == Vec_IntSize(vGroup) ) + continue; + // split the group into individual trees + Vec_IntForEachEntryStart( vGroup, iObj2, n, 1 ) + { + vGroup2 = Vec_WecPushLevel( vGroups ); + vGroup = Vec_WecEntry( vGroups, i ); + Vec_IntPush( vGroup2, iObj2 ); + } + Vec_IntShrink( vGroup, 1 ); + +/* + // this does not work because there can be a pair of independent trees + // with another tree squeezed in between them, so that there is a combo loop + + // divide this group + nNew = 0; + vGroup2 = Vec_WecPushLevel( vGroups ); + vGroup = Vec_WecEntry( vGroups, i ); + Vec_IntForEachEntry( vGroup, iObj2, n ) + { + if ( iObj != iObj2 && Gia_ObjIsTravIdCurrentId(p, iObj2) ) + Vec_IntPush( vGroup2, iObj2 ); + else + Vec_IntWriteEntry( vGroup, nNew++, iObj2 ); + } + Vec_IntShrink( vGroup, nNew ); + i--; + break; +*/ + +/* + // check that none of the others are highlighted + Vec_IntForEachEntry( vGroup, iObj, n ) + if ( n != k && Gia_ObjIsTravIdCurrentId(p, iObj) ) + { + printf( "Overlap of TFI cones of trees %d and %d in group %d of size %d!\n", k, n, i, Vec_IntSize(vGroup) ); + Vec_IntShrink( vGroup, 1 ); + break; + } +*/ + } +} /**Function************************************************************* - Synopsis [] + Synopsis [Simplify multi-input AND/XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSimplifyXor( Vec_Int_t * vSuper ) +{ + int i, k = 0, Prev = -1, This, fCompl = 0; + Vec_IntForEachEntry( vSuper, This, i ) + { + if ( This == 0 ) + continue; + if ( This == 1 ) + fCompl ^= 1; + else if ( Prev != This ) + Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; + else + Prev = -1, k--; + } + Vec_IntShrink( vSuper, k ); + if ( Vec_IntSize( vSuper ) == 0 ) + Vec_IntPush( vSuper, fCompl ); + else if ( fCompl ) + Vec_IntWriteEntry( vSuper, 0, Abc_LitNot(Vec_IntEntry(vSuper, 0)) ); +} +static inline void Gia_ManSimplifyAnd( Vec_Int_t * vSuper ) +{ + int i, k = 0, Prev = -1, This; + Vec_IntForEachEntry( vSuper, This, i ) + { + if ( This == 0 ) + { Vec_IntFill(vSuper, 1, 0); return; } + if ( This == 1 ) + continue; + if ( Prev == -1 || Abc_Lit2Var(Prev) != Abc_Lit2Var(This) ) + Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; + else if ( Prev != This ) + { Vec_IntFill(vSuper, 1, 0); return; } + } + Vec_IntShrink( vSuper, k ); + if ( Vec_IntSize( vSuper ) == 0 ) + Vec_IntPush( vSuper, 1 ); +} + +/**Function************************************************************* + + Synopsis [Collect multi-input AND/XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSuperCollectXor_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + assert( !Gia_IsComplement(pObj) ); + if ( !Gia_ObjIsXor(pObj) || + Gia_ObjRefNum(p, pObj) > 1 || +// Gia_ObjRefNum(p, pObj) > 3 || +// (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || + Vec_IntSize(p->vSuper) > STR_SUPER ) + { + Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); + return; + } + assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) ); +} +static inline void Gia_ManSuperCollectAnd_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_IsComplement(pObj) || + !Gia_ObjIsAndReal(p, pObj) || + Gia_ObjRefNum(p, pObj) > 1 || +// Gia_ObjRefNum(p, pObj) > 3 || +// (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || + Vec_IntSize(p->vSuper) > STR_SUPER ) + { + Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); + return; + } + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) ); + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) ); +} +static inline void Gia_ManSuperCollect( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( p->vSuper == NULL ) + p->vSuper = Vec_IntAlloc( STR_SUPER ); + else + Vec_IntClear( p->vSuper ); + if ( Gia_ObjIsXor(pObj) ) + { + assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) ); + Vec_IntSort( p->vSuper, 0 ); + Gia_ManSimplifyXor( p->vSuper ); + } + else if ( Gia_ObjIsAndReal(p, pObj) ) + { + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) ); + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) ); + Vec_IntSort( p->vSuper, 0 ); + Gia_ManSimplifyAnd( p->vSuper ); + } + else assert( 0 ); + assert( Vec_IntSize(p->vSuper) > 0 ); +} + +/**Function************************************************************* + + Synopsis [Constructs AIG ordered for balancing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Str_ManNormalize_rec( Str_Ntk_t * pNtk, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Wec_t * vGroups, Vec_Int_t * vRoots ) +{ + int i, k, iVar, iLit, iBeg, iEnd; + if ( ~pObj->Value ) + return; + pObj->Value = 0; + assert( Gia_ObjIsAnd(pObj) ); + if ( Gia_ObjIsMux(p, pObj) ) + { + Vec_Int_t * vGroup; + Gia_Obj_t * pRoot, * pMux; + int pFanins[3]; + if ( Vec_IntEntry(vRoots, Gia_ObjId(p, pObj)) == -1 ) + { + Str_ManNormalize_rec( pNtk, p, Gia_ObjFanin0(pObj), vGroups, vRoots ); + Str_ManNormalize_rec( pNtk, p, Gia_ObjFanin1(pObj), vGroups, vRoots ); + Str_ManNormalize_rec( pNtk, p, Gia_ObjFanin2(p, pObj), vGroups, vRoots ); + pFanins[0] = Gia_ObjFanin0Copy(pObj); + pFanins[1] = Gia_ObjFanin1Copy(pObj); + pFanins[2] = Gia_ObjFanin2Copy(p, pObj); + if ( Abc_LitIsCompl(pFanins[2]) ) + { + pFanins[2] = Abc_LitNot(pFanins[2]); + ABC_SWAP( int, pFanins[0], pFanins[1] ); + } + pObj->Value = Str_ObjCreate( pNtk, STR_MUX, 3, pFanins ); + return; + } + vGroup = Vec_WecEntry( vGroups, Vec_IntEntry(vRoots, Gia_ObjId(p, pObj)) ); + // build data-inputs for each tree + Gia_ManForEachObjVec( vGroup, p, pRoot, i ) + { + Str_MuxInputsCollect( p, pRoot, p->vSuper ); + iBeg = Vec_IntSize( p->vStore ); + Vec_IntAppend( p->vStore, p->vSuper ); + iEnd = Vec_IntSize( p->vStore ); + Vec_IntForEachEntryStartStop( p->vStore, iVar, k, iBeg, iEnd ) + Str_ManNormalize_rec( pNtk, p, Gia_ManObj(p, iVar), vGroups, vRoots ); + Vec_IntShrink( p->vStore, iBeg ); + } + // build internal structures + Gia_ManForEachObjVec( vGroup, p, pRoot, i ) + { + Str_MuxStructCollect( p, pRoot, p->vSuper ); + Gia_ManForEachObjVec( p->vSuper, p, pMux, k ) + { + pFanins[0] = Gia_ObjFanin0Copy(pMux); + pFanins[1] = Gia_ObjFanin1Copy(pMux); + pFanins[2] = Gia_ObjFanin2Copy(p, pMux); + if ( Abc_LitIsCompl(pFanins[2]) ) + { + pFanins[2] = Abc_LitNot(pFanins[2]); + ABC_SWAP( int, pFanins[0], pFanins[1] ); + } + pMux->Value = Str_ObjCreate( pNtk, STR_MUX, 3, pFanins ); + } + assert( ~pRoot->Value ); + // set mapping + Gia_ManForEachObjVec( p->vSuper, p, pMux, k ) + Str_NtkObj(pNtk, Abc_Lit2Var(pMux->Value))->iTop = Abc_Lit2Var(pRoot->Value); + pNtk->nTrees++; + } + assert( ~pObj->Value ); + // set mapping + pObj = Gia_ManObj( p, Vec_IntEntryLast(vGroup) ); + Gia_ManForEachObjVec( vGroup, p, pRoot, i ) + Str_NtkObj(pNtk, Abc_Lit2Var(pRoot->Value))->iTop = Abc_Lit2Var(pObj->Value); + pNtk->nGroups++; + //printf( "%d x %d ", Vec_IntSize(vGroup), Vec_IntSize(p->vSuper) ); + return; + } + // find supergate + Gia_ManSuperCollect( p, pObj ); + // save entries + iBeg = Vec_IntSize( p->vStore ); + Vec_IntAppend( p->vStore, p->vSuper ); + iEnd = Vec_IntSize( p->vStore ); + // call recursively + Vec_IntForEachEntryStartStop( p->vStore, iLit, i, iBeg, iEnd ) + { + Gia_Obj_t * pTemp = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + Str_ManNormalize_rec( pNtk, p, pTemp, vGroups, vRoots ); + Vec_IntWriteEntry( p->vStore, i, Abc_LitNotCond(pTemp->Value, Abc_LitIsCompl(iLit)) ); + } + assert( Vec_IntSize(p->vStore) == iEnd ); + // consider general case + pObj->Value = Str_ObjCreate( pNtk, Gia_ObjIsXor(pObj) ? STR_XOR : STR_AND, iEnd-iBeg, Vec_IntEntryP(p->vStore, iBeg) ); + Vec_IntShrink( p->vStore, iBeg ); +} +Str_Ntk_t * Str_ManNormalizeInt( Gia_Man_t * p, Vec_Wec_t * vGroups, Vec_Int_t * vRoots ) +{ + Str_Ntk_t * pNtk; + Gia_Obj_t * pObj; + int i, iFanin; + assert( p->pMuxes != NULL ); + if ( p->vSuper == NULL ) + p->vSuper = Vec_IntAlloc( STR_SUPER ); + if ( p->vStore == NULL ) + p->vStore = Vec_IntAlloc( STR_SUPER ); + Gia_ManFillValue( p ); + pNtk = Str_NtkCreate( Gia_ManObjNum(p), 1 + Gia_ManCoNum(p) + 2 * Gia_ManAndNum(p) + Gia_ManMuxNum(p) ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Str_ObjCreate( pNtk, STR_PI, 0, NULL ); + else if ( Gia_ObjIsCo(pObj) ) + { + Str_ManNormalize_rec( pNtk, p, Gia_ObjFanin0(pObj), vGroups, vRoots ); + iFanin = Gia_ObjFanin0Copy(pObj); + pObj->Value = Str_ObjCreate( pNtk, STR_PO, 1, &iFanin ); + } + } + assert( pNtk->nObjs <= Gia_ManObjNum(p) ); + return pNtk; +} +Str_Ntk_t * Str_ManNormalize( Gia_Man_t * p ) +{ + Str_Ntk_t * pNtk; + Gia_Man_t * pMuxes = Gia_ManDupMuxes( p, 5 ); + Vec_Wec_t * vGroups = Str_ManDeriveTrees( pMuxes ); + Vec_Int_t * vRoots; + Str_ManCheckOverlap( pMuxes, vGroups ); + vRoots = Str_ManCreateRoots( vGroups, Gia_ManObjNum(pMuxes) ); + pNtk = Str_ManNormalizeInt( pMuxes, vGroups, vRoots ); + Gia_ManCleanMark0( pMuxes ); + Gia_ManStop( pMuxes ); + Vec_IntFree( vRoots ); + Vec_WecFree( vGroups ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Delay computation] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Str_Delay2( int d0, int d1, int nLutSize ) +{ + int n, d = Abc_MaxInt( d0 >> 4, d1 >> 4 ); + n = (d == (d0 >> 4)) ? (d0 & 15) : 1; + n += (d == (d1 >> 4)) ? (d1 & 15) : 1; + return (d << 4) + (n > nLutSize ? 18 : n); +} +static inline int Str_Delay3( int d0, int d1, int d2, int nLutSize ) +{ + int n, d = Abc_MaxInt( Abc_MaxInt(d0 >> 4, d1 >> 4), d2 >> 4 ); + n = (d == (d0 >> 4)) ? (d0 & 15) : 1; + n += (d == (d1 >> 4)) ? (d1 & 15) : 1; + n += (d == (d2 >> 4)) ? (d2 & 15) : 1; + return (d << 4) + (n > nLutSize ? 19 : n); +} +static inline int Str_ObjDelay( Gia_Man_t * pNew, int iObj, int nLutSize, Vec_Int_t * vDelay ) +{ + int Delay = Vec_IntEntry( vDelay, iObj ); + if ( Delay == 0 ) + { + if ( Gia_ObjIsMuxId(pNew, iObj) ) + { + int d0 = Vec_IntEntry( vDelay, Gia_ObjFaninId0(Gia_ManObj(pNew, iObj), iObj) ); + int d1 = Vec_IntEntry( vDelay, Gia_ObjFaninId1(Gia_ManObj(pNew, iObj), iObj) ); + int d2 = Vec_IntEntry( vDelay, Gia_ObjFaninId2(pNew, iObj) ); + Delay = Str_Delay3( d0, d1, d2, nLutSize ); + } + else + { + int d0 = Vec_IntEntry( vDelay, Gia_ObjFaninId0(Gia_ManObj(pNew, iObj), iObj) ); + int d1 = Vec_IntEntry( vDelay, Gia_ObjFaninId1(Gia_ManObj(pNew, iObj), iObj) ); + Delay = Str_Delay2( d0, d1, nLutSize ); + } + Vec_IntWriteEntry( vDelay, iObj, Delay ); + } + return Delay; +} + + + +/**Function************************************************************* + + Synopsis [Transposing 64-bit matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void transpose64( word A[64] ) +{ + int j, k; + word t, m = 0x00000000FFFFFFFF; + for ( j = 32; j != 0; j = j >> 1, m = m ^ (m << j) ) + { + for ( k = 0; k < 64; k = (k + j + 1) & ~j ) + { + t = (A[k] ^ (A[k+j] >> j)) & m; + A[k] = A[k] ^ t; + A[k+j] = A[k+j] ^ (t << j); + } + } +} + +/**Function************************************************************* + + Synopsis [Perform affinity computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Str_ManNum( Gia_Man_t * p, int iObj ) { return Vec_IntEntry(&p->vCopies, iObj); } +static inline void Str_ManSetNum( Gia_Man_t * p, int iObj, int Num ) { Vec_IntWriteEntry(&p->vCopies, iObj, Num); } + +int Str_ManVectorAffinity( Gia_Man_t * p, Vec_Int_t * vSuper, Vec_Int_t * vDelay, word Matrix[256], int nLimit ) +{ + int fVerbose = 0; + int Levels[256]; + int nSize = Vec_IntSize(vSuper); + int Prev = nSize, nLevels = 1; + int i, k, iLit, iFanin, nSizeNew; + word Mask; + assert( nSize > 2 ); + if ( nSize > 64 ) + { + for ( i = 0; i < 64; i++ ) + Matrix[i] = 0; + return 0; + } + // mark current nodes + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vSuper, iLit, i ) + { + Gia_ObjSetTravIdCurrentId( p, Abc_Lit2Var(iLit) ); + Str_ManSetNum( p, Abc_Lit2Var(iLit), i ); + Matrix[i] = ((word)1) << (63-i); + Levels[i] = 0; + } + // collect 64 nodes + Vec_IntForEachEntry( vSuper, iLit, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + if ( Gia_ObjIsAnd(pObj) ) + { + for ( k = 0; k < 2; k++ ) + { + iFanin = k ? Gia_ObjFaninId1p(p, pObj) : Gia_ObjFaninId0p(p, pObj); + if ( !Gia_ObjIsTravIdCurrentId(p, iFanin) ) + { + if ( Vec_IntSize(vSuper) == nLimit ) + break; + Gia_ObjSetTravIdCurrentId( p, iFanin ); + Matrix[Vec_IntSize(vSuper)] = 0; + Levels[Vec_IntSize(vSuper)] = nLevels; + Str_ManSetNum( p, iFanin, Vec_IntSize(vSuper) ); + Vec_IntPush( vSuper, Abc_Var2Lit(iFanin, 0) ); + } + Matrix[Str_ManNum(p, iFanin)] |= Matrix[i]; + } + } + if ( Gia_ObjIsMux(p, pObj) ) + { + iFanin = Gia_ObjFaninId2p(p, pObj); + if ( !Gia_ObjIsTravIdCurrentId(p, iFanin) ) + { + if ( Vec_IntSize(vSuper) == nLimit ) + break; + Gia_ObjSetTravIdCurrentId( p, iFanin ); + Matrix[Vec_IntSize(vSuper)] = 0; + Levels[Vec_IntSize(vSuper)] = nLevels; + Str_ManSetNum( p, iFanin, Vec_IntSize(vSuper) ); + Vec_IntPush( vSuper, Abc_Var2Lit(iFanin, 0) ); + } + Matrix[Str_ManNum(p, iFanin)] |= Matrix[i]; + } + if ( Prev == i ) + Prev = Vec_IntSize(vSuper), nLevels++; + if ( nLevels == 8 ) + break; + } + + // remove those that have all 1s or only one 1 + Mask = (~(word)0) << (64 - nSize); + for ( k = i = 0; i < Vec_IntSize(vSuper); i++ ) + { + assert( Matrix[i] ); + if ( (Matrix[i] & (Matrix[i] - 1)) == 0 ) + continue; + if ( Matrix[i] == Mask ) + continue; + Matrix[k] = Matrix[i]; + Levels[k] = Levels[i]; + k++; + if ( k == 64 ) + break; + } + // clean the remaining ones + for ( i = k; i < 64; i++ ) + Matrix[i] = 0; + nSizeNew = k; + if ( nSizeNew == 0 ) + { + Vec_IntShrink( vSuper, nSize ); + return 0; + } +/* + // report + if ( fVerbose && nSize > 20 ) + { + for ( i = 0; i < nSizeNew; i++ ) + Extra_PrintBinary( stdout, Matrix+i, 64 ), printf( "\n" ); + printf( "\n" ); + } +*/ + transpose64( Matrix ); + + // report + if ( fVerbose && nSize > 10 ) + { + printf( "Gate inputs = %d. Collected fanins = %d. All = %d. Good = %d. Levels = %d\n", + nSize, Vec_IntSize(vSuper) - nSize, Vec_IntSize(vSuper), nSizeNew, nLevels ); + printf( " " ); + for ( i = 0; i < nSizeNew; i++ ) + printf( "%d", Levels[i] ); + printf( "\n" ); + for ( i = 0; i < nSize; i++ ) + { + printf( "%6d : ", Abc_Lit2Var(Vec_IntEntry(vSuper, i)) ); + printf( "%3d ", Vec_IntEntry(vDelay, i) >> 4 ); + printf( "%3d ", Vec_IntEntry(vDelay, i) & 15 ); +// Extra_PrintBinary( stdout, Matrix+i, 64 ), printf( "\n" ); + } + i = 0; + } + Vec_IntShrink( vSuper, nSize ); + return nSizeNew; +} + +/**Function************************************************************* + + Synopsis [Count 1s.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Str_CountBits( word i ) +{ + if ( i == 0 ) + return 0; + i = (i & (i - 1)); + if ( i == 0 ) + return 1; + i = (i & (i - 1)); + if ( i == 0 ) + return 2; + i = i - ((i >> 1) & 0x5555555555555555); + i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); + i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); + return (i*(0x0101010101010101))>>56; +} + +static inline void Str_PrintState( int * pCost, int * pSuper, word * pMatrix, int nSize ) +{ + int i; + for ( i = 0; i < nSize; i++ ) + { + printf( "%6d : ", i ); + printf( "%6d : ", Abc_Lit2Var(pSuper[i]) ); + printf( "%3d ", pCost[i] >> 4 ); + printf( "%3d ", pCost[i] & 15 ); +// Extra_PrintBinary( stdout, pMatrix+i, 64 ), printf( "\n" ); + } + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Perform balancing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Str_NtkBalanceMulti2( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec_Int_t * vDelay, int nLutSize ) +{ + int k; + pObj->iCopy = (pObj->Type == STR_AND); + for ( k = 0; k < (int)pObj->nFanins; k++ ) + { + if ( pObj->Type == STR_AND ) + pObj->iCopy = Gia_ManHashAnd( pNew, pObj->iCopy, Str_ObjFaninCopy(p, pObj, k) ); + else + pObj->iCopy = Gia_ManHashXorReal( pNew, pObj->iCopy, Str_ObjFaninCopy(p, pObj, k) ); + Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); + } +} + +int Str_NtkBalanceTwo( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, int i, int j, Vec_Int_t * vDelay, int * pCost, int * pSuper, word * pMatrix, int nSize, int nLutSize, int CostBest ) +{ + int k, iLitRes, Delay; + assert( i < j ); +// printf( "Merging node %d and %d\n", i, j ); + if ( pObj->Type == STR_AND ) + iLitRes = Gia_ManHashAnd( pNew, pSuper[i], pSuper[j] ); + else + iLitRes = Gia_ManHashXorReal( pNew, pSuper[i], pSuper[j] ); + Delay = Str_ObjDelay( pNew, Abc_Lit2Var(iLitRes), nLutSize, vDelay ); + // update + pCost[i] = Delay; + pSuper[i] = iLitRes; + pMatrix[i] |= pMatrix[j]; +// assert( (pCost[i] & 15) == CostBest || CostBest == -1 ); + // remove entry j + nSize--; + for ( k = j; k < nSize; k++ ) + { + pCost[k] = pCost[k+1]; + pSuper[k] = pSuper[k+1]; + pMatrix[k] = pMatrix[k+1]; + } + // move up the first one + nSize--; + for ( k = 0; k < nSize; k++ ) + { + if ( pCost[k] <= pCost[k+1] ) + break; + ABC_SWAP( int, pCost[k], pCost[k+1] ); + ABC_SWAP( int, pSuper[k], pSuper[k+1] ); + ABC_SWAP( word, pMatrix[k], pMatrix[k+1] ); + } + return iLitRes; +} + +void Str_NtkBalanceMulti( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec_Int_t * vDelay, int nLutSize ) +{ + word pMatrix[256]; + int Limit = 256; + Vec_Int_t * vSuper = pNew->vSuper; + Vec_Int_t * vCosts = pNew->vStore; + int * pSuper = Vec_IntArray(vSuper); + int * pCost = Vec_IntArray(vCosts); + int k, iLit, MatrixSize = 0; + assert( Limit <= Vec_IntCap(vSuper) ); + assert( Limit <= Vec_IntCap(vCosts) ); + + // collect nodes + Vec_IntClear( vSuper ); + for ( k = 0; k < (int)pObj->nFanins; k++ ) + Vec_IntPush( vSuper, Str_ObjFaninCopy(p, pObj, k) ); + Vec_IntSort( vSuper, 0 ); + if ( pObj->Type == STR_AND ) + Gia_ManSimplifyAnd( vSuper ); + else + Gia_ManSimplifyXor( vSuper ); + assert( Vec_IntSize(vSuper) > 0 ); + if ( Vec_IntSize(vSuper) == 1 ) + { + pObj->iCopy = Vec_IntEntry(vSuper, 0); + return; + } + if ( Vec_IntSize(vSuper) == 2 ) + { + pObj->iCopy = Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, 2, nLutSize, -1 ); + return; + } + + // sort by cost + Vec_IntClear( vCosts ); + Vec_IntForEachEntry( vSuper, iLit, k ) + Vec_IntPush( vCosts, Vec_IntEntry(vDelay, Abc_Lit2Var(iLit)) ); + Vec_IntSelectSortCost2( pSuper, Vec_IntSize(vSuper), pCost ); + + // compute affinity + if ( Vec_IntSize(vSuper) < 64 ) + MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, Limit ); + + // start the new product + while ( Vec_IntSize(vSuper) > 2 ) + { + // pair the first entry with another one on the same level + int i, iStop, iBest,iBest2; + int CostNew, CostBest, CostBest2; + int OccurNew, OccurBest, OccurBest2; + + if ( Vec_IntSize(vSuper) > 64 ) + { + Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, -1 ); + vSuper->nSize--; + vCosts->nSize--; + continue; + } + + // compute affinity + if ( Vec_IntSize(vSuper) == 64 ) + MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, Limit ); + assert( Vec_IntSize(vSuper) <= 64 ); +// Str_PrintState( pCost, pSuper, pMatrix, Vec_IntSize(vSuper) ); + + // if the first two are PIs group them + if ( pCost[0] == 17 && pCost[1] == 17 ) + { + Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, 2 ); + vSuper->nSize--; + vCosts->nSize--; + continue; + } + + // find the end of the level + for ( iStop = 0; iStop < Vec_IntSize(vSuper); iStop++ ) + if ( (pCost[iStop] >> 4) != (pCost[0] >> 4) ) + break; + // if there is only one this level, pair it with the best match in the next level + if ( iStop == 1 ) + { + iBest = iStop, OccurBest = Str_CountBits(pMatrix[0] & pMatrix[iStop]); + for ( i = iStop + 1; i < Vec_IntSize(vSuper); i++ ) + { + if ( (pCost[i] >> 4) != (pCost[iStop] >> 4) ) + break; + OccurNew = Str_CountBits(pMatrix[0] & pMatrix[i]); + if ( OccurBest < OccurNew ) + iBest = i, OccurBest = OccurNew; + } + assert( iBest > 0 && iBest < Vec_IntSize(vSuper) ); + Str_NtkBalanceTwo( pNew, p, pObj, 0, iBest, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, -1 ); + vSuper->nSize--; + vCosts->nSize--; + continue; + } + // pair the first entry with another one on the same level + iBest = -1; CostBest = -1; OccurBest2 = -1; OccurBest = -1; + for ( i = 1; i < iStop; i++ ) + { + CostNew = (pCost[0] & 15) + (pCost[i] & 15); + if ( CostNew > nLutSize ) + continue; + OccurNew = Str_CountBits(pMatrix[0] & pMatrix[i]); + if ( CostBest < CostNew || (CostBest == CostNew && OccurBest < OccurNew) ) + CostBest = CostNew, iBest = i, OccurBest = OccurNew; + } + // if the best found is perfect, take it + if ( CostBest == nLutSize ) + { + assert( iBest > 0 && iBest < Vec_IntSize(vSuper) ); + Str_NtkBalanceTwo( pNew, p, pObj, 0, iBest, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, CostBest ); + vSuper->nSize--; + vCosts->nSize--; + continue; + } + // find the best pair on this level + iBest = iBest2 = -1; CostBest = CostBest2 = -1, OccurBest = OccurBest2 = -1; + for ( i = 0; i < iStop; i++ ) + for ( k = i+1; k < iStop; k++ ) + { + CostNew = (pCost[i] & 15) + (pCost[k] & 15); + OccurNew = Str_CountBits(pMatrix[i] & pMatrix[k]); + if ( CostNew <= nLutSize ) // the same level + { + if ( OccurBest < OccurNew || (OccurBest == OccurNew && CostBest < CostNew )) + CostBest = CostNew, iBest = (i << 16) | k, OccurBest = OccurNew; + } + else // overflow to the next level + { + if ( OccurBest2 < OccurNew || (OccurBest2 == OccurNew && CostBest2 < CostNew) ) + CostBest2 = CostNew, iBest2 = (i << 16) | k, OccurBest2 = OccurNew; + } + } + if ( iBest >= 0 ) + { + assert( iBest > 0 ); + Str_NtkBalanceTwo( pNew, p, pObj, iBest>>16, iBest&0xFFFF, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, CostBest ); + vSuper->nSize--; + vCosts->nSize--; + continue; + } + // take any remaining pair + assert( iBest2 > 0 ); + Str_NtkBalanceTwo( pNew, p, pObj, iBest2>>16, iBest2&0xFFFF, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, -1 ); + vSuper->nSize--; + vCosts->nSize--; + continue; + } + pObj->iCopy = Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, 2, nLutSize, -1 ); + +/* + // simple + pObj->iCopy = (pObj->Type == STR_AND); + for ( k = 0; k < Vec_IntSize(vSuper); k++ ) + { + if ( pObj->Type == STR_AND ) + pObj->iCopy = Gia_ManHashAnd( pNew, pObj->iCopy, Vec_IntEntry(vSuper, k) ); + else + pObj->iCopy = Gia_ManHashXorReal( pNew, pObj->iCopy, Vec_IntEntry(vSuper, k) ); + Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); + } +*/ +} +void Str_NtkBalanceMux( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec_Int_t * vDelay, int nLutSize, int nGroups, int nMuxes, int fRecursive, int fOptArea, int fVerbose ) +{ + extern int Str_MuxRestructure( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fRecursive, int fOptArea, int fVerbose ); + int n, m, iRes, fUseRestruct = 1; + if ( fUseRestruct ) + { + for ( n = 0; n < nGroups; n++ ) + { + iRes = Str_MuxRestructure( pNew, p, Str_ObjId(p, pObj), nMuxes, vDelay, nLutSize, fRecursive, fOptArea, fVerbose ); + if ( iRes == -1 ) + { + for ( m = 0; m < nMuxes; m++, pObj++ ) + { + pObj->iCopy = Gia_ManHashMuxReal( pNew, Str_ObjFaninCopy(p, pObj, 2), Str_ObjFaninCopy(p, pObj, 1), Str_ObjFaninCopy(p, pObj, 0) ); + Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); + } + } + else + { + pObj += nMuxes - 1; + pObj->iCopy = iRes; + pObj++; + } + } + } + else + { + for ( n = 0; n < nGroups * nMuxes; n++, pObj++ ) + { + pObj->iCopy = Gia_ManHashMuxReal( pNew, Str_ObjFaninCopy(p, pObj, 2), Str_ObjFaninCopy(p, pObj, 1), Str_ObjFaninCopy(p, pObj, 0) ); + Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); + } + } +} +Gia_Man_t * Str_NtkBalance( Gia_Man_t * pGia, Str_Ntk_t * p, int nLutSize, int fUseMuxes, int fRecursive, int fOptArea, int fVerbose ) +{ + Gia_Man_t * pNew, * pTemp; + Vec_Int_t * vDelay; + Str_Obj_t * pObj; + int nGroups, nMuxes, CioId; + int arrTime, Delay = 0; + assert( nLutSize < 16 ); + assert( pGia->pMuxes == NULL ); + pNew = Gia_ManStart( Gia_ManObjNum(pGia) ); + pNew->pName = Abc_UtilStrsav( pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); + Vec_IntFill( &pNew->vCopies, pNew->nObjsAlloc, -1 ); + if ( pNew->vSuper == NULL ) + pNew->vSuper = Vec_IntAlloc( 1000 ); + if ( pNew->vStore == NULL ) + pNew->vStore = Vec_IntAlloc( 1000 ); + vDelay = Vec_IntStart( pNew->nObjsAlloc ); + Gia_ManHashStart( pNew ); + if ( pGia->pManTime != NULL ) // Tim_Man with unit delay 16 + { + Tim_ManInitPiArrivalAll( (Tim_Man_t *)pGia->pManTime, 17 ); + Tim_ManIncrementTravId( (Tim_Man_t *)pGia->pManTime ); + } + Str_NtkManForEachObj( p, pObj ) + { + if ( pObj->Type == STR_PI ) + { + pObj->iCopy = Gia_ManAppendCi( pNew ); + arrTime = 17; + if ( pGia->pManTime != NULL ) + { + CioId = Gia_ObjCioId( Gia_ManObj(pNew, Abc_Lit2Var(pObj->iCopy)) ); + arrTime = (int)Tim_ManGetCiArrival( (Tim_Man_t *)pGia->pManTime, CioId ); + } + Vec_IntWriteEntry( vDelay, Abc_Lit2Var(pObj->iCopy), arrTime ); + } + else if ( pObj->Type == STR_AND || pObj->Type == STR_XOR ) + Str_NtkBalanceMulti( pNew, p, pObj, vDelay, nLutSize ); + else if ( pObj->Type == STR_MUX && pObj->iTop >= 0 && fUseMuxes ) + { + Str_ObjReadGroup( p, pObj, &nGroups, &nMuxes ); + assert( nGroups * nMuxes >= 2 ); + Str_NtkBalanceMux( pNew, p, pObj, vDelay, nLutSize, nGroups, nMuxes, fRecursive, fOptArea, fVerbose ); + pObj += nGroups * nMuxes - 1; + } + else if ( pObj->Type == STR_MUX ) + { + pObj->iCopy = Gia_ManHashMuxReal( pNew, Str_ObjFaninCopy(p, pObj, 2), Str_ObjFaninCopy(p, pObj, 1), Str_ObjFaninCopy(p, pObj, 0) ); + Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); + } + else if ( pObj->Type == STR_PO ) + { + pObj->iCopy = Gia_ManAppendCo( pNew, Str_ObjFaninCopy(p, pObj, 0) ); + arrTime = Vec_IntEntry(vDelay, Abc_Lit2Var(Str_ObjFaninCopy(p, pObj, 0)) ); + Delay = Abc_MaxInt( Delay, arrTime ); + if ( pGia->pManTime != NULL ) + { + CioId = Gia_ObjCioId( Gia_ManObj(pNew, Abc_Lit2Var(pObj->iCopy)) ); + Tim_ManSetCoArrival( (Tim_Man_t *)pGia->pManTime, CioId, (float)arrTime ); + } + } + else if ( pObj->Type == STR_CONST0 ) + pObj->iCopy = 0, Vec_IntWriteEntry(vDelay, 0, 17); + else assert( 0 ); + } + if ( fVerbose ) + printf( "Max delay = %d. Old objs = %d. New objs = %d.\n", Delay >> 4, Gia_ManObjNum(pGia), Gia_ManObjNum(pNew) ); + Vec_IntFree( vDelay ); + ABC_FREE( pNew->vCopies.pArray ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); + pNew = Gia_ManDupNoMuxes( pTemp = pNew ); + Gia_ManStop( pTemp ); +// if ( pGia->pManTime != NULL ) +// pNew->pManTime = Tim_ManDup( (Tim_Man_t *)pGia->pManTime, 0 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Test normalization procedure.] Description [] @@ -45,9 +1376,484 @@ ABC_NAMESPACE_IMPL_START ***********************************************************************/ Gia_Man_t * Gia_ManLutBalance( Gia_Man_t * p, int nLutSize, int fUseMuxes, int fRecursive, int fOptArea, int fVerbose ) { - return Gia_ManDup(p); + Str_Ntk_t * pNtk; + Gia_Man_t * pNew; + abctime clk = Abc_Clock(); + if ( p->pManTime && Tim_ManBoxNum(p->pManTime) && Gia_ManIsNormalized(p) ) + { + Tim_Man_t * pTimOld = (Tim_Man_t *)p->pManTime; + p->pManTime = Tim_ManDup( pTimOld, 16 ); + pNew = Gia_ManDupUnnormalize( p ); + if ( pNew == NULL ) + return NULL; + Gia_ManTransferTiming( pNew, p ); + p = pNew; + // optimize + pNtk = Str_ManNormalize( p ); + pNew = Str_NtkBalance( p, pNtk, nLutSize, fUseMuxes, fRecursive, fOptArea, fVerbose ); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + // normalize + pNew = Gia_ManDupNormalize( p = pNew ); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + // cleanup + Tim_ManStop( (Tim_Man_t *)pNew->pManTime ); + pNew->pManTime = pTimOld; + assert( Gia_ManIsNormalized(pNew) ); + } + else + { + pNtk = Str_ManNormalize( p ); + // Str_NtkPrintGroups( pNtk ); + pNew = Str_NtkBalance( p, pNtk, nLutSize, fUseMuxes, fRecursive, fOptArea, fVerbose ); + Gia_ManTransferTiming( pNew, p ); + } + if ( fVerbose ) + Str_NtkPs( pNtk, Abc_Clock() - clk ); + Str_NtkDelete( pNtk ); + return pNew; +} + + + + + +/**Function************************************************************* + + Synopsis [Perform MUX restructuring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +typedef struct Str_Edg_t_ Str_Edg_t; +struct Str_Edg_t_ +{ + int Fan; // fanin ID + int fCompl; // fanin complement + int FanDel; // fanin delay + int Copy; // fanin copy +}; + +typedef struct Str_Mux_t_ Str_Mux_t; // 64 bytes +struct Str_Mux_t_ +{ + int Id; // node ID + int Delay; // node delay + int Copy; // node copy + int nLutSize; // LUT size + Str_Edg_t Edge[3]; // fanins +}; + +static inline Str_Mux_t * Str_MuxFanin( Str_Mux_t * pMux, int i ) { return pMux - pMux->Id + pMux->Edge[i].Fan; } +static inline int Str_MuxHasFanin( Str_Mux_t * pMux, int i ) { return pMux->Edge[i].Fan > 0 && Str_MuxFanin(pMux, i)->Copy != -2; } + +void Str_MuxDelayPrint_rec( Str_Mux_t * pMux, int i ) +{ + int fShowDelay = 1; + Str_Mux_t * pFanin; + if ( pMux->Edge[i].Fan <= 0 ) + { + printf( "%d", -pMux->Edge[i].Fan ); + if ( fShowDelay ) + printf( "{%d}", pMux->Edge[i].FanDel ); + return; + } + pFanin = Str_MuxFanin( pMux, i ); + printf( "[ " ); + if ( pFanin->Edge[0].fCompl ) + printf( "!" ); + Str_MuxDelayPrint_rec( pFanin, 0 ); + printf( "|" ); + if ( pFanin->Edge[1].fCompl ) + printf( "!" ); + Str_MuxDelayPrint_rec( pFanin, 1 ); + printf( "(" ); + if ( pFanin->Edge[2].fCompl ) + printf( "!" ); + Str_MuxDelayPrint_rec( pFanin, 2 ); + printf( ")" ); + printf( " ]" ); +} +int Str_MuxDelayEdge_rec( Str_Mux_t * pMux, int i ) +{ + if ( pMux->Edge[i].Fan > 0 ) + { + Str_Mux_t * pFanin = Str_MuxFanin( pMux, i ); + Str_MuxDelayEdge_rec( pFanin, 0 ); + Str_MuxDelayEdge_rec( pFanin, 1 ); + pMux->Edge[i].FanDel = Str_Delay3( pFanin->Edge[0].FanDel, pFanin->Edge[1].FanDel, pFanin->Edge[2].FanDel, pFanin->nLutSize ); + } + return pMux->Edge[i].FanDel; +} +void Str_MuxCreate( Str_Mux_t * pTree, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize ) +{ + Str_Obj_t * pObj; + Str_Mux_t * pMux; + int i, k, nPis = 0; + assert( nMuxes >= 2 ); + memset( pTree, 0, sizeof(Str_Mux_t) * (nMuxes + 1) ); + pTree->nLutSize = nLutSize; + pTree->Edge[0].Fan = 1; + for ( i = 1; i <= nMuxes; i++ ) + { + pMux = pTree + i; + pMux->Id = i; + pMux->nLutSize = nLutSize; + pMux->Delay = pMux->Copy = -1; + // assign fanins + pObj = Str_NtkObj( pNtk, iMux + nMuxes - i ); + assert( pObj->Type == STR_MUX ); + for ( k = 0; k < 3; k++ ) + { + pMux->Edge[k].fCompl = Str_ObjFaninC(pNtk, pObj, k); + if ( Str_ObjFaninId(pNtk, pObj, k) >= iMux ) + pMux->Edge[k].Fan = iMux + nMuxes - Str_ObjFaninId(pNtk, pObj, k); + else + { + pMux->Edge[k].Fan = -nPis++; // count external inputs, including controls + pMux->Edge[k].Copy = Str_ObjFanin(pNtk, pObj, k)->iCopy; + pMux->Edge[k].FanDel = Vec_IntEntry( vDelay, Abc_Lit2Var(pMux->Edge[k].Copy) ); + } + } + } +} +int Str_MuxToGia_rec( Gia_Man_t * pNew, Str_Mux_t * pMux, int i, Vec_Int_t * vDelay ) +{ + if ( pMux->Edge[i].Fan > 0 ) + { + Str_Mux_t * pFanin = Str_MuxFanin( pMux, i ); + int iLit0 = Str_MuxToGia_rec( pNew, pFanin, 0, vDelay ); + int iLit1 = Str_MuxToGia_rec( pNew, pFanin, 1, vDelay ); + assert( pFanin->Edge[2].Fan <= 0 ); + assert( pFanin->Edge[2].fCompl == 0 ); + pMux->Edge[i].Copy = Gia_ManHashMuxReal( pNew, pFanin->Edge[2].Copy, iLit1, iLit0 ); + Str_ObjDelay( pNew, Abc_Lit2Var(pMux->Edge[i].Copy), pFanin->nLutSize, vDelay ); + } + return Abc_LitNotCond( pMux->Edge[i].Copy, pMux->Edge[i].fCompl ); } +void Str_MuxChangeOnce( Str_Mux_t * pTree, int * pPath, int i, int k, Str_Mux_t * pBackup, Gia_Man_t * pNew, Vec_Int_t * vDelay ) +{ + Str_Mux_t * pSpots[3]; + int pInds[3], MidFan, MidCom, MidDel, MidCop, c; + int iRes, iCond, fCompl; + // save backup + assert( i + 1 < k ); + if ( pBackup ) + { + pBackup[0] = pTree[ Abc_Lit2Var(pPath[k]) ]; + pBackup[1] = pTree[ Abc_Lit2Var(pPath[i+1])]; + pBackup[2] = pTree[ Abc_Lit2Var(pPath[i]) ]; + } + // perform changes + pSpots[0] = pTree + Abc_Lit2Var(pPath[k]); + pSpots[1] = pTree + Abc_Lit2Var(pPath[i+1]); + pSpots[2] = pTree + Abc_Lit2Var(pPath[i]); + pInds[0] = Abc_LitIsCompl(pPath[k]); + pInds[1] = Abc_LitIsCompl(pPath[i+1]); + pInds[2] = Abc_LitIsCompl(pPath[i]); + // check + assert( pSpots[0]->Edge[pInds[0]].Fan > 0 ); + assert( pSpots[1]->Edge[pInds[1]].Fan > 0 ); + // collect complement + fCompl = 0; + for ( c = i+1; c < k; c++ ) + fCompl ^= pTree[Abc_Lit2Var(pPath[c])].Edge[Abc_LitIsCompl(pPath[c])].fCompl; + // remember bottom side + MidFan = pSpots[2]->Edge[!pInds[2]].Fan; + MidCom = pSpots[2]->Edge[!pInds[2]].fCompl; + MidDel = pSpots[2]->Edge[!pInds[2]].FanDel; + MidCop = pSpots[2]->Edge[!pInds[2]].Copy; + // update bottom + pSpots[2]->Edge[!pInds[2]].Fan = pSpots[0]->Edge[pInds[0]].Fan; + pSpots[2]->Edge[!pInds[2]].fCompl = 0; + // update top + pSpots[0]->Edge[pInds[0]].Fan = pSpots[2]->Id; + // update middle + pSpots[1]->Edge[pInds[1]].Fan = MidFan; + pSpots[1]->Edge[pInds[1]].fCompl ^= MidCom; + pSpots[1]->Edge[pInds[1]].FanDel = MidDel; + pSpots[1]->Edge[pInds[1]].Copy = MidCop; + // update delay of the control + for ( c = i + 1; c < k; c++ ) + pSpots[2]->Edge[2].FanDel = Str_Delay2( pSpots[2]->Edge[2].FanDel, pTree[Abc_Lit2Var(pPath[c])].Edge[2].FanDel, pTree->nLutSize ); + if ( pNew == NULL ) + return; + // create AND gates + iRes = 1; + for ( c = i; c < k; c++ ) + { + assert( pTree[Abc_Lit2Var(pPath[c])].Edge[2].fCompl == 0 ); + iCond = pTree[Abc_Lit2Var(pPath[c])].Edge[2].Copy; + iCond = Abc_LitNotCond( iCond, !Abc_LitIsCompl(pPath[c]) ); + iRes = Gia_ManHashAnd( pNew, iRes, iCond ); + Str_ObjDelay( pNew, Abc_Lit2Var(iRes), pTree->nLutSize, vDelay ); + } + // complement the condition + pSpots[2]->Edge[2].Copy = Abc_LitNotCond( iRes, !Abc_LitIsCompl(pPath[i]) ); + // complement the path + pSpots[2]->Edge[pInds[2]].fCompl ^= fCompl; +} +void Str_MuxChangeUndo( Str_Mux_t * pTree, int * pPath, int i, int k, Str_Mux_t * pBackup ) +{ + pTree[ Abc_Lit2Var(pPath[k]) ] = pBackup[0]; + pTree[ Abc_Lit2Var(pPath[i+1])] = pBackup[1]; + pTree[ Abc_Lit2Var(pPath[i]) ] = pBackup[2]; +} +int Str_MuxFindPathEdge_rec( Str_Mux_t * pMux, int i, int * pPath, int * pnLength ) +{ + extern int Str_MuxFindPath_rec( Str_Mux_t * pMux, int * pPath, int * pnLength ); + if ( pMux->Edge[i].Fan > 0 && !Str_MuxFindPath_rec(Str_MuxFanin(pMux, i), pPath, pnLength) ) + return 0; + pPath[ (*pnLength)++ ] = Abc_Var2Lit(pMux->Id, i); + return 1; +} +int Str_MuxFindPath_rec( Str_Mux_t * pMux, int * pPath, int * pnLength ) +{ + int i, DelayMax = Abc_MaxInt( pMux->Edge[0].FanDel, Abc_MaxInt(pMux->Edge[1].FanDel, pMux->Edge[2].FanDel) ); + for ( i = 0; i < 2; i++ ) + if ( pMux->Edge[i].FanDel == DelayMax ) + return Str_MuxFindPathEdge_rec( pMux, i, pPath, pnLength ); + if ( pMux->Edge[2].FanDel == DelayMax ) + return 0; + assert( 0 ); + return -1; +} +// return node whose both branches are non-trivial +Str_Mux_t * Str_MuxFindBranching( Str_Mux_t * pRoot, int i ) +{ + Str_Mux_t * pMux; + if ( pRoot->Edge[i].Fan <= 0 ) + return NULL; + pMux = Str_MuxFanin( pRoot, i ); + while ( 1 ) + { + if ( pMux->Edge[0].Fan <= 0 && pMux->Edge[1].Fan <= 0 ) + return NULL; + if ( pMux->Edge[0].Fan > 0 && pMux->Edge[1].Fan > 0 ) + return pMux; + if ( pMux->Edge[0].Fan > 0 ) + pMux = Str_MuxFanin( pMux, 0 ); + if ( pMux->Edge[1].Fan > 0 ) + pMux = Str_MuxFanin( pMux, 1 ); + } + assert( 0 ); + return NULL; +} +int Str_MuxTryOnce( Gia_Man_t * pNew, Str_Ntk_t * pNtk, Str_Mux_t * pTree, Str_Mux_t * pRoot, int Edge, Vec_Int_t * vDelay, int fVerbose ) +{ + int pPath[500]; + Str_Mux_t pBackup[3]; + int Delay, DelayBest = Str_MuxDelayEdge_rec( pRoot, Edge ), DelayInit = DelayBest; + int i, k, nLength = 0, ForkBest = -1, nChecks = 0; + int RetValue = Str_MuxFindPathEdge_rec( pRoot, Edge, pPath, &nLength ); + if ( RetValue == 0 ) + return 0; + if ( fVerbose ) + printf( "Trying node %d with path of length %d.\n", pRoot->Id, nLength ); + for ( i = 0; i < nLength; i++ ) + for ( k = i+2; k < nLength; k++ ) + { + Str_MuxChangeOnce( pTree, pPath, i, k, pBackup, NULL, NULL ); + Delay = Str_MuxDelayEdge_rec( pRoot, Edge ); + Str_MuxChangeUndo( pTree, pPath, i, k, pBackup ); + if ( DelayBest > Delay || (ForkBest > 0 && DelayBest == Delay) ) + DelayBest = Delay, ForkBest = (i << 16) | k; + if ( fVerbose ) + printf( "%2d %2d -> %3d (%3d)\n", i, k, Delay, DelayBest ); + nChecks++; + } + if ( ForkBest == -1 ) + { + if ( fVerbose ) + printf( "Did not find!\n" ); + return 0; + } +// Str_MuxDelayPrint_rec( pRoot, Edge ); printf( "\n" ); + Str_MuxChangeOnce( pTree, pPath, ForkBest >> 16, ForkBest & 0xFFFF, NULL, pNew, vDelay ); +// Str_MuxDelayPrint_rec( pRoot, Edge ); printf( "\n" ); + if ( fVerbose ) + printf( "Node %6d (%3d %3d) : Checks = %d. Delay: %d -> %d.\n", + pRoot->Id, ForkBest >> 16, ForkBest & 0xFFFF, nChecks, DelayInit, DelayBest ); + if ( fVerbose ) + printf( "\n" ); + return 1; +} +int Str_MuxRestruct_rec( Gia_Man_t * pNew, Str_Ntk_t * pNtk, Str_Mux_t * pTree, Str_Mux_t * pRoot, int Edge, Vec_Int_t * vDelay, int fVerbose ) +{ + int fChanges = 0; + Str_Mux_t * pMux = Str_MuxFindBranching( pRoot, Edge ); + if ( pMux != NULL ) + fChanges |= Str_MuxRestruct_rec( pNew, pNtk, pTree, pMux, 0, vDelay, fVerbose ); + if ( pMux != NULL ) + fChanges |= Str_MuxRestruct_rec( pNew, pNtk, pTree, pMux, 1, vDelay, fVerbose ); + fChanges |= Str_MuxTryOnce( pNew, pNtk, pTree, pRoot, Edge, vDelay, fVerbose ); + return fChanges; +} +int Str_MuxRestructure2( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose ) +{ + int Limit = 500; + Str_Mux_t pTree[500]; + int Delay, Delay2, fChanges = 0; + if ( nMuxes >= Limit ) + return -1; + assert( nMuxes < Limit ); + Str_MuxCreate( pTree, pNtk, iMux, nMuxes, vDelay, nLutSize ); + Delay = Str_MuxDelayEdge_rec( pTree, 0 ); + while ( 1 ) + { + if ( !Str_MuxRestruct_rec(pNew, pNtk, pTree, pTree, 0, vDelay, fVerbose) ) + break; + fChanges = 1; + } + if ( !fChanges ) + return -1; + Delay2 = Str_MuxDelayEdge_rec( pTree, 0 ); +// printf( "Improved delay for tree %d with %d MUXes (%d -> %d).\n", iMux, nMuxes, Delay, Delay2 ); + pNtk->DelayGain += Delay - Delay2; + return Str_MuxToGia_rec( pNew, pTree, 0, vDelay ); +} +int Str_MuxRestructure1( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose ) +{ + int Limit = 500; + Str_Mux_t pTree[500]; + int Delay, Delay2, fChanges = 0; + if ( nMuxes >= Limit ) + return -1; + assert( nMuxes < Limit ); + Str_MuxCreate( pTree, pNtk, iMux, nMuxes, vDelay, nLutSize ); + Delay = Str_MuxDelayEdge_rec( pTree, 0 ); + while ( 1 ) + { + if ( !Str_MuxTryOnce(pNew, pNtk, pTree, pTree, 0, vDelay, fVerbose) ) + break; + fChanges = 1; + } + if ( !fChanges ) + return -1; + Delay2 = Str_MuxDelayEdge_rec( pTree, 0 ); +// printf( "Improved delay for tree %d with %d MUXes (%d -> %d).\n", iMux, nMuxes, Delay, Delay2 ); + pNtk->DelayGain += Delay - Delay2; + return Str_MuxToGia_rec( pNew, pTree, 0, vDelay ); +} +int Str_MuxRestructure( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fRecursive, int fOptArea, int fVerbose ) +{ + extern int Str_MuxRestructureArea( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose ); + if ( fOptArea ) + { + if ( nMuxes < 2 ) + return Str_MuxRestructure1( pNew, pNtk, iMux, nMuxes, vDelay, nLutSize, fVerbose ); + return Str_MuxRestructureArea( pNew, pNtk, iMux, nMuxes, vDelay, nLutSize, fVerbose ); + } + if ( fRecursive ) + return Str_MuxRestructure2( pNew, pNtk, iMux, nMuxes, vDelay, nLutSize, fVerbose ); + return Str_MuxRestructure1( pNew, pNtk, iMux, nMuxes, vDelay, nLutSize, fVerbose ); +} + +/**Function************************************************************* + + Synopsis [Perform MUX restructuring for area.] + + Description [] + + SideEffects [] + SeeAlso [] + +***********************************************************************/ +int Str_MuxRestructAreaThree( Gia_Man_t * pNew, Str_Mux_t * pMux, Vec_Int_t * vDelay, int fVerbose ) +{ + int iRes; + Str_Mux_t * pFanin0 = Str_MuxFanin( pMux, 0 ); + Str_Mux_t * pFanin1 = Str_MuxFanin( pMux, 1 ); + assert( pMux->Copy == -1 ); + pMux->Copy = -2; + if ( pFanin0->Edge[2].Copy == pFanin1->Edge[2].Copy ) + return 0; + iRes = Gia_ManHashMuxReal( pNew, pMux->Edge[2].Copy, pFanin1->Edge[2].Copy, pFanin0->Edge[2].Copy ); + Str_ObjDelay( pNew, Abc_Lit2Var(iRes), pMux->nLutSize, vDelay ); + pFanin0->Edge[2].Copy = pFanin1->Edge[2].Copy = iRes; +// printf( "Created triple\n" ); + return 0; +} +int Str_MuxRestructArea_rec( Gia_Man_t * pNew, Str_Mux_t * pTree, Str_Mux_t * pRoot, int i, Vec_Int_t * vDelay, int fVerbose ) +{ + int Path[4]; + int fSkipMoving = 1; + Str_Mux_t * pMux, * pFanin0, * pFanin1; + int nMuxes0, nMuxes1; + if ( pRoot->Edge[i].Fan <= 0 ) + return 0; + pMux = Str_MuxFanin( pRoot, i ); + nMuxes0 = Str_MuxRestructArea_rec( pNew, pTree, pMux, 0, vDelay, fVerbose ); + nMuxes1 = Str_MuxRestructArea_rec( pNew, pTree, pMux, 1, vDelay, fVerbose ); + if ( nMuxes0 + nMuxes1 < 2 ) + return 1 + nMuxes0 + nMuxes1; + if ( nMuxes0 + nMuxes1 == 2 ) + { + if ( nMuxes0 == 2 || nMuxes1 == 2 ) + { + pFanin0 = Str_MuxFanin( pMux, (int)(nMuxes1 == 2) ); + assert( Str_MuxHasFanin(pFanin0, 0) != Str_MuxHasFanin(pFanin0, 1) ); + Path[2] = Abc_Var2Lit(pRoot->Id, i); + Path[1] = Abc_Var2Lit(pMux->Id, (int)(nMuxes1 == 2) ); + Path[0] = Abc_Var2Lit(pFanin0->Id, Str_MuxHasFanin(pFanin0, 1)); + Str_MuxChangeOnce( pTree, Path, 0, 2, NULL, pNew, vDelay ); + } + Str_MuxRestructAreaThree( pNew, Str_MuxFanin(pRoot, i), vDelay, fVerbose ); + return 0; + } + assert( nMuxes0 + nMuxes1 == 3 || nMuxes0 + nMuxes1 == 4 ); + assert( nMuxes0 == 2 || nMuxes1 == 2 ); + if ( fSkipMoving ) + { + Str_MuxRestructAreaThree( pNew, pMux, vDelay, fVerbose ); + return 0; + } + if ( nMuxes0 == 2 ) + { + pFanin0 = Str_MuxFanin( pMux, 0 ); + assert( Str_MuxHasFanin(pFanin0, 0) != Str_MuxHasFanin(pFanin0, 1) ); + Path[3] = Abc_Var2Lit(pRoot->Id, i); + Path[2] = Abc_Var2Lit(pMux->Id, 0 ); + Path[1] = Abc_Var2Lit(pFanin0->Id, Str_MuxHasFanin(pFanin0, 1)); + pFanin1 = Str_MuxFanin( pFanin0, Str_MuxHasFanin(pFanin0, 1) ); + assert( !Str_MuxHasFanin(pFanin1, 0) && !Str_MuxHasFanin(pFanin1, 1) ); + Path[0] = Abc_Var2Lit(pFanin1->Id, 0); + Str_MuxChangeOnce( pTree, Path, 0, 3, NULL, pNew, vDelay ); + } + if ( nMuxes1 == 2 ) + { + pFanin0 = Str_MuxFanin( pMux, 1 ); + assert( Str_MuxHasFanin(pFanin0, 0) != Str_MuxHasFanin(pFanin0, 1) ); + Path[3] = Abc_Var2Lit(pRoot->Id, i); + Path[2] = Abc_Var2Lit(pMux->Id, 1 ); + Path[1] = Abc_Var2Lit(pFanin0->Id, Str_MuxHasFanin(pFanin0, 1)); + pFanin1 = Str_MuxFanin( pFanin0, Str_MuxHasFanin(pFanin0, 1) ); + assert( !Str_MuxHasFanin(pFanin1, 0) && !Str_MuxHasFanin(pFanin1, 1) ); + Path[0] = Abc_Var2Lit(pFanin1->Id, 0); + Str_MuxChangeOnce( pTree, Path, 0, 3, NULL, pNew, vDelay ); + } + Str_MuxRestructAreaThree( pNew, pMux, vDelay, fVerbose ); + return nMuxes0 + nMuxes1 - 2; +} +int Str_MuxRestructureArea( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose ) +{ + int Limit = 500; + Str_Mux_t pTree[500]; + int Result; + if ( nMuxes >= Limit ) + return -1; + assert( nMuxes < Limit ); + Str_MuxCreate( pTree, pNtk, iMux, nMuxes, vDelay, nLutSize ); + Result = Str_MuxRestructArea_rec( pNew, pTree, pTree, 0, vDelay, fVerbose ); + assert( Result >= 0 && Result <= 2 ); + return Str_MuxToGia_rec( pNew, pTree, 0, vDelay ); +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// |