abc/src/base/abci/abcTiming.c

1322 lines
43 KiB
C
Raw Normal View History

2005-07-29 17:01:00 +02:00
/**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 "base/abc/abc.h"
#include "base/main/main.h"
#include "map/mio/mio.h"
2005-07-29 17:01:00 +02:00
2010-11-01 09:35:04 +01:00
ABC_NAMESPACE_IMPL_START
2005-07-29 17:01:00 +02:00
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
struct Abc_ManTime_t_
{
Abc_Time_t tArrDef;
Abc_Time_t tReqDef;
Vec_Ptr_t * vArrs;
Vec_Ptr_t * vReqs;
Abc_Time_t tInDriveDef;
Abc_Time_t tOutLoadDef;
Abc_Time_t * tInDrive;
Abc_Time_t * tOutLoad;
2005-07-29 17:01:00 +02:00
};
// static functions
static Abc_ManTime_t * Abc_ManTimeStart( Abc_Ntk_t * pNtk );
2005-07-29 17:01:00 +02:00
static void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive );
// accessing the arrival and required times of a node
2010-11-01 09:35:04 +01:00
static inline Abc_Time_t * Abc_NodeArrival( Abc_Obj_t * pNode ) { return (Abc_Time_t *)pNode->pNtk->pManTime->vArrs->pArray[pNode->Id]; }
static inline Abc_Time_t * Abc_NodeRequired( Abc_Obj_t * pNode ) { return (Abc_Time_t *)pNode->pNtk->pManTime->vReqs->pArray[pNode->Id]; }
2005-07-29 17:01:00 +02:00
////////////////////////////////////////////////////////////////////////
2008-01-31 05:01:00 +01:00
/// FUNCTION DEFINITIONS ///
2005-07-29 17:01:00 +02:00
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Reads the arrival.required time of the node.]
2005-07-29 17:01:00 +02:00
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk )
{
assert( pNtk->pManTime );
return &pNtk->pManTime->tArrDef;
}
Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk )
{
assert( pNtk->pManTime );
return &pNtk->pManTime->tReqDef;
}
2005-07-29 17:01:00 +02:00
Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode )
{
assert( pNode->pNtk->pManTime );
return Abc_NodeArrival(pNode);
}
Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode )
{
assert( pNode->pNtk->pManTime );
return Abc_NodeRequired(pNode);
}
float Abc_NodeReadArrivalAve( Abc_Obj_t * pNode )
{
return 0.5 * Abc_NodeArrival(pNode)->Rise + 0.5 * Abc_NodeArrival(pNode)->Fall;
}
float Abc_NodeReadRequiredAve( Abc_Obj_t * pNode )
{
return 0.5 * Abc_NodeReadRequired(pNode)->Rise + 0.5 * Abc_NodeReadRequired(pNode)->Fall;
}
float Abc_NodeReadArrivalWorst( Abc_Obj_t * pNode )
{
return Abc_MaxFloat( Abc_NodeArrival(pNode)->Rise, Abc_NodeArrival(pNode)->Fall );
}
float Abc_NodeReadRequiredWorst( Abc_Obj_t * pNode )
{
return Abc_MaxFloat( Abc_NodeReadRequired(pNode)->Rise, Abc_NodeReadRequired(pNode)->Fall );
}
2005-07-29 17:01:00 +02:00
/**Function*************************************************************
Synopsis [Reads the input drive / output load of the node.]
2005-07-29 17:01:00 +02:00
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Time_t * Abc_NtkReadDefaultInputDrive( Abc_Ntk_t * pNtk )
2005-07-29 17:01:00 +02:00
{
assert( pNtk->pManTime );
return &pNtk->pManTime->tInDriveDef;
2005-07-29 17:01:00 +02:00
}
Abc_Time_t * Abc_NtkReadDefaultOutputLoad( Abc_Ntk_t * pNtk )
2005-07-29 17:01:00 +02:00
{
assert( pNtk->pManTime );
return &pNtk->pManTime->tOutLoadDef;
2005-07-29 17:01:00 +02:00
}
Abc_Time_t * Abc_NodeReadInputDrive( Abc_Ntk_t * pNtk, int iPi )
{
assert( pNtk->pManTime );
return pNtk->pManTime->tInDrive ? pNtk->pManTime->tInDrive + iPi : NULL;
}
Abc_Time_t * Abc_NodeReadOutputLoad( Abc_Ntk_t * pNtk, int iPo )
{
assert( pNtk->pManTime );
return pNtk->pManTime->tOutLoad ? pNtk->pManTime->tOutLoad + iPo : NULL;
}
float Abc_NodeReadInputDriveWorst( Abc_Ntk_t * pNtk, int iPi )
{
return Abc_MaxFloat( Abc_NodeReadInputDrive(pNtk, iPi)->Rise, Abc_NodeReadInputDrive(pNtk, iPi)->Fall );
}
float Abc_NodeReadOutputLoadWorst( Abc_Ntk_t * pNtk, int iPo )
{
return Abc_MaxFloat( Abc_NodeReadOutputLoad(pNtk, iPo)->Rise, Abc_NodeReadOutputLoad(pNtk, iPo)->Fall );
}
2005-07-29 17:01:00 +02:00
/**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);
2005-07-29 17:01:00 +02:00
pNtk->pManTime->tArrDef.Rise = Rise;
pNtk->pManTime->tArrDef.Fall = Fall;
}
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);
2005-07-29 17:01:00 +02:00
pNtk->pManTime->tReqDef.Rise = Rise;
pNtk->pManTime->tReqDef.Fall = Fall;
2005-07-29 17:01:00 +02:00
}
/**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(pNtk);
2005-07-29 17:01:00 +02:00
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;
2010-11-01 09:35:04 +01:00
pTime = (Abc_Time_t *)vTimes->pArray[ObjId];
2005-07-29 17:01:00 +02:00
pTime->Rise = Rise;
pTime->Fall = Fall;
}
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(pNtk);
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 = (Abc_Time_t *)vTimes->pArray[ObjId];
pTime->Rise = Rise;
pTime->Fall = Fall;
}
/**Function*************************************************************
Synopsis [Sets the default arrival time for the network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkTimeSetDefaultInputDrive( 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);
pNtk->pManTime->tInDriveDef.Rise = Rise;
pNtk->pManTime->tInDriveDef.Fall = Fall;
if ( pNtk->pManTime->tInDrive != NULL )
{
int i;
for ( i = 0; i < Abc_NtkCiNum(pNtk); i++ )
if ( pNtk->pManTime->tInDrive[i].Rise == 0 && pNtk->pManTime->tInDrive[i].Fall == 0 )
pNtk->pManTime->tInDrive[i] = pNtk->pManTime->tInDriveDef;
}
}
void Abc_NtkTimeSetDefaultOutputLoad( 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);
pNtk->pManTime->tOutLoadDef.Rise = Rise;
pNtk->pManTime->tOutLoadDef.Fall = Fall;
if ( pNtk->pManTime->tOutLoad != NULL )
{
int i;
for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ )
if ( pNtk->pManTime->tOutLoad[i].Rise == 0 && pNtk->pManTime->tOutLoad[i].Fall == 0 )
pNtk->pManTime->tOutLoad[i] = pNtk->pManTime->tOutLoadDef;
}
2005-07-29 17:01:00 +02:00
}
/**Function*************************************************************
Synopsis [Sets the arrival time for an object.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkTimeSetInputDrive( Abc_Ntk_t * pNtk, int PiNum, float Rise, float Fall )
2005-07-29 17:01:00 +02:00
{
Abc_Time_t * pTime;
assert( PiNum >= 0 && PiNum < Abc_NtkCiNum(pNtk) );
2005-07-29 17:01:00 +02:00
if ( pNtk->pManTime == NULL )
pNtk->pManTime = Abc_ManTimeStart(pNtk);
if ( pNtk->pManTime->tInDriveDef.Rise == Rise && pNtk->pManTime->tInDriveDef.Fall == Fall )
2005-07-29 17:01:00 +02:00
return;
if ( pNtk->pManTime->tInDrive == NULL )
{
int i;
pNtk->pManTime->tInDrive = ABC_CALLOC( Abc_Time_t, Abc_NtkCiNum(pNtk) );
for ( i = 0; i < Abc_NtkCiNum(pNtk); i++ )
pNtk->pManTime->tInDrive[i] = pNtk->pManTime->tInDriveDef;
}
pTime = pNtk->pManTime->tInDrive + PiNum;
pTime->Rise = Rise;
pTime->Fall = Fall;
}
void Abc_NtkTimeSetOutputLoad( Abc_Ntk_t * pNtk, int PoNum, float Rise, float Fall )
{
Abc_Time_t * pTime;
assert( PoNum >= 0 && PoNum < Abc_NtkCoNum(pNtk) );
if ( pNtk->pManTime == NULL )
pNtk->pManTime = Abc_ManTimeStart(pNtk);
if ( pNtk->pManTime->tOutLoadDef.Rise == Rise && pNtk->pManTime->tOutLoadDef.Fall == Fall )
return;
if ( pNtk->pManTime->tOutLoad == NULL )
{
int i;
pNtk->pManTime->tOutLoad = ABC_CALLOC( Abc_Time_t, Abc_NtkCoNum(pNtk) );
for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ )
pNtk->pManTime->tOutLoad[i] = pNtk->pManTime->tOutLoadDef;
}
pTime = pNtk->pManTime->tOutLoad + PoNum;
2005-07-29 17:01:00 +02:00
pTime->Rise = Rise;
pTime->Fall = Fall;
2005-07-29 17:01:00 +02:00
}
/**Function*************************************************************
Synopsis [Finalizes the timing manager after setting arr/req times.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkOld )
2005-07-29 17:01:00 +02:00
{
Abc_Obj_t * pObj;
Abc_Time_t ** ppTimes, * pTime;
int i;
assert( pNtkOld == NULL || pNtkOld->pManTime != NULL );
2013-07-24 01:15:03 +02:00
assert( pNtkOld == NULL || Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkOld) );
assert( pNtkOld == NULL || Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkOld) );
2005-07-29 17:01:00 +02:00
if ( pNtk->pManTime == NULL )
return;
2005-08-14 17:01:00 +02:00
Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 );
// set global defaults
if ( pNtkOld )
{
pNtk->pManTime->tArrDef = pNtkOld->pManTime->tArrDef;
pNtk->pManTime->tReqDef = pNtkOld->pManTime->tReqDef;
pNtk->AndGateDelay = pNtkOld->AndGateDelay;
}
2005-07-29 17:01:00 +02:00
// set the default timing
ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray;
2013-07-24 01:15:03 +02:00
Abc_NtkForEachCi( pNtk, pObj, i )
2005-07-29 17:01:00 +02:00
{
pTime = ppTimes[pObj->Id];
if ( Abc_MaxFloat(pTime->Fall, pTime->Rise) != -ABC_INFINITY )
2005-07-29 17:01:00 +02:00
continue;
*pTime = pNtkOld ? *Abc_NodeReadArrival(Abc_NtkCi(pNtkOld, i)) : pNtk->pManTime->tArrDef;
2005-07-29 17:01:00 +02:00
}
// set the default timing
ppTimes = (Abc_Time_t **)pNtk->pManTime->vReqs->pArray;
2013-07-24 01:15:03 +02:00
Abc_NtkForEachCo( pNtk, pObj, i )
2005-07-29 17:01:00 +02:00
{
pTime = ppTimes[pObj->Id];
2013-07-24 01:15:03 +02:00
if ( Abc_MaxFloat(pTime->Fall, pTime->Rise) != ABC_INFINITY )
2005-07-29 17:01:00 +02:00
continue;
*pTime = pNtkOld ? *Abc_NodeReadRequired(Abc_NtkCo(pNtkOld, i)) : pNtk->pManTime->tReqDef;
2005-07-29 17:01:00 +02:00
}
2008-01-31 05:01:00 +01:00
// set the 0 arrival times for latch outputs and constant nodes
2005-07-29 17:01:00 +02:00
ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray;
2008-01-31 05:01:00 +01:00
Abc_NtkForEachLatchOutput( pNtk, pObj, i )
2005-07-29 17:01:00 +02:00
{
pTime = ppTimes[pObj->Id];
pTime->Fall = pTime->Rise = 0.0;
2005-07-29 17:01:00 +02:00
}
}
/**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(pNtk);
Abc_NtkTimeInitialize( pNtk, NULL );
2005-07-29 17:01:00 +02:00
return;
}
2005-08-07 17:01:00 +02:00
// if timing manager is given, expand it if necessary
2005-08-14 17:01:00 +02:00
Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 );
2005-08-07 17:01:00 +02:00
// clean arrivals except for PIs
2005-07-29 17:01:00 +02:00
ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray;
Abc_NtkForEachNode( pNtk, pObj, i )
{
pTime = ppTimes[pObj->Id];
pTime->Fall = pTime->Rise = -ABC_INFINITY;
2005-07-29 17:01:00 +02:00
}
2013-07-24 01:15:03 +02:00
Abc_NtkForEachCo( pNtk, pObj, i )
2005-07-29 17:01:00 +02:00
{
pTime = ppTimes[pObj->Id];
pTime->Fall = pTime->Rise = -ABC_INFINITY;
2005-07-29 17:01:00 +02:00
}
2005-08-07 17:01:00 +02:00
// clean required except for POs
ppTimes = (Abc_Time_t **)pNtk->pManTime->vReqs->pArray;
Abc_NtkForEachNode( pNtk, pObj, i )
{
pTime = ppTimes[pObj->Id];
2013-07-24 01:15:03 +02:00
pTime->Fall = pTime->Rise = ABC_INFINITY;
}
2013-07-24 01:15:03 +02:00
Abc_NtkForEachCi( pNtk, pObj, i )
{
pTime = ppTimes[pObj->Id];
2013-07-24 01:15:03 +02:00
pTime->Fall = pTime->Rise = ABC_INFINITY;
}
2005-07-29 17:01:00 +02:00
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_ManTime_t * Abc_ManTimeStart( Abc_Ntk_t * pNtk )
2005-07-29 17:01:00 +02:00
{
Abc_ManTime_t * p;
2009-02-15 17:01:00 +01:00
p = ABC_ALLOC( Abc_ManTime_t, 1 );
2005-07-29 17:01:00 +02:00
memset( p, 0, sizeof(Abc_ManTime_t) );
p->vArrs = Vec_PtrAlloc( 0 );
p->vReqs = Vec_PtrAlloc( 0 );
2013-07-24 01:15:03 +02:00
p->tReqDef.Rise = ABC_INFINITY;
p->tReqDef.Fall = ABC_INFINITY;
Abc_ManTimeExpand( p, Abc_NtkObjNumMax(pNtk) + 1, 0 );
2005-07-29 17:01:00 +02:00
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_ManTimeStop( Abc_ManTime_t * p )
{
if ( p->tInDrive )
ABC_FREE( p->tInDrive );
if ( p->tOutLoad )
ABC_FREE( p->tOutLoad );
2013-07-21 10:28:54 +02:00
if ( Vec_PtrSize(p->vArrs) > 0 )
2009-02-15 17:01:00 +01:00
ABC_FREE( p->vArrs->pArray[0] );
2013-07-21 10:28:54 +02:00
Vec_PtrFree( p->vArrs );
if ( Vec_PtrSize(p->vReqs) > 0 )
2009-02-15 17:01:00 +01:00
ABC_FREE( p->vReqs->pArray[0] );
2013-07-21 10:28:54 +02:00
Vec_PtrFree( p->vReqs );
2009-02-15 17:01:00 +01:00
ABC_FREE( p );
2005-07-29 17:01:00 +02:00
}
/**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_NtkCiNum(pNtkOld) == Abc_NtkCiNum(pNtkNew) );
assert( Abc_NtkCoNum(pNtkOld) == Abc_NtkCoNum(pNtkNew) );
2005-07-29 17:01:00 +02:00
assert( Abc_NtkLatchNum(pNtkOld) == Abc_NtkLatchNum(pNtkNew) );
// create the new timing manager
pNtkNew->pManTime = Abc_ManTimeStart(pNtkNew);
2005-08-14 17:01:00 +02:00
Abc_ManTimeExpand( pNtkNew->pManTime, Abc_NtkObjNumMax(pNtkNew), 0 );
2005-07-29 17:01:00 +02:00
// set the default timing
pNtkNew->pManTime->tArrDef = pNtkOld->pManTime->tArrDef;
pNtkNew->pManTime->tReqDef = pNtkOld->pManTime->tReqDef;
2005-09-02 17:01:00 +02:00
// set the CI timing
2005-07-29 17:01:00 +02:00
ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vArrs->pArray;
ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vArrs->pArray;
2005-09-02 17:01:00 +02:00
Abc_NtkForEachCi( pNtkOld, pObj, i )
*ppTimesNew[ Abc_NtkCi(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ];
// set the CO timing
2005-07-29 17:01:00 +02:00
ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vReqs->pArray;
ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vReqs->pArray;
2005-09-02 17:01:00 +02:00
Abc_NtkForEachCo( pNtkOld, pObj, i )
*ppTimesNew[ Abc_NtkCo(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ];
// duplicate input drive
pNtkNew->pManTime->tInDriveDef = pNtkOld->pManTime->tInDriveDef;
pNtkNew->pManTime->tOutLoadDef = pNtkOld->pManTime->tOutLoadDef;
if ( pNtkOld->pManTime->tInDrive )
{
pNtkNew->pManTime->tInDrive = ABC_ALLOC( Abc_Time_t, Abc_NtkCiNum(pNtkOld) );
memcpy( pNtkNew->pManTime->tInDrive, pNtkOld->pManTime->tInDrive, sizeof(Abc_Time_t) * Abc_NtkCiNum(pNtkOld) );
}
if ( pNtkOld->pManTime->tOutLoad )
{
pNtkNew->pManTime->tOutLoad = ABC_ALLOC( Abc_Time_t, Abc_NtkCiNum(pNtkOld) );
memcpy( pNtkNew->pManTime->tOutLoad, pNtkOld->pManTime->tOutLoad, sizeof(Abc_Time_t) * Abc_NtkCoNum(pNtkOld) );
}
2005-07-29 17:01:00 +02:00
}
/**Function*************************************************************
2005-08-07 17:01:00 +02:00
Synopsis [Expends the storage for timing information.]
2005-07-29 17:01:00 +02:00
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;
2010-11-01 09:35:04 +01:00
ppTimesOld = ( nSizeOld == 0 )? NULL : (Abc_Time_t *)vTimes->pArray[0];
2009-02-15 17:01:00 +01:00
ppTimes = ABC_REALLOC( Abc_Time_t, ppTimesOld, nSizeNew );
2005-07-29 17:01:00 +02:00
for ( i = 0; i < nSizeNew; i++ )
vTimes->pArray[i] = ppTimes + i;
for ( i = nSizeOld; i < nSizeNew; i++ )
{
2010-11-01 09:35:04 +01:00
pTime = (Abc_Time_t *)vTimes->pArray[i];
2005-07-29 17:01:00 +02:00
pTime->Rise = -ABC_INFINITY;
pTime->Fall = -ABC_INFINITY;
}
vTimes = p->vReqs;
Vec_PtrGrow( vTimes, nSizeNew );
vTimes->nSize = nSizeNew;
2010-11-01 09:35:04 +01:00
ppTimesOld = ( nSizeOld == 0 )? NULL : (Abc_Time_t *)vTimes->pArray[0];
2009-02-15 17:01:00 +01:00
ppTimes = ABC_REALLOC( Abc_Time_t, ppTimesOld, nSizeNew );
2005-07-29 17:01:00 +02:00
for ( i = 0; i < nSizeNew; i++ )
vTimes->pArray[i] = ppTimes + i;
for ( i = nSizeOld; i < nSizeNew; i++ )
{
2010-11-01 09:35:04 +01:00
pTime = (Abc_Time_t *)vTimes->pArray[i];
2013-07-24 01:15:03 +02:00
pTime->Rise = ABC_INFINITY;
pTime->Fall = ABC_INFINITY;
2005-07-29 17:01:00 +02:00
}
}
/**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 ( Abc_FrameReadLibGen() == NULL || Mio_LibraryReadNand2((Mio_Library_t *)Abc_FrameReadLibGen()) == NULL )
2005-07-29 17:01:00 +02:00
return;
2010-11-01 09:35:04 +01:00
tAndDelay = Mio_LibraryReadDelayNand2Max((Mio_Library_t *)Abc_FrameReadLibGen());
2013-07-24 01:15:03 +02:00
Abc_NtkForEachCi( pNtkOld, pNodeOld, i )
2005-07-29 17:01:00 +02:00
{
pNodeNew = pNodeOld->pCopy;
pNodeNew->Level = (int)(Abc_NodeReadArrivalWorst(pNodeOld) / tAndDelay);
2005-07-29 17:01:00 +02:00
}
}
/**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 = ABC_CALLOC( Abc_Time_t, Abc_NtkCiNum(pNtk) );
2005-07-29 17:01:00 +02:00
if ( pNtk->pManTime == NULL )
return p;
// set the PI arrival times
2013-07-24 01:15:03 +02:00
Abc_NtkForEachCi( pNtk, pNode, i )
2005-07-29 17:01:00 +02:00
p[i] = *Abc_NodeArrival(pNode);
return p;
}
Abc_Time_t * Abc_NtkGetCoRequiredTimes( Abc_Ntk_t * pNtk )
{
Abc_Time_t * p;
Abc_Obj_t * pNode;
int i;
p = ABC_CALLOC( Abc_Time_t, Abc_NtkCoNum(pNtk) );
if ( pNtk->pManTime == NULL )
return p;
// set the PO required times
2013-07-24 01:15:03 +02:00
Abc_NtkForEachCo( pNtk, pNode, i )
p[i] = *Abc_NodeRequired(pNode);
return p;
}
2005-07-29 17:01:00 +02:00
/**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 = ABC_CALLOC( float, Abc_NtkCiNum(pNtk) );
2005-07-29 17:01:00 +02:00
if ( pNtk->pManTime == NULL )
return p;
2013-07-24 01:15:03 +02:00
Abc_NtkForEachCi( pNtk, pNode, i )
if ( Abc_NodeReadArrivalWorst(pNode) != 0 )
break;
if ( i == Abc_NtkCiNum(pNtk) )
return NULL;
2005-07-29 17:01:00 +02:00
// set the PI arrival times
2013-07-24 01:15:03 +02:00
Abc_NtkForEachCi( pNtk, pNode, i )
p[i] = Abc_NodeReadArrivalWorst(pNode);
2005-07-29 17:01:00 +02:00
return p;
}
float * Abc_NtkGetCoRequiredFloats( Abc_Ntk_t * pNtk )
{
float * p;
Abc_Obj_t * pNode;
int i;
if ( pNtk->pManTime == NULL )
return NULL;
2013-07-24 01:15:03 +02:00
Abc_NtkForEachCo( pNtk, pNode, i )
if ( Abc_NodeReadRequiredWorst(pNode) != ABC_INFINITY )
break;
if ( i == Abc_NtkCoNum(pNtk) )
return NULL;
// set the PO required times
p = ABC_CALLOC( float, Abc_NtkCoNum(pNtk) );
2013-07-24 01:15:03 +02:00
Abc_NtkForEachCo( pNtk, pNode, i )
p[i] = Abc_NodeReadRequiredWorst(pNode);
return p;
}
2005-07-29 17:01:00 +02:00
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Abc_NtkDelayTraceSlackStart( Abc_Ntk_t * pNtk )
2005-07-29 17:01:00 +02:00
{
Vec_Int_t * vSlacks;
Abc_Obj_t * pObj;
int i, k;
vSlacks = Vec_IntAlloc( Abc_NtkObjNumMax(pNtk) + Abc_NtkGetTotalFanins(pNtk) );
Vec_IntFill( vSlacks, Abc_NtkObjNumMax(pNtk), -1 );
Abc_NtkForEachNode( pNtk, pObj, i )
{
Vec_IntWriteEntry( vSlacks, i, Vec_IntSize(vSlacks) );
for ( k = 0; k < Abc_ObjFaninNum(pObj); k++ )
Vec_IntPush( vSlacks, -1 );
}
2012-04-10 00:06:33 +02:00
// assert( Abc_MaxInt(16, Vec_IntSize(vSlacks)) == Vec_IntCap(vSlacks) );
return vSlacks;
}
/**Function*************************************************************
Synopsis [Read/write edge slacks.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline float Abc_NtkDelayTraceSlack( Vec_Int_t * vSlacks, Abc_Obj_t * pObj, int iFanin )
{
return Abc_Int2Float( Vec_IntEntry( vSlacks, Vec_IntEntry(vSlacks, Abc_ObjId(pObj)) + iFanin ) );
}
static inline void Abc_NtkDelayTraceSetSlack( Vec_Int_t * vSlacks, Abc_Obj_t * pObj, int iFanin, float Num )
{
Vec_IntWriteEntry( vSlacks, Vec_IntEntry(vSlacks, Abc_ObjId(pObj)) + iFanin, Abc_Float2Int(Num) );
}
/**Function*************************************************************
Synopsis [Find most-critical path (the path with smallest slacks).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkDelayTraceCritPath_rec( Vec_Int_t * vSlacks, Abc_Obj_t * pNode, Abc_Obj_t * pLeaf, Vec_Int_t * vBest )
{
Abc_Obj_t * pFanin, * pFaninBest = NULL;
float SlackMin = ABC_INFINITY;
2005-07-29 17:01:00 +02:00
int i;
// check primary inputs
if ( Abc_ObjIsCi(pNode) )
return (pLeaf == NULL || pLeaf == pNode);
assert( Abc_ObjIsNode(pNode) );
// check visited
if ( Abc_NodeIsTravIdCurrent( pNode ) )
return Vec_IntEntry(vBest, Abc_ObjId(pNode)) >= 0;
Abc_NodeSetTravIdCurrent( pNode );
// check the node
assert( Abc_ObjIsNode(pNode) );
Abc_ObjForEachFanin( pNode, pFanin, i )
{
if ( !Abc_NtkDelayTraceCritPath_rec( vSlacks, pFanin, pLeaf, vBest ) )
continue;
if ( pFaninBest == NULL || SlackMin > Abc_NtkDelayTraceSlack(vSlacks, pNode, i) )
{
pFaninBest = pFanin;
SlackMin = Abc_NtkDelayTraceSlack(vSlacks, pNode, i);
}
}
if ( pFaninBest != NULL )
Vec_IntWriteEntry( vBest, Abc_ObjId(pNode), Abc_NodeFindFanin(pNode, pFaninBest) );
return (pFaninBest != NULL);
}
2005-07-29 17:01:00 +02:00
/**Function*************************************************************
2005-07-29 17:01:00 +02:00
Synopsis [Find most-critical path (the path with smallest slacks).]
2005-07-29 17:01:00 +02:00
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkDelayTraceCritPathCollect_rec( Vec_Int_t * vSlacks, Abc_Obj_t * pNode, Vec_Int_t * vBest, Vec_Ptr_t * vPath )
{
assert( Abc_ObjIsCi(pNode) || Abc_ObjIsNode(pNode) );
if ( Abc_ObjIsNode(pNode) )
2005-07-29 17:01:00 +02:00
{
int iFanin = Vec_IntEntry( vBest, Abc_ObjId(pNode) );
assert( iFanin >= 0 );
Abc_NtkDelayTraceCritPathCollect_rec( vSlacks, Abc_ObjFanin(pNode, iFanin), vBest, vPath );
2005-07-29 17:01:00 +02:00
}
Vec_PtrPush( vPath, pNode );
2005-07-29 17:01:00 +02:00
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode, Vec_Int_t * vSlacks )
2005-07-29 17:01:00 +02:00
{
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);
2008-01-31 05:01:00 +01:00
pTimeOut->Rise = pTimeOut->Fall = -ABC_INFINITY;
2005-07-29 17:01:00 +02:00
// go through the pins of the gate
2010-11-01 09:35:04 +01:00
pPin = Mio_GateReadPins((Mio_Gate_t *)pNode->pData);
2005-07-29 17:01:00 +02:00
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);
}
// compute edge slacks
if ( vSlacks )
{
float Slack;
// go through the pins of the gate
pPin = Mio_GateReadPins((Mio_Gate_t *)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
Slack = ABC_INFINITY;
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;
Slack = Abc_MinFloat( Slack, Abc_AbsFloat(pTimeIn->Rise + tDelayBlockRise - pTimeOut->Rise) );
Slack = Abc_MinFloat( Slack, Abc_AbsFloat(pTimeIn->Fall + tDelayBlockFall - pTimeOut->Fall) );
}
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;
Slack = Abc_MinFloat( Slack, Abc_AbsFloat(pTimeIn->Fall + tDelayBlockRise - pTimeOut->Rise) );
Slack = Abc_MinFloat( Slack, Abc_AbsFloat(pTimeIn->Rise + tDelayBlockFall - pTimeOut->Fall) );
}
pPin = Mio_PinReadNext(pPin);
Abc_NtkDelayTraceSetSlack( vSlacks, pNode, i, Slack );
}
}
2005-07-29 17:01:00 +02:00
}
2005-08-27 17:01:00 +02:00
/**Function*************************************************************
Synopsis [Performs delay-trace of the network. If input (pIn) or
output (pOut) are given, finds the most-timing-critical path between
them and prints it to the standard output. If input and/or output are
not given, finds the most-critical path in the network and prints it.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk, Abc_Obj_t * pOut, Abc_Obj_t * pIn, int fPrint )
{
Vec_Int_t * vSlacks = NULL;
Abc_Obj_t * pNode, * pDriver;
Vec_Ptr_t * vNodes;
Abc_Time_t * pTime;
float tArrivalMax;
int i;
assert( Abc_NtkIsMappedLogic(pNtk) );
assert( pOut == NULL || Abc_ObjIsCo(pOut) );
assert( pIn == NULL || Abc_ObjIsCi(pIn) );
// create slacks (need slacks if printing is requested even if pIn/pOut are not given)
if ( pOut || pIn || fPrint )
vSlacks = Abc_NtkDelayTraceSlackStart( pNtk );
// compute the timing
Abc_NtkTimePrepare( pNtk );
vNodes = Abc_NtkDfs( pNtk, 1 );
Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
Abc_NodeDelayTraceArrival( pNode, vSlacks );
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 < Abc_MaxFloat(pTime->Fall, pTime->Rise) )
tArrivalMax = Abc_MaxFloat(pTime->Fall, pTime->Rise);
}
// determine the output to print
if ( fPrint && pOut == NULL )
{
Abc_NtkForEachCo( pNtk, pNode, i )
{
pDriver = Abc_ObjFanin0(pNode);
pTime = Abc_NodeArrival(pDriver);
if ( tArrivalMax == Abc_MaxFloat(pTime->Fall, pTime->Rise) )
pOut = pNode;
}
assert( pOut != NULL );
}
if ( fPrint )
{
Vec_Ptr_t * vPath = Vec_PtrAlloc( 100 );
Vec_Int_t * vBest = Vec_IntStartFull( Abc_NtkObjNumMax(pNtk) );
// traverse to determine the critical path
Abc_NtkIncrementTravId( pNtk );
if ( !Abc_NtkDelayTraceCritPath_rec( vSlacks, Abc_ObjFanin0(pOut), pIn, vBest ) )
2012-04-06 09:45:58 +02:00
{
if ( pIn == NULL )
printf( "The logic cone of PO \"%s\" has no primary inputs.\n", Abc_ObjName(pOut) );
else
printf( "There is no combinational path between PI \"%s\" and PO \"%s\".\n", Abc_ObjName(pIn), Abc_ObjName(pOut) );
}
else
{
2012-04-06 22:31:03 +02:00
float Slack = 0.0, SlackAdd;
2012-04-06 09:45:58 +02:00
int k, iFanin, Length = 0;
Abc_Obj_t * pFanin;
2012-04-06 22:31:03 +02:00
// check the additional slack
SlackAdd = Abc_NodeReadRequiredWorst(pOut) - Abc_NodeReadArrivalWorst(Abc_ObjFanin0(pOut));
// collect the critical path
Abc_NtkDelayTraceCritPathCollect_rec( vSlacks, Abc_ObjFanin0(pOut), vBest, vPath );
if ( pIn == NULL )
pIn = (Abc_Obj_t *)Vec_PtrEntry( vPath, 0 );
2012-04-06 09:45:58 +02:00
// find the longest gate name
Vec_PtrForEachEntry( Abc_Obj_t *, vPath, pNode, i )
if ( Abc_ObjIsNode(pNode) )
Length = Abc_MaxInt( Length, strlen(Mio_GateReadName((Mio_Gate_t *)pNode->pData)) );
// print critical path
2012-04-06 22:31:03 +02:00
Abc_NtkLevel( pNtk );
2012-04-06 09:45:58 +02:00
printf( "Critical path from PI \"%s\" to PO \"%s\":\n", Abc_ObjName(pIn), Abc_ObjName(pOut) );
Vec_PtrForEachEntry( Abc_Obj_t *, vPath, pNode, i )
{
2012-04-06 09:45:58 +02:00
printf( "Level %3d : ", Abc_ObjLevel(pNode) );
if ( Abc_ObjIsCi(pNode) )
2012-04-06 09:45:58 +02:00
{
printf( "Primary input \"%s\". ", Abc_ObjName(pNode) );
printf( "Arrival time =%6.1f. ", Abc_NodeReadArrivalWorst(pNode) );
2012-04-06 09:45:58 +02:00
printf( "\n" );
continue;
}
if ( Abc_ObjIsCo(pNode) )
{
printf( "Primary output \"%s\". ", Abc_ObjName(pNode) );
printf( "Arrival =%6.1f. ", Abc_NodeReadArrivalWorst(pNode) );
2012-04-06 09:45:58 +02:00
}
else
{
assert( Abc_ObjIsNode(pNode) );
iFanin = Abc_NodeFindFanin( pNode, (Abc_Obj_t *)Vec_PtrEntry(vPath,i-1) );
2012-04-06 09:45:58 +02:00
Slack = Abc_NtkDelayTraceSlack(vSlacks, pNode, iFanin);
printf( "%10s/", Abc_ObjName(pNode) );
printf( "%-4s", Mio_GateReadPinName((Mio_Gate_t *)pNode->pData, iFanin) );
printf( " (%s)", Mio_GateReadName((Mio_Gate_t *)pNode->pData) );
for ( k = strlen(Mio_GateReadName((Mio_Gate_t *)pNode->pData)); k < Length; k++ )
printf( " " );
printf( " " );
printf( "Arrival =%6.1f. ", Abc_NodeReadArrivalWorst(pNode) );
2012-04-06 22:31:03 +02:00
printf( "I/O times: (" );
2012-04-06 09:45:58 +02:00
Abc_ObjForEachFanin( pNode, pFanin, k )
printf( "%s%.1f", (k? ", ":""), Abc_NodeReadArrivalWorst(pFanin) );
2012-04-10 05:01:40 +02:00
// printf( " -> %.1f)", Abc_NodeReadArrival(pNode)->Worst + Slack + SlackAdd );
printf( " -> %.1f)", Abc_NodeReadArrivalWorst(pNode) );
}
printf( "\n" );
}
2012-04-06 09:45:58 +02:00
printf( "Level %3d : ", Abc_ObjLevel(Abc_ObjFanin0(pOut)) + 1 );
printf( "Primary output \"%s\". ", Abc_ObjName(pOut) );
printf( "Required time = %6.1f. ", Abc_NodeReadRequiredWorst(pOut) );
2012-04-10 03:59:36 +02:00
printf( "Path slack = %6.1f.\n", SlackAdd );
}
Vec_PtrFree( vPath );
Vec_IntFree( vBest );
}
Vec_IntFreeP( &vSlacks );
return tArrivalMax;
}
2005-08-27 17:01:00 +02:00
2005-08-18 17:01:00 +02:00
/**Function*************************************************************
2008-01-31 05:01:00 +01:00
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_MaxFloat( Level, Abc_ObjLevel(pFanin) );
2013-08-10 04:47:58 +02:00
return Level + (int)(Abc_ObjFaninNum(pObj) > 0);
2008-01-31 05:01:00 +01:00
}
/**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_MaxFloat( Level, LevelCur );
2008-01-31 05:01:00 +01:00
}
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.]
2005-08-18 17:01:00 +02:00
2005-08-27 17:01:00 +02:00
Description [This procedure should be called before the required times
are used. It starts internal data structures, which records the level
2008-01-31 05:01:00 +01:00
from the COs of the network nodes in reverse topologogical order.]
2005-08-18 17:01:00 +02:00
SideEffects []
SeeAlso []
***********************************************************************/
2008-01-31 05:01:00 +01:00
void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease )
2005-08-18 17:01:00 +02:00
{
Vec_Ptr_t * vNodes;
2008-01-31 05:01:00 +01:00
Abc_Obj_t * pObj;
int i;
2005-08-27 17:01:00 +02:00
// remember the maximum number of direct levels
2008-01-31 05:01:00 +01:00
pNtk->LevelMax = Abc_NtkLevel(pNtk) + nMaxLevelIncrease;
2005-08-27 17:01:00 +02:00
// start the reverse levels
pNtk->vLevelsR = Vec_IntAlloc( 0 );
2008-01-31 05:01:00 +01:00
Vec_IntFill( pNtk->vLevelsR, 1 + Abc_NtkObjNumMax(pNtk), 0 );
2005-08-18 17:01:00 +02:00
// compute levels in reverse topological order
vNodes = Abc_NtkDfsReverse( pNtk );
2010-11-01 09:35:04 +01:00
Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
2008-01-31 05:01:00 +01:00
Abc_ObjSetReverseLevel( pObj, Abc_ObjReverseLevelNew(pObj) );
2005-08-18 17:01:00 +02:00
Vec_PtrFree( vNodes );
2005-08-27 17:01:00 +02:00
}
/**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*************************************************************
2008-01-31 05:01:00 +01:00
Synopsis [Incrementally updates level of the nodes.]
2005-08-27 17:01:00 +02:00
2008-01-31 05:01:00 +01:00
Description []
2005-08-27 17:01:00 +02:00
SideEffects []
SeeAlso []
***********************************************************************/
2008-01-31 05:01:00 +01:00
void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
2005-08-27 17:01:00 +02:00
{
2008-01-31 05:01:00 +01:00
Abc_Obj_t * pFanout, * pTemp;
int LevelOld, Lev, k, m;
2008-03-26 16:01:00 +01:00
// int Counter = 0, CounterMax = 0;
2008-01-31 05:01:00 +01:00
// 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
2010-11-01 09:35:04 +01:00
Vec_VecForEachEntryStart( Abc_Obj_t *, vLevels, pTemp, Lev, k, LevelOld )
2008-01-31 05:01:00 +01:00
{
2008-03-26 16:01:00 +01:00
// Counter--;
2008-01-31 05:01:00 +01:00
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 );
2008-03-26 16:01:00 +01:00
// Counter++;
// CounterMax = Abc_MaxFloat( CounterMax, Counter );
2008-01-31 05:01:00 +01:00
pFanout->fMarkA = 1;
}
}
}
2008-03-26 16:01:00 +01:00
// printf( "%d ", CounterMax );
2005-08-27 17:01:00 +02:00
}
/**Function*************************************************************
2008-01-31 05:01:00 +01:00
Synopsis [Incrementally updates level of the nodes.]
2005-08-27 17:01:00 +02:00
2008-01-31 05:01:00 +01:00
Description []
2005-08-27 17:01:00 +02:00
SideEffects []
SeeAlso []
***********************************************************************/
2008-01-31 05:01:00 +01:00
void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
2005-08-27 17:01:00 +02:00
{
2008-01-31 05:01:00 +01:00
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
2010-11-01 09:35:04 +01:00
Vec_VecForEachEntryStart( Abc_Obj_t *, vLevels, pTemp, Lev, k, LevelOld )
2008-01-31 05:01:00 +01:00
{
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;
}
}
}
2005-08-27 17:01:00 +02:00
}
/**Function*************************************************************
2008-01-31 05:01:00 +01:00
Synopsis [Replaces the node and incrementally updates levels.]
2005-08-27 17:01:00 +02:00
2008-01-31 05:01:00 +01:00
Description []
2005-08-27 17:01:00 +02:00
SideEffects []
SeeAlso []
***********************************************************************/
2008-01-31 05:01:00 +01:00
void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
2005-08-27 17:01:00 +02:00
{
2008-01-31 05:01:00 +01:00
// 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 );
2005-08-18 17:01:00 +02:00
}
2005-07-29 17:01:00 +02:00
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
2010-11-01 09:35:04 +01:00
ABC_NAMESPACE_IMPL_END