blob: 98907491bcb4fe23b531cb815ce454538708923a [file] [log] [blame]
/**CFile****************************************************************
FileName [giaMan.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Package manager.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
#include "misc/tim/tim.h"
#include "proof/abs/abs.h"
#include "opt/dar/dar.h"
#ifdef WIN32
#include <windows.h>
#endif
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
extern void Gia_ManDfsSlacksPrint( Gia_Man_t * p );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Creates AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManStart( int nObjsMax )
{
Gia_Man_t * p;
assert( nObjsMax > 0 );
p = ABC_CALLOC( Gia_Man_t, 1 );
p->nObjsAlloc = nObjsMax;
p->pObjs = ABC_CALLOC( Gia_Obj_t, nObjsMax );
p->pObjs->iDiff0 = p->pObjs->iDiff1 = GIA_NONE;
p->nObjs = 1;
p->vCis = Vec_IntAlloc( nObjsMax / 20 );
p->vCos = Vec_IntAlloc( nObjsMax / 20 );
return p;
}
/**Function*************************************************************
Synopsis [Deletes AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManStop( Gia_Man_t * p )
{
if ( p->vSeqModelVec )
Vec_PtrFreeFree( p->vSeqModelVec );
Gia_ManStaticFanoutStop( p );
Tim_ManStopP( (Tim_Man_t **)&p->pManTime );
assert( p->pManTime == NULL );
Vec_PtrFreeFree( p->vNamesIn );
Vec_PtrFreeFree( p->vNamesOut );
Vec_IntFreeP( &p->vSwitching );
Vec_IntFreeP( &p->vSuper );
Vec_IntFreeP( &p->vStore );
Vec_IntFreeP( &p->vClassNew );
Vec_IntFreeP( &p->vClassOld );
Vec_WrdFreeP( &p->vSims );
Vec_WrdFreeP( &p->vSimsPi );
Vec_IntFreeP( &p->vTimeStamps );
Vec_FltFreeP( &p->vTiming );
Vec_VecFreeP( &p->vClockDoms );
Vec_IntFreeP( &p->vCofVars );
Vec_IntFreeP( &p->vIdsOrig );
Vec_IntFreeP( &p->vIdsEquiv );
Vec_IntFreeP( &p->vLutConfigs );
Vec_IntFreeP( &p->vEdgeDelay );
Vec_IntFreeP( &p->vEdgeDelayR );
Vec_IntFreeP( &p->vEdge1 );
Vec_IntFreeP( &p->vEdge2 );
Vec_IntFreeP( &p->vUserPiIds );
Vec_IntFreeP( &p->vUserPoIds );
Vec_IntFreeP( &p->vUserFfIds );
Vec_IntFreeP( &p->vFlopClasses );
Vec_IntFreeP( &p->vGateClasses );
Vec_IntFreeP( &p->vObjClasses );
Vec_IntFreeP( &p->vInitClasses );
Vec_IntFreeP( &p->vRegClasses );
Vec_IntFreeP( &p->vRegInits );
Vec_IntFreeP( &p->vDoms );
Vec_IntFreeP( &p->vBarBufs );
Vec_IntFreeP( &p->vXors );
Vec_IntFreeP( &p->vLevels );
Vec_IntFreeP( &p->vTruths );
Vec_IntErase( &p->vCopies );
Vec_IntErase( &p->vCopies2 );
Vec_IntFreeP( &p->vVar2Obj );
Vec_IntErase( &p->vCopiesTwo );
Vec_IntErase( &p->vSuppVars );
Vec_WrdFreeP( &p->vSuppWords );
Vec_IntFreeP( &p->vTtNums );
Vec_IntFreeP( &p->vTtNodes );
Vec_WrdFreeP( &p->vTtMemory );
Vec_PtrFreeP( &p->vTtInputs );
Vec_IntFreeP( &p->vMapping );
Vec_WecFreeP( &p->vMapping2 );
Vec_WecFreeP( &p->vFanouts2 );
Vec_IntFreeP( &p->vCellMapping );
Vec_IntFreeP( &p->vPacking );
Vec_IntFreeP( &p->vConfigs );
ABC_FREE( p->pCellStr );
Vec_FltFreeP( &p->vInArrs );
Vec_FltFreeP( &p->vOutReqs );
Vec_IntFreeP( &p->vCiArrs );
Vec_IntFreeP( &p->vCoReqs );
Vec_IntFreeP( &p->vCoArrs );
Vec_IntFreeP( &p->vCoAttrs );
Gia_ManStopP( &p->pAigExtra );
Vec_IntFree( p->vCis );
Vec_IntFree( p->vCos );
Vec_IntErase( &p->vHash );
Vec_IntErase( &p->vHTable );
Vec_IntErase( &p->vRefs );
ABC_FREE( p->pData2 );
ABC_FREE( p->pTravIds );
ABC_FREE( p->pPlacement );
ABC_FREE( p->pSwitching );
ABC_FREE( p->pCexSeq );
ABC_FREE( p->pCexComb );
ABC_FREE( p->pIso );
// ABC_FREE( p->pMapping );
ABC_FREE( p->pFanData );
ABC_FREE( p->pReprsOld );
ABC_FREE( p->pReprs );
ABC_FREE( p->pNexts );
ABC_FREE( p->pSibls );
ABC_FREE( p->pRefs );
ABC_FREE( p->pLutRefs );
ABC_FREE( p->pMuxes );
ABC_FREE( p->pObjs );
ABC_FREE( p->pSpec );
ABC_FREE( p->pName );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Returns memory used in megabytes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
double Gia_ManMemory( Gia_Man_t * p )
{
double Memory = sizeof(Gia_Man_t);
Memory += sizeof(Gia_Obj_t) * Gia_ManObjNum(p);
Memory += sizeof(int) * Gia_ManCiNum(p);
Memory += sizeof(int) * Gia_ManCoNum(p);
Memory += sizeof(int) * Vec_IntSize(&p->vHTable);
Memory += sizeof(int) * Gia_ManObjNum(p) * (p->pRefs != NULL);
Memory += Vec_IntMemory( p->vLevels );
Memory += Vec_IntMemory( p->vCellMapping );
Memory += Vec_IntMemory( &p->vCopies );
Memory += Vec_FltMemory( p->vInArrs );
Memory += Vec_FltMemory( p->vOutReqs );
Memory += Vec_PtrMemory( p->vNamesIn );
Memory += Vec_PtrMemory( p->vNamesOut );
return Memory;
}
/**Function*************************************************************
Synopsis [Stops the AIG manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManStopP( Gia_Man_t ** p )
{
if ( *p == NULL )
return;
Gia_ManStop( *p );
*p = NULL;
}
/**Function*************************************************************
Synopsis [Prints stats for the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintClasses_old( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
if ( p->vFlopClasses == NULL )
return;
Gia_ManForEachRo( p, pObj, i )
Abc_Print( 1, "%d", Vec_IntEntry(p->vFlopClasses, i) );
Abc_Print( 1, "\n" );
{
Gia_Man_t * pTemp;
pTemp = Gia_ManDupFlopClass( p, 1 );
Gia_AigerWrite( pTemp, "dom1.aig", 0, 0 );
Gia_ManStop( pTemp );
pTemp = Gia_ManDupFlopClass( p, 2 );
Gia_AigerWrite( pTemp, "dom2.aig", 0, 0 );
Gia_ManStop( pTemp );
}
}
/**Function*************************************************************
Synopsis [Prints stats for the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintPlacement( Gia_Man_t * p )
{
int i, nFixed = 0, nUndef = 0;
if ( p->pPlacement == NULL )
return;
for ( i = 0; i < Gia_ManObjNum(p); i++ )
{
nFixed += p->pPlacement[i].fFixed;
nUndef += p->pPlacement[i].fUndef;
}
Abc_Print( 1, "Placement: Objects = %8d. Fixed = %8d. Undef = %8d.\n", Gia_ManObjNum(p), nFixed, nUndef );
}
/**Function*************************************************************
Synopsis [Duplicates AIG for unrolling.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintTents_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjs )
{
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
return;
Gia_ObjSetTravIdCurrent(p, pObj);
Vec_IntPush( vObjs, Gia_ObjId(p, pObj) );
if ( Gia_ObjIsCi(pObj) )
return;
Gia_ManPrintTents_rec( p, Gia_ObjFanin0(pObj), vObjs );
if ( Gia_ObjIsAnd(pObj) )
Gia_ManPrintTents_rec( p, Gia_ObjFanin1(pObj), vObjs );
}
void Gia_ManPrintTents( Gia_Man_t * p )
{
Vec_Int_t * vObjs;
Gia_Obj_t * pObj;
int t, i, iObjId, nSizePrev, nSizeCurr;
assert( Gia_ManPoNum(p) > 0 );
vObjs = Vec_IntAlloc( 100 );
// save constant class
Gia_ManIncrementTravId( p );
Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
Vec_IntPush( vObjs, 0 );
// create starting root
nSizePrev = Vec_IntSize(vObjs);
Gia_ManForEachPo( p, pObj, i )
Gia_ManPrintTents_rec( p, pObj, vObjs );
// build tents
Abc_Print( 1, "Tents: " );
for ( t = 1; nSizePrev < Vec_IntSize(vObjs); t++ )
{
int nPis = 0;
nSizeCurr = Vec_IntSize(vObjs);
Vec_IntForEachEntryStartStop( vObjs, iObjId, i, nSizePrev, nSizeCurr )
{
nPis += Gia_ObjIsPi(p, Gia_ManObj(p, iObjId));
if ( Gia_ObjIsRo(p, Gia_ManObj(p, iObjId)) )
Gia_ManPrintTents_rec( p, Gia_ObjRoToRi(p, Gia_ManObj(p, iObjId)), vObjs );
}
Abc_Print( 1, "%d=%d(%d) ", t, nSizeCurr - nSizePrev, nPis );
nSizePrev = nSizeCurr;
}
Abc_Print( 1, " Unused=%d\n", Gia_ManObjNum(p) - Vec_IntSize(vObjs) );
Vec_IntFree( vObjs );
// the remaining objects are PIs without fanout
// Gia_ManForEachObj( p, pObj, i )
// if ( !Gia_ObjIsTravIdCurrent(p, pObj) )
// Gia_ObjPrint( p, pObj );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintInitClasses( Vec_Int_t * vInits )
{
int i, Value;
int Counts[6] = {0};
Vec_IntForEachEntry( vInits, Value, i )
Counts[Value]++;
for ( i = 0; i < 6; i++ )
if ( Counts[i] )
printf( "%d = %d ", i, Counts[i] );
printf( " " );
printf( "B = %d ", Counts[0] + Counts[1] );
printf( "X = %d ", Counts[2] + Counts[3] );
printf( "Q = %d\n", Counts[4] + Counts[5] );
Vec_IntForEachEntry( vInits, Value, i )
{
Counts[Value]++;
if ( Value == 0 )
printf( "0" );
else if ( Value == 1 )
printf( "1" );
else if ( Value == 2 )
printf( "2" );
else if ( Value == 3 )
printf( "3" );
else if ( Value == 4 )
printf( "4" );
else if ( Value == 5 )
printf( "5" );
else assert( 0 );
}
printf( "\n" );
}
/**Function*************************************************************
Synopsis [Prints stats for the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintChoiceStats( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, nEquivs = 0, nChoices = 0;
Gia_ManMarkFanoutDrivers( p );
Gia_ManForEachAnd( p, pObj, i )
{
if ( !Gia_ObjSibl(p, i) )
continue;
nEquivs++;
if ( pObj->fMark0 )
nChoices++;
assert( !Gia_ObjSiblObj(p, i)->fMark0 );
assert( Gia_ObjIsAnd(Gia_ObjSiblObj(p, i)) );
}
Abc_Print( 1, "Choice stats: Equivs =%7d. Choices =%7d.\n", nEquivs, nChoices );
Gia_ManCleanMark0( p );
}
/**Function*************************************************************
Synopsis [Prints stats for the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManPrintEdges( Gia_Man_t * p )
{
printf( "Edges (Q=2) : " );
printf( "edge =%8d ", (Vec_IntCountPositive(p->vEdge1) + Vec_IntCountPositive(p->vEdge2))/2 );
printf( "lev =%5.1f", 0.1*Gia_ManEvalEdgeDelay(p) );
printf( "\n" );
return 0;
}
/**Function*************************************************************
Synopsis [Prints stats for the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars )
{
extern float Gia_ManLevelAve( Gia_Man_t * p );
if ( pPars && pPars->fMiter )
{
Gia_ManPrintStatsMiter( p, 0 );
return;
}
#ifdef WIN32
SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 15 ); // bright
if ( p->pName )
Abc_Print( 1, "%-8s : ", p->pName );
SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 ); // normal
#else
if ( p->pName )
Abc_Print( 1, "%s%-8s%s : ", "\033[1;37m", p->pName, "\033[0m" ); // bright
#endif
Abc_Print( 1, "i/o =%7d/%7d",
Gia_ManPiNum(p) - Gia_ManBoxCiNum(p) - Gia_ManRegBoxNum(p),
Gia_ManPoNum(p) - Gia_ManBoxCoNum(p) - Gia_ManRegBoxNum(p) );
if ( Gia_ManConstrNum(p) )
Abc_Print( 1, "(c=%d)", Gia_ManConstrNum(p) );
if ( Gia_ManRegNum(p) )
Abc_Print( 1, " ff =%7d", Gia_ManRegNum(p) );
if ( Gia_ManRegBoxNum(p) )
Abc_Print( 1, " boxff =%d(%d)", Gia_ManRegBoxNum(p), Gia_ManClockDomainNum(p) );
#ifdef WIN32
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute( hConsole, 11 ); // blue
Abc_Print( 1, " %s =%8d", p->pMuxes? "nod" : "and", Gia_ManAndNum(p) );
SetConsoleTextAttribute( hConsole, 13 ); // magenta
Abc_Print( 1, " lev =%5d", Gia_ManLevelNum(p) );
Abc_Print( 1, " (%.2f)", Gia_ManLevelAve(p) );
SetConsoleTextAttribute( hConsole, 7 ); // normal
}
#else
Abc_Print( 1, " %s%s =%8d%s", "\033[1;36m", p->pMuxes? "nod" : "and", Gia_ManAndNum(p), "\033[0m" ); // blue
Abc_Print( 1, " %slev =%5d%s", "\033[1;35m", Gia_ManLevelNum(p), "\033[0m" ); // magenta
Abc_Print( 1, " %s(%.2f)%s", "\033[1;35m", Gia_ManLevelAve(p), "\033[0m" );
#endif
Vec_IntFreeP( &p->vLevels );
if ( pPars && pPars->fCut )
Abc_Print( 1, " cut = %d(%d)", Gia_ManCrossCut(p, 0), Gia_ManCrossCut(p, 1) );
Abc_Print( 1, " mem =%5.2f MB", Gia_ManMemory(p)/(1<<20) );
if ( Gia_ManHasChoices(p) )
Abc_Print( 1, " ch =%5d", Gia_ManChoiceNum(p) );
if ( p->pManTime )
Abc_Print( 1, " box = %d", Gia_ManNonRegBoxNum(p) );
if ( p->pManTime )
Abc_Print( 1, " bb = %d", Gia_ManBlackBoxNum(p) );
if ( Gia_ManBufNum(p) )
Abc_Print( 1, " buf = %d", Gia_ManBufNum(p) );
if ( pPars && pPars->fMuxXor )
printf( "\nXOR/MUX " ), Gia_ManPrintMuxStats( p );
if ( pPars && pPars->fSwitch )
{
static int nPiPo = 0;
static float PrevSwiTotal = 0;
float SwiTotal = Gia_ManComputeSwitching( p, 48, 16, 0 );
Abc_Print( 1, " power =%8.1f", SwiTotal );
if ( PrevSwiTotal > 0 && nPiPo == Gia_ManCiNum(p) + Gia_ManCoNum(p) )
Abc_Print( 1, " %6.2f %%", 100.0*(PrevSwiTotal-SwiTotal)/PrevSwiTotal );
else if ( PrevSwiTotal == 0 || nPiPo != Gia_ManCiNum(p) + Gia_ManCoNum(p) )
PrevSwiTotal = SwiTotal, nPiPo = Gia_ManCiNum(p) + Gia_ManCoNum(p);
}
// Abc_Print( 1, "obj =%5d ", Gia_ManObjNum(p) );
Abc_Print( 1, "\n" );
// Gia_ManSatExperiment( p );
if ( p->pReprs && p->pNexts )
Gia_ManEquivPrintClasses( p, 0, 0.0 );
if ( Gia_ManHasMapping(p) && (pPars == NULL || !pPars->fSkipMap) )
Gia_ManPrintMappingStats( p, pPars ? pPars->pDumpFile : NULL );
if ( pPars && pPars->fNpn && Gia_ManHasMapping(p) && Gia_ManLutSizeMax(p) <= 4 )
Gia_ManPrintNpnClasses( p );
if ( p->vPacking )
Gia_ManPrintPackingStats( p );
if ( p->vEdge1 )
Gia_ManPrintEdges( p );
if ( pPars && pPars->fLutProf && Gia_ManHasMapping(p) )
Gia_ManPrintLutStats( p );
if ( p->pPlacement )
Gia_ManPrintPlacement( p );
// if ( p->pManTime )
// Tim_ManPrintStats( (Tim_Man_t *)p->pManTime, p->nAnd2Delay );
Gia_ManPrintFlopClasses( p );
Gia_ManPrintGateClasses( p );
Gia_ManPrintObjClasses( p );
// if ( p->vRegClasses )
// {
// printf( "The design has %d flops with the following class info: ", Vec_IntSize(p->vRegClasses) );
// Vec_IntPrint( p->vRegClasses );
// }
if ( p->vInitClasses )
Gia_ManPrintInitClasses( p->vInitClasses );
// check integrity of boxes
Gia_ManCheckIntegrityWithBoxes( p );
/*
if ( Gia_ManRegBoxNum(p) )
{
int i, Limit = Vec_IntFindMax(p->vRegClasses);
for ( i = 1; i <= Limit; i++ )
printf( "%d ", Vec_IntCountEntry(p->vRegClasses, i) );
printf( "\n" );
}
*/
if ( pPars && pPars->fTents )
{
/*
int k, Entry, Prev = 1;
Vec_Int_t * vLimit = Vec_IntAlloc( 1000 );
Gia_Man_t * pNew = Gia_ManUnrollDup( p, vLimit );
Abc_Print( 1, "Tents: " );
Vec_IntForEachEntryStart( vLimit, Entry, k, 1 )
Abc_Print( 1, "%d=%d ", k, Entry-Prev ), Prev = Entry;
Abc_Print( 1, " Unused=%d.", Gia_ManObjNum(p) - Gia_ManObjNum(pNew) );
Abc_Print( 1, "\n" );
Vec_IntFree( vLimit );
Gia_ManStop( pNew );
*/
Gia_ManPrintTents( p );
}
if ( pPars && pPars->fSlacks )
Gia_ManDfsSlacksPrint( p );
}
/**Function*************************************************************
Synopsis [Prints stats for the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintStatsShort( Gia_Man_t * p )
{
Abc_Print( 1, "i/o =%7d/%7d ", Gia_ManPiNum(p), Gia_ManPoNum(p) );
Abc_Print( 1, "ff =%7d ", Gia_ManRegNum(p) );
Abc_Print( 1, "and =%8d ", Gia_ManAndNum(p) );
Abc_Print( 1, "lev =%5d ", Gia_ManLevelNum(p) );
// Abc_Print( 1, "mem =%5.2f MB", 12.0*Gia_ManObjNum(p)/(1<<20) );
Abc_Print( 1, "\n" );
}
/**Function*************************************************************
Synopsis [Prints stats for the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintMiterStatus( Gia_Man_t * p )
{
Gia_Obj_t * pObj, * pChild;
int i, nSat = 0, nUnsat = 0, nUndec = 0, iOut = -1;
Gia_ManForEachPo( p, pObj, i )
{
pChild = Gia_ObjChild0(pObj);
// check if the output is constant 0
if ( pChild == Gia_ManConst0(p) )
nUnsat++;
// check if the output is constant 1
else if ( pChild == Gia_ManConst1(p) )
{
nSat++;
if ( iOut == -1 )
iOut = i;
}
// check if the output is a primary input
else if ( Gia_ObjIsPi(p, Gia_Regular(pChild)) )
{
nSat++;
if ( iOut == -1 )
iOut = i;
}
/*
// check if the output is 1 for the 0000 pattern
else if ( Gia_Regular(pChild)->fPhase != (unsigned)Gia_IsComplement(pChild) )
{
nSat++;
if ( iOut == -1 )
iOut = i;
}
*/
else
nUndec++;
}
Abc_Print( 1, "Outputs = %7d. Unsat = %7d. Sat = %7d. Undec = %7d.\n",
Gia_ManPoNum(p), nUnsat, nSat, nUndec );
}
/**Function*************************************************************
Synopsis [Statistics of the miter.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintStatsMiter( Gia_Man_t * p, int fVerbose )
{
Gia_Obj_t * pObj;
Vec_Flt_t * vProb;
int i, iObjId;
Gia_ManLevelNum( p );
Gia_ManCreateRefs( p );
vProb = Gia_ManPrintOutputProb( p );
printf( "Statistics for each outputs of the miter:\n" );
Gia_ManForEachPo( p, pObj, i )
{
iObjId = Gia_ObjId(p, pObj);
printf( "%4d : ", i );
printf( "Level = %5d ", Gia_ObjLevelId(p, iObjId) );
printf( "Supp = %5d ", Gia_ManSuppSize(p, &iObjId, 1) );
printf( "Cone = %5d ", Gia_ManConeSize(p, &iObjId, 1) );
printf( "Mffc = %5d ", Gia_NodeMffcSize(p, Gia_ObjFanin0(pObj)) );
printf( "Prob = %8.4f ", Vec_FltEntry(vProb, iObjId) );
printf( "\n" );
}
Vec_FltFree( vProb );
}
/**Function*************************************************************
Synopsis [Prints stats for the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs )
{
assert( p->nRegs == 0 );
p->nRegs = nRegs;
}
/**Function*************************************************************
Synopsis [Reports the reduction of the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew )
{
Abc_Print( 1, "REG: Beg = %5d. End = %5d. (R =%5.1f %%) ",
Gia_ManRegNum(p), Gia_ManRegNum(pNew),
Gia_ManRegNum(p)? 100.0*(Gia_ManRegNum(p)-Gia_ManRegNum(pNew))/Gia_ManRegNum(p) : 0.0 );
Abc_Print( 1, "AND: Beg = %6d. End = %6d. (R =%5.1f %%)",
Gia_ManAndNum(p), Gia_ManAndNum(pNew),
Gia_ManAndNum(p)? 100.0*(Gia_ManAndNum(p)-Gia_ManAndNum(pNew))/Gia_ManAndNum(p) : 0.0 );
Abc_Print( 1, "\n" );
}
/**Function*************************************************************
Synopsis [Prints NPN class statistics.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintNpnClasses( Gia_Man_t * p )
{
extern char ** Kit_DsdNpn4ClassNames();
char ** pNames = Kit_DsdNpn4ClassNames();
Vec_Int_t * vLeaves, * vTruth, * vVisited;
int * pLutClass, ClassCounts[222] = {0};
int i, k, iFan, Class, OtherClasses, OtherClasses2, nTotal, Counter, Counter2;
unsigned * pTruth;
assert( Gia_ManHasMapping(p) );
assert( Gia_ManLutSizeMax( p ) <= 4 );
vLeaves = Vec_IntAlloc( 100 );
vVisited = Vec_IntAlloc( 100 );
vTruth = Vec_IntAlloc( (1<<16) );
pLutClass = ABC_CALLOC( int, Gia_ManObjNum(p) );
Gia_ManCleanTruth( p );
Gia_ManForEachLut( p, i )
{
if ( Gia_ObjLutSize(p,i) > 4 )
continue;
Vec_IntClear( vLeaves );
Gia_LutForEachFanin( p, i, iFan, k )
Vec_IntPush( vLeaves, iFan );
for ( ; k < 4; k++ )
Vec_IntPush( vLeaves, 0 );
pTruth = Gia_ManConvertAigToTruth( p, Gia_ManObj(p, i), vLeaves, vTruth, vVisited );
Class = Dar_LibReturnClass( *pTruth );
ClassCounts[ Class ]++;
pLutClass[i] = Class;
}
Vec_IntFree( vLeaves );
Vec_IntFree( vTruth );
Vec_IntFree( vVisited );
Vec_IntFreeP( &p->vTruths );
nTotal = 0;
for ( i = 0; i < 222; i++ )
nTotal += ClassCounts[i];
Abc_Print( 1, "NPN CLASS STATISTICS (for %d LUT4 present in the current mapping):\n", nTotal );
OtherClasses = 0;
for ( i = k = 0; i < 222; i++ )
{
if ( ClassCounts[i] == 0 )
continue;
// if ( 100.0 * ClassCounts[i] / (nTotal+1) < 0.1 ) // do not show anything below 0.1 percent
// continue;
OtherClasses += ClassCounts[i];
Abc_Print( 1, "%3d: Class %3d : Count = %6d (%7.2f %%) %s\n",
++k, i, ClassCounts[i], 100.0 * ClassCounts[i] / (nTotal+1), pNames[i] );
}
OtherClasses = nTotal - OtherClasses;
Abc_Print( 1, "Other : Count = %6d (%7.2f %%)\n",
OtherClasses, 100.0 * OtherClasses / (nTotal+1) );
// count the number of LUTs that have MUX function and two fanins with MUX functions
OtherClasses = OtherClasses2 = 0;
ABC_FREE( p->pRefs );
Gia_ManSetRefsMapped( p );
Gia_ManForEachLut( p, i )
{
if ( pLutClass[i] != 109 )
continue;
Counter = Counter2 = 0;
Gia_LutForEachFanin( p, i, iFan, k )
{
Counter += (pLutClass[iFan] == 109);
Counter2 += (pLutClass[iFan] == 109) && (Gia_ObjRefNumId(p, iFan) == 1);
}
OtherClasses += (Counter > 1);
OtherClasses2 += (Counter2 > 1);
// Abc_Print( 1, "%d -- ", pLutClass[i] );
// Gia_LutForEachFanin( p, i, iFan, k )
// Abc_Print( 1, "%d ", pLutClass[iFan] );
// Abc_Print( 1, "\n" );
}
ABC_FREE( p->pRefs );
Abc_Print( 1, "Approximate number of 4:1 MUX structures: All = %6d (%7.2f %%) MFFC = %6d (%7.2f %%)\n",
OtherClasses, 100.0 * OtherClasses / (nTotal+1),
OtherClasses2, 100.0 * OtherClasses2 / (nTotal+1) );
ABC_FREE( pLutClass );
}
/**Function*************************************************************
Synopsis [Collects internal nodes and boxes in the DFS order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManDfsCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjs )
{
if ( Gia_ObjIsTravIdCurrent( p, pObj ) )
return;
Gia_ObjSetTravIdCurrent( p, pObj );
if ( Gia_ObjIsCi(pObj) )
{
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
if ( pManTime )
{
int i, iFirst, nTerms, iBox;
iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) );
if ( iBox >= 0 ) // pObj is a box input
{
// mark box outputs
iFirst = Tim_ManBoxOutputFirst( pManTime, iBox );
nTerms = Tim_ManBoxOutputNum( pManTime, iBox );
for ( i = 0; i < nTerms; i++ )
{
pObj = Gia_ManCi( p, iFirst + i );
Gia_ObjSetTravIdCurrent( p, pObj );
}
// traverse box inputs
iFirst = Tim_ManBoxInputFirst( pManTime, iBox );
nTerms = Tim_ManBoxInputNum( pManTime, iBox );
for ( i = 0; i < nTerms; i++ )
{
pObj = Gia_ManCo( p, iFirst + i );
Gia_ManDfsCollect_rec( p, pObj, vObjs );
}
// save the box
Vec_IntPush( vObjs, -iBox-1 );
}
}
return;
}
else if ( Gia_ObjIsCo(pObj) )
{
Gia_ManDfsCollect_rec( p, Gia_ObjFanin0(pObj), vObjs );
}
else if ( Gia_ObjIsAnd(pObj) )
{
int iFan, k, iObj = Gia_ObjId(p, pObj);
if ( Gia_ManHasMapping(p) )
{
assert( Gia_ObjIsLut(p, iObj) );
Gia_LutForEachFanin( p, iObj, iFan, k )
Gia_ManDfsCollect_rec( p, Gia_ManObj(p, iFan), vObjs );
}
else
{
Gia_ManDfsCollect_rec( p, Gia_ObjFanin0(pObj), vObjs );
Gia_ManDfsCollect_rec( p, Gia_ObjFanin1(pObj), vObjs );
}
// save the object
Vec_IntPush( vObjs, iObj );
}
else if ( !Gia_ObjIsConst0(pObj) )
assert( 0 );
}
Vec_Int_t * Gia_ManDfsCollect( Gia_Man_t * p )
{
Vec_Int_t * vObjs = Vec_IntAlloc( Gia_ManObjNum(p) );
Gia_Obj_t * pObj; int i;
Gia_ManIncrementTravId( p );
Gia_ManForEachCo( p, pObj, i )
Gia_ManDfsCollect_rec( p, pObj, vObjs );
Gia_ManForEachCi( p, pObj, i )
Gia_ManDfsCollect_rec( p, pObj, vObjs );
return vObjs;
}
/**Function*************************************************************
Synopsis [Compute arrival/required times.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManDfsArrivals( Gia_Man_t * p, Vec_Int_t * vObjs )
{
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
Vec_Int_t * vTimes = Vec_IntStartFull( Gia_ManObjNum(p) );
Gia_Obj_t * pObj; int j, Entry, k, iFan;
Vec_IntWriteEntry( vTimes, 0, 0 );
if ( pManTime )
{
Tim_ManIncrementTravId( pManTime );
Gia_ManForEachCi( p, pObj, j )
if ( j < Tim_ManPiNum(pManTime) )
{
float arrTime = Tim_ManGetCiArrival( pManTime, j );
Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), (int)arrTime );
}
}
else
{
Gia_ManForEachCi( p, pObj, j )
Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), 0 );
}
Vec_IntForEachEntry( vObjs, Entry, j )
{
if ( Entry < 0 ) // box
{
int Time0, iFirst, nTerms, iBox = -Entry-1;
assert( iBox >= 0 );
// set arrivals for box inputs
iFirst = Tim_ManBoxInputFirst( pManTime, iBox );
nTerms = Tim_ManBoxInputNum( pManTime, iBox );
for ( k = 0; k < nTerms; k++ )
{
pObj = Gia_ManCo( p, iFirst + k );
Time0 = Vec_IntEntry( vTimes, Gia_ObjFaninId0p(p, pObj) );
assert( Time0 >= 0 );
Tim_ManSetCoArrival( pManTime, Gia_ObjCioId(pObj), Time0 );
}
// derive arrivals for box outputs
iFirst = Tim_ManBoxOutputFirst( pManTime, iBox );
nTerms = Tim_ManBoxOutputNum( pManTime, iBox );
for ( k = 0; k < nTerms; k++ )
{
pObj = Gia_ManCi( p, iFirst + k );
Time0 = Tim_ManGetCiArrival( pManTime, Gia_ObjCioId(pObj) );
assert( Time0 >= 0 );
Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), Time0 );
}
}
else if ( Entry > 0 ) // node
{
int Time0, Time1, TimeMax = 0;
if ( Gia_ManHasMapping(p) )
{
assert( Gia_ObjIsLut(p, Entry) );
Gia_LutForEachFanin( p, Entry, iFan, k )
{
Time0 = Vec_IntEntry( vTimes, iFan );
assert( Time0 >= 0 );
TimeMax = Abc_MaxInt( TimeMax, Time0 );
}
}
else
{
pObj = Gia_ManObj( p, Entry );
Time0 = Vec_IntEntry( vTimes, Gia_ObjFaninId0(pObj, Entry) );
Time1 = Vec_IntEntry( vTimes, Gia_ObjFaninId1(pObj, Entry) );
assert( Time0 >= 0 && Time1 >= 0 );
TimeMax = Abc_MaxInt( Time0, Time1 );
}
Vec_IntWriteEntry( vTimes, Entry, TimeMax + 10 );
}
else assert( 0 );
}
return vTimes;
}
static inline void Gia_ManDfsUpdateRequired( Vec_Int_t * vTimes, int iObj, int Req )
{
int *pTime = Vec_IntEntryP( vTimes, iObj );
if (*pTime == -1 || *pTime > Req)
*pTime = Req;
}
Vec_Int_t * Gia_ManDfsRequireds( Gia_Man_t * p, Vec_Int_t * vObjs, int ReqTime )
{
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
Vec_Int_t * vTimes = Vec_IntStartFull( Gia_ManObjNum(p) );
Gia_Obj_t * pObj;
int j, Entry, k, iFan, Req;
Vec_IntWriteEntry( vTimes, 0, 0 );
if ( pManTime )
{
int nCoLimit = Gia_ManCoNum(p) - Tim_ManPoNum(pManTime);
Tim_ManIncrementTravId( pManTime );
//Tim_ManInitPoRequiredAll( pManTime, (float)ReqTime );
Gia_ManForEachCo( p, pObj, j )
if ( j >= nCoLimit )
{
Tim_ManSetCoRequired( pManTime, j, ReqTime );
Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0p(p, pObj), ReqTime );
}
}
else
{
Gia_ManForEachCo( p, pObj, j )
Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0p(p, pObj), ReqTime );
}
Vec_IntForEachEntryReverse( vObjs, Entry, j )
{
if ( Entry < 0 ) // box
{
int iFirst, nTerms, iBox = -Entry-1;
assert( iBox >= 0 );
// set requireds for box outputs
iFirst = Tim_ManBoxOutputFirst( pManTime, iBox );
nTerms = Tim_ManBoxOutputNum( pManTime, iBox );
for ( k = 0; k < nTerms; k++ )
{
pObj = Gia_ManCi( p, iFirst + k );
Req = Vec_IntEntry( vTimes, Gia_ObjId(p, pObj) );
Req = Req == -1 ? ReqTime : Req; // dangling box output
assert( Req >= 0 );
Tim_ManSetCiRequired( pManTime, Gia_ObjCioId(pObj), Req );
}
// derive requireds for box inputs
iFirst = Tim_ManBoxInputFirst( pManTime, iBox );
nTerms = Tim_ManBoxInputNum( pManTime, iBox );
for ( k = 0; k < nTerms; k++ )
{
pObj = Gia_ManCo( p, iFirst + k );
Req = Tim_ManGetCoRequired( pManTime, Gia_ObjCioId(pObj) );
assert( Req >= 0 );
Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0p(p, pObj), Req );
}
}
else if ( Entry > 0 ) // node
{
Req = Vec_IntEntry(vTimes, Entry) - 10;
assert( Req >= 0 );
if ( Gia_ManHasMapping(p) )
{
assert( Gia_ObjIsLut(p, Entry) );
Gia_LutForEachFanin( p, Entry, iFan, k )
Gia_ManDfsUpdateRequired( vTimes, iFan, Req );
}
else
{
pObj = Gia_ManObj( p, Entry );
Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0(pObj, Entry), Req );
Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId1(pObj, Entry), Req );
}
}
else assert( 0 );
}
return vTimes;
}
Vec_Int_t * Gia_ManDfsSlacks( Gia_Man_t * p )
{
Vec_Int_t * vSlack = Vec_IntStartFull( Gia_ManObjNum(p) );
Vec_Int_t * vObjs = Gia_ManDfsCollect( p );
if ( Vec_IntSize(vObjs) > 0 )
{
Vec_Int_t * vArrs = Gia_ManDfsArrivals( p, vObjs );
int Required = Vec_IntFindMax( vArrs );
Vec_Int_t * vReqs = Gia_ManDfsRequireds( p, vObjs, Required );
int i, Arr, Req, Arrivals = ABC_INFINITY;
Vec_IntForEachEntry( vReqs, Req, i )
if ( Req != -1 )
Arrivals = Abc_MinInt( Arrivals, Req );
//if ( Arrivals != 0 )
// printf( "\nGlobal timing check has failed.\n\n" );
//assert( Arrivals == 0 );
Vec_IntForEachEntryTwo( vArrs, vReqs, Arr, Req, i )
{
if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) )
continue;
if ( Gia_ManHasMapping(p) && !Gia_ObjIsLut(p, i) )
continue;
assert( Arr <= Req );
Vec_IntWriteEntry( vSlack, i, Req - Arr );
}
Vec_IntFree( vArrs );
Vec_IntFree( vReqs );
}
Vec_IntFree( vObjs );
return vSlack;
}
void Gia_ManDfsSlacksPrint( Gia_Man_t * p )
{
Vec_Int_t * vCounts, * vSlacks = Gia_ManDfsSlacks( p );
int i, Entry, nRange, nTotal;
if ( Vec_IntSize(vSlacks) == 0 )
{
printf( "Network contains no internal objects.\n" );
Vec_IntFree( vSlacks );
return;
}
// compute slacks
Vec_IntForEachEntry( vSlacks, Entry, i )
if ( Entry != -1 )
Vec_IntWriteEntry( vSlacks, i, Entry/10 );
nRange = Vec_IntFindMax( vSlacks );
// count items
vCounts = Vec_IntStart( nRange + 1 );
Vec_IntForEachEntry( vSlacks, Entry, i )
if ( Entry != -1 )
Vec_IntAddToEntry( vCounts, Entry, 1 );
// print slack ranges
nTotal = Vec_IntSum( vCounts );
assert( nTotal > 0 );
Vec_IntForEachEntry( vCounts, Entry, i )
{
printf( "Slack range %3d = ", i );
printf( "[%4d, %4d) ", 10*i, 10*(i+1) );
printf( "Nodes = %5d ", Entry );
printf( "(%6.2f %%) ", 100.0*Entry/nTotal );
printf( "\n" );
}
Vec_IntFree( vSlacks );
Vec_IntFree( vCounts );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END