mirror of https://github.com/YosysHQ/abc.git
977 lines
29 KiB
C
977 lines
29 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [saigStrSim.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Sequential AIG package.]
|
|
|
|
Synopsis [Structural matching using simulation.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: saigStrSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "saig.h"
|
|
#include "proof/ssw/ssw.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
#define SAIG_WORDS 16
|
|
|
|
static inline Aig_Obj_t * Saig_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; }
|
|
static inline void Saig_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; }
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes hash value of the node using its simulation info.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
unsigned Saig_StrSimHash( Aig_Obj_t * pObj )
|
|
{
|
|
static int s_SPrimes[128] = {
|
|
1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
|
|
1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
|
|
2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
|
|
2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
|
|
3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
|
|
3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
|
|
4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
|
|
4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
|
|
5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
|
|
6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
|
|
6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
|
|
7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
|
|
8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
|
|
};
|
|
unsigned * pSims;
|
|
unsigned uHash = 0;
|
|
int i;
|
|
assert( SAIG_WORDS <= 128 );
|
|
pSims = (unsigned *)pObj->pData;
|
|
for ( i = 0; i < SAIG_WORDS; i++ )
|
|
uHash ^= pSims[i] * s_SPrimes[i & 0x7F];
|
|
return uHash;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes hash value of the node using its simulation info.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_StrSimIsEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
|
|
{
|
|
unsigned * pSims0 = (unsigned *)pObj0->pData;
|
|
unsigned * pSims1 = (unsigned *)pObj1->pData;
|
|
int i;
|
|
for ( i = 0; i < SAIG_WORDS; i++ )
|
|
if ( pSims0[i] != pSims1[i] )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns 1 if simulation info is zero.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_StrSimIsZero( Aig_Obj_t * pObj )
|
|
{
|
|
unsigned * pSims = (unsigned *)pObj->pData;
|
|
int i;
|
|
for ( i = 0; i < SAIG_WORDS; i++ )
|
|
if ( pSims[i] != 0 )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns 1 if simulation info is one.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_StrSimIsOne( Aig_Obj_t * pObj )
|
|
{
|
|
unsigned * pSims = (unsigned *)pObj->pData;
|
|
int i;
|
|
for ( i = 0; i < SAIG_WORDS; i++ )
|
|
if ( pSims[i] != ~0 )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Assigns random simulation info.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimAssignRandom( Aig_Obj_t * pObj )
|
|
{
|
|
unsigned * pSims = (unsigned *)pObj->pData;
|
|
int i;
|
|
for ( i = 0; i < SAIG_WORDS; i++ )
|
|
pSims[i] = Aig_ManRandom(0);
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Assigns constant 0 simulation info.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimAssignOne( Aig_Obj_t * pObj )
|
|
{
|
|
unsigned * pSims = (unsigned *)pObj->pData;
|
|
int i;
|
|
for ( i = 0; i < SAIG_WORDS; i++ )
|
|
pSims[i] = ~0;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Assigns constant 0 simulation info.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimAssignZeroInit( Aig_Obj_t * pObj )
|
|
{
|
|
unsigned * pSims = (unsigned *)pObj->pData;
|
|
pSims[0] = 0;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Simulated one node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimulateNode( Aig_Obj_t * pObj, int i )
|
|
{
|
|
unsigned * pSims = (unsigned *)pObj->pData;
|
|
unsigned * pSims0 = (unsigned *)Aig_ObjFanin0(pObj)->pData;
|
|
unsigned * pSims1 = (unsigned *)Aig_ObjFanin1(pObj)->pData;
|
|
if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) )
|
|
pSims[i] = ~(pSims0[i] | pSims1[i]);
|
|
else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) )
|
|
pSims[i] = (~pSims0[i] & pSims1[i]);
|
|
else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) )
|
|
pSims[i] = (pSims0[i] & ~pSims1[i]);
|
|
else // if ( !Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) )
|
|
pSims[i] = (pSims0[i] & pSims1[i]);
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Saves output of one node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimSaveOutput( Aig_Obj_t * pObj, int i )
|
|
{
|
|
unsigned * pSims = (unsigned *)pObj->pData;
|
|
unsigned * pSims0 = (unsigned *)Aig_ObjFanin0(pObj)->pData;
|
|
if ( Aig_ObjFaninC0(pObj) )
|
|
pSims[i] = ~pSims0[i];
|
|
else
|
|
pSims[i] = pSims0[i];
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Transfers simulation output to another node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimTransfer( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
|
|
{
|
|
unsigned * pSims0 = (unsigned *)pObj0->pData;
|
|
unsigned * pSims1 = (unsigned *)pObj1->pData;
|
|
int i;
|
|
for ( i = 0; i < SAIG_WORDS; i++ )
|
|
pSims1[i] = pSims0[i];
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Transfers simulation output to another node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimTransferNext( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int i )
|
|
{
|
|
unsigned * pSims0 = (unsigned *)pObj0->pData;
|
|
unsigned * pSims1 = (unsigned *)pObj1->pData;
|
|
assert( i < SAIG_WORDS - 1 );
|
|
pSims1[i+1] = pSims0[i];
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Perform one round of simulation.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimulateRound( Aig_Man_t * p0, Aig_Man_t * p1 )
|
|
{
|
|
Aig_Obj_t * pObj0, * pObj1;
|
|
int f, i;
|
|
// simulate the nodes
|
|
Aig_ManForEachObj( p0, pObj0, i )
|
|
{
|
|
if ( !Aig_ObjIsCi(pObj0) && !Aig_ObjIsNode(pObj0) )
|
|
continue;
|
|
pObj1 = Aig_ObjRepr(p0, pObj0);
|
|
if ( pObj1 == NULL )
|
|
continue;
|
|
assert( Aig_ObjRepr(p1, pObj1) == pObj0 );
|
|
Saig_StrSimAssignRandom( pObj0 );
|
|
Saig_StrSimTransfer( pObj0, pObj1 );
|
|
}
|
|
// simulate the timeframes
|
|
for ( f = 0; f < SAIG_WORDS; f++ )
|
|
{
|
|
// simulate the first AIG
|
|
Aig_ManForEachNode( p0, pObj0, i )
|
|
if ( Aig_ObjRepr(p0, pObj0) == NULL )
|
|
Saig_StrSimulateNode( pObj0, f );
|
|
Saig_ManForEachLi( p0, pObj0, i )
|
|
Saig_StrSimSaveOutput( pObj0, f );
|
|
if ( f < SAIG_WORDS - 1 )
|
|
Saig_ManForEachLiLo( p0, pObj0, pObj1, i )
|
|
Saig_StrSimTransferNext( pObj0, pObj1, f );
|
|
// simulate the second AIG
|
|
Aig_ManForEachNode( p1, pObj1, i )
|
|
if ( Aig_ObjRepr(p1, pObj1) == NULL )
|
|
Saig_StrSimulateNode( pObj1, f );
|
|
Saig_ManForEachLi( p1, pObj1, i )
|
|
Saig_StrSimSaveOutput( pObj1, f );
|
|
if ( f < SAIG_WORDS - 1 )
|
|
Saig_ManForEachLiLo( p1, pObj1, pObj0, i )
|
|
Saig_StrSimTransferNext( pObj1, pObj0, f );
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Checks if the entry exists in the table.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Obj_t * Saig_StrSimTableLookup( Aig_Obj_t ** ppTable, Aig_Obj_t ** ppNexts, int nTableSize, Aig_Obj_t * pObj )
|
|
{
|
|
Aig_Obj_t * pEntry;
|
|
int iEntry;
|
|
// find the hash entry
|
|
iEntry = Saig_StrSimHash( pObj ) % nTableSize;
|
|
// check if there are nodes with this signatures
|
|
for ( pEntry = ppTable[iEntry]; pEntry; pEntry = Saig_ObjNext(ppNexts,pEntry) )
|
|
if ( Saig_StrSimIsEqual( pEntry, pObj ) )
|
|
return pEntry;
|
|
return NULL;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Inserts the entry into the table.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimTableInsert( Aig_Obj_t ** ppTable, Aig_Obj_t ** ppNexts, int nTableSize, Aig_Obj_t * pObj )
|
|
{
|
|
// find the hash entry
|
|
int iEntry = Saig_StrSimHash( pObj ) % nTableSize;
|
|
// check if there are nodes with this signatures
|
|
if ( ppTable[iEntry] == NULL )
|
|
ppTable[iEntry] = pObj;
|
|
else
|
|
{
|
|
Saig_ObjSetNext( ppNexts, pObj, Saig_ObjNext(ppNexts, ppTable[iEntry]) );
|
|
Saig_ObjSetNext( ppNexts, ppTable[iEntry], pObj );
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Perform one round of matching.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_StrSimDetectUnique( Aig_Man_t * p0, Aig_Man_t * p1 )
|
|
{
|
|
Aig_Obj_t ** ppTable, ** ppNexts, ** ppCands;
|
|
Aig_Obj_t * pObj, * pEntry;
|
|
int i, nTableSize, Counter;
|
|
|
|
// allocate the hash table hashing simulation info into nodes
|
|
nTableSize = Abc_PrimeCudd( Aig_ManObjNum(p0)/2 );
|
|
ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize );
|
|
ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) );
|
|
ppCands = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) );
|
|
|
|
// hash nodes of the first AIG
|
|
Aig_ManForEachObj( p0, pObj, i )
|
|
{
|
|
if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) )
|
|
continue;
|
|
if ( Aig_ObjRepr(p0, pObj) )
|
|
continue;
|
|
if ( Saig_StrSimIsZero(pObj) || Saig_StrSimIsOne(pObj) )
|
|
continue;
|
|
// check if the entry exists
|
|
pEntry = Saig_StrSimTableLookup( ppTable, ppNexts, nTableSize, pObj );
|
|
if ( pEntry == NULL ) // insert
|
|
Saig_StrSimTableInsert( ppTable, ppNexts, nTableSize, pObj );
|
|
else // mark the entry as not unique
|
|
pEntry->fMarkA = 1;
|
|
}
|
|
|
|
// hash nodes from the second AIG
|
|
Aig_ManForEachObj( p1, pObj, i )
|
|
{
|
|
if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) )
|
|
continue;
|
|
if ( Aig_ObjRepr(p1, pObj) )
|
|
continue;
|
|
if ( Saig_StrSimIsZero(pObj) || Saig_StrSimIsOne(pObj) )
|
|
continue;
|
|
// check if the entry exists
|
|
pEntry = Saig_StrSimTableLookup( ppTable, ppNexts, nTableSize, pObj );
|
|
if ( pEntry == NULL ) // skip
|
|
continue;
|
|
// if there is no candidate, label it
|
|
if ( Saig_ObjNext( ppCands, pEntry ) == NULL )
|
|
Saig_ObjSetNext( ppCands, pEntry, pObj );
|
|
else // mark the entry as not unique
|
|
pEntry->fMarkA = 1;
|
|
}
|
|
|
|
// create representatives for the unique entries
|
|
Counter = 0;
|
|
for ( i = 0; i < nTableSize; i++ )
|
|
for ( pEntry = ppTable[i]; pEntry; pEntry = Saig_ObjNext(ppNexts,pEntry) )
|
|
if ( !pEntry->fMarkA && (pObj = Saig_ObjNext( ppCands, pEntry )) )
|
|
{
|
|
// assert( Aig_ObjIsNode(pEntry) == Aig_ObjIsNode(pObj) );
|
|
if ( Aig_ObjType(pEntry) != Aig_ObjType(pObj) )
|
|
continue;
|
|
Aig_ObjSetRepr( p0, pEntry, pObj );
|
|
Aig_ObjSetRepr( p1, pObj, pEntry );
|
|
Counter++;
|
|
}
|
|
|
|
// cleanup
|
|
Aig_ManCleanMarkA( p0 );
|
|
ABC_FREE( ppTable );
|
|
ABC_FREE( ppNexts );
|
|
ABC_FREE( ppCands );
|
|
return Counter;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Counts the number of matched flops.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_StrSimCountMatchedFlops( Aig_Man_t * p )
|
|
{
|
|
Aig_Obj_t * pObj;
|
|
int i, Counter = 0;
|
|
Saig_ManForEachLo( p, pObj, i )
|
|
if ( Aig_ObjRepr(p, pObj) )
|
|
Counter++;
|
|
return Counter;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Counts the number of matched nodes.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_StrSimCountMatchedNodes( Aig_Man_t * p )
|
|
{
|
|
Aig_Obj_t * pObj;
|
|
int i, Counter = 0;
|
|
Aig_ManForEachNode( p, pObj, i )
|
|
if ( Aig_ObjRepr(p, pObj) )
|
|
Counter++;
|
|
return Counter;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs structural matching of two AIGs using simulation.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimPrepareAig( Aig_Man_t * p )
|
|
{
|
|
Aig_Obj_t * pObj;
|
|
int i;
|
|
Aig_ManReprStart( p, Aig_ManObjNumMax(p) );
|
|
// allocate simulation info
|
|
p->pData2 = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), SAIG_WORDS );
|
|
Aig_ManForEachObj( p, pObj, i )
|
|
pObj->pData = Vec_PtrEntry( (Vec_Ptr_t *)p->pData2, i );
|
|
// set simulation info for constant1 and register outputs
|
|
Saig_StrSimAssignOne( Aig_ManConst1(p) );
|
|
Saig_ManForEachLo( p, pObj, i )
|
|
Saig_StrSimAssignZeroInit( pObj );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs structural matching of two AIGs using simulation.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimSetInitMatching( Aig_Man_t * p0, Aig_Man_t * p1 )
|
|
{
|
|
Aig_Obj_t * pObj0, * pObj1;
|
|
int i;
|
|
pObj0 = Aig_ManConst1( p0 );
|
|
pObj1 = Aig_ManConst1( p1 );
|
|
Aig_ObjSetRepr( p0, pObj0, pObj1 );
|
|
Aig_ObjSetRepr( p1, pObj1, pObj0 );
|
|
Saig_ManForEachPi( p0, pObj0, i )
|
|
{
|
|
pObj1 = Aig_ManCi( p1, i );
|
|
Aig_ObjSetRepr( p0, pObj0, pObj1 );
|
|
Aig_ObjSetRepr( p1, pObj1, pObj0 );
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs structural matching of two AIGs using simulation.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimSetFinalMatching( Aig_Man_t * p0, Aig_Man_t * p1 )
|
|
{
|
|
Aig_Obj_t * pObj0, * pObj1;
|
|
Aig_Obj_t * pFanin00, * pFanin01;
|
|
Aig_Obj_t * pFanin10, * pFanin11;
|
|
int i, CountAll = 0, CountNot = 0;
|
|
Aig_ManIncrementTravId( p0 );
|
|
Aig_ManForEachObj( p0, pObj0, i )
|
|
{
|
|
pObj1 = Aig_ObjRepr( p0, pObj0 );
|
|
if ( pObj1 == NULL )
|
|
continue;
|
|
CountAll++;
|
|
assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) );
|
|
if ( Aig_ObjIsNode(pObj0) )
|
|
{
|
|
assert( Aig_ObjIsNode(pObj1) );
|
|
pFanin00 = Aig_ObjFanin0(pObj0);
|
|
pFanin01 = Aig_ObjFanin1(pObj0);
|
|
pFanin10 = Aig_ObjFanin0(pObj1);
|
|
pFanin11 = Aig_ObjFanin1(pObj1);
|
|
if ( Aig_ObjRepr(p0, pFanin00) != pFanin10 ||
|
|
Aig_ObjRepr(p0, pFanin01) != pFanin11 )
|
|
{
|
|
Aig_ObjSetTravIdCurrent(p0, pObj0);
|
|
CountNot++;
|
|
}
|
|
}
|
|
else if ( Saig_ObjIsLo(p0, pObj0) )
|
|
{
|
|
assert( Saig_ObjIsLo(p1, pObj1) );
|
|
pFanin00 = Aig_ObjFanin0( Saig_ObjLoToLi(p0, pObj0) );
|
|
pFanin10 = Aig_ObjFanin0( Saig_ObjLoToLi(p1, pObj1) );
|
|
if ( Aig_ObjRepr(p0, pFanin00) != pFanin10 )
|
|
{
|
|
Aig_ObjSetTravIdCurrent(p0, pObj0);
|
|
CountNot++;
|
|
}
|
|
}
|
|
}
|
|
// remove irrelevant matches
|
|
Aig_ManForEachObj( p0, pObj0, i )
|
|
{
|
|
pObj1 = Aig_ObjRepr( p0, pObj0 );
|
|
if ( pObj1 == NULL )
|
|
continue;
|
|
assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) );
|
|
if ( Aig_ObjIsTravIdCurrent( p0, pObj0 ) )
|
|
{
|
|
Aig_ObjSetRepr( p0, pObj0, NULL );
|
|
Aig_ObjSetRepr( p1, pObj1, NULL );
|
|
}
|
|
}
|
|
Abc_Print( 1, "Total matches = %6d. Wrong matches = %6d. Ratio = %5.2f %%\n",
|
|
CountAll, CountNot, 100.0*CountNot/CountAll );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns the number of dangling nodes removed.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimSetContiguousMatching_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
|
|
{
|
|
Aig_Obj_t * pFanout;
|
|
int i, iFanout = -1;
|
|
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
|
|
return;
|
|
Aig_ObjSetTravIdCurrent(p, pObj);
|
|
if ( Saig_ObjIsPo( p, pObj ) )
|
|
return;
|
|
if ( Saig_ObjIsLi( p, pObj ) )
|
|
{
|
|
Saig_StrSimSetContiguousMatching_rec( p, Saig_ObjLiToLo(p, pObj) );
|
|
return;
|
|
}
|
|
assert( Aig_ObjIsCi(pObj) || Aig_ObjIsNode(pObj) );
|
|
if ( Aig_ObjRepr(p, pObj) == NULL )
|
|
return;
|
|
// go through the fanouts
|
|
Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
|
|
Saig_StrSimSetContiguousMatching_rec( p, pFanout );
|
|
// go through the fanins
|
|
if ( !Aig_ObjIsCi( pObj ) )
|
|
{
|
|
Saig_StrSimSetContiguousMatching_rec( p, Aig_ObjFanin0(pObj) );
|
|
Saig_StrSimSetContiguousMatching_rec( p, Aig_ObjFanin1(pObj) );
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs structural matching of two AIGs using simulation.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_StrSimSetContiguousMatching( Aig_Man_t * p0, Aig_Man_t * p1 )
|
|
{
|
|
Aig_Obj_t * pObj0, * pObj1;
|
|
int i, CountAll = 0, CountNot = 0;
|
|
// mark nodes reachable through the PIs
|
|
Aig_ManIncrementTravId( p0 );
|
|
Aig_ObjSetTravIdCurrent( p0, Aig_ManConst1(p0) );
|
|
Saig_ManForEachPi( p0, pObj0, i )
|
|
Saig_StrSimSetContiguousMatching_rec( p0, pObj0 );
|
|
// remove irrelevant matches
|
|
Aig_ManForEachObj( p0, pObj0, i )
|
|
{
|
|
pObj1 = Aig_ObjRepr( p0, pObj0 );
|
|
if ( pObj1 == NULL )
|
|
continue;
|
|
CountAll++;
|
|
assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) );
|
|
if ( !Aig_ObjIsTravIdCurrent( p0, pObj0 ) )
|
|
{
|
|
Aig_ObjSetRepr( p0, pObj0, NULL );
|
|
Aig_ObjSetRepr( p1, pObj1, NULL );
|
|
CountNot++;
|
|
}
|
|
}
|
|
Abc_Print( 1, "Total matches = %6d. Wrong matches = %6d. Ratio = %5.2f %%\n",
|
|
CountAll, CountNot, 100.0*CountNot/CountAll );
|
|
}
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Establishes relationship between nodes using pairing.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ssw_StrSimMatchingExtendOne( Aig_Man_t * p, Vec_Ptr_t * vNodes )
|
|
{
|
|
Aig_Obj_t * pNext, * pObj;
|
|
int i, k, iFan = -1;
|
|
Vec_PtrClear( vNodes );
|
|
Aig_ManIncrementTravId( p );
|
|
Aig_ManForEachObj( p, pObj, i )
|
|
{
|
|
if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
|
|
continue;
|
|
if ( Aig_ObjRepr( p, pObj ) != NULL )
|
|
continue;
|
|
if ( Saig_ObjIsLo(p, pObj) )
|
|
{
|
|
pNext = Saig_ObjLoToLi(p, pObj);
|
|
pNext = Aig_ObjFanin0(pNext);
|
|
if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) && !Aig_ObjIsConst1(pNext) )
|
|
{
|
|
Aig_ObjSetTravIdCurrent(p, pNext);
|
|
Vec_PtrPush( vNodes, pNext );
|
|
}
|
|
}
|
|
if ( Aig_ObjIsNode(pObj) )
|
|
{
|
|
pNext = Aig_ObjFanin0(pObj);
|
|
if ( Aig_ObjRepr( p, pNext )&& !Aig_ObjIsTravIdCurrent(p, pNext) )
|
|
{
|
|
Aig_ObjSetTravIdCurrent(p, pNext);
|
|
Vec_PtrPush( vNodes, pNext );
|
|
}
|
|
pNext = Aig_ObjFanin1(pObj);
|
|
if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) )
|
|
{
|
|
Aig_ObjSetTravIdCurrent(p, pNext);
|
|
Vec_PtrPush( vNodes, pNext );
|
|
}
|
|
}
|
|
Aig_ObjForEachFanout( p, pObj, pNext, iFan, k )
|
|
{
|
|
if ( Saig_ObjIsPo(p, pNext) )
|
|
continue;
|
|
if ( Saig_ObjIsLi(p, pNext) )
|
|
pNext = Saig_ObjLiToLo(p, pNext);
|
|
if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) )
|
|
{
|
|
Aig_ObjSetTravIdCurrent(p, pNext);
|
|
Vec_PtrPush( vNodes, pNext );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Establishes relationship between nodes using pairing.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Ssw_StrSimMatchingCountUnmached( Aig_Man_t * p )
|
|
{
|
|
Aig_Obj_t * pObj;
|
|
int i, Counter = 0;
|
|
Aig_ManForEachObj( p, pObj, i )
|
|
{
|
|
if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
|
|
continue;
|
|
if ( Aig_ObjRepr( p, pObj ) != NULL )
|
|
continue;
|
|
Counter++;
|
|
}
|
|
return Counter;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Establishes relationship between nodes using pairing.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ssw_StrSimMatchingExtend( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose )
|
|
{
|
|
Vec_Ptr_t * vNodes0, * vNodes1;
|
|
Aig_Obj_t * pNext0, * pNext1;
|
|
int d, k;
|
|
vNodes0 = Vec_PtrAlloc( 1000 );
|
|
vNodes1 = Vec_PtrAlloc( 1000 );
|
|
if ( fVerbose )
|
|
{
|
|
int nUnmached = Ssw_StrSimMatchingCountUnmached(p0);
|
|
Abc_Print( 1, "Extending islands by %d steps:\n", nDist );
|
|
Abc_Print( 1, "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n",
|
|
0, Aig_ManCiNum(p0) + Aig_ManNodeNum(p0),
|
|
nUnmached, 100.0 * nUnmached/(Aig_ManCiNum(p0) + Aig_ManNodeNum(p0)) );
|
|
}
|
|
for ( d = 0; d < nDist; d++ )
|
|
{
|
|
Ssw_StrSimMatchingExtendOne( p0, vNodes0 );
|
|
Ssw_StrSimMatchingExtendOne( p1, vNodes1 );
|
|
Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pNext0, k )
|
|
{
|
|
pNext1 = Aig_ObjRepr( p0, pNext0 );
|
|
if ( pNext1 == NULL )
|
|
continue;
|
|
assert( pNext0 == Aig_ObjRepr( p1, pNext1 ) );
|
|
if ( Saig_ObjIsPi(p1, pNext1) )
|
|
continue;
|
|
Aig_ObjSetRepr( p0, pNext0, NULL );
|
|
Aig_ObjSetRepr( p1, pNext1, NULL );
|
|
}
|
|
Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pNext1, k )
|
|
{
|
|
pNext0 = Aig_ObjRepr( p1, pNext1 );
|
|
if ( pNext0 == NULL )
|
|
continue;
|
|
assert( pNext1 == Aig_ObjRepr( p0, pNext0 ) );
|
|
if ( Saig_ObjIsPi(p0, pNext0) )
|
|
continue;
|
|
Aig_ObjSetRepr( p0, pNext0, NULL );
|
|
Aig_ObjSetRepr( p1, pNext1, NULL );
|
|
}
|
|
if ( fVerbose )
|
|
{
|
|
int nUnmached = Ssw_StrSimMatchingCountUnmached(p0);
|
|
Abc_Print( 1, "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n",
|
|
d+1, Aig_ManCiNum(p0) + Aig_ManNodeNum(p0),
|
|
nUnmached, 100.0 * nUnmached/(Aig_ManCiNum(p0) + Aig_ManNodeNum(p0)) );
|
|
}
|
|
}
|
|
Vec_PtrFree( vNodes0 );
|
|
Vec_PtrFree( vNodes1 );
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs structural matching of two AIGs using simulation.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter )
|
|
{
|
|
extern Aig_Man_t * Saig_ManWindowExtractMiter( Aig_Man_t * p0, Aig_Man_t * p1 );
|
|
|
|
Vec_Int_t * vPairs;
|
|
Aig_Man_t * pPart0, * pPart1;
|
|
Aig_Obj_t * pObj0, * pObj1;
|
|
int i, nMatches;
|
|
abctime clk, clkTotal = Abc_Clock();
|
|
Aig_ManRandom( 1 );
|
|
// consider the case when a miter is given
|
|
if ( p1 == NULL )
|
|
{
|
|
if ( fVerbose )
|
|
{
|
|
Aig_ManPrintStats( p0 );
|
|
}
|
|
// demiter the miter
|
|
if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) )
|
|
{
|
|
Abc_Print( 1, "Demitering has failed.\n" );
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pPart0 = Aig_ManDupSimple( p0 );
|
|
pPart1 = Aig_ManDupSimple( p1 );
|
|
}
|
|
if ( fVerbose )
|
|
{
|
|
Aig_ManPrintStats( pPart0 );
|
|
Aig_ManPrintStats( pPart1 );
|
|
}
|
|
// start simulation
|
|
Saig_StrSimPrepareAig( pPart0 );
|
|
Saig_StrSimPrepareAig( pPart1 );
|
|
Saig_StrSimSetInitMatching( pPart0, pPart1 );
|
|
if ( fVerbose )
|
|
{
|
|
Abc_Print( 1, "Allocated %6.2f MB to simulate the first AIG.\n",
|
|
1.0 * Aig_ManObjNumMax(pPart0) * SAIG_WORDS * sizeof(unsigned) / (1<<20) );
|
|
Abc_Print( 1, "Allocated %6.2f MB to simulate the second AIG.\n",
|
|
1.0 * Aig_ManObjNumMax(pPart1) * SAIG_WORDS * sizeof(unsigned) / (1<<20) );
|
|
}
|
|
// iterate matching
|
|
nMatches = 1;
|
|
for ( i = 0; nMatches > 0; i++ )
|
|
{
|
|
clk = Abc_Clock();
|
|
Saig_StrSimulateRound( pPart0, pPart1 );
|
|
nMatches = Saig_StrSimDetectUnique( pPart0, pPart1 );
|
|
if ( fVerbose )
|
|
{
|
|
int nFlops = Saig_StrSimCountMatchedFlops(pPart0);
|
|
int nNodes = Saig_StrSimCountMatchedNodes(pPart0);
|
|
Abc_Print( 1, "%3d : Match =%6d. FF =%6d. (%6.2f %%) Node =%6d. (%6.2f %%) ",
|
|
i, nMatches,
|
|
nFlops, 100.0*nFlops/Aig_ManRegNum(pPart0),
|
|
nNodes, 100.0*nNodes/Aig_ManNodeNum(pPart0) );
|
|
ABC_PRT( "Time", Abc_Clock() - clk );
|
|
}
|
|
if ( i == 20 )
|
|
break;
|
|
}
|
|
// cleanup
|
|
Vec_PtrFree( (Vec_Ptr_t *)pPart0->pData2 ); pPart0->pData2 = NULL;
|
|
Vec_PtrFree( (Vec_Ptr_t *)pPart1->pData2 ); pPart1->pData2 = NULL;
|
|
// extend the islands
|
|
Aig_ManFanoutStart( pPart0 );
|
|
Aig_ManFanoutStart( pPart1 );
|
|
if ( nDist )
|
|
Ssw_StrSimMatchingExtend( pPart0, pPart1, nDist, fVerbose );
|
|
Saig_StrSimSetFinalMatching( pPart0, pPart1 );
|
|
// Saig_StrSimSetContiguousMatching( pPart0, pPart1 );
|
|
// copy the results into array
|
|
vPairs = Vec_IntAlloc( 2*Aig_ManObjNumMax(pPart0) );
|
|
Aig_ManForEachObj( pPart0, pObj0, i )
|
|
{
|
|
pObj1 = Aig_ObjRepr(pPart0, pObj0);
|
|
if ( pObj1 == NULL )
|
|
continue;
|
|
assert( pObj0 == Aig_ObjRepr(pPart1, pObj1) );
|
|
Vec_IntPush( vPairs, pObj0->Id );
|
|
Vec_IntPush( vPairs, pObj1->Id );
|
|
}
|
|
// this procedure adds matching of PO and LI
|
|
if ( ppMiter )
|
|
*ppMiter = Saig_ManWindowExtractMiter( pPart0, pPart1 );
|
|
Aig_ManFanoutStop( pPart0 );
|
|
Aig_ManFanoutStop( pPart1 );
|
|
Aig_ManStop( pPart0 );
|
|
Aig_ManStop( pPart1 );
|
|
ABC_PRT( "Total runtime", Abc_Clock() - clkTotal );
|
|
return vPairs;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|