mirror of https://github.com/YosysHQ/abc.git
Crtical path detection for AIGs.
This commit is contained in:
parent
4e1b34d744
commit
e76768b9d3
|
|
@ -3564,10 +3564,435 @@ void Gia_ManFindMutualEquivsTest()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**Function*************************************************************
|
||||||
|
|
||||||
|
Synopsis [Prints longest combinational paths between seq endpoints.]
|
||||||
|
|
||||||
|
Description []
|
||||||
|
|
||||||
|
SideEffects []
|
||||||
|
|
||||||
|
SeeAlso []
|
||||||
|
|
||||||
|
***********************************************************************/
|
||||||
|
static char * Gia_ManPrintPathNameFallback( Gia_Man_t * p, int fCi, int iTerm, char * pBuffer )
|
||||||
|
{
|
||||||
|
if ( fCi )
|
||||||
|
{
|
||||||
|
if ( iTerm < Gia_ManPiNum(p) )
|
||||||
|
sprintf( pBuffer, "pi%d", iTerm );
|
||||||
|
else
|
||||||
|
sprintf( pBuffer, "ro%d", iTerm - Gia_ManPiNum(p) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( iTerm < Gia_ManPoNum(p) )
|
||||||
|
sprintf( pBuffer, "po%d", iTerm );
|
||||||
|
else
|
||||||
|
sprintf( pBuffer, "ri%d", iTerm - Gia_ManPoNum(p) );
|
||||||
|
}
|
||||||
|
return pBuffer;
|
||||||
|
}
|
||||||
|
static int Gia_ManPrintPathNameBufferSize( Gia_Man_t * p )
|
||||||
|
{
|
||||||
|
Vec_Ptr_t * vNames;
|
||||||
|
char * pName;
|
||||||
|
int i, nSize = 64;
|
||||||
|
vNames = p->vNamesIn;
|
||||||
|
if ( vNames )
|
||||||
|
Vec_PtrForEachEntry( char *, vNames, pName, i )
|
||||||
|
if ( pName )
|
||||||
|
nSize = Abc_MaxInt( nSize, (int)strlen(pName) + 64 );
|
||||||
|
vNames = p->vNamesOut;
|
||||||
|
if ( vNames )
|
||||||
|
Vec_PtrForEachEntry( char *, vNames, pName, i )
|
||||||
|
if ( pName )
|
||||||
|
nSize = Abc_MaxInt( nSize, (int)strlen(pName) + 64 );
|
||||||
|
return nSize;
|
||||||
|
}
|
||||||
|
static void Gia_ManPrintPathCopyToken( char * pBuffer, char * pBeg, char * pEnd )
|
||||||
|
{
|
||||||
|
int nChars = pEnd ? (int)(pEnd - pBeg) : (int)strlen(pBeg);
|
||||||
|
memcpy( pBuffer, pBeg, nChars );
|
||||||
|
pBuffer[nChars] = 0;
|
||||||
|
}
|
||||||
|
static char * Gia_ManPrintPathName( Gia_Man_t * p, int fCi, int iTerm, char * pBuffer, int fFull, int fLeaf )
|
||||||
|
{
|
||||||
|
Vec_Ptr_t * vNames = fCi ? p->vNamesIn : p->vNamesOut;
|
||||||
|
char * pName = vNames && iTerm < Vec_PtrSize(vNames) ? (char *)Vec_PtrEntry(vNames, iTerm) : NULL;
|
||||||
|
char * pBeg, * pEnd, * pFirst, * pFirstEnd;
|
||||||
|
if ( pName == NULL )
|
||||||
|
return Gia_ManPrintPathNameFallback( p, fCi, iTerm, pBuffer );
|
||||||
|
if ( fFull )
|
||||||
|
return pName;
|
||||||
|
if ( fLeaf )
|
||||||
|
{
|
||||||
|
pBeg = strrchr( pName, ' ' );
|
||||||
|
return pBeg ? pBeg + 1 : pName;
|
||||||
|
}
|
||||||
|
pFirst = pName;
|
||||||
|
pFirstEnd = strchr( pFirst, ' ' );
|
||||||
|
for ( pBeg = pName; pBeg && *pBeg; pBeg = pEnd ? pEnd + 1 : NULL )
|
||||||
|
{
|
||||||
|
pEnd = strchr( pBeg, ' ' );
|
||||||
|
if ( strstr( pBeg, "reg_" ) && (pEnd == NULL || pEnd > strstr( pBeg, "reg_" )) )
|
||||||
|
{
|
||||||
|
Gia_ManPrintPathCopyToken( pBuffer, pBeg, pEnd );
|
||||||
|
return pBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Gia_ManPrintPathCopyToken( pBuffer, pFirst, pFirstEnd );
|
||||||
|
return pBuffer;
|
||||||
|
}
|
||||||
|
static char * Gia_ManPrintPathKind( Gia_Man_t * p, int fCi, int iTerm )
|
||||||
|
{
|
||||||
|
if ( fCi )
|
||||||
|
return iTerm < Gia_ManPiNum(p) ? (char *)"PI" : (char *)"RO";
|
||||||
|
return iTerm < Gia_ManPoNum(p) ? (char *)"PO" : (char *)"RI";
|
||||||
|
}
|
||||||
|
static int Gia_ManPrintPathTermIndex( Gia_Man_t * p, int fCi, int iTerm )
|
||||||
|
{
|
||||||
|
if ( fCi )
|
||||||
|
return iTerm < Gia_ManPiNum(p) ? iTerm : iTerm - Gia_ManPiNum(p);
|
||||||
|
return iTerm < Gia_ManPoNum(p) ? iTerm : iTerm - Gia_ManPoNum(p);
|
||||||
|
}
|
||||||
|
static int Gia_ManPrintPathParseBit( char * pName, char * pBase, int * pBit, char * pSuffix )
|
||||||
|
{
|
||||||
|
char * pLeft = strrchr( pName, '[' );
|
||||||
|
char * pRight = pLeft ? strchr( pLeft, ']' ) : NULL;
|
||||||
|
char * pTemp;
|
||||||
|
if ( pLeft == NULL || pRight == NULL )
|
||||||
|
return 0;
|
||||||
|
for ( pTemp = pLeft + 1; pTemp < pRight; pTemp++ )
|
||||||
|
if ( *pTemp < '0' || *pTemp > '9' )
|
||||||
|
return 0;
|
||||||
|
Gia_ManPrintPathCopyToken( pBase, pName, pLeft );
|
||||||
|
Gia_ManPrintPathCopyToken( pSuffix, pRight + 1, NULL );
|
||||||
|
*pBit = atoi( pLeft + 1 );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static void Gia_ManPrintPathFormatTermRange( char * pBuffer, char * pKind, int iBeg, int iEnd )
|
||||||
|
{
|
||||||
|
if ( iBeg == iEnd )
|
||||||
|
sprintf( pBuffer, "%s[%d]", pKind, iBeg );
|
||||||
|
else
|
||||||
|
sprintf( pBuffer, "%s[%d..%d]", pKind, iBeg, iEnd );
|
||||||
|
}
|
||||||
|
static void Gia_ManPrintPathFormatNameRange( char * pBuffer, char * pNameBeg, char * pNameEnd, int nNameSize )
|
||||||
|
{
|
||||||
|
char * BaseBeg, * BaseEnd, * SuffixBeg, * SuffixEnd;
|
||||||
|
int BitBeg, BitEnd;
|
||||||
|
if ( !strcmp(pNameBeg, pNameEnd) )
|
||||||
|
{
|
||||||
|
sprintf( pBuffer, "%s", pNameBeg );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BaseBeg = ABC_ALLOC( char, nNameSize );
|
||||||
|
BaseEnd = ABC_ALLOC( char, nNameSize );
|
||||||
|
SuffixBeg = ABC_ALLOC( char, nNameSize );
|
||||||
|
SuffixEnd = ABC_ALLOC( char, nNameSize );
|
||||||
|
if ( Gia_ManPrintPathParseBit(pNameBeg, BaseBeg, &BitBeg, SuffixBeg) &&
|
||||||
|
Gia_ManPrintPathParseBit(pNameEnd, BaseEnd, &BitEnd, SuffixEnd) &&
|
||||||
|
!strcmp(BaseBeg, BaseEnd) && !strcmp(SuffixBeg, SuffixEnd) )
|
||||||
|
sprintf( pBuffer, "%s[%d..%d]%s", BaseBeg, BitBeg, BitEnd, SuffixBeg );
|
||||||
|
else
|
||||||
|
sprintf( pBuffer, "%s..%s", pNameBeg, pNameEnd );
|
||||||
|
ABC_FREE( BaseBeg );
|
||||||
|
ABC_FREE( BaseEnd );
|
||||||
|
ABC_FREE( SuffixBeg );
|
||||||
|
ABC_FREE( SuffixEnd );
|
||||||
|
}
|
||||||
|
static int Gia_ManPrintPathCanGroup( Gia_Man_t * p, int Level0, int Source0, int Sink0, int Level1, int Source1, int Sink1, int nNameSize )
|
||||||
|
{
|
||||||
|
char * pStore, * Buffer0, * Buffer1, * Buffer2, * Buffer3, * Base0, * Base1, * Suffix0, * Suffix1;
|
||||||
|
int Bit0, Bit1;
|
||||||
|
int RetValue;
|
||||||
|
if ( Level0 != Level1 || Source0 != Source1 )
|
||||||
|
return 0;
|
||||||
|
if ( (Sink0 < Gia_ManPoNum(p)) != (Sink1 < Gia_ManPoNum(p)) )
|
||||||
|
return 0;
|
||||||
|
if ( Gia_ManPrintPathTermIndex(p, 0, Sink1) != Gia_ManPrintPathTermIndex(p, 0, Sink0) + 1 )
|
||||||
|
return 0;
|
||||||
|
pStore = ABC_ALLOC( char, 8 * nNameSize );
|
||||||
|
Buffer0 = pStore + 0 * nNameSize;
|
||||||
|
Buffer1 = pStore + 1 * nNameSize;
|
||||||
|
Buffer2 = pStore + 2 * nNameSize;
|
||||||
|
Buffer3 = pStore + 3 * nNameSize;
|
||||||
|
Base0 = pStore + 4 * nNameSize;
|
||||||
|
Base1 = pStore + 5 * nNameSize;
|
||||||
|
Suffix0 = pStore + 6 * nNameSize;
|
||||||
|
Suffix1 = pStore + 7 * nNameSize;
|
||||||
|
Gia_ManPrintPathName( p, 1, Source0, Buffer0, 0, 0 );
|
||||||
|
Gia_ManPrintPathName( p, 1, Source1, Buffer1, 0, 0 );
|
||||||
|
if ( strcmp(Buffer0, Buffer1) )
|
||||||
|
{
|
||||||
|
ABC_FREE( pStore );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Gia_ManPrintPathName( p, 1, Source0, Buffer0, 0, 1 );
|
||||||
|
Gia_ManPrintPathName( p, 1, Source1, Buffer1, 0, 1 );
|
||||||
|
if ( strcmp(Buffer0, Buffer1) )
|
||||||
|
{
|
||||||
|
ABC_FREE( pStore );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Gia_ManPrintPathName( p, 0, Sink0, Buffer2, 0, 0 );
|
||||||
|
Gia_ManPrintPathName( p, 0, Sink1, Buffer3, 0, 0 );
|
||||||
|
if ( !Gia_ManPrintPathParseBit(Buffer2, Base0, &Bit0, Suffix0) ||
|
||||||
|
!Gia_ManPrintPathParseBit(Buffer3, Base1, &Bit1, Suffix1) )
|
||||||
|
{
|
||||||
|
ABC_FREE( pStore );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
RetValue = !strcmp(Base0, Base1) && !strcmp(Suffix0, Suffix1) && Bit1 == Bit0 + 1;
|
||||||
|
ABC_FREE( pStore );
|
||||||
|
return RetValue;
|
||||||
|
}
|
||||||
|
static int Gia_ManPrintPathCandBetter( int Level0, int Source0, int Sink0, int Level1, int Source1, int Sink1 )
|
||||||
|
{
|
||||||
|
if ( Level0 != Level1 )
|
||||||
|
return Level0 > Level1;
|
||||||
|
if ( Source0 != Source1 )
|
||||||
|
return Source0 < Source1;
|
||||||
|
return Sink0 < Sink1;
|
||||||
|
}
|
||||||
|
static int Gia_ManPrintPathFaninBetter( int Level0, int Source0, int Level1, int Source1 )
|
||||||
|
{
|
||||||
|
if ( Source0 < 0 )
|
||||||
|
return 0;
|
||||||
|
if ( Source1 < 0 )
|
||||||
|
return 1;
|
||||||
|
if ( Level0 != Level1 )
|
||||||
|
return Level0 > Level1;
|
||||||
|
return Source0 < Source1;
|
||||||
|
}
|
||||||
|
static void Gia_ManPrintPathInsert( int * pLevels, int * pSources, int * pSinks, int * pDrivers, int * pnPaths, int nPathsMax, int Level, int Source, int Sink, int Driver )
|
||||||
|
{
|
||||||
|
int i, k, nPaths = *pnPaths;
|
||||||
|
if ( Source < 0 )
|
||||||
|
return;
|
||||||
|
for ( i = 0; i < nPaths; i++ )
|
||||||
|
if ( Gia_ManPrintPathCandBetter(Level, Source, Sink, pLevels[i], pSources[i], pSinks[i]) )
|
||||||
|
break;
|
||||||
|
if ( i == nPathsMax )
|
||||||
|
return;
|
||||||
|
if ( nPaths < nPathsMax )
|
||||||
|
nPaths++;
|
||||||
|
for ( k = nPaths - 1; k > i; k-- )
|
||||||
|
{
|
||||||
|
pLevels[k] = pLevels[k-1];
|
||||||
|
pSources[k] = pSources[k-1];
|
||||||
|
pSinks[k] = pSinks[k-1];
|
||||||
|
pDrivers[k] = pDrivers[k-1];
|
||||||
|
}
|
||||||
|
pLevels[i] = Level;
|
||||||
|
pSources[i] = Source;
|
||||||
|
pSinks[i] = Sink;
|
||||||
|
pDrivers[i] = Driver;
|
||||||
|
*pnPaths = nPaths;
|
||||||
|
}
|
||||||
|
static void Gia_ManPrintPathOne( Gia_Man_t * p, Vec_Int_t * vPreds, int Source, int Sink, int Driver, int nNameSize )
|
||||||
|
{
|
||||||
|
Vec_Int_t * vPath = Vec_IntAlloc( 100 );
|
||||||
|
char * pBuffer = ABC_ALLOC( char, 2 * nNameSize );
|
||||||
|
char * pBuffer0 = pBuffer;
|
||||||
|
char * pBuffer1 = pBuffer + nNameSize;
|
||||||
|
int i, Id;
|
||||||
|
for ( Id = Driver; Id > 0 && !Gia_ObjIsCi(Gia_ManObj(p, Id)); Id = Vec_IntEntry(vPreds, Id) )
|
||||||
|
{
|
||||||
|
Vec_IntPush( vPath, Id );
|
||||||
|
if ( Vec_IntEntry(vPreds, Id) < 0 )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf( " %s[%d] %s", Gia_ManPrintPathKind(p, 1, Source), Gia_ManPrintPathTermIndex(p, 1, Source), Gia_ManPrintPathName(p, 1, Source, pBuffer0, 1, 0) );
|
||||||
|
Vec_IntForEachEntryReverse( vPath, Id, i )
|
||||||
|
printf( " -> AND %d", Id );
|
||||||
|
printf( " -> %s[%d] %s\n", Gia_ManPrintPathKind(p, 0, Sink), Gia_ManPrintPathTermIndex(p, 0, Sink), Gia_ManPrintPathName(p, 0, Sink, pBuffer1, 1, 0) );
|
||||||
|
ABC_FREE( pBuffer );
|
||||||
|
Vec_IntFree( vPath );
|
||||||
|
}
|
||||||
|
void Gia_ManPrintPath( Gia_Man_t * p, int nPathsMax, int fVerbose, int fSummary )
|
||||||
|
{
|
||||||
|
Vec_Int_t * vLevels, * vSources, * vPreds;
|
||||||
|
Vec_Int_t * vGroupStarts, * vGroupEnds;
|
||||||
|
Gia_Obj_t * pObj;
|
||||||
|
int * pLevels, * pSources, * pSinks, * pDrivers;
|
||||||
|
int nGroupsMax = nPathsMax;
|
||||||
|
int nPathsAlloc, nNameSize, nLineSize, nSourceTermW, nSourceNameW, nSinkTermW;
|
||||||
|
int nPaths = 0, Counts[4] = {0}, MaxLevels[4] = {0};
|
||||||
|
int i, k, Id, FanId, Level, Source, Sink, Driver, Cost, LevelBest, SourceBest, FanBest, nGroups, iBeg, iEnd;
|
||||||
|
char * Buffer0, * Buffer1, * Buffer2, * Buffer3, * Buffer4, * Buffer5, * Buffer6, * Buffer7, * Buffer8, * Buffer9, * Buffer10;
|
||||||
|
if ( nPathsMax < 1 )
|
||||||
|
nPathsMax = 1;
|
||||||
|
nGroupsMax = nPathsMax;
|
||||||
|
nPathsAlloc = Abc_MinInt( Gia_ManCoNum(p), Abc_MaxInt(32 * nGroupsMax, nGroupsMax) );
|
||||||
|
nNameSize = Gia_ManPrintPathNameBufferSize( p );
|
||||||
|
nLineSize = 4 * nNameSize + 100;
|
||||||
|
Buffer0 = ABC_ALLOC( char, nNameSize );
|
||||||
|
Buffer1 = ABC_ALLOC( char, nNameSize );
|
||||||
|
Buffer2 = ABC_ALLOC( char, nNameSize );
|
||||||
|
Buffer3 = ABC_ALLOC( char, nNameSize );
|
||||||
|
Buffer4 = ABC_ALLOC( char, nNameSize );
|
||||||
|
Buffer5 = ABC_ALLOC( char, nNameSize );
|
||||||
|
Buffer6 = ABC_ALLOC( char, nNameSize );
|
||||||
|
Buffer7 = ABC_ALLOC( char, nLineSize );
|
||||||
|
Buffer8 = ABC_ALLOC( char, nLineSize );
|
||||||
|
Buffer9 = ABC_ALLOC( char, nLineSize );
|
||||||
|
Buffer10 = ABC_ALLOC( char, nLineSize );
|
||||||
|
vGroupStarts = Vec_IntAlloc( nGroupsMax );
|
||||||
|
vGroupEnds = Vec_IntAlloc( nGroupsMax );
|
||||||
|
vLevels = Vec_IntStart( Gia_ManObjNum(p) );
|
||||||
|
vSources = Vec_IntStartFull( Gia_ManObjNum(p) );
|
||||||
|
vPreds = Vec_IntStartFull( Gia_ManObjNum(p) );
|
||||||
|
Gia_ManForEachObj( p, pObj, i )
|
||||||
|
{
|
||||||
|
Id = Gia_ObjId( p, pObj );
|
||||||
|
if ( Gia_ObjIsCi(pObj) )
|
||||||
|
{
|
||||||
|
Vec_IntWriteEntry( vLevels, Id, 0 );
|
||||||
|
Vec_IntWriteEntry( vSources, Id, Gia_ObjCioId(pObj) );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( !Gia_ObjIsAnd(pObj) )
|
||||||
|
continue;
|
||||||
|
Cost = (!p->fGiaSimple && Gia_ObjIsBuf(pObj)) ? 0 : (Gia_ObjIsMux(p, pObj) || Gia_ObjIsXor(pObj) ? 2 : 1);
|
||||||
|
LevelBest = SourceBest = FanBest = -1;
|
||||||
|
for ( k = 0; k < Gia_ObjFaninNum(p, pObj); k++ )
|
||||||
|
{
|
||||||
|
FanId = k == 2 ? Gia_ObjFaninId2(p, Id) : Gia_ObjFaninId(pObj, Id, k);
|
||||||
|
Level = Vec_IntEntry( vLevels, FanId );
|
||||||
|
Source = Vec_IntEntry( vSources, FanId );
|
||||||
|
if ( Gia_ManPrintPathFaninBetter(Level, Source, LevelBest, SourceBest) )
|
||||||
|
LevelBest = Level, SourceBest = Source, FanBest = FanId;
|
||||||
|
}
|
||||||
|
Vec_IntWriteEntry( vLevels, Id, LevelBest + Cost );
|
||||||
|
Vec_IntWriteEntry( vSources, Id, SourceBest );
|
||||||
|
Vec_IntWriteEntry( vPreds, Id, FanBest );
|
||||||
|
}
|
||||||
|
pLevels = ABC_ALLOC( int, nPathsAlloc );
|
||||||
|
pSources = ABC_ALLOC( int, nPathsAlloc );
|
||||||
|
pSinks = ABC_ALLOC( int, nPathsAlloc );
|
||||||
|
pDrivers = ABC_ALLOC( int, nPathsAlloc );
|
||||||
|
Gia_ManForEachCo( p, pObj, i )
|
||||||
|
{
|
||||||
|
Driver = Gia_ObjFaninId0p( p, pObj );
|
||||||
|
Level = Vec_IntEntry( vLevels, Driver );
|
||||||
|
Source = Vec_IntEntry( vSources, Driver );
|
||||||
|
Sink = Gia_ObjCioId( pObj );
|
||||||
|
if ( Source >= 0 )
|
||||||
|
{
|
||||||
|
k = (Source >= Gia_ManPiNum(p) ? 2 : 0) + (Sink >= Gia_ManPoNum(p) ? 1 : 0);
|
||||||
|
Counts[k]++;
|
||||||
|
MaxLevels[k] = Abc_MaxInt( MaxLevels[k], Level );
|
||||||
|
}
|
||||||
|
Gia_ManPrintPathInsert( pLevels, pSources, pSinks, pDrivers, &nPaths, nPathsAlloc, Level, Source, Sink, Driver );
|
||||||
|
}
|
||||||
|
for ( i = 0, nGroups = 0; i < nPaths && nGroups < nGroupsMax; i = iEnd + 1, nGroups++ )
|
||||||
|
{
|
||||||
|
iBeg = iEnd = i;
|
||||||
|
while ( iEnd + 1 < nPaths && Gia_ManPrintPathCanGroup(p, pLevels[iEnd], pSources[iEnd], pSinks[iEnd], pLevels[iEnd+1], pSources[iEnd+1], pSinks[iEnd+1], nNameSize) )
|
||||||
|
iEnd++;
|
||||||
|
Vec_IntPush( vGroupStarts, iBeg );
|
||||||
|
Vec_IntPush( vGroupEnds, iEnd );
|
||||||
|
}
|
||||||
|
nSourceTermW = (int)strlen( "source" );
|
||||||
|
nSourceNameW = 0;
|
||||||
|
nSinkTermW = (int)strlen( "sink" );
|
||||||
|
Vec_IntForEachEntry( vGroupStarts, iBeg, i )
|
||||||
|
{
|
||||||
|
char * pSourceName, * pSourceLeaf, * pSinkNameBeg, * pSinkNameEnd, * pSinkLeafBeg, * pSinkLeafEnd;
|
||||||
|
iEnd = Vec_IntEntry( vGroupEnds, i );
|
||||||
|
pSourceName = Gia_ManPrintPathName(p, 1, pSources[iBeg], Buffer0, 0, 0);
|
||||||
|
pSourceLeaf = Gia_ManPrintPathName(p, 1, pSources[iBeg], Buffer1, 0, 1);
|
||||||
|
pSinkNameBeg = Gia_ManPrintPathName(p, 0, pSinks[iBeg], Buffer2, 0, 0);
|
||||||
|
pSinkNameEnd = Gia_ManPrintPathName(p, 0, pSinks[iEnd], Buffer3, 0, 0);
|
||||||
|
pSinkLeafBeg = Gia_ManPrintPathName(p, 0, pSinks[iBeg], Buffer4, 0, 1);
|
||||||
|
pSinkLeafEnd = Gia_ManPrintPathName(p, 0, pSinks[iEnd], Buffer5, 0, 1);
|
||||||
|
Gia_ManPrintPathFormatTermRange( Buffer6, Gia_ManPrintPathKind(p, 1, pSources[iBeg]), Gia_ManPrintPathTermIndex(p, 1, pSources[iBeg]), Gia_ManPrintPathTermIndex(p, 1, pSources[iBeg]) );
|
||||||
|
sprintf( Buffer7, "%s", pSourceName );
|
||||||
|
if ( strcmp(pSourceName, pSourceLeaf) )
|
||||||
|
sprintf( Buffer7 + strlen(Buffer7), "->%s", pSourceLeaf );
|
||||||
|
Gia_ManPrintPathFormatTermRange( Buffer8, Gia_ManPrintPathKind(p, 0, pSinks[iBeg]), Gia_ManPrintPathTermIndex(p, 0, pSinks[iBeg]), Gia_ManPrintPathTermIndex(p, 0, pSinks[iEnd]) );
|
||||||
|
Gia_ManPrintPathFormatNameRange( Buffer9, pSinkNameBeg, pSinkNameEnd, nNameSize );
|
||||||
|
if ( strcmp(pSinkLeafBeg, pSinkLeafEnd) )
|
||||||
|
Gia_ManPrintPathFormatNameRange( Buffer10, pSinkLeafBeg, pSinkLeafEnd, nNameSize );
|
||||||
|
else
|
||||||
|
sprintf( Buffer10, "%s", pSinkLeafBeg );
|
||||||
|
if ( strcmp(Buffer9, Buffer10) )
|
||||||
|
sprintf( Buffer9 + strlen(Buffer9), "<-%s", Buffer10 );
|
||||||
|
nSourceTermW = Abc_MaxInt( nSourceTermW, (int)strlen(Buffer6) );
|
||||||
|
nSourceNameW = Abc_MaxInt( nSourceNameW, (int)strlen(Buffer7) );
|
||||||
|
nSinkTermW = Abc_MaxInt( nSinkTermW, (int)strlen(Buffer8) );
|
||||||
|
}
|
||||||
|
printf( "Grouped critical combinational paths:\n" );
|
||||||
|
printf( " rank paths lev %-*s %-*s %-*s %s\n", nSourceTermW, "source", nSourceNameW, "", nSinkTermW, "sink", "" );
|
||||||
|
Vec_IntForEachEntry( vGroupStarts, iBeg, i )
|
||||||
|
{
|
||||||
|
char * pSourceName, * pSourceLeaf, * pSinkNameBeg, * pSinkNameEnd, * pSinkLeafBeg, * pSinkLeafEnd;
|
||||||
|
iEnd = Vec_IntEntry( vGroupEnds, i );
|
||||||
|
pSourceName = Gia_ManPrintPathName(p, 1, pSources[iBeg], Buffer0, 0, 0);
|
||||||
|
pSourceLeaf = Gia_ManPrintPathName(p, 1, pSources[iBeg], Buffer1, 0, 1);
|
||||||
|
pSinkNameBeg = Gia_ManPrintPathName(p, 0, pSinks[iBeg], Buffer2, 0, 0);
|
||||||
|
pSinkNameEnd = Gia_ManPrintPathName(p, 0, pSinks[iEnd], Buffer3, 0, 0);
|
||||||
|
pSinkLeafBeg = Gia_ManPrintPathName(p, 0, pSinks[iBeg], Buffer4, 0, 1);
|
||||||
|
pSinkLeafEnd = Gia_ManPrintPathName(p, 0, pSinks[iEnd], Buffer5, 0, 1);
|
||||||
|
Gia_ManPrintPathFormatTermRange( Buffer6, Gia_ManPrintPathKind(p, 1, pSources[iBeg]), Gia_ManPrintPathTermIndex(p, 1, pSources[iBeg]), Gia_ManPrintPathTermIndex(p, 1, pSources[iBeg]) );
|
||||||
|
sprintf( Buffer7, "%s", pSourceName );
|
||||||
|
if ( strcmp(pSourceName, pSourceLeaf) )
|
||||||
|
sprintf( Buffer7 + strlen(Buffer7), "->%s", pSourceLeaf );
|
||||||
|
Gia_ManPrintPathFormatTermRange( Buffer8, Gia_ManPrintPathKind(p, 0, pSinks[iBeg]), Gia_ManPrintPathTermIndex(p, 0, pSinks[iBeg]), Gia_ManPrintPathTermIndex(p, 0, pSinks[iEnd]) );
|
||||||
|
Gia_ManPrintPathFormatNameRange( Buffer9, pSinkNameBeg, pSinkNameEnd, nNameSize );
|
||||||
|
if ( strcmp(pSinkLeafBeg, pSinkLeafEnd) )
|
||||||
|
Gia_ManPrintPathFormatNameRange( Buffer10, pSinkLeafBeg, pSinkLeafEnd, nNameSize );
|
||||||
|
else
|
||||||
|
sprintf( Buffer10, "%s", pSinkLeafBeg );
|
||||||
|
if ( strcmp(Buffer9, Buffer10) )
|
||||||
|
sprintf( Buffer9 + strlen(Buffer9), "<-%s", Buffer10 );
|
||||||
|
if ( iBeg == iEnd )
|
||||||
|
sprintf( Buffer4, "%d", iBeg + 1 );
|
||||||
|
else
|
||||||
|
sprintf( Buffer4, "%d..%d", iBeg + 1, iEnd + 1 );
|
||||||
|
printf( "%5d %-7s %3d %-*s %-*s %-*s %s\n", i + 1, Buffer4, pLevels[iBeg], nSourceTermW, Buffer6, nSourceNameW, Buffer7, nSinkTermW, Buffer8, Buffer9 );
|
||||||
|
}
|
||||||
|
if ( fVerbose )
|
||||||
|
{
|
||||||
|
printf( "\nAIG paths:\n" );
|
||||||
|
Vec_IntForEachEntry( vGroupStarts, iBeg, i )
|
||||||
|
Gia_ManPrintPathOne( p, vPreds, pSources[iBeg], pSinks[iBeg], pDrivers[iBeg], nNameSize );
|
||||||
|
}
|
||||||
|
if ( fSummary )
|
||||||
|
{
|
||||||
|
printf( "\nEndpoint summary:\n" );
|
||||||
|
printf( " PI->PO : paths = %7d max levels = %6d\n", Counts[0], MaxLevels[0] );
|
||||||
|
printf( " PI->RI : paths = %7d max levels = %6d\n", Counts[1], MaxLevels[1] );
|
||||||
|
printf( " RO->PO : paths = %7d max levels = %6d\n", Counts[2], MaxLevels[2] );
|
||||||
|
printf( " RO->RI : paths = %7d max levels = %6d\n", Counts[3], MaxLevels[3] );
|
||||||
|
}
|
||||||
|
ABC_FREE( pLevels );
|
||||||
|
ABC_FREE( pSources );
|
||||||
|
ABC_FREE( pSinks );
|
||||||
|
ABC_FREE( pDrivers );
|
||||||
|
ABC_FREE( Buffer0 );
|
||||||
|
ABC_FREE( Buffer1 );
|
||||||
|
ABC_FREE( Buffer2 );
|
||||||
|
ABC_FREE( Buffer3 );
|
||||||
|
ABC_FREE( Buffer4 );
|
||||||
|
ABC_FREE( Buffer5 );
|
||||||
|
ABC_FREE( Buffer6 );
|
||||||
|
ABC_FREE( Buffer7 );
|
||||||
|
ABC_FREE( Buffer8 );
|
||||||
|
ABC_FREE( Buffer9 );
|
||||||
|
ABC_FREE( Buffer10 );
|
||||||
|
Vec_IntFree( vLevels );
|
||||||
|
Vec_IntFree( vSources );
|
||||||
|
Vec_IntFree( vPreds );
|
||||||
|
Vec_IntFreeP( &vGroupStarts );
|
||||||
|
Vec_IntFreeP( &vGroupEnds );
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
/// END OF FILE ///
|
/// END OF FILE ///
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
ABC_NAMESPACE_IMPL_END
|
ABC_NAMESPACE_IMPL_END
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -668,6 +668,7 @@ static int Abc_CommandAbc9Divide ( Abc_Frame_t * pAbc, int argc, cha
|
||||||
static int Abc_CommandAbc9Pipeline ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
static int Abc_CommandAbc9Pipeline ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||||
static int Abc_CommandAbc9Unpipeline ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
static int Abc_CommandAbc9Unpipeline ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||||
static int Abc_CommandAbc9Regio ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
static int Abc_CommandAbc9Regio ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||||
|
static int Abc_CommandAbc9PrintPath ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||||
|
|
||||||
static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||||
|
|
||||||
|
|
@ -1527,6 +1528,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
|
||||||
Cmd_CommandAdd( pAbc, "ABC9", "&unpipe", Abc_CommandAbc9Unpipeline, 0 );
|
Cmd_CommandAdd( pAbc, "ABC9", "&unpipe", Abc_CommandAbc9Unpipeline, 0 );
|
||||||
Cmd_CommandAdd( pAbc, "ABC9", "®io", Abc_CommandAbc9Regio, 0 );
|
Cmd_CommandAdd( pAbc, "ABC9", "®io", Abc_CommandAbc9Regio, 0 );
|
||||||
|
|
||||||
|
Cmd_CommandAdd( pAbc, "ABC9", "&print_path", Abc_CommandAbc9PrintPath, 0 );
|
||||||
Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 );
|
Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 );
|
||||||
|
|
||||||
Cmd_CommandAdd( pAbc, "ABC9", "&eslim", Abc_CommandAbc9eSLIM, 0 );
|
Cmd_CommandAdd( pAbc, "ABC9", "&eslim", Abc_CommandAbc9eSLIM, 0 );
|
||||||
|
|
@ -61267,6 +61269,67 @@ usage:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Function*************************************************************
|
||||||
|
|
||||||
|
Synopsis []
|
||||||
|
|
||||||
|
Description []
|
||||||
|
|
||||||
|
SideEffects []
|
||||||
|
|
||||||
|
SeeAlso []
|
||||||
|
|
||||||
|
***********************************************************************/
|
||||||
|
int Abc_CommandAbc9PrintPath( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||||
|
{
|
||||||
|
extern void Gia_ManPrintPath( Gia_Man_t * p, int nPaths, int fVerbose, int fSummary );
|
||||||
|
int c, nPaths = 10, fVerbose = 0, fSummary = 0;
|
||||||
|
Extra_UtilGetoptReset();
|
||||||
|
while ( ( c = Extra_UtilGetopt( argc, argv, "Nvsh" ) ) != EOF )
|
||||||
|
{
|
||||||
|
switch ( c )
|
||||||
|
{
|
||||||
|
case 'N':
|
||||||
|
if ( globalUtilOptind >= argc )
|
||||||
|
{
|
||||||
|
Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
|
nPaths = atoi(argv[globalUtilOptind]);
|
||||||
|
globalUtilOptind++;
|
||||||
|
if ( nPaths < 1 )
|
||||||
|
goto usage;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
fVerbose ^= 1;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
fSummary ^= 1;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
goto usage;
|
||||||
|
default:
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( pAbc->pGia == NULL )
|
||||||
|
{
|
||||||
|
Abc_Print( -1, "Abc_CommandAbc9PrintPath(): There is no AIG.\n" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Gia_ManPrintPath( pAbc->pGia, nPaths, fVerbose, fSummary );
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
usage:
|
||||||
|
Abc_Print( -2, "usage: &print_path [-N num] [-vsh]\n" );
|
||||||
|
Abc_Print( -2, "\t prints longest combinational paths between sequential endpoints\n" );
|
||||||
|
Abc_Print( -2, "\t-N num : number of path groups to print [default = %d]\n", nPaths );
|
||||||
|
Abc_Print( -2, "\t-v : toggle printing one AIG path for each path group [default = %s]\n", fVerbose? "yes": "no" );
|
||||||
|
Abc_Print( -2, "\t-s : toggle printing endpoint category summary [default = %s]\n", fSummary? "yes": "no" );
|
||||||
|
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**Function*************************************************************
|
/**Function*************************************************************
|
||||||
|
|
||||||
Synopsis []
|
Synopsis []
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue