2008-08-02 17:01:00 +02:00
|
|
|
/**CFile****************************************************************
|
|
|
|
|
|
|
|
|
|
FileName [dchChoice.c]
|
|
|
|
|
|
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
|
|
|
|
|
|
PackageName [Choice computation for tech-mapping.]
|
|
|
|
|
|
|
|
|
|
Synopsis [Contrustion of choices.]
|
|
|
|
|
|
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
|
|
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
|
|
|
|
|
|
Date [Ver. 1.0. Started - June 29, 2008.]
|
|
|
|
|
|
|
|
|
|
Revision [$Id: dchChoice.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "dchInt.h"
|
|
|
|
|
|
2010-11-01 09:35:04 +01:00
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
|
|
|
|
|
2008-08-02 17:01:00 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// DECLARATIONS ///
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// FUNCTION DEFINITIONS ///
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Counts the number of representatives.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig )
|
|
|
|
|
{
|
|
|
|
|
Aig_Obj_t * pObj, * pRepr;
|
|
|
|
|
int i, nReprs = 0;
|
|
|
|
|
Aig_ManForEachObj( pAig, pObj, i )
|
|
|
|
|
{
|
|
|
|
|
pRepr = Aig_ObjRepr( pAig, pObj );
|
|
|
|
|
if ( pRepr == NULL )
|
|
|
|
|
continue;
|
|
|
|
|
assert( pRepr->Id < pObj->Id );
|
|
|
|
|
nReprs++;
|
|
|
|
|
}
|
|
|
|
|
return nReprs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Counts the number of equivalences.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig )
|
|
|
|
|
{
|
2008-08-03 05:01:00 +02:00
|
|
|
Aig_Obj_t * pObj, * pTemp, * pPrev;
|
|
|
|
|
int i, nEquivs = 0, Counter = 0;
|
2008-08-02 17:01:00 +02:00
|
|
|
Aig_ManForEachObj( pAig, pObj, i )
|
|
|
|
|
{
|
|
|
|
|
if ( !Aig_ObjIsChoice(pAig, pObj) )
|
|
|
|
|
continue;
|
2008-08-03 05:01:00 +02:00
|
|
|
for ( pPrev = pObj, pTemp = Aig_ObjEquiv(pAig, pObj); pTemp;
|
|
|
|
|
pPrev = pTemp, pTemp = Aig_ObjEquiv(pAig, pTemp) )
|
2008-08-02 17:01:00 +02:00
|
|
|
{
|
2008-08-03 05:01:00 +02:00
|
|
|
if ( pTemp->nRefs > 0 )
|
|
|
|
|
{
|
|
|
|
|
// remove referenced node from equivalence class
|
|
|
|
|
assert( pAig->pEquivs[pPrev->Id] == pTemp );
|
|
|
|
|
pAig->pEquivs[pPrev->Id] = pAig->pEquivs[pTemp->Id];
|
2008-08-30 17:01:00 +02:00
|
|
|
pAig->pEquivs[pTemp->Id] = NULL;
|
|
|
|
|
// how about the need to continue iterating over the list?
|
|
|
|
|
// pPrev = pTemp ???
|
2008-08-03 05:01:00 +02:00
|
|
|
Counter++;
|
|
|
|
|
}
|
2008-08-02 17:01:00 +02:00
|
|
|
nEquivs++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-09-01 17:01:00 +02:00
|
|
|
// printf( "Removed %d classes.\n", Counter );
|
2008-08-30 17:01:00 +02:00
|
|
|
|
|
|
|
|
if ( Counter )
|
|
|
|
|
Dch_DeriveChoiceCountEquivs( pAig );
|
2008-08-03 05:01:00 +02:00
|
|
|
// if ( Counter )
|
|
|
|
|
// printf( "Removed %d equiv nodes because of non-zero ref counter.\n", Counter );
|
2008-08-02 17:01:00 +02:00
|
|
|
return nEquivs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Returns 1 if the choice node of pRepr is in the TFI of pObj.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Dch_ObjCheckTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
|
|
|
|
|
{
|
|
|
|
|
// check the trivial cases
|
|
|
|
|
if ( pObj == NULL )
|
|
|
|
|
return 0;
|
2012-03-10 04:50:18 +01:00
|
|
|
if ( Aig_ObjIsCi(pObj) )
|
2008-08-02 17:01:00 +02:00
|
|
|
return 0;
|
|
|
|
|
if ( pObj->fMarkA )
|
|
|
|
|
return 1;
|
|
|
|
|
// skip the visited node
|
|
|
|
|
if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
|
|
|
|
|
return 0;
|
|
|
|
|
Aig_ObjSetTravIdCurrent( p, pObj );
|
|
|
|
|
// check the children
|
|
|
|
|
if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin0(pObj) ) )
|
|
|
|
|
return 1;
|
|
|
|
|
if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin1(pObj) ) )
|
|
|
|
|
return 1;
|
|
|
|
|
// check equivalent nodes
|
|
|
|
|
return Dch_ObjCheckTfi_rec( p, Aig_ObjEquiv(p, pObj) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Returns 1 if the choice node of pRepr is in the TFI of pObj.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Dch_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
|
|
|
|
|
{
|
|
|
|
|
Aig_Obj_t * pTemp;
|
|
|
|
|
int RetValue;
|
|
|
|
|
assert( !Aig_IsComplement(pObj) );
|
|
|
|
|
assert( !Aig_IsComplement(pRepr) );
|
|
|
|
|
// mark nodes of the choice node
|
|
|
|
|
for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) )
|
|
|
|
|
pTemp->fMarkA = 1;
|
|
|
|
|
// traverse the new node
|
|
|
|
|
Aig_ManIncrementTravId( p );
|
|
|
|
|
RetValue = Dch_ObjCheckTfi_rec( p, pObj );
|
|
|
|
|
// unmark nodes of the choice node
|
|
|
|
|
for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) )
|
|
|
|
|
pTemp->fMarkA = 0;
|
|
|
|
|
return RetValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Returns representatives of fanin in approapriate polarity.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
static inline Aig_Obj_t * Aig_ObjGetRepr( Aig_Man_t * p, Aig_Obj_t * pObj )
|
|
|
|
|
{
|
|
|
|
|
Aig_Obj_t * pRepr;
|
|
|
|
|
if ( (pRepr = Aig_ObjRepr(p, Aig_Regular(pObj))) )
|
|
|
|
|
return Aig_NotCond( pRepr, Aig_Regular(pObj)->fPhase ^ pRepr->fPhase ^ Aig_IsComplement(pObj) );
|
|
|
|
|
return pObj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline Aig_Obj_t * Aig_ObjChild0CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild0Copy(pObj) ); }
|
|
|
|
|
static inline Aig_Obj_t * Aig_ObjChild1CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild1Copy(pObj) ); }
|
|
|
|
|
|
2012-09-06 04:39:25 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Marks the TFI of the node.]
|
|
|
|
|
|
|
|
|
|
Description [Returns 1 if there is a CI not marked with previous ID.]
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Dch_ObjMarkTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
|
|
|
|
|
{
|
|
|
|
|
int RetValue;
|
|
|
|
|
if ( pObj == NULL )
|
|
|
|
|
return 0;
|
|
|
|
|
if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
|
|
|
|
|
return 0;
|
|
|
|
|
if ( Aig_ObjIsCi(pObj) )
|
|
|
|
|
{
|
|
|
|
|
RetValue = !Aig_ObjIsTravIdPrevious( p, pObj );
|
|
|
|
|
Aig_ObjSetTravIdCurrent( p, pObj );
|
|
|
|
|
return RetValue;
|
|
|
|
|
}
|
|
|
|
|
assert( Aig_ObjIsNode(pObj) );
|
|
|
|
|
Aig_ObjSetTravIdCurrent( p, pObj );
|
|
|
|
|
RetValue = Dch_ObjMarkTfi_rec( p, Aig_ObjFanin0(pObj) );
|
|
|
|
|
RetValue += Dch_ObjMarkTfi_rec( p, Aig_ObjFanin1(pObj) );
|
|
|
|
|
RetValue += Dch_ObjMarkTfi_rec( p, Aig_ObjEquiv(p, pObj) );
|
|
|
|
|
return (RetValue > 0);
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-02 17:01:00 +02:00
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Derives the AIG with choices from representatives.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
2012-09-06 04:39:25 +02:00
|
|
|
void Dch_DeriveChoiceAigNode( Aig_Man_t * pAigNew, Aig_Man_t * pAigOld, Aig_Obj_t * pObj, int fSkipRedSupps )
|
2008-08-02 17:01:00 +02:00
|
|
|
{
|
|
|
|
|
Aig_Obj_t * pRepr, * pObjNew, * pReprNew;
|
|
|
|
|
// get the new node
|
|
|
|
|
pObj->pData = Aig_And( pAigNew,
|
|
|
|
|
Aig_ObjChild0CopyRepr(pAigNew, pObj),
|
|
|
|
|
Aig_ObjChild1CopyRepr(pAigNew, pObj) );
|
|
|
|
|
pRepr = Aig_ObjRepr( pAigOld, pObj );
|
|
|
|
|
if ( pRepr == NULL )
|
|
|
|
|
return;
|
|
|
|
|
// get the corresponding new nodes
|
2010-11-01 09:35:04 +01:00
|
|
|
pObjNew = Aig_Regular((Aig_Obj_t *)pObj->pData);
|
|
|
|
|
pReprNew = Aig_Regular((Aig_Obj_t *)pRepr->pData);
|
2008-08-02 17:01:00 +02:00
|
|
|
if ( pObjNew == pReprNew )
|
|
|
|
|
return;
|
2008-08-03 05:01:00 +02:00
|
|
|
// skip the earlier nodes
|
|
|
|
|
if ( pReprNew->Id > pObjNew->Id )
|
|
|
|
|
return;
|
|
|
|
|
assert( pReprNew->Id < pObjNew->Id );
|
2008-08-02 17:01:00 +02:00
|
|
|
// set the representatives
|
|
|
|
|
Aig_ObjSetRepr( pAigNew, pObjNew, pReprNew );
|
2008-08-03 05:01:00 +02:00
|
|
|
// skip used nodes
|
|
|
|
|
if ( pObjNew->nRefs > 0 )
|
|
|
|
|
return;
|
|
|
|
|
assert( pObjNew->nRefs == 0 );
|
2008-08-02 17:01:00 +02:00
|
|
|
// update new nodes of the object
|
|
|
|
|
if ( !Aig_ObjIsNode(pRepr) )
|
|
|
|
|
return;
|
|
|
|
|
// skip choices with combinational loops
|
|
|
|
|
if ( Dch_ObjCheckTfi( pAigNew, pObjNew, pReprNew ) )
|
|
|
|
|
return;
|
2012-09-06 04:39:25 +02:00
|
|
|
// don't add choice if structural support of pObjNew and pReprNew differ
|
|
|
|
|
if ( fSkipRedSupps )
|
|
|
|
|
{
|
|
|
|
|
int fSkipChoice = 0;
|
|
|
|
|
// mark support of the representative node (pReprNew)
|
|
|
|
|
Aig_ManIncrementTravId( pAigNew );
|
|
|
|
|
Dch_ObjMarkTfi_rec( pAigNew, pReprNew );
|
|
|
|
|
// detect if the new node (pObjNew) depends on any additional variables
|
|
|
|
|
Aig_ManIncrementTravId( pAigNew );
|
|
|
|
|
if ( Dch_ObjMarkTfi_rec( pAigNew, pObjNew ) )
|
|
|
|
|
fSkipChoice = 1;//, printf( "1" );
|
|
|
|
|
// detect if the representative node (pReprNew) depends on any additional variables
|
|
|
|
|
Aig_ManIncrementTravId( pAigNew );
|
|
|
|
|
if ( Dch_ObjMarkTfi_rec( pAigNew, pReprNew ) )
|
|
|
|
|
fSkipChoice = 1;//, printf( "2" );
|
|
|
|
|
// skip the choice if this is what is happening
|
|
|
|
|
if ( fSkipChoice )
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-08-02 17:01:00 +02:00
|
|
|
// add choice
|
2008-08-03 05:01:00 +02:00
|
|
|
pAigNew->pEquivs[pObjNew->Id] = pAigNew->pEquivs[pReprNew->Id];
|
2008-08-02 17:01:00 +02:00
|
|
|
pAigNew->pEquivs[pReprNew->Id] = pObjNew;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Derives the AIG with choices from representatives.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
2010-11-01 09:35:04 +01:00
|
|
|
Aig_Man_t * Dch_DeriveChoiceAig_old( Aig_Man_t * pAig )
|
2008-08-02 17:01:00 +02:00
|
|
|
{
|
|
|
|
|
Aig_Man_t * pChoices, * pTemp;
|
|
|
|
|
Aig_Obj_t * pObj;
|
|
|
|
|
int i;
|
|
|
|
|
// start recording equivalences
|
|
|
|
|
pChoices = Aig_ManStart( Aig_ManObjNumMax(pAig) );
|
2009-02-15 17:01:00 +01:00
|
|
|
pChoices->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
|
|
|
|
|
pChoices->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
|
2008-08-02 17:01:00 +02:00
|
|
|
// map constants and PIs
|
|
|
|
|
Aig_ManCleanData( pAig );
|
|
|
|
|
Aig_ManConst1(pAig)->pData = Aig_ManConst1(pChoices);
|
2012-03-10 04:32:44 +01:00
|
|
|
Aig_ManForEachCi( pAig, pObj, i )
|
|
|
|
|
pObj->pData = Aig_ObjCreateCi( pChoices );
|
2008-08-03 05:01:00 +02:00
|
|
|
// construct choices for the internal nodes
|
2008-08-02 17:01:00 +02:00
|
|
|
assert( pAig->pReprs != NULL );
|
|
|
|
|
Aig_ManForEachNode( pAig, pObj, i )
|
2012-09-06 04:39:25 +02:00
|
|
|
Dch_DeriveChoiceAigNode( pChoices, pAig, pObj, 0 );
|
2012-03-10 04:32:44 +01:00
|
|
|
Aig_ManForEachCo( pAig, pObj, i )
|
|
|
|
|
Aig_ObjCreateCo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) );
|
2008-08-02 17:01:00 +02:00
|
|
|
Dch_DeriveChoiceCountEquivs( pChoices );
|
|
|
|
|
// there is no need for cleanup
|
2009-02-15 17:01:00 +01:00
|
|
|
ABC_FREE( pChoices->pReprs );
|
2008-08-02 17:01:00 +02:00
|
|
|
pChoices = Aig_ManDupDfs( pTemp = pChoices );
|
|
|
|
|
Aig_ManStop( pTemp );
|
|
|
|
|
return pChoices;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-01 09:35:04 +01:00
|
|
|
|
2010-11-29 10:26:00 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Checks for combinational loops in the AIG.]
|
|
|
|
|
|
|
|
|
|
Description [Returns 1 if combinational loop is detected.]
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Aig_ManCheckAcyclic_rec( Aig_Man_t * p, Aig_Obj_t * pNode, int fVerbose )
|
|
|
|
|
{
|
|
|
|
|
Aig_Obj_t * pFanin;
|
|
|
|
|
int fAcyclic;
|
2012-03-10 04:50:18 +01:00
|
|
|
if ( Aig_ObjIsCi(pNode) || Aig_ObjIsConst1(pNode) )
|
2010-11-29 10:26:00 +01:00
|
|
|
return 1;
|
|
|
|
|
assert( Aig_ObjIsNode(pNode) );
|
|
|
|
|
// make sure the node is not visited
|
|
|
|
|
assert( !Aig_ObjIsTravIdPrevious(p, pNode) );
|
|
|
|
|
// check if the node is part of the combinational loop
|
|
|
|
|
if ( Aig_ObjIsTravIdCurrent(p, pNode) )
|
|
|
|
|
{
|
|
|
|
|
if ( fVerbose )
|
|
|
|
|
Abc_Print( 1, "Network \"%s\" contains combinational loop!\n", p->pSpec? p->pSpec : NULL );
|
|
|
|
|
if ( fVerbose )
|
|
|
|
|
Abc_Print( 1, "Node \"%d\" is encountered twice on the following path to the COs:\n", Aig_ObjId(pNode) );
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
// mark this node as a node on the current path
|
|
|
|
|
Aig_ObjSetTravIdCurrent( p, pNode );
|
|
|
|
|
|
|
|
|
|
// visit the transitive fanin
|
|
|
|
|
pFanin = Aig_ObjFanin0(pNode);
|
|
|
|
|
// check if the fanin is visited
|
|
|
|
|
if ( !Aig_ObjIsTravIdPrevious(p, pFanin) )
|
|
|
|
|
{
|
|
|
|
|
// traverse the fanin's cone searching for the loop
|
|
|
|
|
if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) )
|
|
|
|
|
{
|
|
|
|
|
// return as soon as the loop is detected
|
|
|
|
|
if ( fVerbose )
|
|
|
|
|
Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) );
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// visit the transitive fanin
|
|
|
|
|
pFanin = Aig_ObjFanin1(pNode);
|
|
|
|
|
// check if the fanin is visited
|
|
|
|
|
if ( !Aig_ObjIsTravIdPrevious(p, pFanin) )
|
|
|
|
|
{
|
|
|
|
|
// traverse the fanin's cone searching for the loop
|
|
|
|
|
if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) )
|
|
|
|
|
{
|
|
|
|
|
// return as soon as the loop is detected
|
|
|
|
|
if ( fVerbose )
|
|
|
|
|
Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) );
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// visit choices
|
|
|
|
|
if ( Aig_ObjRepr(p, pNode) == NULL && Aig_ObjEquiv(p, pNode) != NULL )
|
|
|
|
|
{
|
|
|
|
|
for ( pFanin = Aig_ObjEquiv(p, pNode); pFanin; pFanin = Aig_ObjEquiv(p, pFanin) )
|
|
|
|
|
{
|
|
|
|
|
// check if the fanin is visited
|
|
|
|
|
if ( Aig_ObjIsTravIdPrevious(p, pFanin) )
|
|
|
|
|
continue;
|
|
|
|
|
// traverse the fanin's cone searching for the loop
|
|
|
|
|
if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) )
|
|
|
|
|
continue;
|
|
|
|
|
// return as soon as the loop is detected
|
|
|
|
|
if ( fVerbose )
|
|
|
|
|
Abc_Print( 1, " %d", Aig_ObjId(pFanin) );
|
|
|
|
|
if ( fVerbose )
|
|
|
|
|
Abc_Print( 1, " (choice of %d) -> ", Aig_ObjId(pNode) );
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// mark this node as a visited node
|
|
|
|
|
Aig_ObjSetTravIdPrevious( p, pNode );
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Checks for combinational loops in the AIG.]
|
|
|
|
|
|
|
|
|
|
Description [Returns 1 if there is no combinational loops.]
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Aig_ManCheckAcyclic( Aig_Man_t * p, int fVerbose )
|
|
|
|
|
{
|
|
|
|
|
Aig_Obj_t * pNode;
|
|
|
|
|
int fAcyclic;
|
|
|
|
|
int i;
|
|
|
|
|
// set the traversal ID for this DFS ordering
|
|
|
|
|
Aig_ManIncrementTravId( p );
|
|
|
|
|
Aig_ManIncrementTravId( p );
|
|
|
|
|
// pNode->TravId == pNet->nTravIds means "pNode is on the path"
|
|
|
|
|
// pNode->TravId == pNet->nTravIds - 1 means "pNode is visited but is not on the path"
|
|
|
|
|
// pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited"
|
|
|
|
|
// traverse the network to detect cycles
|
|
|
|
|
fAcyclic = 1;
|
2012-03-10 04:32:44 +01:00
|
|
|
Aig_ManForEachCo( p, pNode, i )
|
2010-11-29 10:26:00 +01:00
|
|
|
{
|
|
|
|
|
pNode = Aig_ObjFanin0(pNode);
|
|
|
|
|
if ( Aig_ObjIsTravIdPrevious(p, pNode) )
|
|
|
|
|
continue;
|
|
|
|
|
// traverse the output logic cone
|
|
|
|
|
if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pNode, fVerbose)) )
|
|
|
|
|
continue;
|
|
|
|
|
// stop as soon as the first loop is detected
|
|
|
|
|
if ( fVerbose )
|
|
|
|
|
Abc_Print( 1, " CO %d\n", i );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return fAcyclic;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Removes combinational loop.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
void Aig_ManFixLoopProblem( Aig_Man_t * p, int fVerbose )
|
|
|
|
|
{
|
|
|
|
|
Aig_Obj_t * pObj;
|
|
|
|
|
int i, Counter = 0, Counter2 = 0;
|
|
|
|
|
Aig_ManForEachObj( p, pObj, i )
|
|
|
|
|
{
|
|
|
|
|
if ( !Aig_ObjIsTravIdCurrent(p, pObj) )
|
|
|
|
|
continue;
|
|
|
|
|
Counter2++;
|
|
|
|
|
if ( Aig_ObjRepr(p, pObj) == NULL && Aig_ObjEquiv(p, pObj) != NULL )
|
|
|
|
|
{
|
|
|
|
|
Aig_ObjSetEquiv(p, pObj, NULL);
|
|
|
|
|
Counter++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( fVerbose )
|
|
|
|
|
Abc_Print( 1, "Fixed %d choice nodes on the path with %d objects.\n", Counter, Counter2 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-11-01 09:35:04 +01:00
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Derives the AIG with choices from representatives.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
2012-09-06 04:39:25 +02:00
|
|
|
Aig_Man_t * Dch_DeriveChoiceAigInt( Aig_Man_t * pAig, int fSkipRedSupps )
|
2010-11-01 09:35:04 +01:00
|
|
|
{
|
|
|
|
|
Aig_Man_t * pChoices;
|
|
|
|
|
Aig_Obj_t * pObj;
|
|
|
|
|
int i;
|
|
|
|
|
// start recording equivalences
|
|
|
|
|
pChoices = Aig_ManStart( Aig_ManObjNumMax(pAig) );
|
|
|
|
|
pChoices->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
|
|
|
|
|
pChoices->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
|
|
|
|
|
// map constants and PIs
|
|
|
|
|
Aig_ManCleanData( pAig );
|
|
|
|
|
Aig_ManConst1(pAig)->pData = Aig_ManConst1(pChoices);
|
2012-03-10 04:32:44 +01:00
|
|
|
Aig_ManForEachCi( pAig, pObj, i )
|
|
|
|
|
pObj->pData = Aig_ObjCreateCi( pChoices );
|
2010-11-01 09:35:04 +01:00
|
|
|
// construct choices for the internal nodes
|
|
|
|
|
assert( pAig->pReprs != NULL );
|
|
|
|
|
Aig_ManForEachNode( pAig, pObj, i )
|
2012-09-06 04:39:25 +02:00
|
|
|
Dch_DeriveChoiceAigNode( pChoices, pAig, pObj, fSkipRedSupps );
|
2012-03-10 04:32:44 +01:00
|
|
|
Aig_ManForEachCo( pAig, pObj, i )
|
|
|
|
|
Aig_ObjCreateCo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) );
|
2010-11-01 09:35:04 +01:00
|
|
|
Dch_DeriveChoiceCountEquivs( pChoices );
|
2011-07-16 07:36:06 +02:00
|
|
|
Aig_ManSetRegNum( pChoices, Aig_ManRegNum(pAig) );
|
2010-11-01 09:35:04 +01:00
|
|
|
return pChoices;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Derives the AIG with choices from representatives.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
2012-09-06 04:39:25 +02:00
|
|
|
Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig, int fSkipRedSupps )
|
2010-11-01 09:35:04 +01:00
|
|
|
{
|
2010-11-29 10:26:00 +01:00
|
|
|
extern int Aig_ManCheckAcyclic( Aig_Man_t * pAig, int fVerbose );
|
2010-11-01 09:35:04 +01:00
|
|
|
Aig_Man_t * pChoices, * pTemp;
|
2010-11-29 10:26:00 +01:00
|
|
|
int fVerbose = 0;
|
2012-09-06 04:39:25 +02:00
|
|
|
pChoices = Dch_DeriveChoiceAigInt( pAig, fSkipRedSupps );
|
2010-11-01 09:35:04 +01:00
|
|
|
// pChoices = Dch_DeriveChoiceAigInt( pTemp = pChoices );
|
|
|
|
|
// Aig_ManStop( pTemp );
|
|
|
|
|
// there is no need for cleanup
|
|
|
|
|
ABC_FREE( pChoices->pReprs );
|
2010-11-29 10:26:00 +01:00
|
|
|
while ( !Aig_ManCheckAcyclic( pChoices, fVerbose ) )
|
|
|
|
|
{
|
|
|
|
|
if ( fVerbose )
|
|
|
|
|
Abc_Print( 1, "There is a loop!\n" );
|
|
|
|
|
Aig_ManFixLoopProblem( pChoices, fVerbose );
|
|
|
|
|
}
|
2010-11-01 09:35:04 +01:00
|
|
|
pChoices = Aig_ManDupDfs( pTemp = pChoices );
|
|
|
|
|
Aig_ManStop( pTemp );
|
|
|
|
|
return pChoices;
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-02 17:01:00 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// END OF FILE ///
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
2010-11-01 09:35:04 +01:00
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|
|
|
|