From 0792ab0eb630da4a46b117367f86a6c7a8ab94a0 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 21 Mar 2012 23:19:49 -0700 Subject: Additional features for delay optimization --- src/base/abc/abc.h | 7 +- src/base/abc/abcNtk.c | 19 ++- src/base/abc/abcUtil.c | 42 +++++++ src/base/abci/abc.c | 87 ++++++++++++- src/base/abci/abcBalance.c | 5 +- src/base/abci/abcDar.c | 9 ++ src/base/abci/abcIf.c | 3 +- src/base/abci/abcPrint.c | 4 +- src/base/abci/abcSweep.c | 2 +- src/base/abci/abcTiming.c | 297 +++++++++++++++++++++++++++++++++++++++++---- src/base/io/ioReadBlif.c | 41 +++++++ src/base/io/ioWriteBlif.c | 3 + 12 files changed, 488 insertions(+), 31 deletions(-) (limited to 'src/base') diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 272e4fb6..dc3aba5e 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -204,6 +204,7 @@ struct Abc_Ntk_t_ // Abc_Lib_t * pVerLib; // for structural verilog designs Abc_ManTime_t * pManTime; // the timing manager (for mapped networks) stores arrival/required times for all nodes void * pManCut; // the cut manager (for AIGs) stores information about the cuts computed for the nodes + float AndGateDelay; // an average estimated delay of one AND gate int LevelMax; // maximum number of levels Vec_Int_t * vLevelsR; // level in the reverse topological order (for AIGs) Vec_Ptr_t * vSupps; // CO support information @@ -863,6 +864,8 @@ extern ABC_DLL Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode ); extern ABC_DLL Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode ); extern ABC_DLL Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk ); +extern ABC_DLL float Abc_NodeReadArrivalAve( Abc_Obj_t * pNode ); +extern ABC_DLL float Abc_NodeReadRequiredAve( Abc_Obj_t * pNode ); extern ABC_DLL void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall ); extern ABC_DLL void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall ); extern ABC_DLL void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ); @@ -874,7 +877,7 @@ extern ABC_DLL void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtk extern ABC_DLL float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Time_t * Abc_NtkGetCoRequiredTimes( Abc_Ntk_t * pNtk ); -extern ABC_DLL float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk ); +extern ABC_DLL float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk, Abc_Obj_t * pOut, Abc_Obj_t * pIn, int fPrint ); extern ABC_DLL int Abc_ObjLevelNew( Abc_Obj_t * pObj ); extern ABC_DLL int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj ); extern ABC_DLL int Abc_ObjRequiredLevel( Abc_Obj_t * pObj ); @@ -915,6 +918,7 @@ extern ABC_DLL void Abc_NtkCleanMarkB( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkCleanMarkC( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkCleanMarkAB( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkCleanMarkABC( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NodeFindFanin( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ); extern ABC_DLL Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode ); extern ABC_DLL Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode ); extern ABC_DLL Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode ); @@ -938,6 +942,7 @@ extern ABC_DLL void Abc_NtkReassignIds( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_ObjPointerCompare( void ** pp1, void ** pp2 ); extern ABC_DLL void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkInvertConstraints( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkPrintCiLevels( Abc_Ntk_t * pNtk ); /*=== abcVerify.c ==========================================================*/ diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c index 51b12609..071f69df 100644 --- a/src/base/abc/abcNtk.c +++ b/src/base/abc/abcNtk.c @@ -85,6 +85,8 @@ Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan pNtk->pManName = Nm_ManCreate( 200 ); // attribute manager pNtk->vAttrs = Vec_PtrStart( VEC_ATTR_TOTAL_NUM ); + // estimated AndGateDelay + pNtk->AndGateDelay = 0.0; return pNtk; } @@ -131,6 +133,9 @@ Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_ Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); Abc_NtkForEachBox( pNtk, pObj, i ) Abc_NtkDupBox( pNtkNew, pObj, fCopyNames ); + // transfer logic level + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy->Level = pObj->Level; // transfer the names // Abc_NtkTrasferNames( pNtk, pNtkNew ); Abc_ManTimeDup( pNtk, pNtkNew ); @@ -140,6 +145,14 @@ Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_ pNtkNew->pSeqModel = Abc_CexDup( pNtk->pSeqModel, Abc_NtkLatchNum(pNtk) ); if ( pNtk->vObjPerm ) pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm ); + pNtkNew->AndGateDelay = pNtk->AndGateDelay; + // initialize logic level of the CIs + if ( pNtk->AndGateDelay != 0.0 && pNtk->ntkType != ABC_NTK_STRASH && Type == ABC_NTK_STRASH ) + { + assert( pNtk->pManTime != NULL ); // timing info should be available + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy->Level = (int)(Abc_NodeReadArrivalAve(pObj) / pNtk->AndGateDelay); + } // check that the CI/CO/latches are copied correctly assert( Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkNew) ); assert( Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkNew) ); @@ -195,6 +208,7 @@ Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc } if ( pNtk->vObjPerm ) pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm ); + pNtkNew->AndGateDelay = pNtk->AndGateDelay; // transfer the names // Abc_NtkTrasferNamesNoLatches( pNtk, pNtkNew ); Abc_ManTimeDup( pNtk, pNtkNew ); @@ -337,6 +351,9 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) return NULL; // start the network pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); + // transfer level + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy->Level = pObj->Level; // copy the internal nodes if ( Abc_NtkIsStrash(pNtk) ) { @@ -367,7 +384,7 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } - // remap the real nodess + // remap the real nodes if ( pNtk->vRealNodes ) { assert( pNtkNew->vRealNodes == NULL ); diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c index 59a7bc86..3651e61a 100644 --- a/src/base/abc/abcUtil.c +++ b/src/base/abc/abcUtil.c @@ -736,6 +736,27 @@ void Abc_NtkCleanMarkABC( Abc_Ntk_t * pNtk ) pObj->fMarkA = pObj->fMarkB = pObj->fMarkC = 0; } +/**Function************************************************************* + + Synopsis [Returns the index of the given fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeFindFanin( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pThis; + int i; + Abc_ObjForEachFanin( pNode, pThis, i ) + if ( pThis == pFanin ) + return i; + return -1; +} + /**Function************************************************************* Synopsis [Checks if the internal node has CO fanout.] @@ -1962,6 +1983,27 @@ void Abc_NtkInvertConstraints( Abc_Ntk_t * pNtk ) } } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintCiLevels( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachCi( pNtk, pObj, i ) + printf( "%c=%d ", 'a'+i, pObj->Level ); + printf( "\n" ); + +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// 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(); @@ -2256,6 +2257,90 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + 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] \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 : (optional) the sink of the critical path (primary output or flop input)\n"); + Abc_Print( -2, "\t : (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 [] 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]; } @@ -119,6 +117,38 @@ Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk ) return &pNtk->pManTime->tReqDef; } +/**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.] @@ -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************************************************************* diff --git a/src/base/io/ioReadBlif.c b/src/base/io/ioReadBlif.c index eb919210..7a4ee32a 100644 --- a/src/base/io/ioReadBlif.c +++ b/src/base/io/ioReadBlif.c @@ -67,6 +67,7 @@ static int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vToken static int Io_ReadBlifNetworkOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkDefaultOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkAndGateDelay( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ); //////////////////////////////////////////////////////////////////////// @@ -275,6 +276,8 @@ Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ) fStatus = Io_ReadBlifNetworkDefaultInputArrival( p, p->vTokens ); else if ( !strcmp( pDirective, ".default_output_required" ) ) fStatus = Io_ReadBlifNetworkDefaultOutputRequired( p, p->vTokens ); + else if ( !strcmp( pDirective, ".and_gate_delay" ) ) + fStatus = Io_ReadBlifNetworkAndGateDelay( p, p->vTokens ); // else if ( !strcmp( pDirective, ".subckt" ) ) // fStatus = Io_ReadBlifNetworkSubcircuit( p, p->vTokens ); else if ( !strcmp( pDirective, ".exdc" ) ) @@ -903,6 +906,44 @@ int Io_ReadBlifNetworkDefaultOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTok return 0; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkAndGateDelay( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + char * pFoo1; + double AndGateDelay; + + // make sure this is indeed the .inputs line + assert( strncmp( (char *)vTokens->pArray[0], ".and_gate_delay", 25 ) == 0 ); + if ( vTokens->nSize != 2 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Wrong number of arguments (%d) on .and_gate_delay line (should be 1).", vTokens->nSize-1 ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + AndGateDelay = strtod( (char *)vTokens->pArray[1], &pFoo1 ); + if ( *pFoo1 != '\0' ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Bad value (%s %s) for AND gate delay in on .and_gate_delay line line.", (char*)vTokens->pArray[1] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // set the arrival time + p->pNtkCur->AndGateDelay = (float)AndGateDelay; + return 0; +} + /**Function************************************************************* Synopsis [Prints the error message including the file name and line number.] diff --git a/src/base/io/ioWriteBlif.c b/src/base/io/ioWriteBlif.c index 327e16e1..8b3baef2 100644 --- a/src/base/io/ioWriteBlif.c +++ b/src/base/io/ioWriteBlif.c @@ -591,6 +591,9 @@ void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ) fprintf( pFile, "\n" ); + if ( pNtk->AndGateDelay != 0.0 ) + fprintf( pFile, ".and_gate_delay %g\n", pNtk->AndGateDelay ); + pTimeDef = Abc_NtkReadDefaultArrival( pNtk ); fprintf( pFile, ".default_input_arrival %g %g\n", pTimeDef->Rise, pTimeDef->Fall ); Abc_NtkForEachPi( pNtk, pNode, i ) -- cgit v1.2.3