blob: 2221279367982ec938a663897794c2988c6a4f72 [file] [log] [blame]
/**CFile****************************************************************
FileName [giaTim.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Procedures with hierarchy/timing manager.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaTim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
#include "giaAig.h"
#include "misc/tim/tim.h"
#include "misc/extra/extra.h"
#include "proof/cec/cec.h"
#include "proof/fra/fra.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Returns the number of boxes in the AIG with boxes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManBoxNum( Gia_Man_t * p )
{
return p->pManTime ? Tim_ManBoxNum((Tim_Man_t *)p->pManTime) : 0;
}
int Gia_ManRegBoxNum( Gia_Man_t * p )
{
return p->vRegClasses ? Vec_IntSize(p->vRegClasses) : 0;
}
int Gia_ManNonRegBoxNum( Gia_Man_t * p )
{
return Gia_ManBoxNum(p) - Gia_ManRegBoxNum(p);
}
int Gia_ManBlackBoxNum( Gia_Man_t * p )
{
return Tim_ManBlackBoxNum((Tim_Man_t *)p->pManTime);
}
int Gia_ManBoxCiNum( Gia_Man_t * p )
{
return p->pManTime ? Gia_ManCiNum(p) - Tim_ManPiNum((Tim_Man_t *)p->pManTime) : 0;
}
int Gia_ManBoxCoNum( Gia_Man_t * p )
{
return p->pManTime ? Gia_ManCoNum(p) - Tim_ManPoNum((Tim_Man_t *)p->pManTime) : 0;
}
int Gia_ManClockDomainNum( Gia_Man_t * p )
{
int i, nDoms, Count = 0;
if ( p->vRegClasses == NULL )
return 0;
nDoms = Vec_IntFindMax(p->vRegClasses);
assert( Vec_IntCountEntry(p->vRegClasses, 0) == 0 );
for ( i = 1; i <= nDoms; i++ )
if ( Vec_IntCountEntry(p->vRegClasses, i) > 0 )
Count++;
return Count;
}
/**Function*************************************************************
Synopsis [Returns one if this is a seq AIG with non-trivial boxes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManIsSeqWithBoxes( Gia_Man_t * p )
{
return (Gia_ManRegNum(p) > 0 && Gia_ManBoxNum(p) > 0);
}
/**Function*************************************************************
Synopsis [Makes sure the manager is normalized.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManIsNormalized( Gia_Man_t * p )
{
int i, nOffset;
nOffset = 1;
for ( i = 0; i < Gia_ManCiNum(p); i++ )
if ( !Gia_ObjIsCi( Gia_ManObj(p, nOffset+i) ) )
return 0;
nOffset = 1 + Gia_ManCiNum(p) + Gia_ManAndNum(p);
for ( i = 0; i < Gia_ManCoNum(p); i++ )
if ( !Gia_ObjIsCo( Gia_ManObj(p, nOffset+i) ) )
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Duplicates AIG in the DFS order while putting CIs first.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManDupNormalize( Gia_Man_t * p, int fHashMapping )
{
Gia_Man_t * pNew;
Gia_Obj_t * pObj;
int i;
Gia_ManFillValue( p );
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Gia_ManConst0(p)->Value = 0;
if ( !Gia_ManIsSeqWithBoxes(p) )
{
Gia_ManForEachCi( p, pObj, i )
pObj->Value = Gia_ManAppendCi(pNew);
}
else
{
// current CI order: PIs + FOs + NewCIs
// desired reorder: PIs + NewCIs + FOs
int nCIs = Tim_ManPiNum( (Tim_Man_t *)p->pManTime );
int nAll = Tim_ManCiNum( (Tim_Man_t *)p->pManTime );
int nPis = nCIs - Gia_ManRegNum(p);
assert( nAll == Gia_ManCiNum(p) );
assert( nPis > 0 );
// copy PIs first
for ( i = 0; i < nPis; i++ )
Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew);
// copy new CIs second
for ( i = nCIs; i < nAll; i++ )
Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew);
// copy flops last
for ( i = nCIs - Gia_ManRegNum(p); i < nCIs; i++ )
Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew);
printf( "Warning: Shuffled CI order to be correct sequential AIG.\n" );
}
if ( fHashMapping ) Gia_ManHashAlloc( pNew );
Gia_ManForEachAnd( p, pObj, i )
if ( Gia_ObjIsBuf(pObj) )
pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) );
else if ( fHashMapping )
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
else
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
if ( fHashMapping ) Gia_ManHashStop( pNew );
Gia_ManForEachCo( p, pObj, i )
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
pNew->nConstrs = p->nConstrs;
assert( Gia_ManIsNormalized(pNew) );
Gia_ManDupRemapEquiv( pNew, p );
return pNew;
}
/**Function*************************************************************
Synopsis [Reorders flops for sequential AIGs with boxes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManDupUnshuffleInputs( Gia_Man_t * p )
{
Gia_Man_t * pNew;
Gia_Obj_t * pObj;
int i, nCIs, nAll, nPis;
// sanity checks
assert( Gia_ManIsNormalized(p) );
assert( Gia_ManIsSeqWithBoxes(p) );
Gia_ManFillValue( p );
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Gia_ManConst0(p)->Value = 0;
// change input order
// desired reorder: PIs + NewCIs + FOs
// current CI order: PIs + FOs + NewCIs
nCIs = Tim_ManPiNum( (Tim_Man_t *)p->pManTime );
nAll = Tim_ManCiNum( (Tim_Man_t *)p->pManTime );
nPis = nCIs - Gia_ManRegNum(p);
assert( nAll == Gia_ManCiNum(p) );
assert( nPis > 0 );
// copy PIs first
for ( i = 0; i < nPis; i++ )
Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew);
// copy flops second
for ( i = nAll - Gia_ManRegNum(p); i < nAll; i++ )
Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew);
// copy new CIs last
for ( i = nPis; i < nAll - Gia_ManRegNum(p); i++ )
Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew);
printf( "Warning: Unshuffled CI order to be correct AIG with boxes.\n" );
// other things
Gia_ManForEachAnd( p, pObj, i )
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
Gia_ManForEachCo( p, pObj, i )
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
pNew->nConstrs = p->nConstrs;
assert( Gia_ManIsNormalized(pNew) );
Gia_ManDupRemapEquiv( pNew, p );
return pNew;
}
/**Function*************************************************************
Synopsis [Find the ordering of AIG objects.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManOrderWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
{
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
return 0;
Gia_ObjSetTravIdCurrent(p, pObj);
if ( Gia_ObjIsCi(pObj) )
{
p->iData2 = Gia_ObjCioId(pObj);
return 1;
}
assert( Gia_ObjIsAnd(pObj) );
if ( Gia_ObjIsBuf(pObj) )
{
if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes ) )
return 1;
Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
return 0;
}
if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) )
if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)), vNodes ) )
return 1;
if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes ) )
return 1;
if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin1(pObj), vNodes ) )
return 1;
Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
return 0;
}
Vec_Int_t * Gia_ManOrderWithBoxes( Gia_Man_t * p )
{
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
Vec_Int_t * vNodes;
Gia_Obj_t * pObj;
int i, k, curCi, curCo;
assert( pManTime != NULL );
assert( Gia_ManIsNormalized( p ) );
// start trav IDs
Gia_ManIncrementTravId( p );
// start the array
vNodes = Vec_IntAlloc( Gia_ManObjNum(p) );
// include constant
Vec_IntPush( vNodes, 0 );
Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
// include primary inputs
for ( i = 0; i < Tim_ManPiNum(pManTime); i++ )
{
pObj = Gia_ManCi( p, i );
Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
Gia_ObjSetTravIdCurrent( p, pObj );
assert( Gia_ObjId(p, pObj) == i+1 );
}
// for each box, include box nodes
curCi = Tim_ManPiNum(pManTime);
curCo = 0;
for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ )
{
// add internal nodes
for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ )
{
pObj = Gia_ManCo( p, curCo + k );
if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes ) )
{
int iCiNum = p->iData2;
int iBoxNum = Tim_ManBoxFindFromCiNum( pManTime, iCiNum );
printf( "The command has to terminate. Boxes are not in a topological order.\n" );
printf( "The following information may help debugging (numbers are 0-based):\n" );
printf( "Input %d of BoxA %d (1stCI = %d; 1stCO = %d) has TFI with CI %d,\n",
k, i, Tim_ManBoxOutputFirst(pManTime, i), Tim_ManBoxInputFirst(pManTime, i), iCiNum );
printf( "which corresponds to output %d of BoxB %d (1stCI = %d; 1stCO = %d).\n",
iCiNum - Tim_ManBoxOutputFirst(pManTime, iBoxNum), iBoxNum,
Tim_ManBoxOutputFirst(pManTime, iBoxNum), Tim_ManBoxInputFirst(pManTime, iBoxNum) );
printf( "In a correct topological order, BoxB should precede BoxA.\n" );
Vec_IntFree( vNodes );
p->iData2 = 0;
return NULL;
}
}
// add POs corresponding to box inputs
for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ )
{
pObj = Gia_ManCo( p, curCo + k );
Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
}
curCo += Tim_ManBoxInputNum(pManTime, i);
// add PIs corresponding to box outputs
for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ )
{
pObj = Gia_ManCi( p, curCi + k );
Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
Gia_ObjSetTravIdCurrent( p, pObj );
}
curCi += Tim_ManBoxOutputNum(pManTime, i);
}
// add remaining nodes
for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ )
{
pObj = Gia_ManCo( p, i );
Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes );
}
// add POs
for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ )
{
pObj = Gia_ManCo( p, i );
Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
}
curCo += Tim_ManPoNum(pManTime);
// verify counts
assert( curCi == Gia_ManCiNum(p) );
assert( curCo == Gia_ManCoNum(p) );
//assert( Vec_IntSize(vNodes) == Gia_ManObjNum(p) );
return vNodes;
}
/**Function*************************************************************
Synopsis [Duplicates AIG according to the timing manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManDupUnnormalize( Gia_Man_t * p )
{
Vec_Int_t * vNodes;
Gia_Man_t * pNew;
Gia_Obj_t * pObj;
int i;
assert( !Gia_ManBufNum(p) );
vNodes = Gia_ManOrderWithBoxes( p );
if ( vNodes == NULL )
return NULL;
Gia_ManFillValue( p );
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
if ( Gia_ManHasChoices(p) )
pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) );
Gia_ManForEachObjVec( vNodes, p, pObj, i )
{
if ( Gia_ObjIsBuf(pObj) )
pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) );
else if ( Gia_ObjIsAnd(pObj) )
{
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) )
pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))->Value);
}
else if ( Gia_ObjIsCi(pObj) )
pObj->Value = Gia_ManAppendCi( pNew );
else if ( Gia_ObjIsCo(pObj) )
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
else if ( Gia_ObjIsConst0(pObj) )
pObj->Value = 0;
else assert( 0 );
}
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
Vec_IntFree( vNodes );
return pNew;
}
/**Function*************************************************************
Synopsis [Remaps the AIG from the old manager into the new manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCleanupRemap( Gia_Man_t * p, Gia_Man_t * pGia )
{
Gia_Obj_t * pObj, * pObjGia;
int i, iPrev;
Gia_ManForEachObj1( p, pObj, i )
{
iPrev = Gia_ObjValue(pObj);
if ( iPrev == ~0 )
continue;
pObjGia = Gia_ManObj( pGia, Abc_Lit2Var(iPrev) );
if ( pObjGia->Value == ~0 )
Gia_ObjSetValue( pObj, pObjGia->Value );
else
Gia_ObjSetValue( pObj, Abc_LitNotCond(pObjGia->Value, Abc_LitIsCompl(iPrev)) );
}
}
/**Function*************************************************************
Synopsis [Computes level with boxes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManLevelWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
return 0;
Gia_ObjSetTravIdCurrent(p, pObj);
if ( Gia_ObjIsCi(pObj) )
return 1;
assert( Gia_ObjIsAnd(pObj) );
if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) )
Gia_ManLevelWithBoxes_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)) );
if ( Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ) )
return 1;
if ( Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin1(pObj) ) )
return 1;
Gia_ObjSetAndLevel( p, pObj );
return 0;
}
int Gia_ManLevelWithBoxes( Gia_Man_t * p )
{
int nAnd2Delay = p->nAnd2Delay ? p->nAnd2Delay : 1;
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
Gia_Obj_t * pObj, * pObjIn;
int i, k, j, curCi, curCo, LevelMax;
assert( Gia_ManRegNum(p) == 0 );
assert( Gia_ManBufNum(p) == 0 );
// copy const and real PIs
Gia_ManCleanLevels( p, Gia_ManObjNum(p) );
Gia_ObjSetLevel( p, Gia_ManConst0(p), 0 );
Gia_ManIncrementTravId( p );
Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
for ( i = 0; i < Tim_ManPiNum(pManTime); i++ )
{
pObj = Gia_ManCi( p, i );
Gia_ObjSetLevel( p, pObj, Tim_ManGetCiArrival(pManTime, i) / nAnd2Delay );
Gia_ObjSetTravIdCurrent( p, pObj );
}
// create logic for each box
curCi = Tim_ManPiNum(pManTime);
curCo = 0;
for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ )
{
int nBoxInputs = Tim_ManBoxInputNum( pManTime, i );
int nBoxOutputs = Tim_ManBoxOutputNum( pManTime, i );
float * pDelayTable = Tim_ManBoxDelayTable( pManTime, i );
// compute level for TFI of box inputs
for ( k = 0; k < nBoxInputs; k++ )
{
pObj = Gia_ManCo( p, curCo + k );
if ( Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ) )
{
printf( "Boxes are not in a topological order. Switching to level computation without boxes.\n" );
return Gia_ManLevelNum( p );
}
// set box input level
Gia_ObjSetCoLevel( p, pObj );
}
// compute level for box outputs
for ( k = 0; k < nBoxOutputs; k++ )
{
pObj = Gia_ManCi( p, curCi + k );
Gia_ObjSetTravIdCurrent( p, pObj );
// evaluate delay of this output
LevelMax = 0;
assert( nBoxInputs == (int)pDelayTable[1] );
for ( j = 0; j < nBoxInputs && (pObjIn = Gia_ManCo(p, curCo + j)); j++ )
if ( (int)pDelayTable[3+k*nBoxInputs+j] != -ABC_INFINITY )
LevelMax = Abc_MaxInt( LevelMax, Gia_ObjLevel(p, pObjIn) + ((int)pDelayTable[3+k*nBoxInputs+j] / nAnd2Delay) );
// set box output level
Gia_ObjSetLevel( p, pObj, LevelMax );
}
curCo += nBoxInputs;
curCi += nBoxOutputs;
}
// add remaining nodes
p->nLevels = 0;
for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ )
{
pObj = Gia_ManCo( p, i );
Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) );
Gia_ObjSetCoLevel( p, pObj );
p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) );
}
curCo += Tim_ManPoNum(pManTime);
// verify counts
assert( curCi == Gia_ManCiNum(p) );
assert( curCo == Gia_ManCoNum(p) );
// printf( "Max level is %d.\n", p->nLevels );
return p->nLevels;
}
/**Function*************************************************************
Synopsis [Computes level with boxes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManLutLevelWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
int iObj, k, iFan, Level = 0;
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
return 0;
Gia_ObjSetTravIdCurrent(p, pObj);
if ( Gia_ObjIsCi(pObj) )
return 1;
assert( Gia_ObjIsAnd(pObj) );
iObj = Gia_ObjId( p, pObj );
Gia_LutForEachFanin( p, iObj, iFan, k )
{
if ( Gia_ManLutLevelWithBoxes_rec( p, Gia_ManObj(p, iFan) ) )
return 1;
Level = Abc_MaxInt( Level, Gia_ObjLevelId(p, iFan) );
}
Gia_ObjSetLevelId( p, iObj, Level + 1 );
return 0;
}
int Gia_ManLutLevelWithBoxes( Gia_Man_t * p )
{
// int nAnd2Delay = p->nAnd2Delay ? p->nAnd2Delay : 1;
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
Gia_Obj_t * pObj, * pObjIn;
int i, k, j, curCi, curCo, LevelMax;
assert( Gia_ManRegNum(p) == 0 );
if ( pManTime == NULL )
return Gia_ManLutLevel(p, NULL);
// copy const and real PIs
Gia_ManCleanLevels( p, Gia_ManObjNum(p) );
Gia_ObjSetLevel( p, Gia_ManConst0(p), 0 );
Gia_ManIncrementTravId( p );
Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
for ( i = 0; i < Tim_ManPiNum(pManTime); i++ )
{
pObj = Gia_ManCi( p, i );
// Gia_ObjSetLevel( p, pObj, Tim_ManGetCiArrival(pManTime, i) / nAnd2Delay );
Gia_ObjSetLevel( p, pObj, 0 );
Gia_ObjSetTravIdCurrent( p, pObj );
}
// create logic for each box
curCi = Tim_ManPiNum(pManTime);
curCo = 0;
for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ )
{
int nBoxInputs = Tim_ManBoxInputNum( pManTime, i );
int nBoxOutputs = Tim_ManBoxOutputNum( pManTime, i );
float * pDelayTable = Tim_ManBoxDelayTable( pManTime, i );
// compute level for TFI of box inputs
for ( k = 0; k < nBoxInputs; k++ )
{
pObj = Gia_ManCo( p, curCo + k );
if ( Gia_ManLutLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ) )
{
printf( "Boxes are not in a topological order. Switching to level computation without boxes.\n" );
return Gia_ManLevelNum( p );
}
// set box input level
Gia_ObjSetCoLevel( p, pObj );
}
// compute level for box outputs
for ( k = 0; k < nBoxOutputs; k++ )
{
pObj = Gia_ManCi( p, curCi + k );
Gia_ObjSetTravIdCurrent( p, pObj );
// evaluate delay of this output
LevelMax = 0;
assert( nBoxInputs == (int)pDelayTable[1] );
for ( j = 0; j < nBoxInputs && (pObjIn = Gia_ManCo(p, curCo + j)); j++ )
if ( (int)pDelayTable[3+k*nBoxInputs+j] != -ABC_INFINITY )
// LevelMax = Abc_MaxInt( LevelMax, Gia_ObjLevel(p, pObjIn) + ((int)pDelayTable[3+k*nBoxInputs+j] / nAnd2Delay) );
LevelMax = Abc_MaxInt( LevelMax, Gia_ObjLevel(p, pObjIn) + 1 );
// set box output level
Gia_ObjSetLevel( p, pObj, LevelMax );
}
curCo += nBoxInputs;
curCi += nBoxOutputs;
}
// add remaining nodes
p->nLevels = 0;
for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ )
{
pObj = Gia_ManCo( p, i );
Gia_ManLutLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) );
Gia_ObjSetCoLevel( p, pObj );
p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) );
}
curCo += Tim_ManPoNum(pManTime);
// verify counts
assert( curCi == Gia_ManCiNum(p) );
assert( curCo == Gia_ManCoNum(p) );
// printf( "Max level is %d.\n", p->nLevels );
return p->nLevels;
}
/**Function*************************************************************
Synopsis [Update hierarchy/timing manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void * Gia_ManUpdateTimMan( Gia_Man_t * p, Vec_Int_t * vBoxPres )
{
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
assert( pManTime != NULL );
assert( Vec_IntSize(vBoxPres) == Tim_ManBoxNum(pManTime) );
return Tim_ManTrim( pManTime, vBoxPres );
}
void * Gia_ManUpdateTimMan2( Gia_Man_t * p, Vec_Int_t * vBoxesLeft, int nTermsDiff )
{
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
assert( pManTime != NULL );
assert( Vec_IntSize(vBoxesLeft) <= Tim_ManBoxNum(pManTime) );
return Tim_ManReduce( pManTime, vBoxesLeft, nTermsDiff );
}
/**Function*************************************************************
Synopsis [Update AIG of the holes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManUpdateExtraAig( void * pTime, Gia_Man_t * p, Vec_Int_t * vBoxPres )
{
Gia_Man_t * pNew;
Tim_Man_t * pManTime = (Tim_Man_t *)pTime;
Vec_Int_t * vOutPres = Vec_IntAlloc( 100 );
int i, k, curPo = 0;
assert( Vec_IntSize(vBoxPres) == Tim_ManBoxNum(pManTime) );
assert( Gia_ManCoNum(p) == Tim_ManCiNum(pManTime) - Tim_ManPiNum(pManTime) );
for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ )
{
for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ )
Vec_IntPush( vOutPres, Vec_IntEntry(vBoxPres, i) );
curPo += Tim_ManBoxOutputNum(pManTime, i);
}
assert( curPo == Gia_ManCoNum(p) );
pNew = Gia_ManDupOutputVec( p, vOutPres );
Vec_IntFree( vOutPres );
return pNew;
}
Gia_Man_t * Gia_ManUpdateExtraAig2( void * pTime, Gia_Man_t * p, Vec_Int_t * vBoxesLeft )
{
Gia_Man_t * pNew;
Tim_Man_t * pManTime = (Tim_Man_t *)pTime;
int nRealPis = Tim_ManPiNum(pManTime);
Vec_Int_t * vOutsLeft = Vec_IntAlloc( 100 );
int i, k, iBox, iOutFirst;
assert( Vec_IntSize(vBoxesLeft) <= Tim_ManBoxNum(pManTime) );
assert( Gia_ManCoNum(p) == Tim_ManCiNum(pManTime) - nRealPis );
Vec_IntForEachEntry( vBoxesLeft, iBox, i )
{
iOutFirst = Tim_ManBoxOutputFirst(pManTime, iBox) - nRealPis;
for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, iBox); k++ )
Vec_IntPush( vOutsLeft, iOutFirst + k );
}
pNew = Gia_ManDupSelectedOutputs( p, vOutsLeft );
Vec_IntFree( vOutsLeft );
return pNew;
}
/**Function*************************************************************
Synopsis [Computes AIG with boxes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManDupCollapse_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Man_t * pNew )
{
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
return;
Gia_ObjSetTravIdCurrent(p, pObj);
assert( Gia_ObjIsAnd(pObj) );
if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) )
Gia_ManDupCollapse_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)), pNew );
Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew );
Gia_ManDupCollapse_rec( p, Gia_ObjFanin1(pObj), pNew );
// assert( !~pObj->Value );
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) )
pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))->Value);
}
Gia_Man_t * Gia_ManDupCollapse( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t * vBoxPres, int fSeq )
{
// this procedure assumes that sequential AIG with boxes is unshuffled to have valid boxes
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
Gia_Man_t * pNew, * pTemp;
Gia_Obj_t * pObj, * pObjBox;
int i, k, curCi, curCo, nBBins = 0, nBBouts = 0;
assert( !fSeq || p->vRegClasses );
//assert( Gia_ManRegNum(p) == 0 );
assert( Gia_ManCiNum(p) == Tim_ManPiNum(pManTime) + Gia_ManCoNum(pBoxes) );
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
if ( Gia_ManHasChoices(p) )
pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) );
Gia_ManHashAlloc( pNew );
// copy const and real PIs
Gia_ManFillValue( p );
Gia_ManConst0(p)->Value = 0;
Gia_ManIncrementTravId( p );
Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
for ( i = 0; i < Tim_ManPiNum(pManTime); i++ )
{
pObj = Gia_ManCi( p, i );
pObj->Value = Gia_ManAppendCi(pNew);
Gia_ObjSetTravIdCurrent( p, pObj );
}
// create logic for each box
curCi = Tim_ManPiNum(pManTime);
curCo = 0;
for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ )
{
// clean boxes
Gia_ManIncrementTravId( pBoxes );
Gia_ObjSetTravIdCurrent( pBoxes, Gia_ManConst0(pBoxes) );
Gia_ManConst0(pBoxes)->Value = 0;
// add internal nodes
//printf( "%d ", Tim_ManBoxIsBlack(pManTime, i) );
if ( Tim_ManBoxIsBlack(pManTime, i) )
{
int fSkip = (vBoxPres != NULL && !Vec_IntEntry(vBoxPres, i));
for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ )
{
pObj = Gia_ManCo( p, curCo + k );
Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew );
pObj->Value = fSkip ? -1 : Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
nBBouts++;
}
for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ )
{
pObj = Gia_ManCi( p, curCi + k );
pObj->Value = fSkip ? 0 : Gia_ManAppendCi(pNew);
Gia_ObjSetTravIdCurrent( p, pObj );
nBBins++;
}
}
else
{
for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ )
{
// build logic
pObj = Gia_ManCo( p, curCo + k );
Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew );
// transfer to the PI
pObjBox = Gia_ManCi( pBoxes, k );
pObjBox->Value = Gia_ObjFanin0Copy(pObj);
Gia_ObjSetTravIdCurrent( pBoxes, pObjBox );
}
for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ )
{
// build logic
pObjBox = Gia_ManCo( pBoxes, curCi - Tim_ManPiNum(pManTime) + k );
Gia_ManDupCollapse_rec( pBoxes, Gia_ObjFanin0(pObjBox), pNew );
// transfer to the PI
pObj = Gia_ManCi( p, curCi + k );
pObj->Value = Gia_ObjFanin0Copy(pObjBox);
Gia_ObjSetTravIdCurrent( p, pObj );
}
}
curCo += Tim_ManBoxInputNum(pManTime, i);
curCi += Tim_ManBoxOutputNum(pManTime, i);
}
//printf( "\n" );
// add remaining nodes
for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ )
{
pObj = Gia_ManCo( p, i );
Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew );
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
}
curCo += Tim_ManPoNum(pManTime);
// verify counts
assert( curCi == Gia_ManCiNum(p) );
assert( curCo == Gia_ManCoNum(p) );
Gia_ManSetRegNum( pNew, (fSeq && p->vRegClasses) ? Vec_IntSize(p->vRegClasses) : Gia_ManRegNum(p) );
Gia_ManHashStop( pNew );
pNew = Gia_ManCleanup( pTemp = pNew );
Gia_ManCleanupRemap( p, pTemp );
Gia_ManStop( pTemp );
assert( Tim_ManPoNum(pManTime) == Gia_ManCoNum(pNew) - nBBouts );
assert( Tim_ManPiNum(pManTime) == Gia_ManCiNum(pNew) - nBBins );
// implement initial state if given
if ( fSeq && p->vRegInits && Vec_IntSum(p->vRegInits) )
{
char * pInit = ABC_ALLOC( char, Vec_IntSize(p->vRegInits) + 1 );
Gia_Obj_t * pObj;
int i;
assert( Vec_IntSize(p->vRegInits) == Gia_ManRegNum(pNew) );
Gia_ManForEachRo( pNew, pObj, i )
{
if ( Vec_IntEntry(p->vRegInits, i) == 0 )
pInit[i] = '0';
else if ( Vec_IntEntry(p->vRegInits, i) == 1 )
pInit[i] = '1';
else
pInit[i] = 'X';
}
pInit[i] = 0;
pNew = Gia_ManDupZeroUndc( pTemp = pNew, pInit, 0, 1 );
pNew->nConstrs = pTemp->nConstrs; pTemp->nConstrs = 0;
Gia_ManStop( pTemp );
ABC_FREE( pInit );
}
return pNew;
}
/**Function*************************************************************
Synopsis [Verify XAIG against its spec.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManVerifyWithBoxes( Gia_Man_t * pGia, int nBTLimit, int nTimeLim, int fSeq, int fDumpFiles, int fVerbose, char * pFileSpec )
{
int Status = -1;
Gia_Man_t * pSpec, * pGia0, * pGia1, * pMiter;
Vec_Int_t * vBoxPres = NULL;
if ( pFileSpec == NULL && pGia->pSpec == NULL )
{
printf( "Spec file is not given. Use standard flow.\n" );
return Status;
}
if ( Gia_ManBoxNum(pGia) && pGia->pAigExtra == NULL )
{
printf( "Design has no box logic. Use standard flow.\n" );
return Status;
}
// read original AIG
pSpec = Gia_AigerRead( pFileSpec ? pFileSpec : pGia->pSpec, 0, 0, 0 );
if ( Gia_ManBoxNum(pSpec) && pSpec->pAigExtra == NULL )
{
Gia_ManStop( pSpec );
printf( "Spec has no box logic. Use standard flow.\n" );
return Status;
}
// prepare miter
if ( pGia->pManTime == NULL && pSpec->pManTime == NULL )
{
pGia0 = Gia_ManDup( pSpec );
pGia1 = Gia_ManDup( pGia );
}
else
{
// if timing managers have different number of black boxes,
// it is possible that some of the boxes are swept away
if ( pSpec->pManTime && Tim_ManBlackBoxNum((Tim_Man_t *)pSpec->pManTime) > 0 && Gia_ManBoxNum(pGia) > 0 )
{
// specification cannot have fewer boxes than implementation
if ( Gia_ManBoxNum(pSpec) < Gia_ManBoxNum(pGia) )
{
printf( "Spec has less boxes than the design. Cannot proceed.\n" );
return Status;
}
// to align the boxes, find what boxes of pSpec are dropped in pGia
if ( Gia_ManBoxNum(pSpec) > Gia_ManBoxNum(pGia) )
{
vBoxPres = Tim_ManAlignTwo( (Tim_Man_t *)pSpec->pManTime, (Tim_Man_t *)pGia->pManTime );
if ( vBoxPres == NULL )
{
printf( "Boxes of spec and design cannot be aligned. Cannot proceed.\n" );
return Status;
}
}
}
// collapse two designs
if ( Gia_ManBoxNum(pSpec) > 0 )
pGia0 = Gia_ManDupCollapse( pSpec, pSpec->pAigExtra, vBoxPres, fSeq );
else
pGia0 = Gia_ManDup( pSpec );
if ( Gia_ManBoxNum(pGia) > 0 )
pGia1 = Gia_ManDupCollapse( pGia, pGia->pAigExtra, NULL, fSeq );
else
pGia1 = Gia_ManDup( pGia );
Vec_IntFreeP( &vBoxPres );
}
if ( fDumpFiles )
{
char pFileName0[1000], pFileName1[1000];
char * pNameGeneric = Extra_FileNameGeneric( pFileSpec ? pFileSpec : pGia->pSpec );
sprintf( pFileName0, "%s_spec.aig", pNameGeneric );
sprintf( pFileName1, "%s_impl.aig", pNameGeneric );
Gia_AigerWrite( pGia0, pFileName0, 0, 0 );
Gia_AigerWrite( pGia1, pFileName1, 0, 0 );
ABC_FREE( pNameGeneric );
printf( "Dumped two parts of the miter into files \"%s\" and \"%s\".\n", pFileName0, pFileName1 );
}
// compute the miter
if ( fSeq )
{
pMiter = Gia_ManMiter( pGia0, pGia1, 0, 0, 1, 0, fVerbose );
if ( pMiter )
{
Aig_Man_t * pMan;
Fra_Sec_t SecPar, * pSecPar = &SecPar;
Fra_SecSetDefaultParams( pSecPar );
pSecPar->fRetimeFirst = 0;
pSecPar->nBTLimit = nBTLimit;
pSecPar->TimeLimit = nTimeLim;
pSecPar->fVerbose = fVerbose;
pMan = Gia_ManToAig( pMiter, 0 );
Gia_ManStop( pMiter );
Status = Fra_FraigSec( pMan, pSecPar, NULL );
Aig_ManStop( pMan );
}
}
else
{
pMiter = Gia_ManMiter( pGia0, pGia1, 0, 1, 0, 0, fVerbose );
if ( pMiter )
{
Cec_ParCec_t ParsCec, * pPars = &ParsCec;
Cec_ManCecSetDefaultParams( pPars );
pPars->nBTLimit = nBTLimit;
pPars->TimeLimit = nTimeLim;
pPars->fVerbose = fVerbose;
Status = Cec_ManVerify( pMiter, pPars );
if ( pPars->iOutFail >= 0 )
Abc_Print( 1, "Verification failed for at least one output (%d).\n", pPars->iOutFail );
Gia_ManStop( pMiter );
}
}
Gia_ManStop( pGia0 );
Gia_ManStop( pGia1 );
Gia_ManStop( pSpec );
return Status;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END