blob: 8c7e06e507ff340071b308dde5051e8b5accb54e [file] [log] [blame]
/**CFile****************************************************************
FileName [giaFront.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Frontier representation.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaFront.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Find the next place on the frontier.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Gia_ManFrontFindNext( char * pFront, int nFront, int iFront )
{
assert( iFront < nFront );
for ( ; pFront[iFront]; iFront = (iFront + 1) % nFront );
assert( pFront[iFront] == 0 );
pFront[iFront] = 1;
return iFront;
}
/**Function*************************************************************
Synopsis [Transforms the frontier manager to its initial state.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManFrontTransform( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, * pFrontToId; // mapping of nodes into frontier variables
assert( p->nFront > 0 );
pFrontToId = ABC_FALLOC( int, p->nFront );
Gia_ManForEachObj( p, pObj, i )
{
if ( Gia_ObjIsCo(pObj) )
{
assert( pObj->Value == GIA_NONE );
pObj->iDiff0 = i - pFrontToId[Gia_ObjDiff0(pObj)];
}
else if ( Gia_ObjIsAnd(pObj) )
{
assert( (int)pObj->Value < p->nFront );
pObj->iDiff0 = i - pFrontToId[Gia_ObjDiff0(pObj)];
pObj->iDiff1 = i - pFrontToId[Gia_ObjDiff1(pObj)];
pFrontToId[pObj->Value] = i;
}
else
{
assert( (int)pObj->Value < p->nFront );
pFrontToId[pObj->Value] = i;
}
pObj->Value = 0;
}
ABC_FREE( pFrontToId );
}
/**Function*************************************************************
Synopsis [Determine the frontier.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManCrossCutSimple( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, nCutCur = 0, nCutMax = 0;
Gia_ManCreateValueRefs( p );
Gia_ManForEachObj( p, pObj, i )
{
if ( pObj->Value )
nCutCur++;
if ( nCutMax < nCutCur )
nCutMax = nCutCur;
if ( Gia_ObjIsAnd(pObj) )
{
if ( --Gia_ObjFanin0(pObj)->Value == 0 )
nCutCur--;
if ( --Gia_ObjFanin1(pObj)->Value == 0 )
nCutCur--;
}
else if ( Gia_ObjIsCo(pObj) )
{
if ( --Gia_ObjFanin0(pObj)->Value == 0 )
nCutCur--;
}
}
// Gia_ManForEachObj( p, pObj, i )
// assert( pObj->Value == 0 );
return nCutMax;
}
/**Function*************************************************************
Synopsis [Determine the frontier.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManFront( Gia_Man_t * p )
{
Gia_Man_t * pNew;
Gia_Obj_t * pObj, * pFanin0New, * pFanin1New, * pObjNew;
char * pFront; // places used for the frontier
int i, iLit, nCrossCut = 0, nCrossCutMax = 0;
int nCrossCutMaxInit = Gia_ManCrossCutSimple( p );
int iFront = 0;//, clk = Abc_Clock();
// set references for all objects
Gia_ManCreateValueRefs( p );
// start the new manager
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
pNew->nFront = 1 + (int)((float)1.1 * nCrossCutMaxInit);
// start the frontier
pFront = ABC_CALLOC( char, pNew->nFront );
// add constant node
Gia_ManConst0(pNew)->Value = iFront = Gia_ManFrontFindNext( pFront, pNew->nFront, iFront );
if ( Gia_ObjValue(Gia_ManConst0(p)) == 0 )
pFront[iFront] = 0;
else
nCrossCut = 1;
// iterate through the objects
Gia_ManForEachObj1( p, pObj, i )
{
if ( Gia_ObjIsCi(pObj) )
{
if ( Gia_ObjValue(pObj) && nCrossCutMax < ++nCrossCut )
nCrossCutMax = nCrossCut;
// create new node
iLit = Gia_ManAppendCi( pNew );
pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(iLit) );
assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) );
pObjNew->Value = iFront = Gia_ManFrontFindNext( pFront, pNew->nFront, iFront );
// handle CIs without fanout
if ( Gia_ObjValue(pObj) == 0 )
pFront[iFront] = 0;
continue;
}
if ( Gia_ObjIsCo(pObj) )
{
assert( Gia_ObjValue(pObj) == 0 );
// create new node
iLit = Gia_ManAppendCo( pNew, 0 );
pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(iLit) );
assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) );
// get the fanin
pFanin0New = Gia_ManObj( pNew, Gia_ObjFaninId0(pObj, i) );
assert( pFanin0New->Value != GIA_NONE );
pObjNew->Value = GIA_NONE;
pObjNew->iDiff0 = pFanin0New->Value;
pObjNew->fCompl0 = Gia_ObjFaninC0(pObj);
// deref the fanin
if ( --Gia_ObjFanin0(pObj)->Value == 0 )
{
pFront[pFanin0New->Value] = 0;
nCrossCut--;
}
continue;
}
if ( Gia_ObjValue(pObj) && nCrossCutMax < ++nCrossCut )
nCrossCutMax = nCrossCut;
// create new node
pObjNew = Gia_ManAppendObj( pNew );
assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) );
// assign the first fanin
pFanin0New = Gia_ManObj( pNew, Gia_ObjFaninId0(pObj, i) );
assert( pFanin0New->Value != GIA_NONE );
pObjNew->iDiff0 = pFanin0New->Value;
pObjNew->fCompl0 = Gia_ObjFaninC0(pObj);
// assign the second fanin
pFanin1New = Gia_ManObj( pNew, Gia_ObjFaninId1(pObj, i) );
assert( pFanin1New->Value != GIA_NONE );
pObjNew->iDiff1 = pFanin1New->Value;
pObjNew->fCompl1 = Gia_ObjFaninC1(pObj);
// assign the frontier number
pObjNew->Value = iFront = Gia_ManFrontFindNext( pFront, pNew->nFront, iFront );
// deref the fanins
if ( --Gia_ObjFanin0(pObj)->Value == 0 )
{
pFront[pFanin0New->Value] = 0;
nCrossCut--;
}
if ( --Gia_ObjFanin1(pObj)->Value == 0 )
{
pFront[pFanin1New->Value] = 0;
nCrossCut--;
}
// handle nodes without fanout (choice nodes)
if ( Gia_ObjValue(pObj) == 0 )
pFront[iFront] = 0;
}
assert( pNew->nObjs == p->nObjs );
assert( nCrossCut == 0 || nCrossCutMax == nCrossCutMaxInit );
for ( i = 0; i < pNew->nFront; i++ )
assert( pFront[i] == 0 );
ABC_FREE( pFront );
//printf( "Crosscut = %6d. Frontier = %6d. ", nCrossCutMaxInit, pNew->nFront );
//ABC_PRT( "Time", Abc_Clock() - clk );
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
return pNew;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManFrontTest( Gia_Man_t * p )
{
Gia_Man_t * pNew;
pNew = Gia_ManFront( p );
Gia_ManFrontTransform( pNew );
// Gia_ManCleanValue( p );
// Gia_ManCleanValue( pNew );
if ( memcmp( pNew->pObjs, p->pObjs, sizeof(Gia_Obj_t) * p->nObjs ) )
{
/*
Gia_Obj_t * pObj, * pObjNew;
int i;
Gia_ManForEachObj( p, pObj, i )
{
pObjNew = Gia_ManObj( pNew, i );
printf( "%5d %5d %5d %5d\n",
pObj->iDiff0, pObjNew->iDiff0,
pObj->iDiff1, pObjNew->iDiff1 );
}
*/
printf( "Verification failed.\n" );
}
else
printf( "Verification successful.\n" );
Gia_ManStop( pNew );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END