blob: cd43a65ece179c13631184956b8b5644cabd1d20 [file] [log] [blame]
/**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