mirror of https://github.com/YosysHQ/abc.git
Extending &funtrace to trace functions found in an AIG.
This commit is contained in:
parent
71b409b778
commit
4156a88dbb
|
|
@ -1108,6 +1108,128 @@ Vec_Ptr_t * Gia_ManMatchCutsArray( Vec_Ptr_t * vTtMems, Gia_Man_t * pGia, int nC
|
|||
return vRes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Function enumeration.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Wrd_t * Gia_ManCollectCutFuncs( Gia_Man_t * p, int nCutSize, int nCutNum, int fVerbose )
|
||||
{
|
||||
Gia_Sto_t * pSto = Gia_ManMatchCutsInt( p, nCutSize, nCutNum, 0 );
|
||||
Vec_Wrd_t * vFuncs = Vec_WrdAlloc( 1000 ); Vec_Int_t * vLevel; int i, k, * pCut;
|
||||
Vec_WecForEachLevel( pSto->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) )
|
||||
Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] == nCutSize ) {
|
||||
word * pTruth = Vec_MemReadEntry( pSto->vTtMem, Abc_Lit2Var(pCut[pCut[0]+1]) );
|
||||
Vec_WrdPush( vFuncs, pTruth[0] );
|
||||
}
|
||||
Gia_StoFree( pSto );
|
||||
if ( fVerbose )
|
||||
printf( "Collected %d cut functions using the AIG with %d nodes.\n", Vec_WrdSize(vFuncs), Gia_ManAndNum(p) );
|
||||
return vFuncs;
|
||||
}
|
||||
Vec_Int_t * Gia_ManCountNpnClasses( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, int nClasses, Vec_Wrd_t * vOrig )
|
||||
{
|
||||
assert( Vec_MemEntryNum(vTtMem) == Vec_IntSize(vMap) );
|
||||
Vec_Int_t * vClassCounts = Vec_IntStart( nClasses ); int i; word Func;
|
||||
Vec_WrdForEachEntry( vOrig, Func, i ) {
|
||||
int * pSpot = Vec_MemHashLookup( vTtMem, &Func );
|
||||
if ( *pSpot == -1 )
|
||||
continue;
|
||||
int iClass = Vec_IntEntry( vMap, *pSpot );
|
||||
if ( iClass == -1 )
|
||||
continue;
|
||||
assert( iClass < Vec_IntSize(vClassCounts) );
|
||||
Vec_IntAddToEntry( vClassCounts, iClass, 1 );
|
||||
}
|
||||
return vClassCounts;
|
||||
}
|
||||
Vec_Wrd_t * Gia_ManMatchFilterClasses( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, Vec_Int_t * vClassCounts, int nNumFuncs, int fVerbose )
|
||||
{
|
||||
int * pPerm = Abc_MergeSortCost( Vec_IntArray(vClassCounts), Vec_IntSize(vClassCounts) );
|
||||
Vec_Wrd_t * vBest = Vec_WrdAlloc( nNumFuncs ); int i, k, Entry;
|
||||
Vec_Int_t * vMapNew = Vec_IntStartFull( Vec_IntSize(vMap) );
|
||||
for ( i = Vec_IntSize(vClassCounts)-1; i >= 0; i-- ) {
|
||||
word Best = ~(word)0;
|
||||
Vec_IntForEachEntry( vMap, Entry, k ) {
|
||||
if ( Entry != pPerm[i] )
|
||||
continue;
|
||||
if ( Best > Vec_MemReadEntry(vTtMem, k)[0] )
|
||||
Best = Vec_MemReadEntry(vTtMem, k)[0];
|
||||
Vec_IntWriteEntry( vMapNew, k, Vec_WrdSize(vBest) );
|
||||
}
|
||||
Vec_WrdPush( vBest, Best );
|
||||
assert( ~Best );
|
||||
if ( Vec_WrdSize(vBest) == nNumFuncs )
|
||||
break;
|
||||
}
|
||||
ABC_SWAP( Vec_Int_t, *vMap, *vMapNew );
|
||||
Vec_IntFree( vMapNew );
|
||||
ABC_FREE( pPerm );
|
||||
if ( fVerbose )
|
||||
printf( "Isolated %d (out of %d) most frequently occuring classes.\n", Vec_WrdSize(vBest), Vec_IntSize(vClassCounts) );
|
||||
return vBest;
|
||||
}
|
||||
void Gia_ManMatchProfileFunctions( Vec_Wrd_t * vBestReprs, Vec_Mem_t * vTtMem, Vec_Int_t * vMap, Vec_Wrd_t * vFuncs, int nCutSize )
|
||||
{
|
||||
int BarSize = 60;
|
||||
extern void Dau_DsdPrintFromTruth( word * pTruth, int nVarsInit );
|
||||
Vec_Int_t * vCounts = Gia_ManCountNpnClasses( vTtMem, vMap, Vec_WrdSize(vBestReprs), vFuncs );
|
||||
word Repr; int c, i, MaxCount = Vec_IntFindMax( vCounts );
|
||||
Vec_WrdForEachEntry( vBestReprs, Repr, c )
|
||||
{
|
||||
int nSymb = BarSize*Vec_IntEntry(vCounts, c)/Abc_MaxInt(MaxCount, 1);
|
||||
printf( "Class%4d : ", c );
|
||||
printf( "Count =%6d ", Vec_IntEntry(vCounts, c) );
|
||||
for ( i = 0; i < nSymb; i++ )
|
||||
printf( "*" );
|
||||
for ( i = nSymb; i < BarSize+3; i++ )
|
||||
printf( " " );
|
||||
Dau_DsdPrintFromTruth( &Repr, nCutSize );
|
||||
}
|
||||
Vec_IntFree( vCounts );
|
||||
}
|
||||
void Gia_ManMatchCones( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutSize, int nCutNum, int nNumFuncs, int nNumCones, int fVerbose )
|
||||
{
|
||||
abctime clkStart = Abc_Clock();
|
||||
extern void Dau_CanonicizeArray( Vec_Wrd_t * vFuncs, int nVars, int fVerbose );
|
||||
extern Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int_t ** pvMap, int fVerbose );
|
||||
Vec_Wrd_t * vFuncs = Gia_ManCollectCutFuncs( pSmall, nCutSize, nCutNum, fVerbose );
|
||||
Vec_Wrd_t * vOrig = Vec_WrdDup( vFuncs );
|
||||
Dau_CanonicizeArray( vFuncs, nCutSize, fVerbose );
|
||||
Vec_Int_t * vMap = NULL; int n;
|
||||
Vec_Mem_t * vTtMem = Dau_CollectNpnFunctionsArray( vFuncs, nCutSize, &vMap, fVerbose );
|
||||
Vec_WrdFree( vFuncs );
|
||||
Vec_Int_t * vClassCounts = Gia_ManCountNpnClasses( vTtMem, vMap, Vec_IntEntryLast(vMap)+1, vOrig );
|
||||
Vec_Wrd_t * vBestReprs = Gia_ManMatchFilterClasses( vTtMem, vMap, vClassCounts, nNumFuncs, fVerbose );
|
||||
assert( Vec_WrdSize(vBestReprs) == nNumFuncs );
|
||||
Vec_IntFree( vClassCounts );
|
||||
printf( "Frequency profile for %d most popular classes in the small AIG:\n", nNumFuncs );
|
||||
Gia_ManMatchProfileFunctions( vBestReprs, vTtMem, vMap, vOrig, nCutSize );
|
||||
Vec_WrdFree( vOrig );
|
||||
Abc_Random( 1 );
|
||||
for ( n = 0; n < nNumCones; n++ ) {
|
||||
int nRand = Abc_Random( 0 ) % Gia_ManCoNum(pBig);
|
||||
Gia_Man_t * pCone = Gia_ManDupCones( pBig, &nRand, 1, 1 );
|
||||
Vec_Wrd_t * vCutFuncs = Gia_ManCollectCutFuncs( pCone, nCutSize, nCutNum, 0 );
|
||||
printf( "ITER %d: Considering output cone %d with %d and-nodes. ", n+1, nRand, Gia_ManAndNum(pCone) );
|
||||
printf( "Profiling %d functions of %d-cuts:\n", Vec_WrdSize(vCutFuncs), nCutSize );
|
||||
Gia_ManMatchProfileFunctions( vBestReprs, vTtMem, vMap, vCutFuncs, nCutSize );
|
||||
Vec_WrdFree( vCutFuncs );
|
||||
Gia_ManStop( pCone );
|
||||
}
|
||||
Vec_WrdFree( vBestReprs );
|
||||
Vec_IntFree( vMap );
|
||||
Vec_MemHashFree( vTtMem );
|
||||
Vec_MemFree( vTtMem );
|
||||
Abc_PrintTime( 1, "Total computation time", Abc_Clock() - clkStart );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -54209,10 +54209,10 @@ int Abc_CommandAbc9FunTrace( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
{
|
||||
extern Vec_Mem_t * Dau_CollectNpnFunctions( word * p, int nVars, int fVerbose );
|
||||
extern void Gia_ManMatchCuts( Vec_Mem_t * vTtMem, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose );
|
||||
int c, nVars, nVars2, nCutNum = 8, fVerbose = 0; word * pTruth = NULL;
|
||||
char * pStr = NULL; Vec_Mem_t * vTtMem = NULL;
|
||||
int c, nVars, nVars2, nCutNum = 8, nCutSize = 0, nNumFuncs = 5, nNumCones = 3, fVerbose = 0; word * pTruth = NULL;
|
||||
char * pStr = NULL; Vec_Mem_t * vTtMem = NULL; Gia_Man_t * pTemp;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "Cvh" ) ) != EOF )
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "CKNMvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
|
|
@ -54227,6 +54227,39 @@ int Abc_CommandAbc9FunTrace( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
if ( nCutNum < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'K':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
nCutSize = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( nCutSize < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'N':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
nNumFuncs = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( nNumFuncs < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'M':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
nNumCones = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( nNumCones < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
|
|
@ -54246,6 +54279,22 @@ int Abc_CommandAbc9FunTrace( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
Abc_Print( -1, "Abc_CommandAbc9FunTrace(): Truth table in hex notation should be given on the command line.\n" );
|
||||
return 0;
|
||||
}
|
||||
if ( strstr(argv[globalUtilOptind], ".aig") )
|
||||
{ // the entry on the command line is an AIGER file
|
||||
extern void Gia_ManMatchCones( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutSize, int nCutNum, int nNumFuncs, int nNumCones, int fVerbose );
|
||||
if ( nCutSize == 0 ) {
|
||||
Abc_Print( -1, "Abc_CommandAbc9FunTrace(): The LUT size for profiling should be given on the command line.\n" );
|
||||
return 0;
|
||||
}
|
||||
pTemp = Gia_AigerRead( argv[globalUtilOptind], 0, 0, 0 );
|
||||
if ( pTemp == NULL ) {
|
||||
Abc_Print( -1, "Abc_CommandAbc9FunTrace(): Cannot read input AIG \"%s\".\n", argv[globalUtilOptind] );
|
||||
return 0;
|
||||
}
|
||||
Gia_ManMatchCones( pAbc->pGia, pTemp, nCutSize, nCutNum, nNumFuncs, nNumCones, fVerbose );
|
||||
Gia_ManStop( pTemp );
|
||||
return 0;
|
||||
}
|
||||
pStr = argv[globalUtilOptind];
|
||||
if ( pStr[0] == '0' && pStr[1] == 'x' )
|
||||
pStr += 2;
|
||||
|
|
@ -54271,12 +54320,16 @@ int Abc_CommandAbc9FunTrace( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
return 0;
|
||||
|
||||
usage:
|
||||
Abc_Print( -2, "usage: &funtrace [-C num] [-vh] <truth>\n" );
|
||||
Abc_Print( -2, "usage: &funtrace [-CKNM num] [-vh] {<truth> or <file.aig>}\n" );
|
||||
Abc_Print( -2, "\t traces the presence of the function in the current AIG\n" );
|
||||
Abc_Print( -2, "\t-C num : the number of cuts to compute at each node [default = %d]\n", nCutNum );
|
||||
Abc_Print( -2, "\t-K num : the LUT size to use when <file.aig> is given [default = %d]\n", nCutSize );
|
||||
Abc_Print( -2, "\t-N num : the number of functions to use when <file.aig> is given [default = %d]\n", nNumFuncs );
|
||||
Abc_Print( -2, "\t-M num : the number of logic cones to use when <file.aig> is given [default = %d]\n", nNumCones );
|
||||
Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose ? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
Abc_Print( -2, "\t<truth> : truth table in the hexadecimal notation\n");
|
||||
Abc_Print( -2, "\t<truth> : truth table in the hexadecimal notation used for tracing\n");
|
||||
Abc_Print( -2, "\t<file> : AIG whose K-input functions will be used for tracing\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -859,6 +859,119 @@ Vec_Mem_t * Dau_CollectNpnFunctions( word * p, int nVars, int fVerbose )
|
|||
return vTtMem;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Compute NPN class members.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int_t ** pvMap, int fVerbose )
|
||||
{
|
||||
abctime clkStart = Abc_Clock();
|
||||
Vec_Int_t * vMap = Vec_IntAlloc( 100 );
|
||||
Vec_Int_t * vCnts = Vec_IntAlloc( Vec_WrdSize(vFuncs) );
|
||||
Vec_Mem_t * vTtMem = Vec_MemAllocForTTSimple( nVars );
|
||||
int nWords = Abc_Truth6WordNum(nVars);
|
||||
int nPerms = Extra_Factorial( nVars );
|
||||
int nMints = 1 << nVars;
|
||||
int * pPerm = Extra_PermSchedule( nVars );
|
||||
int * pComp = Extra_GreyCodeSchedule( nVars );
|
||||
int m, i, k, t, Entry; word Truth;
|
||||
assert( nWords == 1 );
|
||||
Vec_WrdForEachEntry( vFuncs, Truth, t )
|
||||
{
|
||||
int nFuncs = Vec_MemEntryNum(vTtMem);
|
||||
Truth = (Truth & 1) ? ~Truth : Truth;
|
||||
word pCopy[1] = {Truth};
|
||||
Vec_MemHashInsert( vTtMem, pCopy );
|
||||
for ( m = 0; m < nMints; m++ ) {
|
||||
Abc_TtFlip( pCopy, nWords, pComp[m] );
|
||||
if ( pCopy[0] & 1 ) {
|
||||
Abc_TtNot( pCopy, nWords );
|
||||
assert( (pCopy[0] & 1) == 0 );
|
||||
Vec_MemHashInsert( vTtMem, pCopy );
|
||||
Abc_TtNot( pCopy, nWords );
|
||||
}
|
||||
else
|
||||
Vec_MemHashInsert( vTtMem, pCopy );
|
||||
}
|
||||
assert( Abc_TtEqual(pCopy, &Truth, nWords) );
|
||||
for ( i = 0; i < nFuncs; i++ ) {
|
||||
Abc_TtCopy( pCopy, Vec_MemReadEntry(vTtMem, i), nWords, 0 );
|
||||
for ( k = 0; k < nPerms; k++ ) {
|
||||
Abc_TtSwapAdjacent( pCopy, nWords, pPerm[k] );
|
||||
assert( (pCopy[0] & 1) == 0 );
|
||||
Vec_MemHashInsert( vTtMem, pCopy );
|
||||
}
|
||||
assert( Abc_TtEqual(pCopy, Vec_MemReadEntry(vTtMem, i), nWords) );
|
||||
}
|
||||
for ( i = nFuncs; i < Vec_MemEntryNum(vTtMem); i++ )
|
||||
Vec_IntPush( vMap, t );
|
||||
Vec_IntPush( vCnts, Vec_MemEntryNum(vTtMem) - nFuncs );
|
||||
}
|
||||
ABC_FREE( pPerm );
|
||||
ABC_FREE( pComp );
|
||||
if ( fVerbose ) {
|
||||
printf( "Collected %d", Vec_MemEntryNum(vTtMem) );
|
||||
Vec_IntForEachEntryStop( vCnts, Entry, i, 7 )
|
||||
printf( " %c %d", i ? '+' : '=', Entry );
|
||||
if ( Vec_IntSize(vCnts) > 7 )
|
||||
printf( " + ..." );
|
||||
printf( " NPN class members. " );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart );
|
||||
fflush(stdout);
|
||||
}
|
||||
Vec_IntFree( vCnts );
|
||||
if ( pvMap )
|
||||
*pvMap = vMap;
|
||||
else
|
||||
Vec_IntFree( vMap );
|
||||
return vTtMem;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Canonicize a set of functions.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dau_CanonicizeArray( Vec_Wrd_t * vFuncs, int nVars, int fVerbose )
|
||||
{
|
||||
abctime clkStart = Abc_Clock();
|
||||
extern unsigned Abc_TtCanonicizeCA(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int iThres);
|
||||
if ( fVerbose ) printf( "Functions: %d (original) ", Vec_WrdSize(vFuncs) );
|
||||
unsigned uCanonPhase; char pCanonPerm[16]; word Func; int i;
|
||||
Vec_WrdUniqify( vFuncs );
|
||||
|
||||
if ( fVerbose ) printf( "-> %d (unique) ", Vec_WrdSize(vFuncs) );
|
||||
Vec_WrdForEachEntry( vFuncs, Func, i ) {
|
||||
uCanonPhase = Abc_TtCanonicize( &Func, nVars, pCanonPerm );
|
||||
Vec_WrdWriteEntry( vFuncs, i, Func );
|
||||
}
|
||||
Vec_WrdUniqify( vFuncs );
|
||||
if ( fVerbose ) printf( "-> %d (approx NPN) ", Vec_WrdSize(vFuncs) );
|
||||
Abc_TtHieMan_t * pMan = Abc_TtHieManStart(nVars, 5);
|
||||
Vec_WrdForEachEntry( vFuncs, Func, i ) {
|
||||
uCanonPhase = Abc_TtCanonicizeWrap(Abc_TtCanonicizeCA, pMan, &Func, nVars, pCanonPerm, 1);
|
||||
Vec_WrdWriteEntry( vFuncs, i, Func );
|
||||
}
|
||||
Vec_WrdUniqify( vFuncs );
|
||||
if ( fVerbose ) printf( "-> %d (exact NPN). ", Vec_WrdSize(vFuncs) );
|
||||
Abc_TtHieManStop(pMan);
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart );
|
||||
fflush( stdout );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
Loading…
Reference in New Issue