mirror of https://github.com/YosysHQ/abc.git
1089 lines
31 KiB
C
1089 lines
31 KiB
C
/**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"
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// 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 int Ivy_FastMapPrint( Ivy_Man_t * pAig, int Time );
|
|
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 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 );
|
|
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 );
|
|
|
|
|
|
extern int 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 )
|
|
{
|
|
Ivy_SuppMan_t * pMan;
|
|
Ivy_Obj_t * pObj;
|
|
int i, Delay, clk, clkTotal = clock();
|
|
// start the memory for supports
|
|
pMan = 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 *)malloc( pMan->nObjs * pMan->nSize );
|
|
pMan->vLuts = Vec_VecAlloc( 100 );
|
|
pAig->pData = pMan;
|
|
clk = 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
|
|
printf( "Delay oriented mapping: " );
|
|
Delay = Ivy_FastMapPrint( pAig, clock() - clk );
|
|
|
|
// perform area recovery
|
|
clk = clock();
|
|
Ivy_FastMapRequired( pAig, Delay );
|
|
// PRT( "Required time computation", clock() - clk );
|
|
|
|
// remap the nodes
|
|
Ivy_FastMapRecover( pAig, nLimit );
|
|
printf( "Area recovery : " );
|
|
Delay = Ivy_FastMapPrint( pAig, clock() - clk );
|
|
|
|
// perform area recovery
|
|
clk = clock();
|
|
Ivy_FastMapRequired( pAig, Delay );
|
|
// PRT( "Required time computation", clock() - clk );
|
|
|
|
// remap the nodes
|
|
Ivy_FastMapRecover( pAig, nLimit );
|
|
printf( "Area recovery : " );
|
|
Delay = Ivy_FastMapPrint( pAig, clock() - clk );
|
|
|
|
s_MappingTime = clock() - clkTotal;
|
|
s_MappingMem = pMan->nObjs * pMan->nSize;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Cleans memory used for decomposition.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ivy_FastMapStop( Ivy_Man_t * pAig )
|
|
{
|
|
Ivy_SuppMan_t * p = pAig->pData;
|
|
Vec_VecFree( p->vLuts );
|
|
free( p->pMem );
|
|
free( p );
|
|
pAig->pData = NULL;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Prints statistics.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Ivy_FastMapPrint( Ivy_Man_t * pAig, int Time )
|
|
{
|
|
int Delay, Area;
|
|
Delay = Ivy_FastMapDelay( pAig );
|
|
Area = Ivy_FastMapArea( pAig );
|
|
printf( "Delay = %3d. Area = %6d. ", Delay, Area );
|
|
PRT( "Time", Time );
|
|
return Delay;
|
|
}
|
|
|
|
/**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 []
|
|
|
|
***********************************************************************/
|
|
void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit )
|
|
{
|
|
Ivy_Supp_t * pSupp0, * pSupp1, * pSupp;
|
|
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++;
|
|
pSupp->nSize = 2;
|
|
pSupp->pArray[0] = Ivy_ObjFaninId0(pObj);
|
|
pSupp->pArray[1] = Ivy_ObjFaninId1(pObj);
|
|
}
|
|
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 [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 )
|
|
{
|
|
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( 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" );
|
|
*/
|
|
}
|
|
|
|
/**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( vFront, pFanin, i )
|
|
{
|
|
pSuppF = Ivy_ObjSupp( pAig, pFanin );
|
|
if ( pSuppF->nRefs == 1 )
|
|
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 == 1 )
|
|
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 == 1 )
|
|
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 == 1 )
|
|
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( 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( 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( 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( 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;
|
|
pSupp = Ivy_ObjSupp( pAig, pObj );
|
|
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
|
|
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 );
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|