blob: 0d59399358386a8a2930d73ae0c554f8aa82d9de [file] [log] [blame]
/**CFile****************************************************************
FileName [gia.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: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
#include "map/if/if.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Sorts the pins in the decreasing order of delays.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_LutDelayTraceSortPins( Gia_Man_t * p, int iObj, int * pPinPerm, float * pPinDelays )
{
int iFanin, i, j, best_i, temp;
assert( Gia_ObjIsLut(p, iObj) );
// start the trivial permutation and collect pin delays
Gia_LutForEachFanin( p, iObj, iFanin, i )
{
pPinPerm[i] = i;
pPinDelays[i] = Gia_ObjTimeArrival(p, iFanin);
}
// selection sort the pins in the decreasible order of delays
// this order will match the increasing order of LUT input pins
for ( i = 0; i < Gia_ObjLutSize(p, iObj)-1; i++ )
{
best_i = i;
for ( j = i+1; j < Gia_ObjLutSize(p, iObj); j++ )
if ( pPinDelays[pPinPerm[j]] > pPinDelays[pPinPerm[best_i]] )
best_i = j;
if ( best_i == i )
continue;
temp = pPinPerm[i];
pPinPerm[i] = pPinPerm[best_i];
pPinPerm[best_i] = temp;
}
// verify
assert( Gia_ObjLutSize(p, iObj) == 0 || pPinPerm[0] < Gia_ObjLutSize(p, iObj) );
for ( i = 1; i < Gia_ObjLutSize(p, iObj); i++ )
{
assert( pPinPerm[i] < Gia_ObjLutSize(p, iObj) );
assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] );
}
}
/**Function*************************************************************
Synopsis [Sorts the pins in the decreasing order of delays.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_LutWhereIsPin( Gia_Man_t * p, int iFanout, int iFanin, int * pPinPerm )
{
int i;
for ( i = 0; i < Gia_ObjLutSize(p, iFanout); i++ )
if ( Gia_ObjLutFanin(p, iFanout, pPinPerm[i]) == iFanin )
return i;
return -1;
}
/**Function*************************************************************
Synopsis [Computes the arrival times for the given object.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float Gia_ObjComputeArrival( Gia_Man_t * p, int iObj, int fUseSorting )
{
If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib;
Gia_Obj_t * pObj = Gia_ManObj( p, iObj );
int k, iFanin, pPinPerm[32];
float pPinDelays[32];
float tArrival, * pDelays;
if ( Gia_ObjIsCi(pObj) )
return Gia_ObjTimeArrival(p, iObj);
if ( Gia_ObjIsCo(pObj) )
return Gia_ObjTimeArrival(p, Gia_ObjFaninId0p(p, pObj) );
assert( Gia_ObjIsLut(p, iObj) );
tArrival = -TIM_ETERNITY;
if ( pLutLib == NULL )
{
Gia_LutForEachFanin( p, iObj, iFanin, k )
if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + 1.0 )
tArrival = Gia_ObjTimeArrival(p, iFanin) + 1.0;
}
else if ( !pLutLib->fVarPinDelays )
{
pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)];
Gia_LutForEachFanin( p, iObj, iFanin, k )
if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + pDelays[0] )
tArrival = Gia_ObjTimeArrival(p, iFanin) + pDelays[0];
}
else
{
pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)];
if ( fUseSorting )
{
Gia_LutDelayTraceSortPins( p, iObj, pPinPerm, pPinDelays );
Gia_LutForEachFanin( p, iObj, iFanin, k )
if ( tArrival < Gia_ObjTimeArrival( p, Gia_ObjLutFanin(p,iObj,pPinPerm[k])) + pDelays[k] )
tArrival = Gia_ObjTimeArrival( p, Gia_ObjLutFanin(p,iObj,pPinPerm[k])) + pDelays[k];
}
else
{
Gia_LutForEachFanin( p, iObj, iFanin, k )
if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + pDelays[k] )
tArrival = Gia_ObjTimeArrival(p, iFanin) + pDelays[k];
}
}
if ( Gia_ObjLutSize(p, iObj) == 0 )
tArrival = 0.0;
return tArrival;
}
/**Function*************************************************************
Synopsis [Propagates the required times through the given node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float Gia_ObjPropagateRequired( Gia_Man_t * p, int iObj, int fUseSorting )
{
If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib;
int k, iFanin, pPinPerm[32];
float pPinDelays[32];
float tRequired = 0.0; // Suppress "might be used uninitialized"
float * pDelays;
assert( Gia_ObjIsLut(p, iObj) );
if ( pLutLib == NULL )
{
tRequired = Gia_ObjTimeRequired( p, iObj) - (float)1.0;
Gia_LutForEachFanin( p, iObj, iFanin, k )
if ( Gia_ObjTimeRequired(p, iFanin) > tRequired )
Gia_ObjSetTimeRequired( p, iFanin, tRequired );
}
else if ( !pLutLib->fVarPinDelays )
{
pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)];
tRequired = Gia_ObjTimeRequired(p, iObj) - pDelays[0];
Gia_LutForEachFanin( p, iObj, iFanin, k )
if ( Gia_ObjTimeRequired(p, iFanin) > tRequired )
Gia_ObjSetTimeRequired( p, iFanin, tRequired );
}
else
{
pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)];
if ( fUseSorting )
{
Gia_LutDelayTraceSortPins( p, iObj, pPinPerm, pPinDelays );
Gia_LutForEachFanin( p, iObj, iFanin, k )
{
tRequired = Gia_ObjTimeRequired( p, iObj) - pDelays[k];
if ( Gia_ObjTimeRequired( p, Gia_ObjLutFanin(p, iObj,pPinPerm[k])) > tRequired )
Gia_ObjSetTimeRequired( p, Gia_ObjLutFanin(p, iObj,pPinPerm[k]), tRequired );
}
}
else
{
Gia_LutForEachFanin( p, iObj, iFanin, k )
{
tRequired = Gia_ObjTimeRequired(p, iObj) - pDelays[k];
if ( Gia_ObjTimeRequired(p, iFanin) > tRequired )
Gia_ObjSetTimeRequired( p, iFanin, tRequired );
}
}
}
return tRequired;
}
/**Function*************************************************************
Synopsis [Computes the delay trace of the given network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float Gia_ManDelayTraceLut( Gia_Man_t * p )
{
int fUseSorting = 1;
If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib;
Vec_Int_t * vObjs;
Gia_Obj_t * pObj;
float tArrival, tArrivalCur, tRequired, tSlack;
int i, iObj;
// get the library
if ( pLutLib && pLutLib->LutMax < Gia_ManLutSizeMax(p) )
{
printf( "The max LUT size (%d) is less than the max fanin count (%d).\n",
pLutLib->LutMax, Gia_ManLutSizeMax(p) );
return -TIM_ETERNITY;
}
// initialize the arrival times
Gia_ManTimeStart( p );
// propagate arrival times
if ( p->pManTime )
Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime );
Gia_ManForEachObj( p, pObj, i )
{
if ( !Gia_ObjIsCi(pObj) && !Gia_ObjIsCo(pObj) && !Gia_ObjIsLut(p, i) )
continue;
tArrival = Gia_ObjComputeArrival( p, i, fUseSorting );
if ( Gia_ObjIsCi(pObj) && p->pManTime )
{
tArrival = Tim_ManGetCiArrival( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj) );
//printf( "%.3f ", tArrival );
}
if ( Gia_ObjIsCo(pObj) && p->pManTime )
Tim_ManSetCoArrival( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj), tArrival );
Gia_ObjSetTimeArrival( p, i, tArrival );
}
// get the latest arrival times
tArrival = -TIM_ETERNITY;
Gia_ManForEachCo( p, pObj, i )
{
tArrivalCur = Gia_ObjTimeArrivalObj( p, Gia_ObjFanin0(pObj) );
Gia_ObjSetTimeArrival( p, Gia_ObjId(p,pObj), tArrivalCur );
if ( tArrival < tArrivalCur )
tArrival = tArrivalCur;
}
// initialize the required times
if ( p->pManTime )
{
Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime );
Tim_ManInitPoRequiredAll( (Tim_Man_t *)p->pManTime, tArrival );
}
else
{
Gia_ManForEachCo( p, pObj, i )
Gia_ObjSetTimeRequiredObj( p, pObj, tArrival );
}
// propagate the required times
vObjs = Gia_ManOrderReverse( p );
Vec_IntForEachEntry( vObjs, iObj, i )
{
pObj = Gia_ManObj(p, iObj);
if ( Gia_ObjIsLut(p, iObj) )
{
Gia_ObjPropagateRequired( p, iObj, fUseSorting );
}
else if ( Gia_ObjIsCi(pObj) )
{
if ( p->pManTime )
Tim_ManSetCiRequired( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj), Gia_ObjTimeRequired(p, iObj) );
}
else if ( Gia_ObjIsCo(pObj) )
{
if ( p->pManTime )
{
tRequired = Tim_ManGetCoRequired( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj) );
Gia_ObjSetTimeRequired( p, iObj, tRequired );
}
if ( Gia_ObjTimeRequired(p, Gia_ObjFaninId0p(p, pObj)) > Gia_ObjTimeRequired(p, iObj) )
Gia_ObjSetTimeRequired(p, Gia_ObjFaninId0p(p, pObj), Gia_ObjTimeRequired(p, iObj) );
}
// set slack for this object
tSlack = Gia_ObjTimeRequired(p, iObj) - Gia_ObjTimeArrival(p, iObj);
assert( tSlack + 0.01 > 0.0 );
Gia_ObjSetTimeSlack( p, iObj, tSlack < 0.0 ? 0.0 : tSlack );
}
Vec_IntFree( vObjs );
return tArrival;
}
#if 0
/**Function*************************************************************
Synopsis [Computes the required times for the given node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float Gia_ObjComputeRequired( Gia_Man_t * p, int iObj, int fUseSorting )
{
If_LibLut_t * pLutLib = p->pLutLib;
int pPinPerm[32];
float pPinDelays[32];
Gia_Obj_t * pFanout;
float tRequired, tDelay, * pDelays;
int k, iFanin;
if ( Gia_ObjIsCo(iObj) )
return Gia_ObjTimeRequired( p, iObj);
tRequired = TIM_ETERNITY;
if ( pLutLib == NULL )
{
Gia_ObjForEachFanout( iObj, pFanout, k )
{
tDelay = Gia_ObjIsCo(pFanout)? 0.0 : 1.0;
if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay )
tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay;
}
}
else if ( !pLutLib->fVarPinDelays )
{
Gia_ObjForEachFanout( iObj, pFanout, k )
{
pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, pFanout)];
tDelay = Gia_ObjIsCo(pFanout)? 0.0 : pDelays[0];
if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay )
tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay;
}
}
else
{
if ( fUseSorting )
{
Gia_ObjForEachFanout( iObj, pFanout, k )
{
pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, pFanout)];
Gia_LutDelayTraceSortPins( p, pFanout, pPinPerm, pPinDelays );
iFanin = Gia_LutWhereIsPin( p, pFanout, iObj, pPinPerm );
assert( Gia_ObjLutFanin( p, pFanout, pPinPerm[iFanin]) == iObj );
tDelay = Gia_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin];
if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay )
tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay;
}
}
else
{
Gia_ObjForEachFanout( iObj, pFanout, k )
{
pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, pFanout)];
iFanin = Gia_ObjFindFanin( p, pFanout, iObj );
assert( Gia_ObjLutFanin(p, pFanout, iFanin) == iObj );
tDelay = Gia_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin];
if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay )
tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay;
}
}
}
return tRequired;
}
/**Function*************************************************************
Synopsis [Computes the arrival times for the given node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_LutVerifyTiming( Gia_Man_t * p )
{
int iObj;
float tArrival, tRequired;
int i;
Gia_LutForEachObj( p, iObj, i )
{
if ( Gia_ObjIsCi(iObj) && Gia_ObjFanoutNum(iObj) == 0 )
continue;
tArrival = Gia_ObjComputeArrival( p, iObj, 1 );
tRequired = Gia_ObjComputeRequired( p, iObj, 1 );
if ( !Gia_LutTimeEqual( tArrival, Gia_ObjTimeArrival( p, iObj), (float)0.01 ) )
printf( "Gia_LutVerifyTiming(): Object %d has different arrival time (%.2f) from computed (%.2f).\n",
iObj->Id, Gia_ObjTimeArrival( p, iObj), tArrival );
if ( !Gia_LutTimeEqual( tRequired, Gia_ObjTimeRequired( p, iObj), (float)0.01 ) )
printf( "Gia_LutVerifyTiming(): Object %d has different required time (%.2f) from computed (%.2f).\n",
iObj->Id, Gia_ObjTimeRequired( p, iObj), tRequired );
}
return 1;
}
#endif
/**Function*************************************************************
Synopsis [Prints the delay trace for the given network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float Gia_ManDelayTraceLutPrint( Gia_Man_t * p, int fVerbose )
{
If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib;
int i, Nodes, * pCounters;
float tArrival, tDelta, nSteps, Num;
// get the library
if ( pLutLib && pLutLib->LutMax < Gia_ManLutSizeMax(p) )
{
printf( "The max LUT size (%d) is less than the max fanin count (%d).\n",
pLutLib->LutMax, Gia_ManLutSizeMax(p) );
return -ABC_INFINITY;
}
// decide how many steps
nSteps = pLutLib ? 20 : Gia_ManLutLevel(p, NULL);
pCounters = ABC_ALLOC( int, nSteps + 1 );
memset( pCounters, 0, sizeof(int)*(nSteps + 1) );
// perform delay trace
tArrival = Gia_ManDelayTraceLut( p );
tDelta = tArrival / nSteps;
// count how many nodes have slack in the corresponding intervals
Gia_ManForEachLut( p, i )
{
if ( Gia_ObjLutSize(p, i) == 0 )
continue;
Num = Gia_ObjTimeSlack(p, i) / tDelta;
if ( Num > nSteps )
continue;
assert( Num >=0 && Num <= nSteps );
pCounters[(int)Num]++;
}
// print the results
if ( fVerbose )
{
printf( "Max delay = %6.2f. Delay trace using %s model:\n", tArrival, pLutLib? "LUT library" : "unit-delay" );
Nodes = 0;
for ( i = 0; i < nSteps; i++ )
{
Nodes += pCounters[i];
printf( "%3d %s : %5d (%6.2f %%)\n", pLutLib? 5*(i+1) : i+1,
pLutLib? "%":"lev", Nodes, 100.0*Nodes/Gia_ManLutNum(p) );
}
}
ABC_FREE( pCounters );
Gia_ManTimeStop( p );
return tArrival;
}
/**Function*************************************************************
Synopsis [Determines timing-critical edges of the node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
unsigned Gia_LutDelayTraceTCEdges( Gia_Man_t * p, int iObj, float tDelta )
{
If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib;
int pPinPerm[32];
float pPinDelays[32];
float tRequired, * pDelays;
unsigned uResult = 0;
int k, iFanin;
tRequired = Gia_ObjTimeRequired( p, iObj );
if ( pLutLib == NULL )
{
Gia_LutForEachFanin( p, iObj, iFanin, k )
if ( tRequired < Gia_ObjTimeArrival(p, iFanin) + 1.0 + tDelta )
uResult |= (1 << k);
}
else if ( !pLutLib->fVarPinDelays )
{
pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)];
Gia_LutForEachFanin( p, iObj, iFanin, k )
if ( tRequired < Gia_ObjTimeArrival(p, iFanin) + pDelays[0] + tDelta )
uResult |= (1 << k);
}
else
{
pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)];
Gia_LutDelayTraceSortPins( p, iObj, pPinPerm, pPinDelays );
Gia_LutForEachFanin( p, iObj, iFanin, k )
if ( tRequired < Gia_ObjTimeArrival( p, Gia_ObjLutFanin(p, iObj,pPinPerm[k])) + pDelays[k] + tDelta )
uResult |= (1 << pPinPerm[k]);
}
return uResult;
}
/**Function*************************************************************
Synopsis [Adds strashed nodes for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManSpeedupObj_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
{
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
return 1;
Gia_ObjSetTravIdCurrent( p, pObj );
if ( Gia_ObjIsCi(pObj) )
return 0;
assert( Gia_ObjIsAnd(pObj) );
if ( !Gia_ManSpeedupObj_rec( p, Gia_ObjFanin0(pObj), vNodes ) )
return 0;
if ( !Gia_ManSpeedupObj_rec( p, Gia_ObjFanin1(pObj), vNodes ) )
return 0;
Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
return 1;
}
/**Function*************************************************************
Synopsis [Adds strashed nodes for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSpeedupObj( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Int_t * vTimes )
{
Vec_Int_t * vNodes;
Gia_Obj_t * pTemp = NULL;
int pCofs[32], nCofs, nSkip, i, k, iResult, iObj;
// mark the leaves
Gia_ManIncrementTravId( p );
Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
Gia_ManForEachObjVec( vLeaves, p, pTemp, i )
Gia_ObjSetTravIdCurrent( p, pTemp );
// collect the AIG nodes
vNodes = Vec_IntAlloc( 100 );
if ( !Gia_ManSpeedupObj_rec( p, pObj, vNodes ) )
{
printf( "Bad node!!!\n" );
Vec_IntFree( vNodes );
return;
}
// derive cofactors
nCofs = (1 << Vec_IntSize(vTimes));
for ( i = 0; i < nCofs; i++ )
{
Gia_ManForEachObjVec( vLeaves, p, pTemp, k )
pTemp->Value = Abc_Var2Lit( Gia_ObjId(p, pTemp), 0 );
Gia_ManForEachObjVec( vTimes, p, pTemp, k )
pTemp->Value = ((i & (1<<k)) != 0);
Gia_ManForEachObjVec( vNodes, p, pTemp, k )
pTemp->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pTemp), Gia_ObjFanin1Copy(pTemp) );
pCofs[i] = pTemp->Value;
}
Vec_IntFree( vNodes );
// collect the resulting tree
Gia_ManForEachObjVec( vTimes, p, pTemp, k )
for ( nSkip = (1<<k), i = 0; i < nCofs; i += 2*nSkip )
pCofs[i] = Gia_ManHashMux( pNew, Gia_ObjToLit(p,pTemp), pCofs[i+nSkip], pCofs[i] );
// create choice node (pObj is repr and ppCofs[0] is new)
iObj = Gia_ObjId( p, pObj );
iResult = Abc_Lit2Var( pCofs[0] );
if ( iResult <= iObj )
return;
Gia_ObjSetRepr( pNew, iResult, iObj );
Gia_ObjSetNext( pNew, iResult, Gia_ObjNext(pNew, iObj) );
Gia_ObjSetNext( pNew, iObj, iResult );
}
/**Function*************************************************************
Synopsis [Adds choices to speed up the network by the given percentage.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManSpeedup( Gia_Man_t * p, int Percentage, int Degree, int fVerbose, int fVeryVerbose )
{
Gia_Man_t * pNew, * pTemp;
Vec_Int_t * vTimeCries, * vTimeFanins;
int iObj, iFanin, iFanin2, nNodesNew;
float tDelta, tArrival;
int i, k, k2, Counter, CounterRes, nTimeCris;
int fUseLutLib = (p->pLutLib != NULL);
void * pTempTim = NULL;
unsigned * puTCEdges;
assert( Gia_ManHasMapping(p) );
if ( !fUseLutLib && p->pManTime )
{
pTempTim = p->pManTime;
p->pManTime = Tim_ManDup( (Tim_Man_t *)pTempTim, 1 );
}
// perform delay trace
tArrival = Gia_ManDelayTraceLut( p );
tDelta = fUseLutLib ? tArrival*Percentage/100.0 : 1.0;
if ( fVerbose )
{
printf( "Max delay = %.2f. Delta = %.2f. ", tArrival, tDelta );
printf( "Using %s model. ", fUseLutLib ? "LUT library" : "unit-delay" );
if ( fUseLutLib )
printf( "Percentage = %d. ", Percentage );
printf( "\n" );
}
// mark the timing critical nodes and edges
puTCEdges = ABC_CALLOC( unsigned, Gia_ManObjNum(p) );
Gia_ManForEachLut( p, iObj )
{
if ( Gia_ObjTimeSlack(p, iObj) >= tDelta )
continue;
puTCEdges[iObj] = Gia_LutDelayTraceTCEdges( p, iObj, tDelta );
}
if ( fVerbose )
{
Counter = CounterRes = 0;
Gia_ManForEachLut( p, iObj )
{
Gia_LutForEachFanin( p, iObj, iFanin, k )
if ( !Gia_ObjIsCi(Gia_ManObj(p, iFanin)) && Gia_ObjTimeSlack(p, iFanin) < tDelta )
Counter++;
CounterRes += Gia_WordCountOnes( puTCEdges[iObj] );
}
printf( "Edges: Total = %7d. 0-slack = %7d. Critical = %7d. Ratio = %4.2f\n",
Gia_ManLutFaninCount(p), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 );
}
// start the resulting network
pNew = Gia_ManDup( p );
Gia_ManHashStart( pNew );
nNodesNew = 1000 + 3 * Gia_ManObjNum(pNew);
pNew->pNexts = ABC_CALLOC( int, nNodesNew );
pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, nNodesNew );
for ( i = 0; i < nNodesNew; i++ )
Gia_ObjSetRepr( pNew, i, GIA_VOID );
// collect nodes to be used for resynthesis
Counter = CounterRes = 0;
vTimeCries = Vec_IntAlloc( 16 );
vTimeFanins = Vec_IntAlloc( 16 );
Gia_ManForEachLut( p, iObj )
{
if ( Gia_ObjTimeSlack(p, iObj) >= tDelta )
continue;
// count the number of non-PI timing-critical nodes
nTimeCris = 0;
Gia_LutForEachFanin( p, iObj, iFanin, k )
if ( !Gia_ObjIsCi(Gia_ManObj(p, iFanin)) && (puTCEdges[iObj] & (1<<k)) )
nTimeCris++;
if ( !fVeryVerbose && nTimeCris == 0 )
continue;
Counter++;
// count the total number of timing critical second-generation nodes
Vec_IntClear( vTimeCries );
if ( nTimeCris )
{
Gia_LutForEachFanin( p, iObj, iFanin, k )
if ( !Gia_ObjIsCi(Gia_ManObj(p, iFanin)) && (puTCEdges[iObj] & (1<<k)) )
Gia_LutForEachFanin( p, iFanin, iFanin2, k2 )
if ( puTCEdges[iFanin] & (1<<k2) )
Vec_IntPushUnique( vTimeCries, iFanin2 );
}
// if ( !fVeryVerbose && (Vec_IntSize(vTimeCries) == 0 || Vec_IntSize(vTimeCries) > Degree) )
if ( (Vec_IntSize(vTimeCries) == 0 || Vec_IntSize(vTimeCries) > Degree) )
continue;
CounterRes++;
// collect second generation nodes
Vec_IntClear( vTimeFanins );
Gia_LutForEachFanin( p, iObj, iFanin, k )
{
if ( Gia_ObjIsCi(Gia_ManObj(p, iFanin)) )
Vec_IntPushUnique( vTimeFanins, iFanin );
else
Gia_LutForEachFanin( p, iFanin, iFanin2, k2 )
Vec_IntPushUnique( vTimeFanins, iFanin2 );
}
// print the results
if ( fVeryVerbose )
{
printf( "%5d Node %5d : %d %2d %2d ", Counter, iObj,
nTimeCris, Vec_IntSize(vTimeCries), Vec_IntSize(vTimeFanins) );
Gia_LutForEachFanin( p, iObj, iFanin, k )
printf( "%d(%.2f)%s ", iFanin, Gia_ObjTimeSlack(p, iFanin), (puTCEdges[iObj] & (1<<k))? "*":"" );
printf( "\n" );
}
// add the node to choices
if ( Vec_IntSize(vTimeCries) == 0 || Vec_IntSize(vTimeCries) > Degree )
continue;
// order the fanins in the increasing order of criticalily
if ( Vec_IntSize(vTimeCries) > 1 )
{
iFanin = Vec_IntEntry( vTimeCries, 0 );
iFanin2 = Vec_IntEntry( vTimeCries, 1 );
if ( Gia_ObjTimeSlack(p, iFanin) < Gia_ObjTimeSlack(p, iFanin2) )
{
Vec_IntWriteEntry( vTimeCries, 0, iFanin2 );
Vec_IntWriteEntry( vTimeCries, 1, iFanin );
}
}
if ( Vec_IntSize(vTimeCries) > 2 )
{
iFanin = Vec_IntEntry( vTimeCries, 1 );
iFanin2 = Vec_IntEntry( vTimeCries, 2 );
if ( Gia_ObjTimeSlack(p, iFanin) < Gia_ObjTimeSlack(p, iFanin2) )
{
Vec_IntWriteEntry( vTimeCries, 1, iFanin2 );
Vec_IntWriteEntry( vTimeCries, 2, iFanin );
}
iFanin = Vec_IntEntry( vTimeCries, 0 );
iFanin2 = Vec_IntEntry( vTimeCries, 1 );
if ( Gia_ObjTimeSlack(p, iFanin) < Gia_ObjTimeSlack(p, iFanin2) )
{
Vec_IntWriteEntry( vTimeCries, 0, iFanin2 );
Vec_IntWriteEntry( vTimeCries, 1, iFanin );
}
}
// add choice
Gia_ManSpeedupObj( pNew, p, Gia_ManObj(p,iObj), vTimeFanins, vTimeCries );
// quit if the number of nodes is large
if ( Gia_ManObjNum(pNew) > nNodesNew - 100 )
{
printf( "Speedup stopped adding choices because there was too many to add.\n" );
break;
}
}
Gia_ManTimeStop( p );
Vec_IntFree( vTimeCries );
Vec_IntFree( vTimeFanins );
ABC_FREE( puTCEdges );
if ( fVerbose )
printf( "Nodes: Total = %7d. 0-slack = %7d. Workable = %7d. Ratio = %4.2f\n",
Gia_ManLutNum(p), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 );
if ( pTempTim )
{
Tim_ManStop( (Tim_Man_t *)p->pManTime );
p->pManTime = pTempTim;
}
// derive AIG with choices
//Gia_ManPrintStats( pNew, 0 );
pTemp = Gia_ManEquivToChoices( pNew, 1 );
Gia_ManStop( pNew );
//Gia_ManPrintStats( pTemp, 0 );
// pNew = Gia_ManDupOrderDfsChoices( pTemp );
// Gia_ManStop( pTemp );
//Gia_ManPrintStats( pNew, 0 );
// return pNew;
return pTemp;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END