/src/proof/dch/dchChoice.c
C | 552 lines | 343 code | 22 blank | 187 comment | 96 complexity | a382ddd00f34d534c5d0f502d61d4ef9 MD5 | raw file
Possible License(s): BSD-3-Clause
- /**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"
- ABC_NAMESPACE_IMPL_START
- ////////////////////////////////////////////////////////////////////////
- /// DECLARATIONS ///
- ////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////
- /// FUNCTION DEFINITIONS ///
- ////////////////////////////////////////////////////////////////////////
-
- /**Function*************************************************************
-
- Synopsis [Counts support nodes.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
- ***********************************************************************/
- int Dch_ObjCountSupp_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
- {
- int Count;
- if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
- return 0;
- Aig_ObjSetTravIdCurrent( p, pObj );
- if ( Aig_ObjIsCi(pObj) )
- return 1;
- assert( Aig_ObjIsNode(pObj) );
- Count = Dch_ObjCountSupp_rec( p, Aig_ObjFanin0(pObj) );
- Count += Dch_ObjCountSupp_rec( p, Aig_ObjFanin1(pObj) );
- return Count;
- }
- int Dch_ObjCountSupp( Aig_Man_t * p, Aig_Obj_t * pObj )
- {
- Aig_ManIncrementTravId( p );
- return Dch_ObjCountSupp_rec( p, pObj );
- }
-
- /**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;
- }
- int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig )
- {
- Aig_Obj_t * pObj, * pEquiv;
- int i, nEquivs = 0;
- Aig_ManForEachObj( pAig, pObj, i )
- {
- pEquiv = Aig_ObjEquiv( pAig, pObj );
- if ( pEquiv == NULL )
- continue;
- assert( pEquiv->Id < pObj->Id );
- nEquivs++;
- }
- return nEquivs;
- }
-
- /**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);
- }
- int Dch_ObjCheckSuppRed( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
- {
- // mark support of the representative node (pRepr)
- Aig_ManIncrementTravId( p );
- Dch_ObjMarkTfi_rec( p, pRepr );
- // detect if the new node (pObj) depends on additional variables
- Aig_ManIncrementTravId( p );
- if ( Dch_ObjMarkTfi_rec( p, pObj ) )
- return 1;//, printf( "1" );
- // detect if the representative node (pRepr) depends on additional variables
- Aig_ManIncrementTravId( p );
- if ( Dch_ObjMarkTfi_rec( p, pRepr ) )
- return 1;//, printf( "2" );
- // skip the choice if this is what is happening
- return 0;
- }
-
- /**Function*************************************************************
-
- Synopsis [Make sure reprsentative nodes do not have representatives.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
- ***********************************************************************/
- void Aig_ManCheckReprs( Aig_Man_t * p )
- {
- int fPrintConst = 0;
- Aig_Obj_t * pObj;
- int i, fProb = 0;
- int Class0 = 0, ClassCi = 0;
- Aig_ManForEachObj( p, pObj, i )
- {
- if ( Aig_ObjRepr(p, pObj) == NULL )
- continue;
- if ( !Aig_ObjIsNode(pObj) )
- printf( "Obj %d is not an AND but it has a repr %d.\n", i, Aig_ObjId(Aig_ObjRepr(p, pObj)) ), fProb = 1;
- else if ( Aig_ObjRepr(p, Aig_ObjRepr(p, pObj)) )
- printf( "Obj %d has repr %d with a repr %d.\n", i, Aig_ObjId(Aig_ObjRepr(p, pObj)), Aig_ObjId(Aig_ObjRepr(p, Aig_ObjRepr(p, pObj))) ), fProb = 1;
- }
- if ( !fProb )
- printf( "Representive verification successful.\n" );
- else
- printf( "Representive verification FAILED.\n" );
- if ( !fPrintConst )
- return;
- // count how many representatives are const0 or a CI
- Aig_ManForEachObj( p, pObj, i )
- {
- if ( Aig_ObjRepr(p, pObj) == Aig_ManConst1(p) )
- Class0++;
- if ( Aig_ObjRepr(p, pObj) && Aig_ObjIsCi(Aig_ObjRepr(p, pObj)) )
- ClassCi++;
- }
- printf( "Const0 nodes = %d. ConstCI nodes = %d.\n", Class0, ClassCi );
- }
-
- /**Function*************************************************************
-
- Synopsis [Verify correctness of choices.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
- ***********************************************************************/
- void Dch_CheckChoices( Aig_Man_t * p, int fSkipRedSupps )
- {
- Aig_Obj_t * pObj;
- int i, fProb = 0;
- Aig_ManCleanMarkA( p );
- Aig_ManForEachNode( p, pObj, i )
- {
- if ( p->pEquivs[i] != NULL )
- {
- if ( pObj->fMarkA == 1 )
- printf( "node %d participates in more than one choice class\n", i ), fProb = 1;
- pObj->fMarkA = 1;
- // check redundancy
- if ( fSkipRedSupps && Dch_ObjCheckSuppRed( p, pObj, p->pEquivs[i]) )
- printf( "node %d and repr %d have diff supports\n", pObj->Id, p->pEquivs[i]->Id );
- // consider the next one
- pObj = p->pEquivs[i];
- if ( p->pEquivs[Aig_ObjId(pObj)] == NULL )
- {
- if ( pObj->fMarkA == 1 )
- printf( "repr %d has final node %d participates in more than one choice class\n", i, pObj->Id ), fProb = 1;
- pObj->fMarkA = 1;
- }
- // consider the non-head ones
- if ( pObj->nRefs > 0 )
- printf( "node %d belonging to choice has fanout %d\n", pObj->Id, pObj->nRefs );
- }
- if ( p->pReprs && p->pReprs[i] != NULL )
- {
- if ( pObj->nRefs > 0 )
- printf( "node %d has representative %d and fanout count %d\n", pObj->Id, p->pReprs[i]->Id, pObj->nRefs ), fProb = 1;
- }
- }
- Aig_ManCleanMarkA( p );
- if ( !fProb )
- printf( "Verification of choice AIG succeeded.\n" );
- else
- printf( "Verification of choice AIG FAILED.\n" );
- }
-
- /**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_ObjIsCi(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;
- }
- 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_ManForEachCo( 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 [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;
- if ( Aig_ObjIsCi(pObj) )
- 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) );
- }
- 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) ); }
-
- /**Function*************************************************************
-
- Synopsis [Derives the AIG with choices from representatives.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
- ***********************************************************************/
- void Dch_DeriveChoiceAigNode( Aig_Man_t * pAigNew, Aig_Man_t * pAigOld, Aig_Obj_t * pObj, int fSkipRedSupps )
- {
- Aig_Obj_t * pRepr, * pObjNew, * pReprNew;
- assert( !Aig_IsComplement(pObj) );
- // get the representative
- pRepr = Aig_ObjRepr( pAigOld, pObj );
- if ( pRepr != NULL && (Aig_ObjIsConst1(pRepr) || Aig_ObjIsCi(pRepr)) )
- {
- assert( pRepr->pData != NULL );
- pObj->pData = Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pObj->fPhase ^ pRepr->fPhase );
- return;
- }
- // get the new node
- pObjNew = Aig_And( pAigNew,
- Aig_ObjChild0CopyRepr(pAigNew, pObj),
- Aig_ObjChild1CopyRepr(pAigNew, pObj) );
- // pObjNew = Aig_ObjGetRepr( pAigNew, pObjNew );
- while ( 1 )
- {
- Aig_Obj_t * pObjNew2 = pObjNew;
- pObjNew = Aig_ObjGetRepr( pAigNew, pObjNew2 );
- if ( pObjNew == pObjNew2 )
- break;
- }
- // assert( Aig_ObjRepr( pAigNew, pObjNew ) == NULL );
- // assign the copy
- assert( pObj->pData == NULL );
- pObj->pData = pObjNew;
- // skip those without reprs
- if ( pRepr == NULL )
- return;
- assert( pRepr->Id < pObj->Id );
- assert( Aig_ObjIsNode(pRepr) );
- // get the corresponding new nodes
- pObjNew = Aig_Regular((Aig_Obj_t *)pObj->pData);
- pReprNew = Aig_Regular((Aig_Obj_t *)pRepr->pData);
- // skip earlier nodes
- if ( pReprNew->Id >= pObjNew->Id )
- return;
- assert( pReprNew->Id < pObjNew->Id );
- // set the representatives
- Aig_ObjSetRepr( pAigNew, pObjNew, pReprNew );
- // skip used nodes
- if ( pObjNew->nRefs > 0 )
- return;
- assert( pObjNew->nRefs == 0 );
- // skip choices that can lead to combo loops
- if ( Dch_ObjCheckTfi( pAigNew, pObjNew, pReprNew ) )
- return;
- // don't add choice if structural support of pObjNew and pReprNew differ
- if ( fSkipRedSupps && Dch_ObjCheckSuppRed(pAigNew, pObjNew, pReprNew) )
- return;
- // add choice to the end of the list
- while ( pAigNew->pEquivs[pReprNew->Id] != NULL )
- pReprNew = pAigNew->pEquivs[pReprNew->Id];
- assert( pAigNew->pEquivs[pReprNew->Id] == NULL );
- pAigNew->pEquivs[pReprNew->Id] = pObjNew;
- }
- Aig_Man_t * Dch_DeriveChoiceAigInt( Aig_Man_t * pAig, int fSkipRedSupps )
- {
- 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);
- Aig_ManForEachCi( pAig, pObj, i )
- pObj->pData = Aig_ObjCreateCi( pChoices );
- // construct choices for the internal nodes
- assert( pAig->pReprs != NULL );
- Aig_ManForEachNode( pAig, pObj, i )
- Dch_DeriveChoiceAigNode( pChoices, pAig, pObj, fSkipRedSupps );
- Aig_ManForEachCo( pAig, pObj, i )
- Aig_ObjCreateCo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) );
- Aig_ManSetRegNum( pChoices, Aig_ManRegNum(pAig) );
- return pChoices;
- }
- Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig, int fSkipRedSupps )
- {
- int fCheck = 0;
- Aig_Man_t * pChoices, * pTemp;
- // verify
- if ( fCheck )
- Aig_ManCheckReprs( pAig );
- // compute choices
- pChoices = Dch_DeriveChoiceAigInt( pAig, fSkipRedSupps );
- ABC_FREE( pChoices->pReprs );
- // verify
- if ( fCheck )
- Dch_CheckChoices( pChoices, fSkipRedSupps );
- // find correct topo order with choices
- pChoices = Aig_ManDupDfs( pTemp = pChoices );
- Aig_ManStop( pTemp );
- // verify
- if ( fCheck )
- Dch_CheckChoices( pChoices, fSkipRedSupps );
- return pChoices;
- }
- ////////////////////////////////////////////////////////////////////////
- /// END OF FILE ///
- ////////////////////////////////////////////////////////////////////////
- ABC_NAMESPACE_IMPL_END