| /**CFile**************************************************************** |
| |
| FileName [giaCone.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Scalable AIG package.] |
| |
| Synopsis [] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: giaCone.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "gia.h" |
| #include "misc/extra/extra.h" |
| #include "misc/vec/vecHsh.h" |
| #include "misc/vec/vecWec.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| typedef struct Opa_Man_t_ Opa_Man_t; |
| struct Opa_Man_t_ |
| { |
| Gia_Man_t * pGia; |
| Vec_Int_t * vFront; |
| Vec_Int_t * pvParts; |
| int * pId2Part; |
| int nParts; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline Opa_Man_t * Opa_ManStart( Gia_Man_t * pGia) |
| { |
| Opa_Man_t * p; |
| Gia_Obj_t * pObj; |
| int i; |
| p = ABC_CALLOC( Opa_Man_t, 1 ); |
| p->pGia = pGia; |
| p->pvParts = ABC_CALLOC( Vec_Int_t, Gia_ManPoNum(pGia) ); |
| p->pId2Part = ABC_FALLOC( int, Gia_ManObjNum(pGia) ); |
| p->vFront = Vec_IntAlloc( 100 ); |
| Gia_ManForEachPo( pGia, pObj, i ) |
| { |
| Vec_IntPush( p->pvParts + i, Gia_ObjId(pGia, pObj) ); |
| p->pId2Part[Gia_ObjId(pGia, pObj)] = i; |
| Vec_IntPush( p->vFront, Gia_ObjId(pGia, pObj) ); |
| } |
| p->nParts = Gia_ManPoNum(pGia); |
| return p; |
| } |
| static inline void Opa_ManStop( Opa_Man_t * p ) |
| { |
| int i; |
| Vec_IntFree( p->vFront ); |
| for ( i = 0; i < Gia_ManPoNum(p->pGia); i++ ) |
| ABC_FREE( p->pvParts[i].pArray ); |
| ABC_FREE( p->pvParts ); |
| ABC_FREE( p->pId2Part ); |
| ABC_FREE( p ); |
| } |
| static inline void Opa_ManPrint( Opa_Man_t * p ) |
| { |
| int i, k; |
| printf( "Groups:\n" ); |
| for ( i = 0; i < Gia_ManPoNum(p->pGia); i++ ) |
| { |
| if ( p->pvParts[i].nSize == 0 ) |
| continue; |
| printf( "%3d : ", i ); |
| for ( k = 0; k < p->pvParts[i].nSize; k++ ) |
| printf( "%d ", p->pvParts[i].pArray[k] ); |
| printf( "\n" ); |
| } |
| } |
| static inline void Opa_ManPrint2( Opa_Man_t * p ) |
| { |
| Gia_Obj_t * pObj; |
| int i, k, Count; |
| printf( "Groups %d: ", p->nParts ); |
| for ( i = 0; i < Gia_ManPoNum(p->pGia); i++ ) |
| { |
| if ( p->pvParts[i].nSize == 0 ) |
| continue; |
| // count POs in this group |
| Count = 0; |
| Gia_ManForEachObjVec( p->pvParts + i, p->pGia, pObj, k ) |
| Count += Gia_ObjIsPo(p->pGia, pObj); |
| printf( "%d ", Count ); |
| } |
| printf( "\n" ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Opa_ManMoveOne( Opa_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin ) |
| { |
| int iObj = Gia_ObjId(p->pGia, pObj); |
| int iFanin = Gia_ObjId(p->pGia, pFanin); |
| if ( iFanin == 0 ) |
| return; |
| assert( p->pId2Part[ iObj ] >= 0 ); |
| if ( p->pId2Part[ iFanin ] == -1 ) |
| { |
| p->pId2Part[ iFanin ] = p->pId2Part[ iObj ]; |
| Vec_IntPush( p->pvParts + p->pId2Part[ iObj ], iFanin ); |
| assert( Gia_ObjIsCi(pFanin) || Gia_ObjIsAnd(pFanin) ); |
| if ( Gia_ObjIsAnd(pFanin) ) |
| Vec_IntPush( p->vFront, iFanin ); |
| else if ( Gia_ObjIsRo(p->pGia, pFanin) ) |
| { |
| pFanin = Gia_ObjRoToRi(p->pGia, pFanin); |
| iFanin = Gia_ObjId(p->pGia, pFanin); |
| assert( p->pId2Part[ iFanin ] == -1 ); |
| p->pId2Part[ iFanin ] = p->pId2Part[ iObj ]; |
| Vec_IntPush( p->pvParts + p->pId2Part[ iObj ], iFanin ); |
| Vec_IntPush( p->vFront, iFanin ); |
| } |
| } |
| else if ( p->pId2Part[ iObj ] != p->pId2Part[ iFanin ] ) |
| { |
| Vec_Int_t * vPartObj = p->pvParts + p->pId2Part[ iObj ]; |
| Vec_Int_t * vPartFan = p->pvParts + p->pId2Part[ iFanin ]; |
| int iTemp, i; |
| // printf( "Moving %d to %d (%d -> %d)\n", iObj, iFanin, Vec_IntSize(vPartObj), Vec_IntSize(vPartFan) ); |
| // add group of iObj to group of iFanin |
| assert( Vec_IntSize(vPartObj) > 0 ); |
| Vec_IntForEachEntry( vPartObj, iTemp, i ) |
| { |
| Vec_IntPush( vPartFan, iTemp ); |
| p->pId2Part[ iTemp ] = p->pId2Part[ iFanin ]; |
| } |
| Vec_IntShrink( vPartObj, 0 ); |
| p->nParts--; |
| } |
| } |
| void Opa_ManPerform( Gia_Man_t * pGia ) |
| { |
| Opa_Man_t * p; |
| Gia_Obj_t * pObj; |
| int i, Limit, Count = 0; |
| |
| p = Opa_ManStart( pGia ); |
| Limit = Vec_IntSize(p->vFront); |
| //Opa_ManPrint2( p ); |
| Gia_ManForEachObjVec( p->vFront, pGia, pObj, i ) |
| { |
| if ( i == Limit ) |
| { |
| printf( "%6d : %6d -> %6d\n", ++Count, i, p->nParts ); |
| Limit = Vec_IntSize(p->vFront); |
| if ( Count > 1 ) |
| Opa_ManPrint2( p ); |
| } |
| // printf( "*** Object %d ", Gia_ObjId(pGia, pObj) ); |
| if ( Gia_ObjIsAnd(pObj) ) |
| { |
| Opa_ManMoveOne( p, pObj, Gia_ObjFanin0(pObj) ); |
| Opa_ManMoveOne( p, pObj, Gia_ObjFanin1(pObj) ); |
| } |
| else if ( Gia_ObjIsCo(pObj) ) |
| Opa_ManMoveOne( p, pObj, Gia_ObjFanin0(pObj) ); |
| else assert( 0 ); |
| // if ( i % 10 == 0 ) |
| // printf( "%d ", p->nParts ); |
| if ( p->nParts == 1 ) |
| break; |
| if ( Count == 5 ) |
| break; |
| } |
| printf( "\n" ); |
| Opa_ManStop( p ); |
| } |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Gia_ManConeMark_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRoots, int nLimit ) |
| { |
| if ( Gia_ObjIsTravIdCurrent(p, pObj) ) |
| return 0; |
| Gia_ObjSetTravIdCurrent(p, pObj); |
| if ( Gia_ObjIsAnd(pObj) ) |
| { |
| if ( Gia_ManConeMark_rec( p, Gia_ObjFanin0(pObj), vRoots, nLimit ) ) |
| return 1; |
| if ( Gia_ManConeMark_rec( p, Gia_ObjFanin1(pObj), vRoots, nLimit ) ) |
| return 1; |
| } |
| else if ( Gia_ObjIsCo(pObj) ) |
| { |
| if ( Gia_ManConeMark_rec( p, Gia_ObjFanin0(pObj), vRoots, nLimit ) ) |
| return 1; |
| } |
| else if ( Gia_ObjIsRo(p, pObj) ) |
| Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) ); |
| else if ( Gia_ObjIsPi(p, pObj) ) |
| {} |
| else assert( 0 ); |
| return (int)(Vec_IntSize(vRoots) > nLimit); |
| } |
| int Gia_ManConeMark( Gia_Man_t * p, int iOut, int Limit ) |
| { |
| Vec_Int_t * vRoots; |
| Gia_Obj_t * pObj; |
| int i, RetValue; |
| // start the outputs |
| pObj = Gia_ManPo( p, iOut ); |
| vRoots = Vec_IntAlloc( 100 ); |
| Vec_IntPush( vRoots, Gia_ObjId(p, pObj) ); |
| // mark internal nodes |
| Gia_ManIncrementTravId( p ); |
| Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); |
| Gia_ManForEachObjVec( vRoots, p, pObj, i ) |
| if ( Gia_ManConeMark_rec( p, pObj, vRoots, Limit ) ) |
| break; |
| RetValue = Vec_IntSize( vRoots ) - 1; |
| Vec_IntFree( vRoots ); |
| return RetValue; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Gia_ManCountFlops( Gia_Man_t * p, Vec_Int_t * vOuts ) |
| { |
| int Limit = ABC_INFINITY; |
| Vec_Int_t * vRoots; |
| Gia_Obj_t * pObj; |
| int i, RetValue, iOut; |
| // start the outputs |
| vRoots = Vec_IntAlloc( 100 ); |
| Vec_IntForEachEntry( vOuts, iOut, i ) |
| { |
| pObj = Gia_ManPo( p, iOut ); |
| Vec_IntPush( vRoots, Gia_ObjId(p, pObj) ); |
| } |
| // mark internal nodes |
| Gia_ManIncrementTravId( p ); |
| Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); |
| Gia_ManForEachObjVec( vRoots, p, pObj, i ) |
| if ( Gia_ManConeMark_rec( p, pObj, vRoots, Limit ) ) |
| break; |
| RetValue = Vec_IntSize( vRoots ) - Vec_IntSize(vOuts); |
| Vec_IntFree( vRoots ); |
| return RetValue; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Gia_Man_t * Gia_ManFindPoPartition3( Gia_Man_t * p, int iOut, int nDelta, int nOutsMin, int nOutsMax, int fVerbose, Vec_Ptr_t ** pvPosEquivs ) |
| { |
| /* |
| int i, Count = 0; |
| // mark nodes belonging to output 'iOut' |
| for ( i = 0; i < Gia_ManPoNum(p); i++ ) |
| Count += (Gia_ManConeMark(p, i, 10000) < 10000); |
| // printf( "%d ", Gia_ManConeMark(p, i, 1000) ); |
| printf( "%d out of %d\n", Count, Gia_ManPoNum(p) ); |
| |
| // add other outputs as long as they are nDelta away |
| */ |
| // Opa_ManPerform( p ); |
| |
| return NULL; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Gia_ManFindPivots( Gia_Man_t * p, int SelectShift, int fOnlyCis, int fVerbose ) |
| { |
| Vec_Int_t * vPivots, * vWeights; |
| Vec_Int_t * vCount, * vResult; |
| int i, j, Count, * pPerm, Limit; |
| /* |
| Gia_Obj_t * pObj; |
| // count MUX controls |
| vCount = Vec_IntStart( Gia_ManObjNum(p) ); |
| Gia_ManForEachAnd( p, pObj, i ) |
| { |
| Gia_Obj_t * pNodeC, * pNodeT, * pNodeE; |
| if ( !Gia_ObjIsMuxType(pObj) ) |
| continue; |
| pNodeC = Gia_ObjRecognizeMux( pObj, &pNodeT, &pNodeE ); |
| Vec_IntAddToEntry( vCount, Gia_ObjId(p, Gia_Regular(pNodeC)), 1 ); |
| } |
| */ |
| // count references |
| Gia_ManCreateRefs( p ); |
| vCount = Vec_IntAllocArray( p->pRefs, Gia_ManObjNum(p) ); p->pRefs = NULL; |
| |
| // collect nodes |
| vPivots = Vec_IntAlloc( 100 ); |
| vWeights = Vec_IntAlloc( 100 ); |
| Vec_IntForEachEntry( vCount, Count, i ) |
| { |
| if ( Count < 2 ) continue; |
| if ( fOnlyCis && !Gia_ObjIsCi(Gia_ManObj(p, i)) ) |
| continue; |
| Vec_IntPush( vPivots, i ); |
| Vec_IntPush( vWeights, Count ); |
| } |
| Vec_IntFree( vCount ); |
| |
| if ( fVerbose ) |
| printf( "Selected %d pivots with more than one fanout (out of %d CIs and ANDs).\n", Vec_IntSize(vWeights), Gia_ManCiNum(p) + Gia_ManAndNum(p) ); |
| |
| // permute |
| Gia_ManRandom(1); |
| Gia_ManRandom(0); |
| for ( i = 0; i < Vec_IntSize(vWeights); i++ ) |
| { |
| j = (Gia_ManRandom(0) >> 1) % Vec_IntSize(vWeights); |
| ABC_SWAP( int, vPivots->pArray[i], vPivots->pArray[j] ); |
| ABC_SWAP( int, vWeights->pArray[i], vWeights->pArray[j] ); |
| } |
| // sort |
| if ( SelectShift == 0 ) |
| pPerm = Abc_QuickSortCost( Vec_IntArray(vWeights), Vec_IntSize(vWeights), 1 ); |
| else |
| { |
| Vec_Int_t * vTemp = Vec_IntStartNatural( Vec_IntSize(vWeights) ); |
| pPerm = Vec_IntReleaseArray( vTemp ); |
| Vec_IntFree( vTemp ); |
| } |
| |
| // select |
| Limit = Abc_MinInt( 64, Vec_IntSize(vWeights) ); |
| vResult = Vec_IntAlloc( Limit ); |
| for ( i = 0; i < Limit; i++ ) |
| { |
| j = (i + SelectShift) % Vec_IntSize(vWeights); |
| if ( fVerbose ) |
| printf( "%2d : Pivot =%7d Fanout =%7d\n", j, Vec_IntEntry(vPivots, pPerm[j]), Vec_IntEntry(vWeights, pPerm[j]) ); |
| Vec_IntPush( vResult, Vec_IntEntry(vPivots, pPerm[j]) ); |
| } |
| |
| Vec_IntFree( vPivots ); |
| Vec_IntFree( vWeights ); |
| ABC_FREE( pPerm ); |
| |
| return vResult; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Wrd_t * Gia_ManDeriveSigns( Gia_Man_t * p, Vec_Int_t * vPivots, int fVerbose ) |
| { |
| Vec_Wrd_t * vSigns; |
| Gia_Obj_t * pObj, * pObjRi; |
| int i, fChange = 1, Counter; |
| |
| Gia_ManFillValue( p ); |
| Gia_ManForEachObjVec( vPivots, p, pObj, i ) |
| pObj->Value = i; |
| |
| if ( fVerbose ) |
| printf( "Signature propagation: " ); |
| vSigns = Vec_WrdStart( Gia_ManObjNum(p) ); |
| while ( fChange ) |
| { |
| fChange = 0; |
| Gia_ManForEachObj( p, pObj, i ) |
| { |
| if ( ~pObj->Value ) |
| { |
| assert( pObj->Value >= 0 && pObj->Value < 64 ); |
| *Vec_WrdEntryP( vSigns, i ) |= ( (word)1 << pObj->Value ); |
| } |
| if ( Gia_ObjIsAnd(pObj) ) |
| *Vec_WrdEntryP( vSigns, i ) |= Vec_WrdEntry(vSigns, Gia_ObjFaninId0(pObj, i)) | Vec_WrdEntry(vSigns, Gia_ObjFaninId1(pObj, i)); |
| else if ( Gia_ObjIsCo(pObj) ) |
| *Vec_WrdEntryP( vSigns, i ) |= Vec_WrdEntry(vSigns, Gia_ObjFaninId0(pObj, i)); |
| } |
| Counter = 0; |
| Gia_ManForEachRiRo( p, pObjRi, pObj, i ) |
| { |
| word Value = Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj)); |
| *Vec_WrdEntryP( vSigns, Gia_ObjId(p, pObj) ) |= Vec_WrdEntry(vSigns, Gia_ObjId(p, pObjRi)); |
| if ( Value != Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj)) ) |
| fChange = 1, Counter++; |
| } |
| if ( fVerbose ) |
| printf( "%d ", Counter ); |
| } |
| if ( fVerbose ) |
| printf( "\n" ); |
| return vSigns; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Ptr_t * Gia_ManHashOutputs( Gia_Man_t * p, Vec_Wrd_t * vSigns, int fVerbose ) |
| { |
| Vec_Ptr_t * vBins; |
| Vec_Wec_t * vClasses; |
| Vec_Wrd_t * vSignsPo; |
| Vec_Int_t * vPriority, * vBin; |
| Gia_Obj_t * pObj; |
| int i; |
| // collect PO signatures |
| vSignsPo = Vec_WrdAlloc( Gia_ManPoNum(p) ); |
| Gia_ManForEachPo( p, pObj, i ) |
| Vec_WrdPush( vSignsPo, Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj)) ); |
| // find equivalence classes |
| vPriority = Hsh_WrdManHashArray( vSignsPo, 1 ); |
| Vec_WrdFree( vSignsPo ); |
| vClasses = Vec_WecCreateClasses( vPriority ); |
| Vec_IntFree( vPriority ); |
| vBins = (Vec_Ptr_t *)Vec_WecConvertToVecPtr( vClasses ); |
| Vec_WecFree( vClasses ); |
| Vec_VecSort( (Vec_Vec_t *)vBins, 1 ); |
| |
| if ( fVerbose ) |
| printf( "Computed %d partitions:\n", Vec_PtrSize(vBins) ); |
| if ( !fVerbose ) |
| printf( "Listing partitions with more than 100 outputs:\n" ); |
| Vec_PtrForEachEntry( Vec_Int_t *, vBins, vBin, i ) |
| { |
| assert( Vec_IntSize(vBin) > 0 ); |
| if ( fVerbose || Vec_IntSize(vBin) > 100 ) |
| { |
| int PoNum = Vec_IntEntry( vBin, 0 ); |
| Gia_Obj_t * pObj = Gia_ManPo( p, PoNum ); |
| word Sign = Vec_WrdEntry( vSigns, Gia_ObjId(p, pObj) ); |
| // print |
| printf( "%3d ", i ); |
| Extra_PrintBinary( stdout, (unsigned *)&Sign, 64 ); |
| printf( " " ); |
| printf( "PO =%7d ", Vec_IntSize(vBin) ); |
| printf( "FF =%7d", Gia_ManCountFlops(p, vBin) ); |
| printf( "\n" ); |
| } |
| } |
| return vBins; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Gia_Man_t * Gia_ManFindPoPartition2( Gia_Man_t * p, int iStartNum, int nDelta, int nOutsMin, int nOutsMax, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs ) |
| { |
| return NULL; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Gia_Man_t * Gia_ManFindPoPartition( Gia_Man_t * p, int SelectShift, int fOnlyCis, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs ) |
| { |
| Gia_Man_t * pGia = NULL; |
| Vec_Int_t * vPivots; |
| Vec_Wrd_t * vSigns; |
| Vec_Ptr_t * vParts; |
| Vec_Int_t * vPart; |
| abctime clk = Abc_Clock(); |
| vPivots = Gia_ManFindPivots( p, SelectShift, fOnlyCis, fVerbose ); |
| vSigns = Gia_ManDeriveSigns( p, vPivots, fVerbose ); |
| Vec_IntFree( vPivots ); |
| vParts = Gia_ManHashOutputs( p, vSigns, fVerbose ); |
| Vec_WrdFree( vSigns ); |
| if ( fSetLargest ) |
| { |
| vPart = Vec_VecEntryInt( (Vec_Vec_t *)vParts, 0 ); |
| pGia = Gia_ManDupCones( p, Vec_IntArray(vPart), Vec_IntSize(vPart), 1 ); |
| } |
| if ( pvPosEquivs ) |
| { |
| *pvPosEquivs = vParts; |
| printf( "The algorithm divided %d POs into %d partitions. ", Gia_ManPoNum(p), Vec_PtrSize(vParts) ); |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| } |
| else |
| Vec_VecFree( (Vec_Vec_t *)vParts ); |
| return pGia; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |