mirror of https://github.com/YosysHQ/abc.git
446 lines
14 KiB
C
446 lines
14 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [absDup.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Abstraction package.]
|
|
|
|
Synopsis [Duplication procedures.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: absDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "abs.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Duplicates the AIG manager recursively.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Gia_ManDupAbsFlops_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj )
|
|
{
|
|
if ( ~pObj->Value )
|
|
return;
|
|
assert( Gia_ObjIsAnd(pObj) );
|
|
Gia_ManDupAbsFlops_rec( pNew, Gia_ObjFanin0(pObj) );
|
|
Gia_ManDupAbsFlops_rec( pNew, Gia_ObjFanin1(pObj) );
|
|
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Extractes a flop-level abstraction given a flop map.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Gia_Man_t * Gia_ManDupAbsFlops( Gia_Man_t * p, Vec_Int_t * vFlopClasses )
|
|
{
|
|
Gia_Man_t * pNew, * pTemp;
|
|
Gia_Obj_t * pObj;
|
|
int i, nFlops = 0;
|
|
Gia_ManFillValue( p );
|
|
// start the new manager
|
|
pNew = Gia_ManStart( 5000 );
|
|
pNew->pName = Abc_UtilStrsav( p->pName );
|
|
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
|
|
// create PIs
|
|
Gia_ManConst0(p)->Value = 0;
|
|
Gia_ManForEachPi( p, pObj, i )
|
|
pObj->Value = Gia_ManAppendCi(pNew);
|
|
// create additional PIs
|
|
Gia_ManForEachRo( p, pObj, i )
|
|
if ( !Vec_IntEntry(vFlopClasses, i) )
|
|
pObj->Value = Gia_ManAppendCi(pNew);
|
|
// create ROs
|
|
Gia_ManForEachRo( p, pObj, i )
|
|
if ( Vec_IntEntry(vFlopClasses, i) )
|
|
pObj->Value = Gia_ManAppendCi(pNew);
|
|
// create POs
|
|
Gia_ManHashAlloc( pNew );
|
|
Gia_ManForEachPo( p, pObj, i )
|
|
{
|
|
Gia_ManDupAbsFlops_rec( pNew, Gia_ObjFanin0(pObj) );
|
|
Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
|
|
}
|
|
// create RIs
|
|
Gia_ManForEachRi( p, pObj, i )
|
|
if ( Vec_IntEntry(vFlopClasses, i) )
|
|
{
|
|
Gia_ManDupAbsFlops_rec( pNew, Gia_ObjFanin0(pObj) );
|
|
Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
|
|
nFlops++;
|
|
}
|
|
Gia_ManHashStop( pNew );
|
|
Gia_ManSetRegNum( pNew, nFlops );
|
|
// clean up
|
|
pNew = Gia_ManSeqCleanup( pTemp = pNew );
|
|
Gia_ManStop( pTemp );
|
|
return pNew;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns the array of neighbors.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Int_t * Gia_GlaCollectAssigned( Gia_Man_t * p, Vec_Int_t * vGateClasses )
|
|
{
|
|
Vec_Int_t * vAssigned;
|
|
Gia_Obj_t * pObj;
|
|
int i, Entry;
|
|
vAssigned = Vec_IntAlloc( 1000 );
|
|
Vec_IntForEachEntry( vGateClasses, Entry, i )
|
|
{
|
|
if ( Entry == 0 )
|
|
continue;
|
|
assert( Entry > 0 );
|
|
pObj = Gia_ManObj( p, i );
|
|
Vec_IntPush( vAssigned, Gia_ObjId(p, pObj) );
|
|
if ( Gia_ObjIsAnd(pObj) )
|
|
{
|
|
Vec_IntPush( vAssigned, Gia_ObjFaninId0p(p, pObj) );
|
|
Vec_IntPush( vAssigned, Gia_ObjFaninId1p(p, pObj) );
|
|
}
|
|
else if ( Gia_ObjIsRo(p, pObj) )
|
|
Vec_IntPush( vAssigned, Gia_ObjFaninId0p(p, Gia_ObjRoToRi(p, pObj)) );
|
|
else assert( Gia_ObjIsConst0(pObj) );
|
|
}
|
|
Vec_IntUniqify( vAssigned );
|
|
return vAssigned;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Collects PIs and PPIs of the abstraction.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Gia_ManGlaCollect( Gia_Man_t * p, Vec_Int_t * vGateClasses, Vec_Int_t ** pvPis, Vec_Int_t ** pvPPis, Vec_Int_t ** pvFlops, Vec_Int_t ** pvNodes )
|
|
{
|
|
Vec_Int_t * vAssigned;
|
|
Gia_Obj_t * pObj;
|
|
int i;
|
|
assert( Gia_ManPoNum(p) == 1 );
|
|
assert( Vec_IntSize(vGateClasses) == Gia_ManObjNum(p) );
|
|
// create included objects and their fanins
|
|
vAssigned = Gia_GlaCollectAssigned( p, vGateClasses );
|
|
// create additional arrays
|
|
if ( pvPis ) *pvPis = Vec_IntAlloc( 100 );
|
|
if ( pvPPis ) *pvPPis = Vec_IntAlloc( 100 );
|
|
if ( pvFlops ) *pvFlops = Vec_IntAlloc( 100 );
|
|
if ( pvNodes ) *pvNodes = Vec_IntAlloc( 1000 );
|
|
Gia_ManForEachObjVec( vAssigned, p, pObj, i )
|
|
{
|
|
if ( Gia_ObjIsPi(p, pObj) )
|
|
{ if ( pvPis ) Vec_IntPush( *pvPis, Gia_ObjId(p,pObj) ); }
|
|
else if ( !Vec_IntEntry(vGateClasses, Gia_ObjId(p,pObj)) )
|
|
{ if ( pvPPis ) Vec_IntPush( *pvPPis, Gia_ObjId(p,pObj) ); }
|
|
else if ( Gia_ObjIsRo(p, pObj) )
|
|
{ if ( pvFlops ) Vec_IntPush( *pvFlops, Gia_ObjId(p,pObj) ); }
|
|
else if ( Gia_ObjIsAnd(pObj) )
|
|
{ if ( pvNodes ) Vec_IntPush( *pvNodes, Gia_ObjId(p,pObj) ); }
|
|
else assert( Gia_ObjIsConst0(pObj) );
|
|
}
|
|
Vec_IntFree( vAssigned );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Duplicates the AIG manager recursively.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Gia_ManDupAbsGates_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj )
|
|
{
|
|
if ( ~pObj->Value )
|
|
return;
|
|
assert( Gia_ObjIsAnd(pObj) );
|
|
Gia_ManDupAbsGates_rec( pNew, Gia_ObjFanin0(pObj) );
|
|
Gia_ManDupAbsGates_rec( pNew, Gia_ObjFanin1(pObj) );
|
|
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Extractes a gate-level abstraction given a gate map.]
|
|
|
|
Description [The array contains 1 for those objects (const, RO, AND)
|
|
that are included in the abstraction; 0, otherwise.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Gia_Man_t * Gia_ManDupAbsGates( Gia_Man_t * p, Vec_Int_t * vGateClasses )
|
|
{
|
|
Vec_Int_t * vPis, * vPPis, * vFlops, * vNodes;
|
|
Gia_Man_t * pNew, * pTemp;
|
|
Gia_Obj_t * pObj, * pCopy;
|
|
int i;//, nFlops = 0;
|
|
assert( Gia_ManPoNum(p) == 1 );
|
|
assert( Vec_IntSize(vGateClasses) == Gia_ManObjNum(p) );
|
|
|
|
// create additional arrays
|
|
Gia_ManGlaCollect( p, vGateClasses, &vPis, &vPPis, &vFlops, &vNodes );
|
|
|
|
// start the new manager
|
|
pNew = Gia_ManStart( 5000 );
|
|
pNew->pName = Abc_UtilStrsav( p->pName );
|
|
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
|
|
// create constant
|
|
Gia_ManFillValue( p );
|
|
Gia_ManConst0(p)->Value = 0;
|
|
// create PIs
|
|
Gia_ManForEachObjVec( vPis, p, pObj, i )
|
|
pObj->Value = Gia_ManAppendCi(pNew);
|
|
// create additional PIs
|
|
Gia_ManForEachObjVec( vPPis, p, pObj, i )
|
|
pObj->Value = Gia_ManAppendCi(pNew);
|
|
// create ROs
|
|
Gia_ManForEachObjVec( vFlops, p, pObj, i )
|
|
pObj->Value = Gia_ManAppendCi(pNew);
|
|
// create internal nodes
|
|
Gia_ManForEachObjVec( vNodes, p, pObj, i )
|
|
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
|
// Gia_ManDupAbsGates_rec( pNew, pObj );
|
|
// create PO
|
|
Gia_ManForEachPo( p, pObj, i )
|
|
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
|
|
// create RIs
|
|
Gia_ManForEachObjVec( vFlops, p, pObj, i )
|
|
Gia_ObjRoToRi(p, pObj)->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ObjRoToRi(p, pObj)) );
|
|
Gia_ManSetRegNum( pNew, Vec_IntSize(vFlops) );
|
|
// clean up
|
|
pNew = Gia_ManSeqCleanup( pTemp = pNew );
|
|
// transfer copy values: (p -> pTemp -> pNew) => (p -> pNew)
|
|
if ( Gia_ManObjNum(pTemp) != Gia_ManObjNum(pNew) )
|
|
{
|
|
// printf( "Gia_ManDupAbsGates() Internal error: object mismatch.\n" );
|
|
Gia_ManForEachObj( p, pObj, i )
|
|
{
|
|
if ( !~pObj->Value )
|
|
continue;
|
|
assert( !Abc_LitIsCompl(pObj->Value) );
|
|
pCopy = Gia_ObjCopy( pTemp, pObj );
|
|
if ( !~pCopy->Value )
|
|
{
|
|
Vec_IntWriteEntry( vGateClasses, i, 0 );
|
|
pObj->Value = ~0;
|
|
continue;
|
|
}
|
|
assert( !Abc_LitIsCompl(pCopy->Value) );
|
|
pObj->Value = pCopy->Value;
|
|
}
|
|
}
|
|
Gia_ManStop( pTemp );
|
|
|
|
Vec_IntFree( vPis );
|
|
Vec_IntFree( vPPis );
|
|
Vec_IntFree( vFlops );
|
|
Vec_IntFree( vNodes );
|
|
return pNew;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Prints stats for the AIG.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Gia_ManPrintFlopClasses( Gia_Man_t * p )
|
|
{
|
|
int Counter0, Counter1;
|
|
if ( p->vFlopClasses == NULL )
|
|
return;
|
|
if ( Vec_IntSize(p->vFlopClasses) != Gia_ManRegNum(p) )
|
|
{
|
|
printf( "Gia_ManPrintFlopClasses(): The number of flop map entries differs from the number of flops.\n" );
|
|
return;
|
|
}
|
|
Counter0 = Vec_IntCountEntry( p->vFlopClasses, 0 );
|
|
Counter1 = Vec_IntCountEntry( p->vFlopClasses, 1 );
|
|
printf( "Flop-level abstraction: Excluded FFs = %d Included FFs = %d (%.2f %%) ",
|
|
Counter0, Counter1, 100.0*Counter1/(Counter0 + Counter1 + 1) );
|
|
if ( Counter0 + Counter1 < Gia_ManRegNum(p) )
|
|
printf( "and there are other FF classes..." );
|
|
printf( "\n" );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Prints stats for the AIG.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Gia_ManPrintGateClasses( Gia_Man_t * p )
|
|
{
|
|
Vec_Int_t * vPis, * vPPis, * vFlops, * vNodes;
|
|
int nTotal;
|
|
if ( p->vGateClasses == NULL )
|
|
return;
|
|
if ( Vec_IntSize(p->vGateClasses) != Gia_ManObjNum(p) )
|
|
{
|
|
printf( "Gia_ManPrintGateClasses(): The number of flop map entries differs from the number of flops.\n" );
|
|
return;
|
|
}
|
|
// create additional arrays
|
|
Gia_ManGlaCollect( p, p->vGateClasses, &vPis, &vPPis, &vFlops, &vNodes );
|
|
nTotal = 1 + Vec_IntSize(vFlops) + Vec_IntSize(vNodes);
|
|
printf( "Gate-level abstraction: PI = %d PPI = %d FF = %d (%.2f %%) AND = %d (%.2f %%) Obj = %d (%.2f %%)\n",
|
|
Vec_IntSize(vPis), Vec_IntSize(vPPis),
|
|
Vec_IntSize(vFlops), 100.0*Vec_IntSize(vFlops)/(Gia_ManRegNum(p)+1),
|
|
Vec_IntSize(vNodes), 100.0*Vec_IntSize(vNodes)/(Gia_ManAndNum(p)+1),
|
|
nTotal, 100.0*nTotal /(Gia_ManRegNum(p)+Gia_ManAndNum(p)+1) );
|
|
Vec_IntFree( vPis );
|
|
Vec_IntFree( vPPis );
|
|
Vec_IntFree( vFlops );
|
|
Vec_IntFree( vNodes );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Prints stats for the AIG.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Gia_ManPrintObjClasses( Gia_Man_t * p )
|
|
{
|
|
Vec_Int_t * vSeens; // objects seen so far
|
|
Vec_Int_t * vAbs = p->vObjClasses;
|
|
int i, k, Entry, iStart, iStop = -1, nFrames;
|
|
int nObjBits, nObjMask, iObj, iFrame, nWords;
|
|
unsigned * pInfo;
|
|
int * pCountAll, * pCountUni;
|
|
if ( vAbs == NULL )
|
|
return;
|
|
nFrames = Vec_IntEntry( vAbs, 0 );
|
|
assert( Vec_IntEntry(vAbs, nFrames+1) == Vec_IntSize(vAbs) );
|
|
pCountAll = ABC_ALLOC( int, nFrames + 1 );
|
|
pCountUni = ABC_ALLOC( int, nFrames + 1 );
|
|
// start storage for seen objects
|
|
nWords = Abc_BitWordNum( nFrames );
|
|
vSeens = Vec_IntStart( Gia_ManObjNum(p) * nWords );
|
|
// get the bitmasks
|
|
nObjBits = Abc_Base2Log( Gia_ManObjNum(p) );
|
|
nObjMask = (1 << nObjBits) - 1;
|
|
assert( Gia_ManObjNum(p) <= nObjMask );
|
|
// print info about frames
|
|
printf( "Frame Core F0 F1 F2 F3 ...\n" );
|
|
for ( i = 0; i < nFrames; i++ )
|
|
{
|
|
iStart = Vec_IntEntry( vAbs, i+1 );
|
|
iStop = Vec_IntEntry( vAbs, i+2 );
|
|
memset( pCountAll, 0, sizeof(int) * (nFrames + 1) );
|
|
memset( pCountUni, 0, sizeof(int) * (nFrames + 1) );
|
|
Vec_IntForEachEntryStartStop( vAbs, Entry, k, iStart, iStop )
|
|
{
|
|
iObj = (Entry & nObjMask);
|
|
iFrame = (Entry >> nObjBits);
|
|
pInfo = (unsigned *)Vec_IntEntryP( vSeens, nWords * iObj );
|
|
if ( Abc_InfoHasBit(pInfo, iFrame) == 0 )
|
|
{
|
|
Abc_InfoSetBit( pInfo, iFrame );
|
|
pCountUni[iFrame+1]++;
|
|
pCountUni[0]++;
|
|
}
|
|
pCountAll[iFrame+1]++;
|
|
pCountAll[0]++;
|
|
}
|
|
assert( pCountAll[0] == (iStop - iStart) );
|
|
// printf( "%5d%5d ", pCountAll[0], pCountUni[0] );
|
|
printf( "%3d :", i );
|
|
printf( "%7d", pCountAll[0] );
|
|
if ( i >= 10 )
|
|
{
|
|
for ( k = 0; k < 4; k++ )
|
|
printf( "%5d", pCountAll[k+1] );
|
|
printf( " ..." );
|
|
for ( k = i-4; k <= i; k++ )
|
|
printf( "%5d", pCountAll[k+1] );
|
|
}
|
|
else
|
|
{
|
|
for ( k = 0; k <= i; k++ )
|
|
if ( k <= i )
|
|
printf( "%5d", pCountAll[k+1] );
|
|
}
|
|
// for ( k = 0; k < nFrames; k++ )
|
|
// if ( k <= i )
|
|
// printf( "%5d", pCountAll[k+1] );
|
|
printf( "\n" );
|
|
}
|
|
assert( iStop == Vec_IntSize(vAbs) );
|
|
Vec_IntFree( vSeens );
|
|
ABC_FREE( pCountAll );
|
|
ABC_FREE( pCountUni );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|