Additional features for delay optimization

This commit is contained in:
Alan Mishchenko 2012-03-21 23:19:49 -07:00
parent f50ce3dbd9
commit 0792ab0eb6
17 changed files with 548 additions and 50 deletions

View File

@ -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 ==========================================================*/

View File

@ -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 );

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View File

@ -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] <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 []

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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 );

View File

@ -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 );
}

View File

@ -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;
int i;
assert( Abc_NtkIsMappedLogic(pNtk) );
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 );
// get the latest arrival times
tArrivalMax = -ABC_INFINITY;
Abc_NtkForEachCo( pNtk, pNode, i )
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 )
{
pDriver = Abc_ObjFanin0(pNode);
pTime = Abc_NodeArrival(pDriver);
if ( tArrivalMax < pTime->Worst )
tArrivalMax = pTime->Worst;
Vec_IntWriteEntry( vSlacks, i, Vec_IntSize(vSlacks) );
for ( k = 0; k < Abc_ObjFaninNum(pObj); k++ )
Vec_IntPush( vSlacks, -1 );
}
return tArrivalMax;
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);
}
/**Function*************************************************************
Synopsis [Find most-critical path (the path with smallest slacks).]
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) )
{
int iFanin = Vec_IntEntry( vBest, Abc_ObjId(pNode) );
assert( iFanin >= 0 );
Abc_NtkDelayTraceCritPathCollect_rec( vSlacks, Abc_ObjFanin(pNode, iFanin), vBest, vPath );
}
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*************************************************************

View File

@ -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.]

View File

@ -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 )

View File

@ -49,7 +49,7 @@ ABC_NAMESPACE_IMPL_START
***********************************************************************/
int Map_Mapping( Map_Man_t * p )
{
int fShowSwitching = 1;
int fShowSwitching = 0;
int fUseAreaFlow = 1;
int fUseExactArea = !p->fSwitching;
int fUseExactAreaWithPhase = !p->fSwitching;

View File

@ -231,6 +231,7 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
Abc_Ntk_t * pNet;
char * FileName;
int fVerbose;
double WireDelay;
int c;
pNet = Abc_FrameReadNtk(pAbc);
@ -238,12 +239,24 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
pErr = Abc_FrameReadErr(pAbc);
// set the defaults
WireDelay = 0.0;
fVerbose = 1;
Extra_UtilGetoptReset();
while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF )
while ( (c = Extra_UtilGetopt(argc, argv, "Wvh")) != EOF )
{
switch (c)
{
case 'W':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-W\" should be followed by a floating point number.\n" );
goto usage;
}
WireDelay = (float)atof(argv[globalUtilOptind]);
globalUtilOptind++;
if ( WireDelay <= 0.0 )
goto usage;
break;
case 'v':
fVerbose ^= 1;
break;
@ -280,6 +293,10 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
fprintf( pErr, "Reading GENLIB library has failed.\n" );
return 1;
}
// add the fixed number (wire delay) to all delays in the library
if ( WireDelay != 0.0 )
Mio_LibraryShift( pLib, WireDelay );
// free the current superlib because it depends on the old Mio library
if ( Abc_FrameReadLibSuper() )
{
@ -304,13 +321,14 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
return 0;
usage:
fprintf( pErr, "usage: read_library [-vh]\n");
fprintf( pErr, "\t read the library from a genlib file\n" );
fprintf( pErr, "\t (if the library contains more than one gate\n" );
fprintf( pErr, "\t with the same Boolean function, only the gate\n" );
fprintf( pErr, "\t with the smallest area will be used)\n" );
fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : enable verbose output\n");
fprintf( pErr, "usage: read_library [-W float] [-vh]\n");
fprintf( pErr, "\t read the library from a genlib file\n" );
fprintf( pErr, "\t (if the library contains more than one gate\n" );
fprintf( pErr, "\t with the same Boolean function, only the gate\n" );
fprintf( pErr, "\t with the smallest area will be used)\n" );
Abc_Print( -2, "\t-W float : wire delay (added to pin-to-pin gate delays) [default = %g]\n", WireDelay );
fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : enable verbose output\n");
return 1; /* error exit */
}

View File

@ -84,7 +84,6 @@ extern char * Mio_LibraryReadName ( Mio_Library_t * pLib );
extern int Mio_LibraryReadGateNum ( Mio_Library_t * pLib );
extern Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib );
extern Mio_Gate_t ** Mio_LibraryReadGatesByName( Mio_Library_t * pLib );
//extern DdManager * Mio_LibraryReadDd ( Mio_Library_t * pLib );
extern Mio_Gate_t * Mio_LibraryReadGateByName ( Mio_Library_t * pLib, char * pName );
extern char * Mio_LibraryReadSopByName ( Mio_Library_t * pLib, char * pName );
extern Mio_Gate_t * Mio_LibraryReadConst0 ( Mio_Library_t * pLib );
@ -114,7 +113,6 @@ extern Mio_Gate_t * Mio_GateReadNext ( Mio_Gate_t * pGate );
extern int Mio_GateReadInputs ( Mio_Gate_t * pGate );
extern double Mio_GateReadDelayMax ( Mio_Gate_t * pGate );
extern char * Mio_GateReadSop ( Mio_Gate_t * pGate );
//extern DdNode * Mio_GateReadFunc ( Mio_Gate_t * pGate );
extern word Mio_GateReadTruth ( Mio_Gate_t * pGate );
extern int Mio_GateReadValue ( Mio_Gate_t * pGate );
extern void Mio_GateSetValue ( Mio_Gate_t * pGate, int Value );
@ -150,8 +148,7 @@ extern void Mio_DeriveGateDelays( Mio_Gate_t * pGate,
float ** ptPinDelays, int nPins, int nInputs, float tDelayZero,
float * ptDelaysRes, float * ptPinDelayMax );
extern Mio_Gate_t * Mio_GateCreatePseudo( int nInputs );
extern void Mio_LibraryShift( Mio_Library_t * pLib, double Shift );
ABC_NAMESPACE_HEADER_END

View File

@ -72,7 +72,6 @@ struct Mio_LibraryStruct_t_
Mio_Gate_t * pGateNand2; // the NAND2 gate
Mio_Gate_t * pGateAnd2; // the AND2 gate
st_table * tName2Gate; // the mapping of gate names into their pointer
// DdManager * dd; // the nanager storing functions of gates
Mem_Flex_t * pMmFlex; // the memory manaqer for SOPs
Vec_Str_t * vCube; // temporary cube
};
@ -93,7 +92,6 @@ struct Mio_GateStruct_t_
// the derived information
int nInputs; // the number of inputs
double dDelayMax; // the maximum delay
// DdNode * bFunc; // the functionality
char * pSop; // sum-of-products
Vec_Int_t * vExpr; // boolean expression
union { word uTruth; // truth table

View File

@ -613,6 +613,34 @@ Mio_Gate_t * Mio_GateCreatePseudo( int nInputs )
return pGate;
}
/**Function*************************************************************
Synopsis [Adds constant value to all delay values.]
Description [The pseudo-gate is a N-input gate with all info set to 0.]
SideEffects []
SeeAlso []
***********************************************************************/
void Mio_LibraryShift( Mio_Library_t * pLib, double Shift )
{
Mio_Gate_t * pGate;
Mio_Pin_t * pPin;
Mio_LibraryForEachGate( pLib, pGate )
{
pGate->dDelayMax += Shift;
Mio_GateForEachPin( pGate, pPin )
{
pPin->dDelayBlockRise += Shift;
pPin->dDelayBlockFall += Shift;
pPin->dDelayBlockMax += Shift;
}
}
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////