summaryrefslogtreecommitdiffstats
path: root/src/base/abci
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/abci')
-rw-r--r--src/base/abci/abc.c87
-rw-r--r--src/base/abci/abcBalance.c5
-rw-r--r--src/base/abci/abcDar.c9
-rw-r--r--src/base/abci/abcIf.c3
-rw-r--r--src/base/abci/abcPrint.c4
-rw-r--r--src/base/abci/abcSweep.c2
-rw-r--r--src/base/abci/abcTiming.c297
7 files changed, 378 insertions, 29 deletions
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index 04f4b6d7..3ca2aab2 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -82,6 +82,7 @@ static int Abc_CommandPrintDsd ( Abc_Frame_t * pAbc, int argc, cha
static int Abc_CommandPrintCone ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandPrintMiter ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandPrintStatus ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintDelay ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandShow ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -525,6 +526,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Printing", "print_cone", Abc_CommandPrintCone, 0 );
Cmd_CommandAdd( pAbc, "Printing", "print_miter", Abc_CommandPrintMiter, 0 );
Cmd_CommandAdd( pAbc, "Printing", "print_status", Abc_CommandPrintStatus, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_delay", Abc_CommandPrintDelay, 0 );
Cmd_CommandAdd( pAbc, "Printing", "show", Abc_CommandShow, 0 );
Cmd_CommandAdd( pAbc, "Printing", "show_bdd", Abc_CommandShowBdd, 0 );
@@ -2225,7 +2227,6 @@ usage:
***********************************************************************/
int Abc_CommandPrintStatus( Abc_Frame_t * pAbc, int argc, char ** argv )
{
-// Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
int c;
// set defaults
Extra_UtilGetoptReset();
@@ -2267,6 +2268,90 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandPrintDelay( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+ Abc_Obj_t * pObjIn = NULL, * pObjOut = NULL;
+ int c;
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ Abc_Print( -1, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsMappedLogic(pNtk) )
+ {
+ Abc_Print( -1, "Delay trace works only for network mapped into standard cells.\n" );
+ return 1;
+ }
+ if ( argc > globalUtilOptind + 2 )
+ {
+ Abc_Print( -1, "Wrong number of auguments.\n" );
+ goto usage;
+ }
+ // collect the first name (PO name)
+ if ( argc >= globalUtilOptind + 1 )
+ {
+ int Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind], ABC_OBJ_PO );
+ if ( Num < 0 )
+ Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind], ABC_OBJ_BI );
+ if ( Num >= 0 )
+ pObjOut = Abc_NtkObj( pNtk, Num );
+ if ( pObjOut == NULL )
+ {
+ Abc_Print( -1, "Cannot find combinational output \"%s\".\n", argv[globalUtilOptind] );
+ return 1;
+ }
+ }
+ // collect the second name (PI name)
+ if ( argc == globalUtilOptind + 2 )
+ {
+ int Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind+1], ABC_OBJ_PI );
+ if ( Num < 0 )
+ Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind+1], ABC_OBJ_BO );
+ if ( Num >= 0 )
+ pObjIn = Abc_NtkObj( pNtk, Num );
+ if ( pObjIn == NULL )
+ {
+ Abc_Print( -1, "Cannot find combinational input \"%s\".\n", argv[globalUtilOptind+1] );
+ return 1;
+ }
+ }
+ Abc_NtkDelayTrace( pNtk, pObjOut, pObjIn, 1 );
+ return 0;
+
+usage:
+ Abc_Print( -2, "usage: print_delay [-h] <CO_name> <CI_name>\n" );
+ Abc_Print( -2, "\t prints one critical path of the mapped network\n" );
+ Abc_Print( -2, "\t-h : print the command usage\n");
+ Abc_Print( -2, "\t<CO_name> : (optional) the sink of the critical path (primary output or flop input)\n");
+ Abc_Print( -2, "\t<CI_name> : (optional) the source of the critical path (primary input or flop output)\n");
+ Abc_Print( -2, "\t (if CO and/or CI are not given, uses the most critical ones)\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
diff --git a/src/base/abci/abcBalance.c b/src/base/abci/abcBalance.c
index c46fd4b7..8317558d 100644
--- a/src/base/abci/abcBalance.c
+++ b/src/base/abci/abcBalance.c
@@ -84,6 +84,7 @@ Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, int fDuplicate, int fSelective, in
Abc_NtkDelete( pNtkAig );
return NULL;
}
+//Abc_NtkPrintCiLevels( pNtkAig );
return pNtkAig;
}
@@ -104,7 +105,9 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, int fDuplicat
Vec_Vec_t * vStorage;
Abc_Obj_t * pNode, * pDriver;
int i;
-
+ // transfer level
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ pNode->pCopy->Level = pNode->Level;
// set the level of PIs of AIG according to the arrival times of the old network
Abc_NtkSetNodeLevelsArrival( pNtk );
// allocate temporary storage for supergates
diff --git a/src/base/abci/abcDar.c b/src/base/abci/abcDar.c
index e11dc283..466af072 100644
--- a/src/base/abci/abcDar.c
+++ b/src/base/abci/abcDar.c
@@ -254,7 +254,11 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters )
// transfer the pointers to the basic nodes
Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan);
Abc_NtkForEachCi( pNtk, pObj, i )
+ {
pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreateCi(pMan);
+ // initialize logic level of the CIs
+ ((Aig_Obj_t *)pObj->pCopy)->Level = pObj->Level;
+ }
// complement the 1-values registers
if ( fRegisters ) {
Abc_NtkForEachLatch( pNtk, pObj, i )
@@ -385,7 +389,11 @@ Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
// transfer the pointers to the basic nodes
Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
Aig_ManForEachCi( pMan, pObj, i )
+ {
pObj->pData = Abc_NtkCi(pNtkNew, i);
+ // initialize logic level of the CIs
+ ((Abc_Obj_t *)pObj->pData)->Level = pObj->Level;
+ }
// rebuild the AIG
vNodes = Aig_ManDfs( pMan, 1 );
Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
@@ -404,6 +412,7 @@ Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
// if there are assertions, add them
if ( !Abc_NtkCheck( pNtkNew ) )
Abc_Print( 1, "Abc_NtkFromDar(): Network check has failed.\n" );
+//Abc_NtkPrintCiLevels( pNtkNew );
return pNtkNew;
}
diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c
index 2d6915e4..f2b101b9 100644
--- a/src/base/abci/abcIf.c
+++ b/src/base/abci/abcIf.c
@@ -209,7 +209,8 @@ If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
Abc_NtkForEachCi( pNtk, pNode, i )
{
pNode->pCopy = (Abc_Obj_t *)If_ManCreateCi( pIfMan );
-//printf( "AIG CI %2d -> IF CI %2d\n", pNode->Id, ((If_Obj_t *)pNode->pCopy)->Id );
+ // transfer logic level information
+ ((If_Obj_t *)pNode->pCopy)->Level = pNode->Level;
}
// load the AIG into the mapper
diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c
index 6c2296b9..d257a1d2 100644
--- a/src/base/abci/abcPrint.c
+++ b/src/base/abci/abcPrint.c
@@ -261,7 +261,7 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum
else if ( Abc_NtkHasMapping(pNtk) )
{
fprintf( pFile, " area =%5.2f", Abc_NtkGetMappedArea(pNtk) );
- fprintf( pFile, " delay =%5.2f", Abc_NtkDelayTrace(pNtk) );
+ fprintf( pFile, " delay =%5.2f", Abc_NtkDelayTrace(pNtk, NULL, NULL, 0) );
}
else if ( !Abc_NtkHasBlackbox(pNtk) )
{
@@ -842,7 +842,7 @@ void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListN
int DelayInt, nOutsSum, nOutsTotal;
// get the max delay and delta
- DelayMax = Abc_NtkDelayTrace( pNtk );
+ DelayMax = Abc_NtkDelayTrace( pNtk, NULL, NULL, 0 );
DelayDelta = DelayMax/nIntervals;
// collect outputs by delay
pLevelCounts = ABC_ALLOC( int, nIntervals );
diff --git a/src/base/abci/abcSweep.c b/src/base/abci/abcSweep.c
index a5649794..2670939b 100644
--- a/src/base/abci/abcSweep.c
+++ b/src/base/abci/abcSweep.c
@@ -282,7 +282,7 @@ void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv,
// merge nodes in the classes
if ( Abc_NtkHasMapping( pNtk ) )
{
- Abc_NtkDelayTrace( pNtk );
+ Abc_NtkDelayTrace( pNtk, NULL, NULL, 0 );
stmm_foreach_item( tEquiv, gen, (char **)&pList, NULL )
Abc_NtkFraigMergeClassMapped( pNtk, pList, fUseInv, fVerbose );
}
diff --git a/src/base/abci/abcTiming.c b/src/base/abci/abcTiming.c
index a9b50563..3f47b241 100644
--- a/src/base/abci/abcTiming.c
+++ b/src/base/abci/abcTiming.c
@@ -41,8 +41,6 @@ struct Abc_ManTime_t_
static Abc_ManTime_t * Abc_ManTimeStart();
static void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive );
-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 (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]; }
@@ -121,6 +119,38 @@ Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk )
/**Function*************************************************************
+ Synopsis [Reads average arrival time of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Abc_NodeReadArrivalAve( Abc_Obj_t * pNode )
+{
+ return 0.5 * Abc_NodeArrival(pNode)->Rise + 0.5 * Abc_NodeArrival(pNode)->Fall;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads average required time of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Abc_NodeReadRequiredAve( Abc_Obj_t * pNode )
+{
+ return 0.5 * Abc_NodeReadRequired(pNode)->Rise + 0.5 * Abc_NodeReadRequired(pNode)->Fall;
+}
+
+/**Function*************************************************************
+
Synopsis [Sets the default arrival time for the network.]
Description []
@@ -246,6 +276,7 @@ void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkOld )
{
pNtk->pManTime->tArrDef = pNtkOld->pManTime->tArrDef;
pNtk->pManTime->tReqDef = pNtkOld->pManTime->tReqDef;
+ pNtk->AndGateDelay = pNtkOld->AndGateDelay;
}
// set the default timing
ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray;
@@ -492,7 +523,7 @@ void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtkOld )
int i;
if ( pNtkOld->pManTime == NULL )
return;
- if ( Mio_LibraryReadNand2((Mio_Library_t *)Abc_FrameReadLibGen()) == NULL )
+ if ( Abc_FrameReadLibGen() == NULL || Mio_LibraryReadNand2((Mio_Library_t *)Abc_FrameReadLibGen()) == NULL )
return;
tAndDelay = Mio_LibraryReadDelayNand2Max((Mio_Library_t *)Abc_FrameReadLibGen());
Abc_NtkForEachPi( pNtkOld, pNodeOld, i )
@@ -590,32 +621,105 @@ float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk )
+Vec_Int_t * Abc_NtkDelayTraceSlackStart( Abc_Ntk_t * pNtk )
{
- Abc_Obj_t * pNode, * pDriver;
- Vec_Ptr_t * vNodes;
- Abc_Time_t * pTime;
- float tArrivalMax;
+ 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 );
+ }
+ assert( 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;
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);
+}
- assert( Abc_NtkIsMappedLogic(pNtk) );
+/**Function*************************************************************
- Abc_NtkTimePrepare( pNtk );
- vNodes = Abc_NtkDfs( pNtk, 1 );
- for ( i = 0; i < vNodes->nSize; i++ )
- Abc_NodeDelayTraceArrival( (Abc_Obj_t *)vNodes->pArray[i] );
- Vec_PtrFree( vNodes );
+ Synopsis [Find most-critical path (the path with smallest slacks).]
- // get the latest arrival times
- tArrivalMax = -ABC_INFINITY;
- Abc_NtkForEachCo( pNtk, pNode, i )
+ 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) )
{
- pDriver = Abc_ObjFanin0(pNode);
- pTime = Abc_NodeArrival(pDriver);
- if ( tArrivalMax < pTime->Worst )
- tArrivalMax = pTime->Worst;
+ int iFanin = Vec_IntEntry( vBest, Abc_ObjId(pNode) );
+ assert( iFanin >= 0 );
+ Abc_NtkDelayTraceCritPathCollect_rec( vSlacks, Abc_ObjFanin(pNode, iFanin), vBest, vPath );
}
- return tArrivalMax;
+ Vec_PtrPush( vPath, pNode );
}
/**Function*************************************************************
@@ -629,7 +733,7 @@ float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode )
+void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode, Vec_Int_t * vSlacks )
{
Abc_Obj_t * pFanin;
Abc_Time_t * pTimeIn, * pTimeOut;
@@ -668,9 +772,156 @@ void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode )
pPin = Mio_PinReadNext(pPin);
}
pTimeOut->Worst = Abc_MaxFloat( pTimeOut->Rise, pTimeOut->Fall );
+
+ // 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 );
+ }
+ }
}
+/**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 < pTime->Worst )
+ tArrivalMax = pTime->Worst;
+ }
+
+ // determine the output to print
+ if ( fPrint && pOut == NULL )
+ {
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ pDriver = Abc_ObjFanin0(pNode);
+ pTime = Abc_NodeArrival(pDriver);
+ if ( tArrivalMax == pTime->Worst )
+ 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 ) )
+ printf( "There is no combinational path between PO \"%s\" and PI \"%s\".\n", Abc_ObjName(pOut), Abc_ObjName(pIn) );
+ else
+ {
+ // collect the critical path
+ Abc_NtkDelayTraceCritPathCollect_rec( vSlacks, Abc_ObjFanin0(pOut), vBest, vPath );
+ if ( pIn == NULL )
+ pIn = (Abc_Obj_t *)Vec_PtrEntry( vPath, 0 );
+ // print critical path
+ printf( "Critical path to PO \"%s\" from PI \"%s\":\n", Abc_ObjName(pOut), Abc_ObjName(pIn) );
+ Vec_PtrForEachEntryReverse( Abc_Obj_t *, vPath, pNode, i )
+ {
+
+ printf( "Obj =%7d. ", Abc_ObjId(pNode) );
+ printf( "Lev =%4d. ", Abc_ObjLevel(pNode) );
+ printf( " " );
+ printf( "Rise =%6.1f. ", Abc_NodeReadArrival(pNode)->Rise );
+ printf( "Fall =%6.1f. ", Abc_NodeReadArrival(pNode)->Fall );
+ printf( " " );
+ if ( Abc_ObjIsCi(pNode) )
+ printf( "Primary input \"%s\".", Abc_ObjName(pNode) );
+ else if ( Abc_ObjIsCo(pNode) )
+ printf( "Primary output \"%s\".", Abc_ObjName(pNode) );
+ else
+ {
+ int iFanin;
+ assert( Abc_ObjIsNode(pNode) );
+ iFanin = Abc_NodeFindFanin( pNode, (Abc_Obj_t *)Vec_PtrEntry(vPath,i-1) );
+ printf( "Slack =%6.1f. ", Abc_NtkDelayTraceSlack(vSlacks, pNode, iFanin) );
+ printf( "Mapping: Pin = %d. Gate = %s. ", iFanin, Mio_GateReadName(pNode->pData) );
+ }
+ printf( "\n" );
+ }
+ }
+ Vec_PtrFree( vPath );
+ Vec_IntFree( vBest );
+ }
+
+ Vec_IntFreeP( &vSlacks );
+ return tArrivalMax;
+}
+
/**Function*************************************************************