blob: 2d8e705b2c400549992f5ad5cfe7e6ec369c13a7 [file] [log] [blame]
/**CFile****************************************************************
FileName [giaSweep.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Sweeping of GIA manager.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaSweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
#include "giaAig.h"
#include "proof/dch/dch.h"
#include "misc/tim/tim.h"
#include "proof/cec/cec.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Mark GIA nodes that feed into POs.]
Description [Returns the array of classes of remaining registers.]
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManMarkSeqGiaWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRoots )
{
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
int i, iBox, nBoxIns, nBoxOuts, iShift, nRealCis;
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
return;
Gia_ObjSetTravIdCurrent(p, pObj);
if ( Gia_ObjIsAnd(pObj) )
{
Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin0(pObj), vRoots );
Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin1(pObj), vRoots );
return;
}
assert( Gia_ObjIsCi(pObj) );
nRealCis = Tim_ManPiNum(pManTime);
if ( Gia_ObjCioId(pObj) < nRealCis )
{
int nRegs = Gia_ManRegBoxNum(p);
int iFlop = Gia_ObjCioId(pObj) - (nRealCis - nRegs);
assert( iFlop >= 0 && iFlop < nRegs );
pObj = Gia_ManCo( p, Gia_ManPoNum(p) - nRegs + iFlop );
Vec_IntPush( vRoots, Gia_ObjId(p, pObj) );
return;
}
// get the box
iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) );
nBoxIns = Tim_ManBoxInputNum(pManTime, iBox);
nBoxOuts = Tim_ManBoxOutputNum(pManTime, iBox);
// mark all outputs
iShift = Tim_ManBoxOutputFirst(pManTime, iBox);
for ( i = 0; i < nBoxOuts; i++ )
Gia_ObjSetTravIdCurrent(p, Gia_ManCi(p, iShift + i));
// traverse from inputs
iShift = Tim_ManBoxInputFirst(pManTime, iBox);
for ( i = 0; i < nBoxIns; i++ )
Gia_ObjSetTravIdCurrent(p, Gia_ManCo(p, iShift + i));
for ( i = 0; i < nBoxIns; i++ )
Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin0(Gia_ManCo(p, iShift + i)), vRoots );
}
void Gia_ManMarkSeqGiaWithBoxes( Gia_Man_t * p, int fSeq )
{
// CI order: real PIs + flop outputs + box outputs
// CO order: box inputs + real POs + flop inputs
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
Vec_Int_t * vRoots;
Gia_Obj_t * pObj;
int nRealCis = Tim_ManPiNum(pManTime);
int nRealCos = Tim_ManPoNum(pManTime);
int i, nRegs = fSeq ? Gia_ManRegBoxNum(p) : 0;
assert( Gia_ManRegNum(p) == 0 );
assert( Gia_ManBoxNum(p) > 0 );
// mark the terminals
Gia_ManIncrementTravId( p );
Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
for ( i = 0; i < nRealCis - nRegs; i++ )
Gia_ObjSetTravIdCurrent( p, Gia_ManPi(p, i) );
// collect flops reachable from the POs
vRoots = Vec_IntAlloc( Gia_ManRegBoxNum(p) );
for ( i = Gia_ManPoNum(p) - nRealCos; i < Gia_ManPoNum(p) - nRegs; i++ )
{
Gia_ObjSetTravIdCurrent( p, Gia_ManPo(p, i) );
Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin0(Gia_ManPo(p, i)), vRoots );
}
// collect flops reachable from roots
if ( fSeq )
{
Gia_ManForEachObjVec( vRoots, p, pObj, i )
{
assert( Gia_ObjIsCo(pObj) );
Gia_ObjSetTravIdCurrent( p, pObj );
Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin0(pObj), vRoots );
}
//printf( "Explored %d flops\n", Vec_IntSize(vRoots) );
}
Vec_IntFree( vRoots );
}
Gia_Man_t * Gia_ManDupWithBoxes( Gia_Man_t * p, int fSeq )
{
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
Gia_Man_t * pNew;
Gia_Obj_t * pObj;
Vec_Int_t * vBoxesLeft;
int curCi, curCo, nBoxIns, nBoxOuts;
int i, k, iShift, nMarked;
assert( Gia_ManBoxNum(p) > 0 );
// mark useful boxes
Gia_ManMarkSeqGiaWithBoxes( p, fSeq );
// duplicate marked entries
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Gia_ManConst0(p)->Value = 0;
Gia_ManForEachObj1( p, pObj, i )
{
if ( !Gia_ObjIsTravIdCurrent(p, pObj) )
continue;
if ( Gia_ObjIsCi(pObj) )
pObj->Value = Gia_ManAppendCi(pNew);
else if ( Gia_ObjIsAnd(pObj) )
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
else if ( Gia_ObjIsCo(pObj) )
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
else assert( 0 );
}
assert( !Gia_ManHasDangling(pNew) );
// collect remaining flops
if ( fSeq )
{
pNew->vRegClasses = Vec_IntAlloc( Gia_ManRegBoxNum(p) );
if ( p->vRegInits )
pNew->vRegInits = Vec_IntAlloc( Gia_ManRegBoxNum(p) );
iShift = Gia_ManPoNum(p) - Gia_ManRegBoxNum(p);
for ( i = 0; i < Gia_ManRegBoxNum(p); i++ )
if ( Gia_ObjIsTravIdCurrent(p, Gia_ManCo(p, iShift + i)) )
{
Vec_IntPush( pNew->vRegClasses, Vec_IntEntry(p->vRegClasses, i) );
if ( p->vRegInits )
Vec_IntPush( pNew->vRegInits, Vec_IntEntry(p->vRegInits, i) );
}
}
else
{
if ( p->vRegClasses )
pNew->vRegClasses = Vec_IntDup( p->vRegClasses );
if ( p->vRegInits )
pNew->vRegInits = Vec_IntDup( p->vRegInits );
}
// collect remaining boxes
vBoxesLeft = Vec_IntAlloc( Gia_ManBoxNum(p) );
curCi = Tim_ManPiNum(pManTime);
curCo = 0;
for ( i = 0; i < Gia_ManBoxNum(p); i++ )
{
nBoxIns = Tim_ManBoxInputNum(pManTime, i);
nBoxOuts = Tim_ManBoxOutputNum(pManTime, i);
nMarked = 0;
for ( k = 0; k < nBoxIns; k++ )
nMarked += Gia_ObjIsTravIdCurrent( p, Gia_ManCo(p, curCo + k) );
for ( k = 0; k < nBoxOuts; k++ )
nMarked += Gia_ObjIsTravIdCurrent( p, Gia_ManCi(p, curCi + k) );
curCo += nBoxIns;
curCi += nBoxOuts;
// check presence
assert( nMarked == 0 || nMarked == nBoxIns + nBoxOuts );
if ( nMarked )
Vec_IntPush( vBoxesLeft, i );
}
curCo += Tim_ManPoNum(pManTime);
assert( curCi == Gia_ManCiNum(p) );
assert( curCo == Gia_ManCoNum(p) );
// update timing manager
pNew->pManTime = Gia_ManUpdateTimMan2( p, vBoxesLeft, Gia_ManRegBoxNum(p) - Gia_ManRegBoxNum(pNew) );
// update extra STG
assert( p->pAigExtra != NULL );
assert( pNew->pAigExtra == NULL );
pNew->pAigExtra = Gia_ManUpdateExtraAig2( p->pManTime, p->pAigExtra, vBoxesLeft );
assert( Gia_ManCiNum(pNew) == Tim_ManPiNum((Tim_Man_t*)pNew->pManTime) + Gia_ManCoNum(pNew->pAigExtra) );
Vec_IntFree( vBoxesLeft );
return pNew;
}
/**Function*************************************************************
Synopsis [Mark GIA nodes that feed into POs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManFraigCheckCis( Gia_Man_t * p, Gia_Obj_t * pObj )
{
for ( assert( Gia_ObjIsCi(pObj) ); Gia_ObjIsCi(pObj); pObj-- )
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
return 1;
return 0;
}
Gia_Obj_t * Gia_ManFraigMarkCis( Gia_Man_t * p, Gia_Obj_t * pObj, int fMark )
{
for ( assert( Gia_ObjIsCi(pObj) ); Gia_ObjIsCi(pObj); pObj-- )
if ( fMark )
Gia_ObjSetTravIdCurrent( p, pObj );
return pObj;
}
Gia_Obj_t * Gia_ManFraigMarkCos( Gia_Man_t * p, Gia_Obj_t * pObj, int fMark )
{
for ( assert( Gia_ObjIsCo(pObj) ); Gia_ObjIsCo(pObj); pObj-- )
if ( fMark )
{
Gia_ObjSetTravIdCurrent( p, pObj );
Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) );
}
return pObj;
}
Gia_Obj_t * Gia_ManFraigMarkAnd( Gia_Man_t * p, Gia_Obj_t * pObj )
{
for ( assert( Gia_ObjIsAnd(pObj) ); Gia_ObjIsAnd(pObj); pObj-- )
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
{
Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) );
Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin1(pObj) );
}
return pObj;
}
Gia_Man_t * Gia_ManFraigCreateGia( Gia_Man_t * p )
{
Vec_Int_t * vBoxPres;
Gia_Man_t * pNew;
Gia_Obj_t * pObj;
int i, fLabelPos;
assert( p->pManTime != NULL );
// start marks
Gia_ManIncrementTravId( p );
Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
vBoxPres = Vec_IntAlloc( 1000 );
// mark primary outputs
fLabelPos = 1;
pObj = Gia_ManObj( p, Gia_ManObjNum(p) - 1 );
assert( Gia_ObjIsCo(pObj) );
while ( Gia_ObjIsCo(pObj) )
{
pObj = Gia_ManFraigMarkCos( p, pObj, fLabelPos );
if ( Gia_ObjIsAnd(pObj) )
pObj = Gia_ManFraigMarkAnd( p, pObj );
assert( Gia_ObjIsCi(pObj) );
fLabelPos = Gia_ManFraigCheckCis(p, pObj);
pObj = Gia_ManFraigMarkCis( p, pObj, fLabelPos );
Vec_IntPush( vBoxPres, fLabelPos );
}
Vec_IntPop( vBoxPres );
Vec_IntReverseOrder( vBoxPres );
assert( Gia_ObjIsConst0(pObj) );
// mark primary inputs
Gia_ManForEachObj1( p, pObj, i )
if ( Gia_ObjIsCi(pObj) )
Gia_ObjSetTravIdCurrent( p, pObj );
else
break;
// duplicate marked entries
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Gia_ManConst0(p)->Value = 0;
Gia_ManForEachObj1( p, pObj, i )
{
if ( !Gia_ObjIsTravIdCurrent(p, pObj) )
continue;
if ( Gia_ObjIsCi(pObj) )
pObj->Value = Gia_ManAppendCi(pNew);
else if ( Gia_ObjIsAnd(pObj) )
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
else if ( Gia_ObjIsCo(pObj) )
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
else assert( 0 );
}
// update timing manager
pNew->pManTime = Gia_ManUpdateTimMan( p, vBoxPres );
// update extra STG
assert( p->pAigExtra != NULL );
assert( pNew->pAigExtra == NULL );
pNew->pAigExtra = Gia_ManUpdateExtraAig( p->pManTime, p->pAigExtra, vBoxPres );
Vec_IntFree( vBoxPres );
// assert( Gia_ManPiNum(pNew) == Tim_ManCiNum(pNew->pManTime) );
// assert( Gia_ManPoNum(pNew) == Tim_ManCoNum(pNew->pManTime) );
// assert( Gia_ManPiNum(pNew) == Tim_ManPiNum(pNew->pManTime) + Gia_ManPoNum(pNew->pAigExtra) );
return pNew;
}
/**Function*************************************************************
Synopsis [Duplicates the AIG in the DFS order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ObjFanin0CopyRepr( Gia_Man_t * p, Gia_Obj_t * pObj, int * pReprs )
{
int fanId = Gia_ObjFaninId0p( p, pObj );
if ( pReprs[fanId] == -1 )
return Gia_ObjFanin0Copy( pObj );
assert( Abc_Lit2Var(pReprs[fanId]) < Gia_ObjId(p, pObj) );
return Abc_LitNotCond( Gia_ObjValue(Gia_ManObj(p, Abc_Lit2Var(pReprs[fanId]))), Gia_ObjFaninC0(pObj) ^ Abc_LitIsCompl(pReprs[fanId]) );
}
int Gia_ObjFanin1CopyRepr( Gia_Man_t * p, Gia_Obj_t * pObj, int * pReprs )
{
int fanId = Gia_ObjFaninId1p( p, pObj );
if ( pReprs[fanId] == -1 )
return Gia_ObjFanin1Copy( pObj );
assert( Abc_Lit2Var(pReprs[fanId]) < Gia_ObjId(p, pObj) );
return Abc_LitNotCond( Gia_ObjValue(Gia_ManObj(p, Abc_Lit2Var(pReprs[fanId]))), Gia_ObjFaninC1(pObj) ^ Abc_LitIsCompl(pReprs[fanId]) );
}
Gia_Man_t * Gia_ManFraigReduceGia( Gia_Man_t * p, int * pReprs )
{
Gia_Man_t * pNew;
Gia_Obj_t * pObj;
int i;
assert( pReprs != NULL );
assert( Gia_ManRegNum(p) == 0 );
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Gia_ManFillValue( p );
Gia_ManHashAlloc( pNew );
Gia_ManForEachObj( p, pObj, i )
{
if ( Gia_ObjIsAnd(pObj) )
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0CopyRepr(p, pObj, pReprs), Gia_ObjFanin1CopyRepr(p, pObj, pReprs) );
else if ( Gia_ObjIsCi(pObj) )
pObj->Value = Gia_ManAppendCi( pNew );
else if ( Gia_ObjIsCo(pObj) )
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0CopyRepr(p, pObj, pReprs) );
else if ( Gia_ObjIsConst0(pObj) )
pObj->Value = 0;
else assert( 0 );
}
Gia_ManHashStop( pNew );
return pNew;
}
/**Function*************************************************************
Synopsis [Compute the set of CIs representing carry-outs of boxes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManComputeCarryOuts( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
int i, iLast, iBox, nBoxes = Tim_ManBoxNum( pManTime );
Vec_Int_t * vCarryOuts = Vec_IntAlloc( nBoxes );
for ( i = 0; i < nBoxes; i++ )
{
iLast = Tim_ManBoxInputLast( pManTime, i );
pObj = Gia_ObjFanin0( Gia_ManCo(p, iLast) );
if ( !Gia_ObjIsCi(pObj) )
continue;
iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) );
if ( iBox == -1 )
continue;
assert( Gia_ObjIsCi(pObj) );
if ( Gia_ObjCioId(pObj) == Tim_ManBoxOutputLast(pManTime, iBox) )
Vec_IntPush( vCarryOuts, Gia_ObjId(p, pObj) );
}
return vCarryOuts;
}
/**Function*************************************************************
Synopsis [Checks integriting of complex flops and carry-chains.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCheckIntegrityWithBoxes( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
Vec_Int_t * vCarryOuts;
int i, nCountReg = 0, nCountCarry = 0;
if ( p->pManTime == NULL )
return;
ABC_FREE( p->pRefs );
Gia_ManCreateRefs( p );
for ( i = Gia_ManPoNum(p) - Gia_ManRegBoxNum(p); i < Gia_ManPoNum(p); i++ )
{
pObj = Gia_ObjFanin0( Gia_ManPo(p, i) );
assert( Gia_ObjIsCi(pObj) );
if ( Gia_ObjRefNum(p, pObj) > 1 )
nCountReg++;
}
vCarryOuts = Gia_ManComputeCarryOuts( p );
Gia_ManForEachObjVec( vCarryOuts, p, pObj, i )
if ( Gia_ObjRefNum(p, pObj) > 1 )
nCountCarry++;
Vec_IntFree( vCarryOuts );
if ( nCountReg || nCountCarry )
printf( "Warning: AIG with boxes has internal fanout in %d complex flops and %d carries.\n", nCountReg, nCountCarry );
ABC_FREE( p->pRefs );
}
/**Function*************************************************************
Synopsis [Computes representatives in terms of the original objects.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int * Gia_ManFraigSelectReprs( Gia_Man_t * p, Gia_Man_t * pClp, int fVerbose, int pFlopTypes[3] )
{
Gia_Obj_t * pObj;
Vec_Int_t * vCarryOuts;
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
int * pReprs = ABC_FALLOC( int, Gia_ManObjNum(p) );
int * pClp2Gia = ABC_FALLOC( int, Gia_ManObjNum(pClp) );
int i, iLitClp, iLitClp2, iReprClp, fCompl;
int nConsts = 0, nReprs = 0;
assert( pManTime != NULL );
// count the number of equivalent objects
Gia_ManForEachObj1( pClp, pObj, i )
{
if ( Gia_ObjIsCo(pObj) )
continue;
if ( i == Gia_ObjReprSelf(pClp, i) )
continue;
if ( Gia_ObjReprSelf(pClp, i) == 0 )
nConsts++;
else
nReprs++;
}
if ( fVerbose )
printf( "Computed %d const objects and %d other objects.\n", nConsts, nReprs );
nConsts = nReprs = 0;
// mark flop input boxes
Gia_ManCleanMark0( p );
for ( i = Gia_ManPoNum(p) - Gia_ManRegBoxNum(p); i < Gia_ManPoNum(p); i++ )
{
pObj = Gia_ObjFanin0( Gia_ManPo(p, i) );
assert( Gia_ObjIsCi(pObj) );
pObj->fMark0 = 1;
}
// mark connects between last box inputs and first box outputs
vCarryOuts = Gia_ManComputeCarryOuts( p );
Gia_ManForEachObjVec( vCarryOuts, p, pObj, i )
pObj->fMark0 = 1;
if ( fVerbose )
printf( "Fixed %d flop inputs and %d box/box connections (out of %d non-flop boxes).\n",
Gia_ManRegBoxNum(p), Vec_IntSize(vCarryOuts), Gia_ManNonRegBoxNum(p) );
Vec_IntFree( vCarryOuts );
// collect equivalent node info
pFlopTypes[0] = pFlopTypes[1] = pFlopTypes[2] = 0;
Gia_ManForEachRo( pClp, pObj, i )
{
Gia_Obj_t * pRepr = Gia_ObjReprObj(pClp, i);
if ( pRepr && pRepr != pObj )
{
if ( pRepr == Gia_ManConst0(pClp) )
pFlopTypes[0]++;
else if ( Gia_ObjIsRo(pClp, pRepr) )
pFlopTypes[1]++;
}
}
// compute representatives
pClp2Gia[0] = 0;
Gia_ManSetPhase( pClp );
Gia_ManForEachObj1( p, pObj, i )
{
if ( Gia_ObjIsCo(pObj) )
continue;
if ( Gia_ObjIsCi(pObj) && pObj->fMark0 ) // skip CI pointed by CO
continue;
assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
iLitClp = Gia_ObjValue(pObj);
if ( iLitClp == -1 )
continue;
iReprClp = Gia_ObjReprSelf( pClp, Abc_Lit2Var(iLitClp) );
if ( pClp2Gia[iReprClp] == -1 )
pClp2Gia[iReprClp] = i;
else
{
iLitClp2 = Gia_ObjValue( Gia_ManObj(p, pClp2Gia[iReprClp]) );
assert( Gia_ObjReprSelf(pClp, Abc_Lit2Var(iLitClp)) == Gia_ObjReprSelf(pClp, Abc_Lit2Var(iLitClp2)) );
fCompl = Abc_LitIsCompl(iLitClp) ^ Abc_LitIsCompl(iLitClp2);
fCompl ^= Gia_ManObj(pClp, Abc_Lit2Var(iLitClp))->fPhase;
fCompl ^= Gia_ManObj(pClp, Abc_Lit2Var(iLitClp2))->fPhase;
pReprs[i] = Abc_Var2Lit( pClp2Gia[iReprClp], fCompl );
assert( Abc_Lit2Var(pReprs[i]) < i );
if ( pClp2Gia[iReprClp] == 0 )
nConsts++;
else
nReprs++;
}
}
ABC_FREE( pClp2Gia );
Gia_ManForEachCi( p, pObj, i )
pObj->fMark0 = 0;
if ( fVerbose )
printf( "Found %d const objects and %d other objects.\n", nConsts, nReprs );
return pReprs;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManFraigSweepPerform( Gia_Man_t * p, void * pPars )
{
Aig_Man_t * pNew;
pNew = Gia_ManToAigSimple( p );
assert( Gia_ManObjNum(p) == Aig_ManObjNum(pNew) );
Dch_ComputeEquivalences( pNew, (Dch_Pars_t *)pPars );
Gia_ManReprFromAigRepr( pNew, p );
Aig_ManStop( pNew );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManFraigSweepSimple( Gia_Man_t * p, void * pPars )
{
Gia_Man_t * pNew;
assert( p->pManTime == NULL || Gia_ManBoxNum(p) == 0 );
Gia_ManFraigSweepPerform( p, pPars );
pNew = Gia_ManEquivReduce( p, 1, 0, 0, 0 );
if ( pNew == NULL )
pNew = Gia_ManDup(p);
Gia_ManTransferTiming( pNew, p );
return pNew;
}
/**Function*************************************************************
Synopsis [Computes equivalences for one clock domain.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSweepComputeOneDomainEquivs( Gia_Man_t * p, Vec_Int_t * vRegClasses, int iDom, void * pParsS, int fConst, int fEquiv, int fVerbose )
{
Gia_Man_t * pNew;
Gia_Obj_t * pObj;
Vec_Int_t * vPerm;
int i, Class, nFlops;
int nDoms = Vec_IntFindMax(vRegClasses);
assert( iDom >= 1 && iDom <= nDoms );
assert( p->pManTime == NULL );
assert( Gia_ManRegNum(p) > 0 );
// create required flop permutation
vPerm = Vec_IntAlloc( Gia_ManRegNum(p) );
Vec_IntForEachEntry( vRegClasses, Class, i )
if ( Class != iDom )
Vec_IntPush( vPerm, i );
nFlops = Vec_IntSize( vPerm );
Vec_IntForEachEntry( vRegClasses, Class, i )
if ( Class == iDom )
Vec_IntPush( vPerm, i );
nFlops = Vec_IntSize(vPerm) - nFlops;
assert( Vec_IntSize(vPerm) == Gia_ManRegNum(p) );
// derive new AIG
pNew = Gia_ManDupPermFlop( p, vPerm );
assert( Gia_ManObjNum(pNew) == Gia_ManObjNum(p) );
Vec_IntFree( vPerm );
// perform computation of equivalences
pNew->nRegs = nFlops;
if ( pParsS )
Cec_ManLSCorrespondenceClasses( pNew, (Cec_ParCor_t *)pParsS );
else
Gia_ManSeqCleanupClasses( pNew, fConst, fEquiv, fVerbose );
pNew->nRegs = Gia_ManRegNum(p);
// make new point to old
Gia_ManForEachObj( p, pObj, i )
{
assert( !Abc_LitIsCompl(pObj->Value) );
Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value))->Value = Abc_Var2Lit(i, 0);
}
// transfer
Gia_ManDupRemapEquiv( p, pNew );
Gia_ManStop( pNew );
}
Gia_Man_t * Gia_ManSweepWithBoxesAndDomains( Gia_Man_t * p, void * pParsS, int fConst, int fEquiv, int fVerbose, int fVerbEquivs )
{
Gia_Man_t * pClp, * pNew, * pTemp;
int nDoms = Vec_IntFindMax(p->vRegClasses);
int * pReprs, iDom, pFlopTypes[3] = {0};
assert( Gia_ManRegNum(p) == 0 );
assert( p->pAigExtra != NULL );
assert( nDoms > 1 );
// order AIG objects
pNew = Gia_ManDupUnnormalize( p );
if ( pNew == NULL )
return NULL;
Gia_ManTransferTiming( pNew, p );
// iterate over domains
for ( iDom = 1; iDom <= nDoms; iDom++ )
{
int nFlopsNew, nFlops = Vec_IntCountEntry(pNew->vRegClasses, iDom);
if ( nFlops < 2 )
continue;
// find global equivalences
pClp = Gia_ManDupCollapse( pNew, pNew->pAigExtra, NULL, 1 );
//Gia_DumpAiger( pClp, p->pSpec, iDom, 2 );
//Gia_ManPrintStats( pClp, NULL );
// compute equivalences
Gia_ManSweepComputeOneDomainEquivs( pClp, pNew->vRegClasses, iDom, pParsS, fConst, fEquiv, fVerbose );
// transfer equivalences
pReprs = Gia_ManFraigSelectReprs( pNew, pClp, fVerbose, pFlopTypes );
Gia_ManStop( pClp );
// reduce AIG
Gia_ManTransferTiming( p, pNew );
pNew = Gia_ManFraigReduceGia( pTemp = pNew, pReprs );
Gia_ManTransferTiming( pNew, p );
Gia_ManStop( pTemp );
ABC_FREE( pReprs );
// derive new AIG
pNew = Gia_ManDupWithBoxes( pTemp = pNew, 1 );
Gia_ManStop( pTemp );
// report
nFlopsNew = Vec_IntCountEntry(pNew->vRegClasses, iDom);
pFlopTypes[2] = nFlops - nFlopsNew - (pFlopTypes[0] + pFlopTypes[1]);
if ( fVerbEquivs )
{
printf( "Domain %2d : %5d -> %5d : ", iDom, nFlops, nFlopsNew );
printf( "EqConst =%4d. EqFlop =%4d. Dangling =%4d. Unused =%4d.\n",
pFlopTypes[0], pFlopTypes[1], Abc_MaxInt(0, pFlopTypes[2]), Abc_MaxInt(0, -pFlopTypes[2]) );
//Gia_ManPrintStats( pNew, NULL );
}
}
// normalize the result
pNew = Gia_ManDupNormalize( pTemp = pNew, 0 );
Gia_ManTransferTiming( pNew, pTemp );
Gia_ManStop( pTemp );
// check integrity
//Gia_ManCheckIntegrityWithBoxes( pNew );
return pNew;
}
/**Function*************************************************************
Synopsis [Reduces root model with scorr.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManSweepWithBoxes( Gia_Man_t * p, void * pParsC, void * pParsS, int fConst, int fEquiv, int fVerbose, int fVerbEquivs )
{
Gia_Man_t * pClp, * pNew, * pTemp;
int * pReprs, pFlopTypes[3] = {0};
int nFlopsNew, nFlops;
assert( Gia_ManRegNum(p) == 0 );
assert( p->pAigExtra != NULL );
// consider seq synthesis with multiple clock domains
if ( pParsC == NULL && Gia_ManClockDomainNum(p) > 1 )
return Gia_ManSweepWithBoxesAndDomains( p, pParsS, fConst, fEquiv, fVerbose, fVerbEquivs );
// order AIG objects
pNew = Gia_ManDupUnnormalize( p );
if ( pNew == NULL )
return NULL;
Gia_ManTransferTiming( pNew, p );
nFlops = Vec_IntCountEntry(pNew->vRegClasses, 1);
// find global equivalences
pClp = Gia_ManDupCollapse( pNew, pNew->pAigExtra, NULL, pParsC ? 0 : 1 );
//Gia_DumpAiger( pClp, p->pSpec, 1, 1 );
// compute equivalences
if ( pParsC )
Gia_ManFraigSweepPerform( pClp, pParsC );
else if ( pParsS )
Cec_ManLSCorrespondenceClasses( pClp, (Cec_ParCor_t *)pParsS );
else
Gia_ManSeqCleanupClasses( pClp, fConst, fEquiv, fVerbose );
// transfer equivalences
pReprs = Gia_ManFraigSelectReprs( pNew, pClp, fVerbose, pFlopTypes );
Gia_ManStop( pClp );
// reduce AIG
Gia_ManTransferTiming( p, pNew );
pNew = Gia_ManFraigReduceGia( pTemp = pNew, pReprs );
Gia_ManTransferTiming( pNew, p );
Gia_ManStop( pTemp );
ABC_FREE( pReprs );
// derive new AIG
pNew = Gia_ManDupWithBoxes( pTemp = pNew, pParsC ? 0 : 1 );
Gia_ManStop( pTemp );
// report
nFlopsNew = Vec_IntCountEntry(pNew->vRegClasses, 1);
pFlopTypes[2] = nFlops - nFlopsNew - (pFlopTypes[0] + pFlopTypes[1]);
if ( fVerbEquivs )
{
printf( "Domain %2d : %5d -> %5d : ", 1, nFlops, nFlopsNew );
printf( "EqConst =%4d. EqFlop =%4d. Dangling =%4d. Unused =%4d.\n",
pFlopTypes[0], pFlopTypes[1], Abc_MaxInt(0, pFlopTypes[2]), Abc_MaxInt(0, -pFlopTypes[2]) );
}
// normalize the result
pNew = Gia_ManDupNormalize( pTemp = pNew, 0 );
Gia_ManTransferTiming( pNew, pTemp );
Gia_ManStop( pTemp );
// check integrity
//Gia_ManCheckIntegrityWithBoxes( pNew );
return pNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END