diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2007-10-01 08:01:00 -0700 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2007-10-01 08:01:00 -0700 |
commit | 4812c90424dfc40d26725244723887a2d16ddfd9 (patch) | |
tree | b32ace96e7e2d84d586e09ba605463b6f49c3271 /src/base/abci/abcTiming.c | |
parent | e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7 (diff) | |
download | abc-4812c90424dfc40d26725244723887a2d16ddfd9.tar.gz abc-4812c90424dfc40d26725244723887a2d16ddfd9.tar.bz2 abc-4812c90424dfc40d26725244723887a2d16ddfd9.zip |
Version abc71001
Diffstat (limited to 'src/base/abci/abcTiming.c')
-rw-r--r-- | src/base/abci/abcTiming.c | 905 |
1 files changed, 905 insertions, 0 deletions
diff --git a/src/base/abci/abcTiming.c b/src/base/abci/abcTiming.c new file mode 100644 index 00000000..967e4617 --- /dev/null +++ b/src/base/abci/abcTiming.c @@ -0,0 +1,905 @@ +/**CFile**************************************************************** + + FileName [abcTiming.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Computation of timing info for mapped circuits.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcTiming.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Abc_ManTime_t_ +{ + Abc_Time_t tArrDef; + Abc_Time_t tReqDef; + Vec_Ptr_t * vArrs; + Vec_Ptr_t * vReqs; +}; + +// static functions +static Abc_ManTime_t * Abc_ManTimeStart(); +static void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive ); +void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk ); + +void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode ); + +// accessing the arrival and required times of a node +static inline Abc_Time_t * Abc_NodeArrival( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vArrs->pArray[pNode->Id]; } +static inline Abc_Time_t * Abc_NodeRequired( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vReqs->pArray[pNode->Id]; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the arrival time of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode ) +{ + assert( pNode->pNtk->pManTime ); + return Abc_NodeArrival(pNode); +} + +/**Function************************************************************* + + Synopsis [Reads the arrival time of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode ) +{ + assert( pNode->pNtk->pManTime ); + return Abc_NodeRequired(pNode); +} + +/**Function************************************************************* + + Synopsis [Reads the arrival time of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk ) +{ + assert( pNtk->pManTime ); + return &pNtk->pManTime->tArrDef; +} + +/**Function************************************************************* + + Synopsis [Reads the arrival time of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk ) +{ + assert( pNtk->pManTime ); + return &pNtk->pManTime->tReqDef; +} + +/**Function************************************************************* + + Synopsis [Sets the default arrival time for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall ) +{ + if ( Rise == 0.0 && Fall == 0.0 ) + return; + if ( pNtk->pManTime == NULL ) + pNtk->pManTime = Abc_ManTimeStart(); + pNtk->pManTime->tArrDef.Rise = Rise; + pNtk->pManTime->tArrDef.Fall = Fall; + pNtk->pManTime->tArrDef.Worst = ABC_MAX( Rise, Fall ); +} + +/**Function************************************************************* + + Synopsis [Sets the default arrival time for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall ) +{ + if ( Rise == 0.0 && Fall == 0.0 ) + return; + if ( pNtk->pManTime == NULL ) + pNtk->pManTime = Abc_ManTimeStart(); + pNtk->pManTime->tReqDef.Rise = Rise; + pNtk->pManTime->tReqDef.Rise = Fall; + pNtk->pManTime->tReqDef.Worst = ABC_MAX( Rise, Fall ); +} + +/**Function************************************************************* + + Synopsis [Sets the arrival time for an object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ) +{ + Vec_Ptr_t * vTimes; + Abc_Time_t * pTime; + if ( pNtk->pManTime == NULL ) + pNtk->pManTime = Abc_ManTimeStart(); + if ( pNtk->pManTime->tArrDef.Rise == Rise && pNtk->pManTime->tArrDef.Fall == Fall ) + return; + Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 ); + // set the arrival time + vTimes = pNtk->pManTime->vArrs; + pTime = vTimes->pArray[ObjId]; + pTime->Rise = Rise; + pTime->Fall = Rise; + pTime->Worst = ABC_MAX( Rise, Fall ); +} + +/**Function************************************************************* + + Synopsis [Sets the arrival time for an object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ) +{ + Vec_Ptr_t * vTimes; + Abc_Time_t * pTime; + if ( pNtk->pManTime == NULL ) + pNtk->pManTime = Abc_ManTimeStart(); + if ( pNtk->pManTime->tReqDef.Rise == Rise && pNtk->pManTime->tReqDef.Fall == Fall ) + return; + Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 ); + // set the required time + vTimes = pNtk->pManTime->vReqs; + pTime = vTimes->pArray[ObjId]; + pTime->Rise = Rise; + pTime->Fall = Rise; + pTime->Worst = ABC_MAX( Rise, Fall ); +} + +/**Function************************************************************* + + Synopsis [Finalizes the timing manager after setting arr/req times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + Abc_Time_t ** ppTimes, * pTime; + int i; + if ( pNtk->pManTime == NULL ) + return; + Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 ); + // set the default timing + ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; + Abc_NtkForEachPi( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + if ( pTime->Worst != -ABC_INFINITY ) + continue; + *pTime = pNtk->pManTime->tArrDef; + } + // set the default timing + ppTimes = (Abc_Time_t **)pNtk->pManTime->vReqs->pArray; + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + if ( pTime->Worst != -ABC_INFINITY ) + continue; + *pTime = pNtk->pManTime->tReqDef; + } + // set the 0 arrival times for latch outputs and constant nodes + ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; + Abc_NtkForEachLatchOutput( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + pTime->Fall = pTime->Rise = pTime->Worst = 0.0; + } +} + +/**Function************************************************************* + + Synopsis [Prepares the timing manager for delay trace.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + Abc_Time_t ** ppTimes, * pTime; + int i; + // if there is no timing manager, allocate and initialize + if ( pNtk->pManTime == NULL ) + { + pNtk->pManTime = Abc_ManTimeStart(); + Abc_NtkTimeInitialize( pNtk ); + return; + } + // if timing manager is given, expand it if necessary + Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 ); + // clean arrivals except for PIs + ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY; + } + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY; + } + // clean required except for POs +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ManTime_t * Abc_ManTimeStart() +{ + Abc_ManTime_t * p; + p = ALLOC( Abc_ManTime_t, 1 ); + memset( p, 0, sizeof(Abc_ManTime_t) ); + p->vArrs = Vec_PtrAlloc( 0 ); + p->vReqs = Vec_PtrAlloc( 0 ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManTimeStop( Abc_ManTime_t * p ) +{ + if ( p->vArrs->nSize > 0 ) + { + free( p->vArrs->pArray[0] ); + Vec_PtrFree( p->vArrs ); + } + if ( p->vReqs->nSize > 0 ) + { + free( p->vReqs->pArray[0] ); + Vec_PtrFree( p->vReqs ); + } + free( p ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the timing manager with the PI/PO timing info.] + + Description [The PIs/POs of the new network should be allocated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj; + Abc_Time_t ** ppTimesOld, ** ppTimesNew; + int i; + if ( pNtkOld->pManTime == NULL ) + return; + assert( Abc_NtkPiNum(pNtkOld) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtkOld) == Abc_NtkPoNum(pNtkNew) ); + assert( Abc_NtkLatchNum(pNtkOld) == Abc_NtkLatchNum(pNtkNew) ); + // create the new timing manager + pNtkNew->pManTime = Abc_ManTimeStart(); + Abc_ManTimeExpand( pNtkNew->pManTime, Abc_NtkObjNumMax(pNtkNew), 0 ); + // set the default timing + pNtkNew->pManTime->tArrDef = pNtkOld->pManTime->tArrDef; + pNtkNew->pManTime->tReqDef = pNtkOld->pManTime->tReqDef; + // set the CI timing + ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vArrs->pArray; + ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vArrs->pArray; + Abc_NtkForEachCi( pNtkOld, pObj, i ) + *ppTimesNew[ Abc_NtkCi(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ]; + // set the CO timing + ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vReqs->pArray; + ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vReqs->pArray; + Abc_NtkForEachCo( pNtkOld, pObj, i ) + *ppTimesNew[ Abc_NtkCo(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ]; +} + +/**Function************************************************************* + + Synopsis [Expends the storage for timing information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive ) +{ + Vec_Ptr_t * vTimes; + Abc_Time_t * ppTimes, * ppTimesOld, * pTime; + int nSizeOld, nSizeNew, i; + + nSizeOld = p->vArrs->nSize; + if ( nSizeOld >= nSize ) + return; + nSizeNew = fProgressive? 2 * nSize : nSize; + if ( nSizeNew < 100 ) + nSizeNew = 100; + + vTimes = p->vArrs; + Vec_PtrGrow( vTimes, nSizeNew ); + vTimes->nSize = nSizeNew; + ppTimesOld = ( nSizeOld == 0 )? NULL : vTimes->pArray[0]; + ppTimes = REALLOC( Abc_Time_t, ppTimesOld, nSizeNew ); + for ( i = 0; i < nSizeNew; i++ ) + vTimes->pArray[i] = ppTimes + i; + for ( i = nSizeOld; i < nSizeNew; i++ ) + { + pTime = vTimes->pArray[i]; + pTime->Rise = -ABC_INFINITY; + pTime->Fall = -ABC_INFINITY; + pTime->Worst = -ABC_INFINITY; + } + + vTimes = p->vReqs; + Vec_PtrGrow( vTimes, nSizeNew ); + vTimes->nSize = nSizeNew; + ppTimesOld = ( nSizeOld == 0 )? NULL : vTimes->pArray[0]; + ppTimes = REALLOC( Abc_Time_t, ppTimesOld, nSizeNew ); + for ( i = 0; i < nSizeNew; i++ ) + vTimes->pArray[i] = ppTimes + i; + for ( i = nSizeOld; i < nSizeNew; i++ ) + { + pTime = vTimes->pArray[i]; + pTime->Rise = -ABC_INFINITY; + pTime->Fall = -ABC_INFINITY; + pTime->Worst = -ABC_INFINITY; + } +} + + + + + + +/**Function************************************************************* + + Synopsis [Sets the CI node levels according to the arrival info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtkOld ) +{ + Abc_Obj_t * pNodeOld, * pNodeNew; + float tAndDelay; + int i; + if ( pNtkOld->pManTime == NULL ) + return; + if ( Mio_LibraryReadNand2(Abc_FrameReadLibGen()) == NULL ) + return; + tAndDelay = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen()); + Abc_NtkForEachPi( pNtkOld, pNodeOld, i ) + { + pNodeNew = pNodeOld->pCopy; + pNodeNew->Level = (int)(Abc_NodeArrival(pNodeOld)->Worst / tAndDelay); + } +} + +/**Function************************************************************* + + Synopsis [Sets the CI node levels according to the arrival info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk ) +{ + Abc_Time_t * p; + Abc_Obj_t * pNode; + int i; + p = ALLOC( Abc_Time_t, Abc_NtkCiNum(pNtk) ); + memset( p, 0, sizeof(Abc_Time_t) * Abc_NtkCiNum(pNtk) ); + if ( pNtk->pManTime == NULL ) + return p; + // set the PI arrival times + Abc_NtkForEachPi( pNtk, pNode, i ) + p[i] = *Abc_NodeArrival(pNode); + return p; +} + + +/**Function************************************************************* + + Synopsis [Sets the CI node levels according to the arrival info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk ) +{ + float * p; + Abc_Obj_t * pNode; + int i; + p = ALLOC( float, Abc_NtkCiNum(pNtk) ); + memset( p, 0, sizeof(float) * Abc_NtkCiNum(pNtk) ); + if ( pNtk->pManTime == NULL ) + return p; + // set the PI arrival times + Abc_NtkForEachPi( pNtk, pNode, i ) + p[i] = Abc_NodeArrival(pNode)->Worst; + return p; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pDriver; + Vec_Ptr_t * vNodes; + Abc_Time_t * pTime; + float tArrivalMax; + int i; + + assert( Abc_NtkIsMappedLogic(pNtk) ); + + Abc_NtkTimePrepare( pNtk ); + vNodes = Abc_NtkDfs( pNtk, 1 ); + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_NodeDelayTraceArrival( vNodes->pArray[i] ); + Vec_PtrFree( vNodes ); + + // get the latest arrival times + tArrivalMax = -ABC_INFINITY; + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pDriver = Abc_ObjFanin0(pNode); + pTime = Abc_NodeArrival(pDriver); + if ( tArrivalMax < pTime->Worst ) + tArrivalMax = pTime->Worst; + } + return tArrivalMax; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + Abc_Time_t * pTimeIn, * pTimeOut; + float tDelayBlockRise, tDelayBlockFall; + Mio_PinPhase_t PinPhase; + Mio_Pin_t * pPin; + int i; + + // start the arrival time of the node + pTimeOut = Abc_NodeArrival(pNode); + pTimeOut->Rise = pTimeOut->Fall = -ABC_INFINITY; + // go through the pins of the gate + pPin = Mio_GateReadPins(pNode->pData); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + pTimeIn = Abc_NodeArrival(pFanin); + // get the interesting parameters of this pin + PinPhase = Mio_PinReadPhase(pPin); + tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); + tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin ); + // compute the arrival times of the positive phase + if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present + { + if ( pTimeOut->Rise < pTimeIn->Rise + tDelayBlockRise ) + pTimeOut->Rise = pTimeIn->Rise + tDelayBlockRise; + if ( pTimeOut->Fall < pTimeIn->Fall + tDelayBlockFall ) + pTimeOut->Fall = pTimeIn->Fall + tDelayBlockFall; + } + if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present + { + if ( pTimeOut->Rise < pTimeIn->Fall + tDelayBlockRise ) + pTimeOut->Rise = pTimeIn->Fall + tDelayBlockRise; + if ( pTimeOut->Fall < pTimeIn->Rise + tDelayBlockFall ) + pTimeOut->Fall = pTimeIn->Rise + tDelayBlockFall; + } + pPin = Mio_PinReadNext(pPin); + } + pTimeOut->Worst = ABC_MAX( pTimeOut->Rise, pTimeOut->Fall ); +} + + + + +/**Function************************************************************* + + Synopsis [Computes the level of the node using its fanin levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjLevelNew( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i, Level = 0; + Abc_ObjForEachFanin( pObj, pFanin, i ) + Level = ABC_MAX( Level, Abc_ObjLevel(pFanin) ); + return Level + 1; +} + +/**Function************************************************************* + + Synopsis [Computes the reverse level of the node using its fanout levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i, LevelCur, Level = 0; + Abc_ObjForEachFanout( pObj, pFanout, i ) + { + LevelCur = Abc_ObjReverseLevel( pFanout ); + Level = ABC_MAX( Level, LevelCur ); + } + return Level + 1; +} + +/**Function************************************************************* + + Synopsis [Returns required level of the node.] + + Description [Converts the reverse levels of the node into its required + level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjRequiredLevel( Abc_Obj_t * pObj ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + assert( pNtk->vLevelsR ); + return pNtk->LevelMax + 1 - Abc_ObjReverseLevel(pObj); +} + +/**Function************************************************************* + + Synopsis [Returns the reverse level of the node.] + + Description [The reverse level is the level of the node in reverse + topological order, starting from the COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjReverseLevel( Abc_Obj_t * pObj ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + assert( pNtk->vLevelsR ); + Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 ); + return Vec_IntEntry(pNtk->vLevelsR, pObj->Id); +} + +/**Function************************************************************* + + Synopsis [Sets the reverse level of the node.] + + Description [The reverse level is the level of the node in reverse + topological order, starting from the COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + assert( pNtk->vLevelsR ); + Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 ); + Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, LevelR ); +} + +/**Function************************************************************* + + Synopsis [Prepares for the computation of required levels.] + + Description [This procedure should be called before the required times + are used. It starts internal data structures, which records the level + from the COs of the network nodes in reverse topologogical order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + // remember the maximum number of direct levels + pNtk->LevelMax = Abc_NtkLevel(pNtk) + nMaxLevelIncrease; + // start the reverse levels + pNtk->vLevelsR = Vec_IntAlloc( 0 ); + Vec_IntFill( pNtk->vLevelsR, 1 + Abc_NtkObjNumMax(pNtk), 0 ); + // compute levels in reverse topological order + vNodes = Abc_NtkDfsReverse( pNtk ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + Abc_ObjSetReverseLevel( pObj, Abc_ObjReverseLevelNew(pObj) ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Cleans the data structures used to compute required levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk ) +{ + assert( pNtk->vLevelsR ); + Vec_IntFree( pNtk->vLevelsR ); + pNtk->vLevelsR = NULL; + pNtk->LevelMax = 0; + +} + +/**Function************************************************************* + + Synopsis [Incrementally updates level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) +{ + Abc_Obj_t * pFanout, * pTemp; + int LevelOld, Lev, k, m; + // check if level has changed + LevelOld = Abc_ObjLevel(pObjNew); + if ( LevelOld == Abc_ObjLevelNew(pObjNew) ) + return; + // start the data structure for level update + // we cannot fail to visit a node when using this structure because the + // nodes are stored by their _old_ levels, which are assumed to be correct + Vec_VecClear( vLevels ); + Vec_VecPush( vLevels, LevelOld, pObjNew ); + pObjNew->fMarkA = 1; + // recursively update level + Vec_VecForEachEntryStart( vLevels, pTemp, Lev, k, LevelOld ) + { + pTemp->fMarkA = 0; + assert( Abc_ObjLevel(pTemp) == Lev ); + Abc_ObjSetLevel( pTemp, Abc_ObjLevelNew(pTemp) ); + // if the level did not change, no need to check the fanout levels + if ( Abc_ObjLevel(pTemp) == Lev ) + continue; + // schedule fanout for level update + Abc_ObjForEachFanout( pTemp, pFanout, m ) + { + if ( !Abc_ObjIsCo(pFanout) && !pFanout->fMarkA ) + { + assert( Abc_ObjLevel(pFanout) >= Lev ); + Vec_VecPush( vLevels, Abc_ObjLevel(pFanout), pFanout ); + pFanout->fMarkA = 1; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Incrementally updates level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) +{ + Abc_Obj_t * pFanin, * pTemp; + int LevelOld, LevFanin, Lev, k, m; + // check if level has changed + LevelOld = Abc_ObjReverseLevel(pObjNew); + if ( LevelOld == Abc_ObjReverseLevelNew(pObjNew) ) + return; + // start the data structure for level update + // we cannot fail to visit a node when using this structure because the + // nodes are stored by their _old_ levels, which are assumed to be correct + Vec_VecClear( vLevels ); + Vec_VecPush( vLevels, LevelOld, pObjNew ); + pObjNew->fMarkA = 1; + // recursively update level + Vec_VecForEachEntryStart( vLevels, pTemp, Lev, k, LevelOld ) + { + pTemp->fMarkA = 0; + LevelOld = Abc_ObjReverseLevel(pTemp); + assert( LevelOld == Lev ); + Abc_ObjSetReverseLevel( pTemp, Abc_ObjReverseLevelNew(pTemp) ); + // if the level did not change, no need to check the fanout levels + if ( Abc_ObjReverseLevel(pTemp) == Lev ) + continue; + // schedule fanins for level update + Abc_ObjForEachFanin( pTemp, pFanin, m ) + { + if ( !Abc_ObjIsCi(pFanin) && !pFanin->fMarkA ) + { + LevFanin = Abc_ObjReverseLevel( pFanin ); + assert( LevFanin >= Lev ); + Vec_VecPush( vLevels, LevFanin, pFanin ); + pFanin->fMarkA = 1; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Replaces the node and incrementally updates levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) +{ + // replace the old node by the new node + pObjNew->Level = pObj->Level; + Abc_ObjReplace( pObj, pObjNew ); + // update the level of the node + Abc_NtkUpdateLevel( pObjNew, vLevels ); + Abc_ObjSetReverseLevel( pObjNew, 0 ); + Abc_NtkUpdateReverseLevel( pObjNew, vLevels ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + |