summaryrefslogtreecommitdiffstats
path: root/src/aig/dch/dchChoice.c
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2010-11-29 01:26:00 -0800
committerAlan Mishchenko <alanmi@berkeley.edu>2010-11-29 01:26:00 -0800
commita2e2661e1f4464227ebb29dac4606673ef01f7ef (patch)
tree55e0bd57b9d54bd8eccea1365bcc0db5e15d48eb /src/aig/dch/dchChoice.c
parentcdcbd60b392eade8468f2bdb11b9dd56de9d557f (diff)
downloadabc-a2e2661e1f4464227ebb29dac4606673ef01f7ef.tar.gz
abc-a2e2661e1f4464227ebb29dac4606673ef01f7ef.tar.bz2
abc-a2e2661e1f4464227ebb29dac4606673ef01f7ef.zip
Fixing combinational loop problem in choice computation
Diffstat (limited to 'src/aig/dch/dchChoice.c')
-rw-r--r--src/aig/dch/dchChoice.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/src/aig/dch/dchChoice.c b/src/aig/dch/dchChoice.c
index c20d2974..fd517fb9 100644
--- a/src/aig/dch/dchChoice.c
+++ b/src/aig/dch/dchChoice.c
@@ -272,6 +272,165 @@ Aig_Man_t * Dch_DeriveChoiceAig_old( Aig_Man_t * pAig )
}
+
+
+/**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;
+ if ( Aig_ObjIsPi(pNode) || Aig_ObjIsConst1(pNode) )
+ 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;
+ Aig_ManForEachPo( p, pNode, i )
+ {
+ 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 );
+}
+
+
/**Function*************************************************************
Synopsis [Derives the AIG with choices from representatives.]
@@ -320,12 +479,20 @@ Aig_Man_t * Dch_DeriveChoiceAigInt( Aig_Man_t * pAig )
***********************************************************************/
Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig )
{
+ extern int Aig_ManCheckAcyclic( Aig_Man_t * pAig, int fVerbose );
Aig_Man_t * pChoices, * pTemp;
+ int fVerbose = 0;
pChoices = Dch_DeriveChoiceAigInt( pAig );
// pChoices = Dch_DeriveChoiceAigInt( pTemp = pChoices );
// Aig_ManStop( pTemp );
// there is no need for cleanup
ABC_FREE( pChoices->pReprs );
+ while ( !Aig_ManCheckAcyclic( pChoices, fVerbose ) )
+ {
+ if ( fVerbose )
+ Abc_Print( 1, "There is a loop!\n" );
+ Aig_ManFixLoopProblem( pChoices, fVerbose );
+ }
pChoices = Aig_ManDupDfs( pTemp = pChoices );
Aig_ManStop( pTemp );
return pChoices;