| /**CFile**************************************************************** |
| |
| FileName [ivyUtil.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [And-Inverter Graph package.] |
| |
| Synopsis [Various procedures.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - May 11, 2006.] |
| |
| Revision [$Id: ivyUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "ivy.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Increments the current traversal ID of the network.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_ManIncrementTravId( Ivy_Man_t * p ) |
| { |
| if ( p->nTravIds >= (1<<30)-1 - 1000 ) |
| Ivy_ManCleanTravId( p ); |
| p->nTravIds++; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Sets the DFS ordering of the nodes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_ManCleanTravId( Ivy_Man_t * p ) |
| { |
| Ivy_Obj_t * pObj; |
| int i; |
| p->nTravIds = 1; |
| Ivy_ManForEachObj( p, pObj, i ) |
| pObj->TravId = 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes truth table of the cut.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_ManCollectCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vNodes ) |
| { |
| if ( pNode->fMarkA ) |
| return; |
| pNode->fMarkA = 1; |
| assert( Ivy_ObjIsAnd(pNode) || Ivy_ObjIsExor(pNode) ); |
| Ivy_ManCollectCut_rec( p, Ivy_ObjFanin0(pNode), vNodes ); |
| Ivy_ManCollectCut_rec( p, Ivy_ObjFanin1(pNode), vNodes ); |
| Vec_IntPush( vNodes, pNode->Id ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes truth table of the cut.] |
| |
| Description [Does not modify the array of leaves. Uses array vTruth to store |
| temporary truth tables. The returned pointer should be used immediately.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) |
| { |
| int i, Leaf; |
| // collect and mark the leaves |
| Vec_IntClear( vNodes ); |
| Vec_IntForEachEntry( vLeaves, Leaf, i ) |
| { |
| Vec_IntPush( vNodes, Leaf ); |
| Ivy_ManObj(p, Leaf)->fMarkA = 1; |
| } |
| // collect and mark the nodes |
| Ivy_ManCollectCut_rec( p, pRoot, vNodes ); |
| // clean the nodes |
| Vec_IntForEachEntry( vNodes, Leaf, i ) |
| Ivy_ManObj(p, Leaf)->fMarkA = 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns the pointer to the truth table.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| unsigned * Ivy_ObjGetTruthStore( int ObjNum, Vec_Int_t * vTruth ) |
| { |
| return ((unsigned *)Vec_IntArray(vTruth)) + 8 * ObjNum; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes truth table of the cut.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_ManCutTruthOne( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vTruth, int nWords ) |
| { |
| unsigned * pTruth, * pTruth0, * pTruth1; |
| int i; |
| pTruth = Ivy_ObjGetTruthStore( pNode->TravId, vTruth ); |
| pTruth0 = Ivy_ObjGetTruthStore( Ivy_ObjFanin0(pNode)->TravId, vTruth ); |
| pTruth1 = Ivy_ObjGetTruthStore( Ivy_ObjFanin1(pNode)->TravId, vTruth ); |
| if ( Ivy_ObjIsExor(pNode) ) |
| for ( i = 0; i < nWords; i++ ) |
| pTruth[i] = pTruth0[i] ^ pTruth1[i]; |
| else if ( !Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) |
| for ( i = 0; i < nWords; i++ ) |
| pTruth[i] = pTruth0[i] & pTruth1[i]; |
| else if ( !Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) |
| for ( i = 0; i < nWords; i++ ) |
| pTruth[i] = pTruth0[i] & ~pTruth1[i]; |
| else if ( Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) |
| for ( i = 0; i < nWords; i++ ) |
| pTruth[i] = ~pTruth0[i] & pTruth1[i]; |
| else // if ( Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) |
| for ( i = 0; i < nWords; i++ ) |
| pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes truth table of the cut.] |
| |
| Description [Does not modify the array of leaves. Uses array vTruth to store |
| temporary truth tables. The returned pointer should be used immediately.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ) |
| { |
| static unsigned uTruths[8][8] = { // elementary truth tables |
| { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, |
| { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, |
| { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, |
| { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, |
| { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, |
| { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, |
| { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, |
| { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } |
| }; |
| int i, Leaf; |
| // collect the cut |
| Ivy_ManCollectCut( p, pRoot, vLeaves, vNodes ); |
| // set the node numbers |
| Vec_IntForEachEntry( vNodes, Leaf, i ) |
| Ivy_ManObj(p, Leaf)->TravId = i; |
| // alloc enough memory |
| Vec_IntClear( vTruth ); |
| Vec_IntGrow( vTruth, 8 * Vec_IntSize(vNodes) ); |
| // set the elementary truth tables |
| Vec_IntForEachEntry( vLeaves, Leaf, i ) |
| memcpy( Ivy_ObjGetTruthStore(i, vTruth), uTruths[i], 8 * sizeof(unsigned) ); |
| // compute truths for other nodes |
| Vec_IntForEachEntryStart( vNodes, Leaf, i, Vec_IntSize(vLeaves) ) |
| Ivy_ManCutTruthOne( p, Ivy_ManObj(p, Leaf), vTruth, 8 ); |
| return Ivy_ObjGetTruthStore( pRoot->TravId, vTruth ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collect the latches.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p ) |
| { |
| Vec_Int_t * vLatches; |
| Ivy_Obj_t * pObj; |
| int i; |
| vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) ); |
| Ivy_ManForEachLatch( p, pObj, i ) |
| Vec_IntPush( vLatches, pObj->Id ); |
| return vLatches; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collect the latches.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_ManLevels( Ivy_Man_t * p ) |
| { |
| Ivy_Obj_t * pObj; |
| int i, LevelMax = 0; |
| Ivy_ManForEachPo( p, pObj, i ) |
| LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level ); |
| return LevelMax; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collect the latches.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_ManResetLevels_rec( Ivy_Obj_t * pObj ) |
| { |
| if ( pObj->Level || Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) ) |
| return pObj->Level; |
| if ( Ivy_ObjIsBuf(pObj) ) |
| return pObj->Level = Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); |
| assert( Ivy_ObjIsNode(pObj) ); |
| Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); |
| Ivy_ManResetLevels_rec( Ivy_ObjFanin1(pObj) ); |
| return pObj->Level = Ivy_ObjLevelNew( pObj ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collect the latches.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_ManResetLevels( Ivy_Man_t * p ) |
| { |
| Ivy_Obj_t * pObj; |
| int i; |
| Ivy_ManForEachObj( p, pObj, i ) |
| pObj->Level = 0; |
| Ivy_ManForEachCo( p, pObj, i ) |
| Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [References/references the node and returns MFFC size.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_ObjRefDeref( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fReference, int fLabel ) |
| { |
| Ivy_Obj_t * pNode0, * pNode1; |
| int Counter; |
| // label visited nodes |
| if ( fLabel ) |
| Ivy_ObjSetTravIdCurrent( p, pNode ); |
| // skip the CI |
| if ( Ivy_ObjIsPi(pNode) ) |
| return 0; |
| assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsBuf(pNode) || Ivy_ObjIsLatch(pNode) ); |
| // process the internal node |
| pNode0 = Ivy_ObjFanin0(pNode); |
| pNode1 = Ivy_ObjFanin1(pNode); |
| Counter = Ivy_ObjIsNode(pNode); |
| if ( fReference ) |
| { |
| if ( pNode0->nRefs++ == 0 ) |
| Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); |
| if ( pNode1 && pNode1->nRefs++ == 0 ) |
| Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); |
| } |
| else |
| { |
| assert( pNode0->nRefs > 0 ); |
| assert( pNode1 == NULL || pNode1->nRefs > 0 ); |
| if ( --pNode0->nRefs == 0 ) |
| Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); |
| if ( pNode1 && --pNode1->nRefs == 0 ) |
| Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); |
| } |
| return Counter; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Labels MFFC with the current label.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pNode ) |
| { |
| int nConeSize1, nConeSize2; |
| assert( !Ivy_IsComplement( pNode ) ); |
| assert( Ivy_ObjIsNode( pNode ) ); |
| nConeSize1 = Ivy_ObjRefDeref( p, pNode, 0, 1 ); // dereference |
| nConeSize2 = Ivy_ObjRefDeref( p, pNode, 1, 0 ); // reference |
| assert( nConeSize1 == nConeSize2 ); |
| assert( nConeSize1 > 0 ); |
| return nConeSize1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Recursively updates fanout levels.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ) |
| { |
| Ivy_Obj_t * pFanout; |
| Vec_Ptr_t * vFanouts; |
| int i, LevelNew; |
| assert( p->fFanout ); |
| assert( Ivy_ObjIsNode(pObj) ); |
| vFanouts = Vec_PtrAlloc( 10 ); |
| Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) |
| { |
| if ( Ivy_ObjIsCo(pFanout) ) |
| { |
| // assert( (int)Ivy_ObjFanin0(pFanout)->Level <= p->nLevelMax ); |
| continue; |
| } |
| LevelNew = Ivy_ObjLevelNew( pFanout ); |
| if ( (int)pFanout->Level == LevelNew ) |
| continue; |
| pFanout->Level = LevelNew; |
| Ivy_ObjUpdateLevel_rec( p, pFanout ); |
| } |
| Vec_PtrFree( vFanouts ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Compute the new required level.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_ObjLevelRNew( Ivy_Man_t * p, Ivy_Obj_t * pObj ) |
| { |
| Ivy_Obj_t * pFanout; |
| Vec_Ptr_t * vFanouts; |
| int i, Required, LevelNew = 1000000; |
| assert( p->fFanout && p->vRequired ); |
| vFanouts = Vec_PtrAlloc( 10 ); |
| Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) |
| { |
| Required = Vec_IntEntry(p->vRequired, pFanout->Id); |
| LevelNew = IVY_MIN( LevelNew, Required ); |
| } |
| Vec_PtrFree( vFanouts ); |
| return LevelNew - 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Recursively updates fanout levels.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew ) |
| { |
| Ivy_Obj_t * pFanin; |
| if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) |
| return; |
| assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); |
| // process the first fanin |
| pFanin = Ivy_ObjFanin0(pObj); |
| if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) |
| { |
| Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); |
| Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); |
| } |
| if ( Ivy_ObjIsBuf(pObj) ) |
| return; |
| // process the second fanin |
| pFanin = Ivy_ObjFanin1(pObj); |
| if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) |
| { |
| Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); |
| Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_ObjIsMuxType( Ivy_Obj_t * pNode ) |
| { |
| Ivy_Obj_t * pNode0, * pNode1; |
| // check that the node is regular |
| assert( !Ivy_IsComplement(pNode) ); |
| // if the node is not AND, this is not MUX |
| if ( !Ivy_ObjIsAnd(pNode) ) |
| return 0; |
| // if the children are not complemented, this is not MUX |
| if ( !Ivy_ObjFaninC0(pNode) || !Ivy_ObjFaninC1(pNode) ) |
| return 0; |
| // get children |
| pNode0 = Ivy_ObjFanin0(pNode); |
| pNode1 = Ivy_ObjFanin1(pNode); |
| // if the children are not ANDs, this is not MUX |
| if ( !Ivy_ObjIsAnd(pNode0) || !Ivy_ObjIsAnd(pNode1) ) |
| return 0; |
| // otherwise the node is MUX iff it has a pair of equal grandchildren |
| return (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || |
| (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1))) || |
| (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || |
| (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1))); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Recognizes what nodes are control and data inputs of a MUX.] |
| |
| Description [If the node is a MUX, returns the control variable C. |
| Assigns nodes T and E to be the then and else variables of the MUX. |
| Node C is never complemented. Nodes T and E can be complemented. |
| This function also recognizes EXOR/NEXOR gates as MUXes.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pNode, Ivy_Obj_t ** ppNodeT, Ivy_Obj_t ** ppNodeE ) |
| { |
| Ivy_Obj_t * pNode0, * pNode1; |
| assert( !Ivy_IsComplement(pNode) ); |
| assert( Ivy_ObjIsMuxType(pNode) ); |
| // get children |
| pNode0 = Ivy_ObjFanin0(pNode); |
| pNode1 = Ivy_ObjFanin1(pNode); |
| // find the control variable |
| // if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) |
| if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) |
| { |
| // if ( Fraig_IsComplement(pNode1->p1) ) |
| if ( Ivy_ObjFaninC0(pNode0) ) |
| { // pNode2->p1 is positive phase of C |
| *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); |
| *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); |
| return Ivy_ObjChild0(pNode1);//pNode2->p1; |
| } |
| else |
| { // pNode1->p1 is positive phase of C |
| *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); |
| *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); |
| return Ivy_ObjChild0(pNode0);//pNode1->p1; |
| } |
| } |
| // else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) |
| else if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) |
| { |
| // if ( Fraig_IsComplement(pNode1->p1) ) |
| if ( Ivy_ObjFaninC0(pNode0) ) |
| { // pNode2->p2 is positive phase of C |
| *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); |
| *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); |
| return Ivy_ObjChild1(pNode1);//pNode2->p2; |
| } |
| else |
| { // pNode1->p1 is positive phase of C |
| *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); |
| *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); |
| return Ivy_ObjChild0(pNode0);//pNode1->p1; |
| } |
| } |
| // else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) |
| else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) |
| { |
| // if ( Fraig_IsComplement(pNode1->p2) ) |
| if ( Ivy_ObjFaninC1(pNode0) ) |
| { // pNode2->p1 is positive phase of C |
| *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); |
| *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); |
| return Ivy_ObjChild0(pNode1);//pNode2->p1; |
| } |
| else |
| { // pNode1->p2 is positive phase of C |
| *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); |
| *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); |
| return Ivy_ObjChild1(pNode0);//pNode1->p2; |
| } |
| } |
| // else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) |
| else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) |
| { |
| // if ( Fraig_IsComplement(pNode1->p2) ) |
| if ( Ivy_ObjFaninC1(pNode0) ) |
| { // pNode2->p2 is positive phase of C |
| *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); |
| *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); |
| return Ivy_ObjChild1(pNode1);//pNode2->p2; |
| } |
| else |
| { // pNode1->p2 is positive phase of C |
| *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); |
| *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); |
| return Ivy_ObjChild1(pNode0);//pNode1->p2; |
| } |
| } |
| assert( 0 ); // this is not MUX |
| return NULL; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns the real fanin.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj ) |
| { |
| Ivy_Obj_t * pFanin; |
| if ( pObj == NULL || !Ivy_ObjIsBuf( Ivy_Regular(pObj) ) ) |
| return pObj; |
| pFanin = Ivy_ObjReal( Ivy_ObjChild0(Ivy_Regular(pObj)) ); |
| return Ivy_NotCond( pFanin, Ivy_IsComplement(pObj) ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints node in HAIG.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig ) |
| { |
| Ivy_Obj_t * pTemp; |
| int fShowFanouts = 0; |
| assert( !Ivy_IsComplement(pObj) ); |
| printf( "Node %5d : ", Ivy_ObjId(pObj) ); |
| if ( Ivy_ObjIsConst1(pObj) ) |
| printf( "constant 1" ); |
| else if ( Ivy_ObjIsPi(pObj) ) |
| printf( "PI" ); |
| else if ( Ivy_ObjIsPo(pObj) ) |
| printf( "PO" ); |
| else if ( Ivy_ObjIsLatch(pObj) ) |
| printf( "latch (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); |
| else if ( Ivy_ObjIsBuf(pObj) ) |
| printf( "buffer (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); |
| else |
| printf( "AND( %5d%s, %5d%s )", |
| Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " "), |
| Ivy_ObjFanin1(pObj)->Id, (Ivy_ObjFaninC1(pObj)? "\'" : " ") ); |
| printf( " (refs = %3d)", Ivy_ObjRefs(pObj) ); |
| if ( fShowFanouts ) |
| { |
| Vec_Ptr_t * vFanouts; |
| Ivy_Obj_t * pFanout; |
| int i; |
| vFanouts = Vec_PtrAlloc( 10 ); |
| printf( "\nFanouts:\n" ); |
| Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) |
| { |
| printf( " " ); |
| printf( "Node %5d : ", Ivy_ObjId(pFanout) ); |
| if ( Ivy_ObjIsPo(pFanout) ) |
| printf( "PO" ); |
| else if ( Ivy_ObjIsLatch(pFanout) ) |
| printf( "latch (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); |
| else if ( Ivy_ObjIsBuf(pFanout) ) |
| printf( "buffer (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); |
| else |
| printf( "AND( %5d%s, %5d%s )", |
| Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " "), |
| Ivy_ObjFanin1(pFanout)->Id, (Ivy_ObjFaninC1(pFanout)? "\'" : " ") ); |
| printf( "\n" ); |
| } |
| Vec_PtrFree( vFanouts ); |
| return; |
| } |
| if ( !fHaig ) |
| { |
| if ( pObj->pEquiv == NULL ) |
| printf( " HAIG node not given" ); |
| else |
| printf( " HAIG node = %d%s", Ivy_Regular(pObj->pEquiv)->Id, (Ivy_IsComplement(pObj->pEquiv)? "\'" : " ") ); |
| return; |
| } |
| if ( pObj->pEquiv == NULL ) |
| return; |
| // there are choices |
| if ( Ivy_ObjRefs(pObj) > 0 ) |
| { |
| // print equivalence class |
| printf( " { %5d ", pObj->Id ); |
| assert( !Ivy_IsComplement(pObj->pEquiv) ); |
| for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) |
| printf( " %5d%s", pTemp->Id, (Ivy_IsComplement(pTemp->pEquiv)? "\'" : " ") ); |
| printf( " }" ); |
| return; |
| } |
| // this is a secondary node |
| for ( pTemp = Ivy_Regular(pObj->pEquiv); Ivy_ObjRefs(pTemp) == 0; pTemp = Ivy_Regular(pTemp->pEquiv) ); |
| assert( Ivy_ObjRefs(pTemp) > 0 ); |
| printf( " class of %d", pTemp->Id ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints node in HAIG.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig ) |
| { |
| Vec_Int_t * vNodes; |
| Ivy_Obj_t * pObj; |
| int i; |
| printf( "PIs: " ); |
| Ivy_ManForEachPi( p, pObj, i ) |
| printf( " %d", pObj->Id ); |
| printf( "\n" ); |
| printf( "POs: " ); |
| Ivy_ManForEachPo( p, pObj, i ) |
| printf( " %d", pObj->Id ); |
| printf( "\n" ); |
| printf( "Latches: " ); |
| Ivy_ManForEachLatch( p, pObj, i ) |
| printf( " %d=%d%s", pObj->Id, Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); |
| printf( "\n" ); |
| vNodes = Ivy_ManDfsSeq( p, NULL ); |
| Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) |
| Ivy_ObjPrintVerbose( p, pObj, fHaig ), printf( "\n" ); |
| printf( "\n" ); |
| Vec_IntFree( vNodes ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs incremental rewriting of the AIG.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_CutTruthPrint2( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ) |
| { |
| int i; |
| printf( "Trying cut : {" ); |
| for ( i = 0; i < pCut->nSize; i++ ) |
| printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); |
| printf( " } " ); |
| Extra_PrintBinary( stdout, &uTruth, 16 ); printf( "\n" ); |
| return 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs incremental rewriting of the AIG.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ) |
| { |
| Vec_Ptr_t * vArray; |
| Ivy_Obj_t * pObj, * pFanout; |
| int nLatches = 0; |
| int nPresent = 0; |
| int i, k; |
| int fVerbose = 0; |
| |
| if ( fVerbose ) |
| printf( "Trying cut : {" ); |
| for ( i = 0; i < pCut->nSize; i++ ) |
| { |
| if ( fVerbose ) |
| printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); |
| nLatches += Ivy_LeafLat(pCut->pArray[i]); |
| } |
| if ( fVerbose ) |
| printf( " } " ); |
| if ( fVerbose ) |
| printf( "Latches = %d. ", nLatches ); |
| |
| // check if there are latches on the fanout edges |
| vArray = Vec_PtrAlloc( 100 ); |
| for ( i = 0; i < pCut->nSize; i++ ) |
| { |
| pObj = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[i]) ); |
| Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, k ) |
| { |
| if ( Ivy_ObjIsLatch(pFanout) ) |
| { |
| nPresent++; |
| break; |
| } |
| } |
| } |
| Vec_PtrSize( vArray ); |
| if ( fVerbose ) |
| { |
| printf( "Present = %d. ", nPresent ); |
| if ( nLatches > nPresent ) |
| printf( "Clauses = %d. ", 2*(nLatches - nPresent) ); |
| printf( "\n" ); |
| } |
| return ( nLatches > nPresent ) ? 2*(nLatches - nPresent) : 0; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |