blob: b8322b3fd19569913b1ac7bb822ad113acbaa7b5 [file] [log] [blame]
/**CFile****************************************************************
FileName [ivyFastMap.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [And-Inverter Graph package.]
Synopsis [Fast FPGA mapping.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - May 11, 2006.]
Revision [$Id: ivyFastMap.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
***********************************************************************/
#include "ivy.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define IVY_INFINITY 10000
typedef struct Ivy_SuppMan_t_ Ivy_SuppMan_t;
struct Ivy_SuppMan_t_
{
int nLimit; // the limit on the number of inputs
int nObjs; // the number of entries
int nSize; // size of each entry in bytes
char * pMem; // memory allocated
Vec_Vec_t * vLuts; // the array of nodes used in the mapping
};
typedef struct Ivy_Supp_t_ Ivy_Supp_t;
struct Ivy_Supp_t_
{
char nSize; // the number of support nodes
char fMark; // multipurpose mask
char fMark2; // multipurpose mask
char fMark3; // multipurpose mask
int nRefs; // the number of references
short Delay; // the delay of the node
short DelayR; // the reverse delay of the node
int pArray[0]; // the support nodes
};
static inline Ivy_Supp_t * Ivy_ObjSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
{
return (Ivy_Supp_t *)(((Ivy_SuppMan_t*)pAig->pData)->pMem + pObj->Id * ((Ivy_SuppMan_t*)pAig->pData)->nSize);
}
static inline Ivy_Supp_t * Ivy_ObjSuppStart( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
{
Ivy_Supp_t * pSupp;
pSupp = Ivy_ObjSupp( pAig, pObj );
pSupp->fMark = 0;
pSupp->Delay = 0;
pSupp->nSize = 1;
pSupp->pArray[0] = pObj->Id;
return pSupp;
}
static void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, abctime Time, char * pStr );
static int Ivy_FastMapDelay( Ivy_Man_t * pAig );
static int Ivy_FastMapArea( Ivy_Man_t * pAig );
static void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit );
static void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit );
static int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit );
static void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter );
static void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit );
static int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
static int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
static int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
static void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld );
static int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
static int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
extern abctime s_MappingTime;
extern int s_MappingMem;
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Performs fast K-LUT mapping of the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose )
{
Ivy_SuppMan_t * pMan;
Ivy_Obj_t * pObj;
int i, Delay, Area;
abctime clk, clkTotal = Abc_Clock();
// start the memory for supports
pMan = ABC_ALLOC( Ivy_SuppMan_t, 1 );
memset( pMan, 0, sizeof(Ivy_SuppMan_t) );
pMan->nLimit = nLimit;
pMan->nObjs = Ivy_ManObjIdMax(pAig) + 1;
pMan->nSize = sizeof(Ivy_Supp_t) + nLimit * sizeof(int);
pMan->pMem = (char *)ABC_ALLOC( char, pMan->nObjs * pMan->nSize );
memset( pMan->pMem, 0, pMan->nObjs * pMan->nSize );
pMan->vLuts = Vec_VecAlloc( 100 );
pAig->pData = pMan;
clk = Abc_Clock();
// set the PI mapping
Ivy_ObjSuppStart( pAig, Ivy_ManConst1(pAig) );
Ivy_ManForEachPi( pAig, pObj, i )
Ivy_ObjSuppStart( pAig, pObj );
// iterate through all nodes in the topological order
Ivy_ManForEachNode( pAig, pObj, i )
Ivy_FastMapNode( pAig, pObj, nLimit );
// find the best arrival time and area
Delay = Ivy_FastMapDelay( pAig );
Area = Ivy_FastMapArea(pAig);
if ( fVerbose )
Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Delay oriented mapping: " );
// 2-1-2 (doing 2-1-2-1-2 improves 0.5%)
if ( fRecovery )
{
clk = Abc_Clock();
Ivy_FastMapRequired( pAig, Delay, 0 );
// remap the nodes
Ivy_FastMapRecover( pAig, nLimit );
Delay = Ivy_FastMapDelay( pAig );
Area = Ivy_FastMapArea(pAig);
if ( fVerbose )
Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Area recovery 2 : " );
clk = Abc_Clock();
Ivy_FastMapRequired( pAig, Delay, 0 );
// iterate through all nodes in the topological order
Ivy_ManForEachNode( pAig, pObj, i )
Ivy_FastMapNodeArea( pAig, pObj, nLimit );
Delay = Ivy_FastMapDelay( pAig );
Area = Ivy_FastMapArea(pAig);
if ( fVerbose )
Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Area recovery 1 : " );
clk = Abc_Clock();
Ivy_FastMapRequired( pAig, Delay, 0 );
// remap the nodes
Ivy_FastMapRecover( pAig, nLimit );
Delay = Ivy_FastMapDelay( pAig );
Area = Ivy_FastMapArea(pAig);
if ( fVerbose )
Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Area recovery 2 : " );
}
s_MappingTime = Abc_Clock() - clkTotal;
s_MappingMem = pMan->nObjs * pMan->nSize;
/*
{
Vec_Ptr_t * vNodes;
vNodes = Vec_PtrAlloc( 100 );
Vec_VecForEachEntry( Ivy_Obj_t *, pMan->vLuts, pObj, i, k )
Vec_PtrPush( vNodes, pObj );
Ivy_ManShow( pAig, 0, vNodes );
Vec_PtrFree( vNodes );
}
*/
}
/**Function*************************************************************
Synopsis [Cleans memory used for decomposition.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapStop( Ivy_Man_t * pAig )
{
Ivy_SuppMan_t * p = (Ivy_SuppMan_t *)pAig->pData;
Vec_VecFree( p->vLuts );
ABC_FREE( p->pMem );
ABC_FREE( p );
pAig->pData = NULL;
}
/**Function*************************************************************
Synopsis [Prints statistics.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, abctime Time, char * pStr )
{
printf( "%s : Delay = %3d. Area = %6d. ", pStr, Delay, Area );
ABC_PRT( "Time", Time );
}
/**Function*************************************************************
Synopsis [Computes delay after LUT mapping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_FastMapDelay( Ivy_Man_t * pAig )
{
Ivy_Supp_t * pSupp;
Ivy_Obj_t * pObj;
int i, DelayMax = 0;
Ivy_ManForEachPo( pAig, pObj, i )
{
pObj = Ivy_ObjFanin0(pObj);
if ( !Ivy_ObjIsNode(pObj) )
continue;
pSupp = Ivy_ObjSupp( pAig, pObj );
if ( DelayMax < pSupp->Delay )
DelayMax = pSupp->Delay;
}
return DelayMax;
}
/**Function*************************************************************
Synopsis [Computes area after mapping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_FastMapArea_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Vec_t * vLuts )
{
Ivy_Supp_t * pSupp;
int i, Counter;
pSupp = Ivy_ObjSupp( pAig, pObj );
// skip visited nodes and PIs
if ( pSupp->fMark || pSupp->nSize == 1 )
return 0;
pSupp->fMark = 1;
// compute the area of this node
Counter = 0;
for ( i = 0; i < pSupp->nSize; i++ )
Counter += Ivy_FastMapArea_rec( pAig, Ivy_ManObj(pAig, pSupp->pArray[i]), vLuts );
// add the node to the array of LUTs
Vec_VecPush( vLuts, pSupp->Delay, pObj );
return 1 + Counter;
}
/**Function*************************************************************
Synopsis [Computes area after mapping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_FastMapArea( Ivy_Man_t * pAig )
{
Vec_Vec_t * vLuts;
Ivy_Obj_t * pObj;
int i, Counter = 0;
// get the array to store the nodes
vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts;
Vec_VecClear( vLuts );
// explore starting from each node
Ivy_ManForEachPo( pAig, pObj, i )
Counter += Ivy_FastMapArea_rec( pAig, Ivy_ObjFanin0(pObj), vLuts );
// clean the marks
Ivy_ManForEachNode( pAig, pObj, i )
Ivy_ObjSupp( pAig, pObj )->fMark = 0;
return Counter;
}
/**Function*************************************************************
Synopsis [Performs fast mapping for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Ivy_ObjIsNodeInt1( Ivy_Obj_t * pObj )
{
return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) == 1;
}
/**Function*************************************************************
Synopsis [Performs fast mapping for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Ivy_ObjIsNodeInt2( Ivy_Obj_t * pObj )
{
return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) <= 2;
}
/**Function*************************************************************
Synopsis [Performs fast mapping for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntRemoveDup( int * pArray, int nSize )
{
int i, k;
if ( nSize < 2 )
return nSize;
for ( i = k = 1; i < nSize; i++ )
if ( pArray[i] != pArray[i-1] )
pArray[k++] = pArray[i];
return k;
}
/**Function*************************************************************
Synopsis [Performs fast mapping for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapNodeArea2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit )
{
static int Store[32], StoreSize;
static char Supp0[16], Supp1[16];
static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0;
static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1;
Ivy_Obj_t * pFanin0, * pFanin1;
Ivy_Supp_t * pSupp0, * pSupp1, * pSupp;
int RetValue, DelayOld;
assert( nLimit <= 32 );
assert( Ivy_ObjIsNode(pObj) );
// get the fanins
pFanin0 = Ivy_ObjFanin0(pObj);
pFanin1 = Ivy_ObjFanin1(pObj);
// get the supports
pSupp0 = Ivy_ObjSupp( pAig, pFanin0 );
pSupp1 = Ivy_ObjSupp( pAig, pFanin1 );
pSupp = Ivy_ObjSupp( pAig, pObj );
assert( pSupp->fMark == 0 );
// get the old delay of the node
DelayOld = Ivy_FastMapNodeDelay(pAig, pObj);
assert( DelayOld <= pSupp->DelayR );
// copy the current cut
memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize );
StoreSize = pSupp->nSize;
// get the fanin support
if ( Ivy_ObjRefs(pFanin0) > 1 && pSupp0->Delay < pSupp->DelayR )
{
pSupp0 = pTemp0;
pSupp0->nSize = 1;
pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj);
}
// get the fanin support
if ( Ivy_ObjRefs(pFanin1) > 1 && pSupp1->Delay < pSupp->DelayR )
{
pSupp1 = pTemp1;
pSupp1->nSize = 1;
pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj);
}
// merge the cuts
if ( pSupp0->nSize < pSupp1->nSize )
RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit );
else
RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit );
if ( !RetValue )
{
pSupp->nSize = 2;
pSupp->pArray[0] = Ivy_ObjFaninId0(pObj);
pSupp->pArray[1] = Ivy_ObjFaninId1(pObj);
}
// check the resulting delay
pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj);
if ( pSupp->Delay > pSupp->DelayR )
{
pSupp->nSize = StoreSize;
memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize );
pSupp->Delay = DelayOld;
}
}
/**Function*************************************************************
Synopsis [Performs fast mapping for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit )
{
static int Store[32], StoreSize;
static char Supp0[16], Supp1[16];
static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0;
static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1;
Ivy_Obj_t * pFanin0, * pFanin1;
Ivy_Supp_t * pSupp0, * pSupp1, * pSupp;
int RetValue, DelayOld, RefsOld;
int AreaBef, AreaAft;
assert( nLimit <= 32 );
assert( Ivy_ObjIsNode(pObj) );
// get the fanins
pFanin0 = Ivy_ObjFanin0(pObj);
pFanin1 = Ivy_ObjFanin1(pObj);
// get the supports
pSupp0 = Ivy_ObjSupp( pAig, pFanin0 );
pSupp1 = Ivy_ObjSupp( pAig, pFanin1 );
pSupp = Ivy_ObjSupp( pAig, pObj );
assert( pSupp->fMark == 0 );
// get the area
if ( pSupp->nRefs == 0 )
AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj );
else
AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
// if ( AreaBef == 1 )
// return;
// deref the cut if the node is refed
if ( pSupp->nRefs != 0 )
Ivy_FastMapNodeDeref( pAig, pObj );
// get the old delay of the node
DelayOld = Ivy_FastMapNodeDelay(pAig, pObj);
assert( DelayOld <= pSupp->DelayR );
// copy the current cut
memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize );
StoreSize = pSupp->nSize;
// get the fanin support
if ( Ivy_ObjRefs(pFanin0) > 2 && pSupp0->Delay < pSupp->DelayR )
// if ( pSupp0->nRefs > 0 && pSupp0->Delay < pSupp->DelayR ) // this leads to 2% worse results
{
pSupp0 = pTemp0;
pSupp0->nSize = 1;
pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj);
}
// get the fanin support
if ( Ivy_ObjRefs(pFanin1) > 2 && pSupp1->Delay < pSupp->DelayR )
// if ( pSupp1->nRefs > 0 && pSupp1->Delay < pSupp->DelayR )
{
pSupp1 = pTemp1;
pSupp1->nSize = 1;
pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj);
}
// merge the cuts
if ( pSupp0->nSize < pSupp1->nSize )
RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit );
else
RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit );
if ( !RetValue )
{
pSupp->nSize = 2;
pSupp->pArray[0] = Ivy_ObjFaninId0(pObj);
pSupp->pArray[1] = Ivy_ObjFaninId1(pObj);
}
// check the resulting delay
pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj);
RefsOld = pSupp->nRefs; pSupp->nRefs = 0;
AreaAft = Ivy_FastMapNodeAreaDerefed( pAig, pObj );
pSupp->nRefs = RefsOld;
if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR )
// if ( pSupp->Delay > pSupp->DelayR )
{
pSupp->nSize = StoreSize;
memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize );
pSupp->Delay = DelayOld;
// printf( "-" );
}
// else
// printf( "+" );
if ( pSupp->nRefs != 0 )
Ivy_FastMapNodeRef( pAig, pObj );
}
/**Function*************************************************************
Synopsis [Performs fast mapping for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit )
{
Ivy_Supp_t * pSupp0, * pSupp1, * pSupp;
int fFaninParam = 2;
int RetValue;
assert( Ivy_ObjIsNode(pObj) );
// get the supports
pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) );
pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) );
pSupp = Ivy_ObjSupp( pAig, pObj );
pSupp->fMark = 0;
// get the delays
if ( pSupp0->Delay == pSupp1->Delay )
pSupp->Delay = (pSupp0->Delay == 0) ? pSupp0->Delay + 1: pSupp0->Delay;
else if ( pSupp0->Delay > pSupp1->Delay )
{
pSupp->Delay = pSupp0->Delay;
pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) );
pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj);
}
else // if ( pSupp0->Delay < pSupp1->Delay )
{
pSupp->Delay = pSupp1->Delay;
pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) );
pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj);
}
// merge the cuts
if ( pSupp0->nSize < pSupp1->nSize )
RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit );
else
RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit );
if ( !RetValue )
{
pSupp->Delay++;
if ( fFaninParam == 2 )
{
pSupp->nSize = 2;
pSupp->pArray[0] = Ivy_ObjFaninId0(pObj);
pSupp->pArray[1] = Ivy_ObjFaninId1(pObj);
}
else if ( fFaninParam == 3 )
{
Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB;
pFanin0 = Ivy_ObjFanin0(pObj);
pFanin1 = Ivy_ObjFanin1(pObj);
pSupp->nSize = 0;
// process the first fanin
if ( Ivy_ObjIsNodeInt1(pFanin0) )
{
pFaninA = Ivy_ObjFanin0(pFanin0);
pFaninB = Ivy_ObjFanin1(pFanin0);
if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) )
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0);
else
{
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA);
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB);
}
}
else
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0);
// process the second fanin
if ( Ivy_ObjIsNodeInt1(pFanin1) )
{
pFaninA = Ivy_ObjFanin0(pFanin1);
pFaninB = Ivy_ObjFanin1(pFanin1);
if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) )
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1);
else
{
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA);
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB);
}
}
else
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1);
// sort the fanins
Vec_IntSelectSort( pSupp->pArray, pSupp->nSize );
pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize );
assert( pSupp->pArray[0] < pSupp->pArray[1] );
}
else if ( fFaninParam == 4 )
{
Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB;
pFanin0 = Ivy_ObjFanin0(pObj);
pFanin1 = Ivy_ObjFanin1(pObj);
pSupp->nSize = 0;
// consider the case when exactly one of them is internal
if ( Ivy_ObjIsNodeInt1(pFanin0) ^ Ivy_ObjIsNodeInt1(pFanin1) )
{
pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) );
pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) );
if ( Ivy_ObjIsNodeInt1(pFanin0) && pSupp0->nSize < nLimit )
{
pSupp->Delay = IVY_MAX( pSupp0->Delay, pSupp1->Delay + 1 );
pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) );
pSupp1->pArray[0] = Ivy_ObjId(pFanin1);
// merge the cuts
RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit );
assert( RetValue );
assert( pSupp->nSize > 1 );
return;
}
if ( Ivy_ObjIsNodeInt1(pFanin1) && pSupp1->nSize < nLimit )
{
pSupp->Delay = IVY_MAX( pSupp1->Delay, pSupp0->Delay + 1 );
pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) );
pSupp0->pArray[0] = Ivy_ObjId(pFanin0);
// merge the cuts
RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit );
assert( RetValue );
assert( pSupp->nSize > 1 );
return;
}
}
// process the first fanin
if ( Ivy_ObjIsNodeInt1(pFanin0) )
{
pFaninA = Ivy_ObjFanin0(pFanin0);
pFaninB = Ivy_ObjFanin1(pFanin0);
if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) )
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0);
else
{
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA);
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB);
}
}
else
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0);
// process the second fanin
if ( Ivy_ObjIsNodeInt1(pFanin1) )
{
pFaninA = Ivy_ObjFanin0(pFanin1);
pFaninB = Ivy_ObjFanin1(pFanin1);
if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) )
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1);
else
{
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA);
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB);
}
}
else
pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1);
// sort the fanins
Vec_IntSelectSort( pSupp->pArray, pSupp->nSize );
pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize );
assert( pSupp->pArray[0] < pSupp->pArray[1] );
assert( pSupp->nSize > 1 );
}
}
assert( pSupp->Delay > 0 );
}
/**Function*************************************************************
Synopsis [Merges two supports]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit )
{
int i, k, c;
assert( pSupp0->nSize >= pSupp1->nSize );
// the case of the largest cut sizes
if ( pSupp0->nSize == nLimit && pSupp1->nSize == nLimit )
{
for ( i = 0; i < pSupp0->nSize; i++ )
if ( pSupp0->pArray[i] != pSupp1->pArray[i] )
return 0;
for ( i = 0; i < pSupp0->nSize; i++ )
pSupp->pArray[i] = pSupp0->pArray[i];
pSupp->nSize = pSupp0->nSize;
return 1;
}
// the case when one of the cuts is the largest
if ( pSupp0->nSize == nLimit )
{
for ( i = 0; i < pSupp1->nSize; i++ )
{
for ( k = pSupp0->nSize - 1; k >= 0; k-- )
if ( pSupp0->pArray[k] == pSupp1->pArray[i] )
break;
if ( k == -1 ) // did not find
return 0;
}
for ( i = 0; i < pSupp0->nSize; i++ )
pSupp->pArray[i] = pSupp0->pArray[i];
pSupp->nSize = pSupp0->nSize;
return 1;
}
// compare two cuts with different numbers
i = k = 0;
for ( c = 0; c < nLimit; c++ )
{
if ( k == pSupp1->nSize )
{
if ( i == pSupp0->nSize )
{
pSupp->nSize = c;
return 1;
}
pSupp->pArray[c] = pSupp0->pArray[i++];
continue;
}
if ( i == pSupp0->nSize )
{
if ( k == pSupp1->nSize )
{
pSupp->nSize = c;
return 1;
}
pSupp->pArray[c] = pSupp1->pArray[k++];
continue;
}
if ( pSupp0->pArray[i] < pSupp1->pArray[k] )
{
pSupp->pArray[c] = pSupp0->pArray[i++];
continue;
}
if ( pSupp0->pArray[i] > pSupp1->pArray[k] )
{
pSupp->pArray[c] = pSupp1->pArray[k++];
continue;
}
pSupp->pArray[c] = pSupp0->pArray[i++];
k++;
}
if ( i < pSupp0->nSize || k < pSupp1->nSize )
return 0;
pSupp->nSize = c;
return 1;
}
/**Function*************************************************************
Synopsis [Creates integer vector with the support of the node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves )
{
Ivy_Supp_t * pSupp;
pSupp = Ivy_ObjSupp( pAig, pObj );
vLeaves->nCap = 8;
vLeaves->nSize = pSupp->nSize;
vLeaves->pArray = pSupp->pArray;
}
/**Function*************************************************************
Synopsis [Sets the required times of the intermediate nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapRequired_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Ivy_Obj_t * pRoot, int DelayR )
{
Ivy_Supp_t * pSupp;
pSupp = Ivy_ObjSupp( pAig, pObj );
if ( pObj != pRoot && (pSupp->nRefs > 0 || Ivy_ObjIsCi(pObj)) )
return;
Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin0(pObj), pRoot, DelayR );
Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin1(pObj), pRoot, DelayR );
// assert( pObj == pRoot || pSupp->DelayR == IVY_INFINITY );
pSupp->DelayR = DelayR;
}
/**Function*************************************************************
Synopsis [Computes the required times for each node.]
Description [Sets reference counters for each node.]
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter )
{
Vec_Vec_t * vLuts;
Vec_Ptr_t * vNodes;
Ivy_Obj_t * pObj;
Ivy_Supp_t * pSupp, * pSuppF;
int i, k, c;
// clean the required times
Ivy_ManForEachPi( pAig, pObj, i )
{
pSupp = Ivy_ObjSupp( pAig, pObj );
pSupp->DelayR = IVY_INFINITY;
pSupp->nRefs = 0;
}
Ivy_ManForEachNode( pAig, pObj, i )
{
pSupp = Ivy_ObjSupp( pAig, pObj );
pSupp->DelayR = IVY_INFINITY;
pSupp->nRefs = 0;
}
// set the required times of the POs
Ivy_ManForEachPo( pAig, pObj, i )
{
pSupp = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) );
pSupp->DelayR = Delay;
pSupp->nRefs++;
}
// get the levelized nodes used in the mapping
vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts;
// propagate the required times
Vec_VecForEachLevelReverse( vLuts, vNodes, i )
Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, k )
{
pSupp = Ivy_ObjSupp( pAig, pObj );
assert( pSupp->nRefs > 0 );
for ( c = 0; c < pSupp->nSize; c++ )
{
pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) );
pSuppF->DelayR = IVY_MIN( pSuppF->DelayR, pSupp->DelayR - 1 );
pSuppF->nRefs++;
}
}
/*
// print out some of the required times
Ivy_ManForEachPi( pAig, pObj, i )
{
pSupp = Ivy_ObjSupp( pAig, pObj );
printf( "%d ", pSupp->DelayR );
}
printf( "\n" );
*/
if ( fSetInter )
{
// set the required times of the intermediate nodes
Vec_VecForEachLevelReverse( vLuts, vNodes, i )
Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, k )
{
pSupp = Ivy_ObjSupp( pAig, pObj );
Ivy_FastMapRequired_rec( pAig, pObj, pObj, pSupp->DelayR );
}
// make sure that all required times are assigned
Ivy_ManForEachNode( pAig, pObj, i )
{
pSupp = Ivy_ObjSupp( pAig, pObj );
assert( pSupp->DelayR < IVY_INFINITY );
}
}
}
/**Function*************************************************************
Synopsis [Performs area recovery for each node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit )
{
Vec_Ptr_t * vFront, * vFrontOld;
Ivy_Obj_t * pObj;
int i;
vFront = Vec_PtrAlloc( nLimit );
vFrontOld = Vec_PtrAlloc( nLimit );
Ivy_ManCleanTravId( pAig );
// iterate through all nodes in the topological order
Ivy_ManForEachNode( pAig, pObj, i )
Ivy_FastMapNodeRecover( pAig, pObj, nLimit, vFront, vFrontOld );
Vec_PtrFree( vFrontOld );
Vec_PtrFree( vFront );
}
/**Function*************************************************************
Synopsis [Computes the delay of the cut rooted at this node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
{
Ivy_Supp_t * pSupp, * pSuppF;
int c, Delay = 0;
pSupp = Ivy_ObjSupp( pAig, pObj );
for ( c = 0; c < pSupp->nSize; c++ )
{
pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) );
Delay = IVY_MAX( Delay, pSuppF->Delay );
}
return 1 + Delay;
}
/**function*************************************************************
synopsis [References the cut.]
description [This procedure is similar to the procedure NodeReclaim.]
sideeffects []
seealso []
***********************************************************************/
int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
{
Ivy_Supp_t * pSupp, * pSuppF;
Ivy_Obj_t * pNodeChild;
int aArea, i;
// start the area of this cut
aArea = 1;
// go through the children
pSupp = Ivy_ObjSupp( pAig, pObj );
assert( pSupp->nSize > 1 );
for ( i = 0; i < pSupp->nSize; i++ )
{
pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]);
pSuppF = Ivy_ObjSupp( pAig, pNodeChild );
assert( pSuppF->nRefs >= 0 );
if ( pSuppF->nRefs++ > 0 )
continue;
if ( pSuppF->nSize == 1 )
continue;
aArea += Ivy_FastMapNodeRef( pAig, pNodeChild );
}
return aArea;
}
/**function*************************************************************
synopsis [Dereferences the cut.]
description [This procedure is similar to the procedure NodeRecusiveDeref.]
sideeffects []
seealso []
***********************************************************************/
int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
{
Ivy_Supp_t * pSupp, * pSuppF;
Ivy_Obj_t * pNodeChild;
int aArea, i;
// start the area of this cut
aArea = 1;
// go through the children
pSupp = Ivy_ObjSupp( pAig, pObj );
assert( pSupp->nSize > 1 );
for ( i = 0; i < pSupp->nSize; i++ )
{
pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]);
pSuppF = Ivy_ObjSupp( pAig, pNodeChild );
assert( pSuppF->nRefs > 0 );
if ( --pSuppF->nRefs > 0 )
continue;
if ( pSuppF->nSize == 1 )
continue;
aArea += Ivy_FastMapNodeDeref( pAig, pNodeChild );
}
return aArea;
}
/**function*************************************************************
synopsis [Computes the exact area associated with the cut.]
description []
sideeffects []
seealso []
***********************************************************************/
int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
{
Ivy_Supp_t * pSupp;
int aResult, aResult2;
if ( Ivy_ObjIsCi(pObj) )
return 0;
assert( Ivy_ObjIsNode(pObj) );
pSupp = Ivy_ObjSupp( pAig, pObj );
assert( pSupp->nRefs > 0 );
aResult = Ivy_FastMapNodeDeref( pAig, pObj );
aResult2 = Ivy_FastMapNodeRef( pAig, pObj );
assert( aResult == aResult2 );
return aResult;
}
/**function*************************************************************
synopsis [Computes the exact area associated with the cut.]
description []
sideeffects []
seealso []
***********************************************************************/
int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
{
Ivy_Supp_t * pSupp;
int aResult, aResult2;
if ( Ivy_ObjIsCi(pObj) )
return 0;
assert( Ivy_ObjIsNode(pObj) );
pSupp = Ivy_ObjSupp( pAig, pObj );
assert( pSupp->nRefs == 0 );
aResult2 = Ivy_FastMapNodeRef( pAig, pObj );
aResult = Ivy_FastMapNodeDeref( pAig, pObj );
assert( aResult == aResult2 );
return aResult;
}
/**Function*************************************************************
Synopsis [Counts the number of nodes with no external fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_FastMapCutCost( Ivy_Man_t * pAig, Vec_Ptr_t * vFront )
{
Ivy_Supp_t * pSuppF;
Ivy_Obj_t * pFanin;
int i, Counter = 0;
Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i )
{
pSuppF = Ivy_ObjSupp( pAig, pFanin );
if ( pSuppF->nRefs == 0 )
Counter++;
}
return Counter;
}
/**Function*************************************************************
Synopsis [Performs area recovery for each node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapMark_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
{
if ( Ivy_ObjIsTravIdCurrent(pAig, pObj) )
return;
assert( Ivy_ObjIsNode(pObj) );
Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin0(pObj) );
Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin1(pObj) );
Ivy_ObjSetTravIdCurrent(pAig, pObj);
}
/**Function*************************************************************
Synopsis [Returns 1 if the number of fanins will grow.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_FastMapNodeWillGrow( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
{
Ivy_Obj_t * pFanin0, * pFanin1;
assert( Ivy_ObjIsNode(pObj) );
pFanin0 = Ivy_ObjFanin0(pObj);
pFanin1 = Ivy_ObjFanin1(pObj);
return !Ivy_ObjIsTravIdCurrent(pAig, pFanin0) && !Ivy_ObjIsTravIdCurrent(pAig, pFanin1);
}
/**Function*************************************************************
Synopsis [Returns the increase in the number of fanins with no external refs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_FastMapNodeFaninCost( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
{
Ivy_Supp_t * pSuppF;
Ivy_Obj_t * pFanin;
int Counter = 0;
assert( Ivy_ObjIsNode(pObj) );
// check if the node has external refs
pSuppF = Ivy_ObjSupp( pAig, pObj );
if ( pSuppF->nRefs == 0 )
Counter--;
// increment the number of fanins without external refs
pFanin = Ivy_ObjFanin0(pObj);
pSuppF = Ivy_ObjSupp( pAig, pFanin );
if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 )
Counter++;
// increment the number of fanins without external refs
pFanin = Ivy_ObjFanin1(pObj);
pSuppF = Ivy_ObjSupp( pAig, pFanin );
if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 )
Counter++;
return Counter;
}
/**Function*************************************************************
Synopsis [Updates the frontier.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapNodeFaninUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront )
{
Ivy_Obj_t * pFanin;
assert( Ivy_ObjIsNode(pObj) );
Vec_PtrRemove( vFront, pObj );
pFanin = Ivy_ObjFanin0(pObj);
if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) )
{
Ivy_ObjSetTravIdCurrent(pAig, pFanin);
Vec_PtrPush( vFront, pFanin );
}
pFanin = Ivy_ObjFanin1(pObj);
if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) )
{
Ivy_ObjSetTravIdCurrent(pAig, pFanin);
Vec_PtrPush( vFront, pFanin );
}
}
/**Function*************************************************************
Synopsis [Compacts the number of external refs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_FastMapNodeFaninCompact0( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
{
Ivy_Obj_t * pFanin;
int i;
Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i )
{
if ( Ivy_ObjIsCi(pFanin) )
continue;
if ( Ivy_FastMapNodeWillGrow(pAig, pFanin) )
continue;
if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 )
{
Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront );
return 1;
}
}
return 0;
}
/**Function*************************************************************
Synopsis [Compacts the number of external refs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_FastMapNodeFaninCompact1( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
{
Ivy_Obj_t * pFanin;
int i;
Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i )
{
if ( Ivy_ObjIsCi(pFanin) )
continue;
if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) < 0 )
{
Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront );
return 1;
}
}
return 0;
}
/**Function*************************************************************
Synopsis [Compacts the number of external refs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_FastMapNodeFaninCompact2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
{
Ivy_Obj_t * pFanin;
int i;
Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i )
{
if ( Ivy_ObjIsCi(pFanin) )
continue;
if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 )
{
Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront );
return 1;
}
}
return 0;
}
/**Function*************************************************************
Synopsis [Compacts the number of external refs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_FastMapNodeFaninCompact_int( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
{
if ( Ivy_FastMapNodeFaninCompact0(pAig, pObj, nLimit, vFront) )
return 1;
if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact1(pAig, pObj, nLimit, vFront) )
return 1;
if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact2(pAig, pObj, nLimit, vFront) )
return 1;
assert( Vec_PtrSize(vFront) <= nLimit );
return 0;
}
/**Function*************************************************************
Synopsis [Compacts the number of external refs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapNodeFaninCompact( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
{
while ( Ivy_FastMapNodeFaninCompact_int( pAig, pObj, nLimit, vFront ) );
}
/**Function*************************************************************
Synopsis [Prepares node mapping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapNodePrepare( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld )
{
Ivy_Supp_t * pSupp;
Ivy_Obj_t * pFanin;
int i;
pSupp = Ivy_ObjSupp( pAig, pObj );
// expand the cut downwards from the given place
Vec_PtrClear( vFront );
Vec_PtrClear( vFrontOld );
Ivy_ManIncrementTravId( pAig );
for ( i = 0; i < pSupp->nSize; i++ )
{
pFanin = Ivy_ManObj(pAig, pSupp->pArray[i]);
Vec_PtrPush( vFront, pFanin );
Vec_PtrPush( vFrontOld, pFanin );
Ivy_ObjSetTravIdCurrent( pAig, pFanin );
}
// mark the nodes in the cone
Ivy_FastMapMark_rec( pAig, pObj );
}
/**Function*************************************************************
Synopsis [Updates the frontier.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapNodeUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront )
{
Ivy_Supp_t * pSupp;
Ivy_Obj_t * pFanin;
int i;
pSupp = Ivy_ObjSupp( pAig, pObj );
// deref node's cut
Ivy_FastMapNodeDeref( pAig, pObj );
// update the node's cut
pSupp->nSize = Vec_PtrSize(vFront);
Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i )
pSupp->pArray[i] = pFanin->Id;
// ref the new cut
Ivy_FastMapNodeRef( pAig, pObj );
}
/**Function*************************************************************
Synopsis [Performs area recovery for each node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapNodeRecover2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld )
{
Ivy_Supp_t * pSupp;
int CostBef, CostAft;
int AreaBef, AreaAft;
pSupp = Ivy_ObjSupp( pAig, pObj );
// if ( pSupp->nRefs == 0 )
// return;
if ( pSupp->nRefs == 0 )
AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj );
else
AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
// get the area
if ( AreaBef == 1 )
return;
if ( pSupp->nRefs == 0 )
{
pSupp->nRefs = 1000000;
Ivy_FastMapNodeRef( pAig, pObj );
}
// the cut is non-trivial
Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld );
// iteratively modify the cut
CostBef = Ivy_FastMapCutCost( pAig, vFront );
Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront );
CostAft = Ivy_FastMapCutCost( pAig, vFront );
assert( CostBef >= CostAft );
// update the node
Ivy_FastMapNodeUpdate( pAig, pObj, vFront );
// get the new area
AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
if ( AreaAft > AreaBef )
{
Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld );
AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
assert( AreaAft == AreaBef );
}
if ( pSupp->nRefs == 1000000 )
{
pSupp->nRefs = 0;
Ivy_FastMapNodeDeref( pAig, pObj );
}
}
/**Function*************************************************************
Synopsis [Performs area recovery for each node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld )
{
Ivy_Supp_t * pSupp;
int CostBef, CostAft;
int AreaBef, AreaAft;
int DelayOld;
pSupp = Ivy_ObjSupp( pAig, pObj );
DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj );
assert( pSupp->Delay <= pSupp->DelayR );
if ( pSupp->nRefs == 0 )
return;
// get the area
AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
// if ( AreaBef == 1 )
// return;
// the cut is non-trivial
Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld );
// iteratively modify the cut
Ivy_FastMapNodeDeref( pAig, pObj );
CostBef = Ivy_FastMapCutCost( pAig, vFront );
Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront );
CostAft = Ivy_FastMapCutCost( pAig, vFront );
Ivy_FastMapNodeRef( pAig, pObj );
assert( CostBef >= CostAft );
// update the node
Ivy_FastMapNodeUpdate( pAig, pObj, vFront );
pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj );
// get the new area
AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR )
{
Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld );
AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
assert( AreaAft == AreaBef );
pSupp->Delay = DelayOld;
}
}
/**Function*************************************************************
Synopsis [Performs area recovery for each node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_FastMapNodeRecover4( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld )
{
Ivy_Supp_t * pSupp;
int CostBef, CostAft;
int AreaBef, AreaAft;
int DelayOld;
pSupp = Ivy_ObjSupp( pAig, pObj );
DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj );
assert( pSupp->Delay <= pSupp->DelayR );
// if ( pSupp->nRefs == 0 )
// return;
// AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
// get the area
if ( pSupp->nRefs == 0 )
AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj );
else
AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
if ( AreaBef == 1 )
return;
if ( pSupp->nRefs == 0 )
{
pSupp->nRefs = 1000000;
Ivy_FastMapNodeRef( pAig, pObj );
}
// the cut is non-trivial
Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld );
// iteratively modify the cut
CostBef = Ivy_FastMapCutCost( pAig, vFront );
Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront );
CostAft = Ivy_FastMapCutCost( pAig, vFront );
assert( CostBef >= CostAft );
// update the node
Ivy_FastMapNodeUpdate( pAig, pObj, vFront );
pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj );
// get the new area
AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR )
{
Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld );
AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
assert( AreaAft == AreaBef );
pSupp->Delay = DelayOld;
}
if ( pSupp->nRefs == 1000000 )
{
pSupp->nRefs = 0;
Ivy_FastMapNodeDeref( pAig, pObj );
}
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END