| /**CFile**************************************************************** |
| |
| FileName [abcMiter.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Network and node package.] |
| |
| Synopsis [Procedures to derive the miter of two circuits.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: abcMiter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "base/abc/abc.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| static Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize, int fImplic, int fMulti ); |
| static void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize, int fMulti ); |
| static void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter ); |
| static void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize, int fImplic, int fMulti ); |
| static void Abc_NtkAddFrame( Abc_Ntk_t * pNetNew, Abc_Ntk_t * pNet, int iFrame ); |
| |
| // to be exported |
| typedef void (*AddFrameMapping)( Abc_Obj_t*, Abc_Obj_t*, int, void*); |
| extern Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg ); |
| static void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg ); |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives the miter of two networks.] |
| |
| Description [Preprocesses the networks to make sure that they are strashed.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize, int fImplic, int fMulti ) |
| { |
| Abc_Ntk_t * pTemp = NULL; |
| int fRemove1, fRemove2; |
| assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); |
| assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); |
| // check that the networks have the same PIs/POs/latches |
| if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, fImplic, fComb ) ) |
| return NULL; |
| // make sure the circuits are strashed |
| fRemove1 = (!Abc_NtkIsStrash(pNtk1) || Abc_NtkGetChoiceNum(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0, 0)); |
| fRemove2 = (!Abc_NtkIsStrash(pNtk2) || Abc_NtkGetChoiceNum(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0, 0)); |
| if ( pNtk1 && pNtk2 ) |
| pTemp = Abc_NtkMiterInt( pNtk1, pNtk2, fComb, nPartSize, fImplic, fMulti ); |
| if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); |
| if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); |
| return pTemp; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives the miter of two sequential networks.] |
| |
| Description [Assumes that the networks are strashed.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize, int fImplic, int fMulti ) |
| { |
| char Buffer[1000]; |
| Abc_Ntk_t * pNtkMiter; |
| |
| assert( Abc_NtkIsStrash(pNtk1) ); |
| assert( Abc_NtkIsStrash(pNtk2) ); |
| |
| // start the new network |
| pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); |
| sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); |
| pNtkMiter->pName = Extra_UtilStrsav(Buffer); |
| |
| // perform strashing |
| Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize, fMulti ); |
| Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); |
| Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); |
| Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize, fImplic, fMulti ); |
| Abc_AigCleanup((Abc_Aig_t *)pNtkMiter->pManFunc); |
| |
| // make sure that everything is okay |
| if ( !Abc_NtkCheck( pNtkMiter ) ) |
| { |
| printf( "Abc_NtkMiter: The network check has failed.\n" ); |
| Abc_NtkDelete( pNtkMiter ); |
| return NULL; |
| } |
| return pNtkMiter; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prepares the network for mitering.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize, int fMulti ) |
| { |
| Abc_Obj_t * pObj, * pObjNew; |
| int i; |
| // clean the copy field in all objects |
| // Abc_NtkCleanCopy( pNtk1 ); |
| // Abc_NtkCleanCopy( pNtk2 ); |
| Abc_AigConst1(pNtk1)->pCopy = Abc_AigConst1(pNtkMiter); |
| Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtkMiter); |
| |
| if ( fComb ) |
| { |
| // create new PIs and remember them in the old PIs |
| Abc_NtkForEachCi( pNtk1, pObj, i ) |
| { |
| pObjNew = Abc_NtkCreatePi( pNtkMiter ); |
| // remember this PI in the old PIs |
| pObj->pCopy = pObjNew; |
| pObj = Abc_NtkCi(pNtk2, i); |
| pObj->pCopy = pObjNew; |
| // add name |
| Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); |
| } |
| if ( nPartSize <= 0 ) |
| { |
| // create POs |
| if ( fMulti ) |
| { |
| Abc_NtkForEachCo( pNtk1, pObj, i ) |
| { |
| pObjNew = Abc_NtkCreatePo( pNtkMiter ); |
| Abc_ObjAssignName( pObjNew, "miter", Abc_ObjName(pObjNew) ); |
| } |
| |
| } |
| else |
| { |
| pObjNew = Abc_NtkCreatePo( pNtkMiter ); |
| Abc_ObjAssignName( pObjNew, "miter", NULL ); |
| } |
| } |
| } |
| else |
| { |
| // create new PIs and remember them in the old PIs |
| Abc_NtkForEachPi( pNtk1, pObj, i ) |
| { |
| pObjNew = Abc_NtkCreatePi( pNtkMiter ); |
| // remember this PI in the old PIs |
| pObj->pCopy = pObjNew; |
| pObj = Abc_NtkPi(pNtk2, i); |
| pObj->pCopy = pObjNew; |
| // add name |
| Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); |
| } |
| if ( nPartSize <= 0 ) |
| { |
| // create POs |
| if ( fMulti ) |
| { |
| Abc_NtkForEachPo( pNtk1, pObj, i ) |
| { |
| pObjNew = Abc_NtkCreatePo( pNtkMiter ); |
| Abc_ObjAssignName( pObjNew, "miter", Abc_ObjName(pObjNew) ); |
| } |
| |
| } |
| else |
| { |
| pObjNew = Abc_NtkCreatePo( pNtkMiter ); |
| Abc_ObjAssignName( pObjNew, "miter", NULL ); |
| } |
| } |
| // create the latches |
| Abc_NtkForEachLatch( pNtk1, pObj, i ) |
| { |
| pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 ); |
| // add names |
| Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_1" ); |
| Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_1" ); |
| Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_1" ); |
| } |
| Abc_NtkForEachLatch( pNtk2, pObj, i ) |
| { |
| pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 ); |
| // add name |
| Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_2" ); |
| Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_2" ); |
| Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_2" ); |
| } |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs mitering for one network.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter ) |
| { |
| Abc_Obj_t * pNode; |
| int i; |
| assert( Abc_NtkIsDfsOrdered(pNtk) ); |
| Abc_AigForEachAnd( pNtk, pNode, i ) |
| pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs mitering for one network.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pRoot ) |
| { |
| Vec_Ptr_t * vNodes; |
| Abc_Obj_t * pNode; |
| int i; |
| // map the constant nodes |
| Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkMiter); |
| // perform strashing |
| vNodes = Abc_NtkDfsNodes( pNtk, &pRoot, 1 ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) |
| if ( Abc_AigNodeIsAnd(pNode) ) |
| pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); |
| Vec_PtrFree( vNodes ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Finalizes the miter by adding the output part.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize, int fImplic, int fMulti ) |
| { |
| Vec_Ptr_t * vPairs; |
| Abc_Obj_t * pMiter, * pNode; |
| int i; |
| assert( nPartSize == 0 || fMulti == 0 ); |
| // collect the PO pairs from both networks |
| vPairs = Vec_PtrAlloc( 100 ); |
| if ( fComb ) |
| { |
| // collect the CO nodes for the miter |
| Abc_NtkForEachCo( pNtk1, pNode, i ) |
| { |
| if ( fMulti ) |
| { |
| pMiter = Abc_AigXor( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild0Copy(Abc_NtkCo(pNtk2, i)) ); |
| Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,i), pMiter ); |
| } |
| else |
| { |
| Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); |
| pNode = Abc_NtkCo( pNtk2, i ); |
| Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); |
| } |
| } |
| } |
| else |
| { |
| // collect the PO nodes for the miter |
| Abc_NtkForEachPo( pNtk1, pNode, i ) |
| { |
| if ( fMulti ) |
| { |
| pMiter = Abc_AigXor( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild0Copy(Abc_NtkCo(pNtk2, i)) ); |
| Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,i), pMiter ); |
| } |
| else |
| { |
| Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); |
| pNode = Abc_NtkPo( pNtk2, i ); |
| Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); |
| } |
| } |
| // connect new latches |
| Abc_NtkForEachLatch( pNtk1, pNode, i ) |
| Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) ); |
| Abc_NtkForEachLatch( pNtk2, pNode, i ) |
| Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) ); |
| } |
| // add the miter |
| if ( nPartSize <= 0 ) |
| { |
| if ( !fMulti ) |
| { |
| pMiter = Abc_AigMiter( (Abc_Aig_t *)pNtkMiter->pManFunc, vPairs, fImplic ); |
| Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); |
| } |
| } |
| else |
| { |
| char Buffer[1024]; |
| Vec_Ptr_t * vPairsPart; |
| int nParts, i, k, iCur; |
| assert( Vec_PtrSize(vPairs) == 2 * Abc_NtkCoNum(pNtk1) ); |
| // create partitions |
| nParts = Abc_NtkCoNum(pNtk1) / nPartSize + (int)((Abc_NtkCoNum(pNtk1) % nPartSize) > 0); |
| vPairsPart = Vec_PtrAlloc( nPartSize ); |
| for ( i = 0; i < nParts; i++ ) |
| { |
| Vec_PtrClear( vPairsPart ); |
| for ( k = 0; k < nPartSize; k++ ) |
| { |
| iCur = i * nPartSize + k; |
| if ( iCur >= Abc_NtkCoNum(pNtk1) ) |
| break; |
| Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur ) ); |
| Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur+1) ); |
| } |
| pMiter = Abc_AigMiter( (Abc_Aig_t *)pNtkMiter->pManFunc, vPairsPart, fImplic ); |
| pNode = Abc_NtkCreatePo( pNtkMiter ); |
| Abc_ObjAddFanin( pNode, pMiter ); |
| // assign the name to the node |
| if ( nPartSize == 1 ) |
| sprintf( Buffer, "%s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) ); |
| else |
| sprintf( Buffer, "%d", i ); |
| Abc_ObjAssignName( pNode, "miter_", Buffer ); |
| } |
| Vec_PtrFree( vPairsPart ); |
| } |
| Vec_PtrFree( vPairs ); |
| } |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives the AND of two miters.] |
| |
| Description [The network should have the same names of PIs.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 ) |
| { |
| char Buffer[1000]; |
| Abc_Ntk_t * pNtkMiter; |
| Abc_Obj_t * pOutput1, * pOutput2; |
| Abc_Obj_t * pRoot1, * pRoot2, * pMiter; |
| |
| assert( Abc_NtkIsStrash(pNtk1) ); |
| assert( Abc_NtkIsStrash(pNtk2) ); |
| assert( 1 == Abc_NtkCoNum(pNtk1) ); |
| assert( 1 == Abc_NtkCoNum(pNtk2) ); |
| assert( 0 == Abc_NtkLatchNum(pNtk1) ); |
| assert( 0 == Abc_NtkLatchNum(pNtk2) ); |
| assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) ); |
| assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); |
| assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); |
| |
| // start the new network |
| pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); |
| // sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); |
| sprintf( Buffer, "product" ); |
| pNtkMiter->pName = Extra_UtilStrsav(Buffer); |
| |
| // perform strashing |
| Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, 1, -1, 0 ); |
| Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); |
| Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); |
| // Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, 1 ); |
| pRoot1 = Abc_NtkPo(pNtk1,0); |
| pRoot2 = Abc_NtkPo(pNtk2,0); |
| pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot1)->pCopy, Abc_ObjFaninC0(pRoot1) ); |
| pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot2)->pCopy, (int)Abc_ObjFaninC0(pRoot2) ^ fCompl2 ); |
| |
| // create the miter of the two outputs |
| if ( fOr ) |
| pMiter = Abc_AigOr( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 ); |
| else |
| pMiter = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 ); |
| Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); |
| |
| // make sure that everything is okay |
| if ( !Abc_NtkCheck( pNtkMiter ) ) |
| { |
| printf( "Abc_NtkMiterAnd: The network check has failed.\n" ); |
| Abc_NtkDelete( pNtkMiter ); |
| return NULL; |
| } |
| return pNtkMiter; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives the cofactor of the miter w.r.t. the set of vars.] |
| |
| Description [The array of variable values contains -1/0/1 for each PI. |
| -1 means this PI remains, 0/1 means this PI is set to 0/1.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ) |
| { |
| char Buffer[1000]; |
| Abc_Ntk_t * pNtkMiter; |
| Abc_Obj_t * pRoot, * pOutput1; |
| int Value, i; |
| |
| assert( Abc_NtkIsStrash(pNtk) ); |
| assert( 1 == Abc_NtkCoNum(pNtk) ); |
| assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); |
| |
| // start the new network |
| pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); |
| sprintf( Buffer, "%s_miter", pNtk->pName ); |
| pNtkMiter->pName = Extra_UtilStrsav(Buffer); |
| |
| // get the root output |
| pRoot = Abc_NtkCo( pNtk, 0 ); |
| |
| // perform strashing |
| Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1, 0 ); |
| // set the first cofactor |
| Vec_IntForEachEntry( vPiValues, Value, i ) |
| { |
| if ( Value == -1 ) |
| continue; |
| if ( Value == 0 ) |
| { |
| Abc_NtkCi(pNtk, i)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); |
| continue; |
| } |
| if ( Value == 1 ) |
| { |
| Abc_NtkCi(pNtk, i)->pCopy = Abc_AigConst1(pNtkMiter); |
| continue; |
| } |
| assert( 0 ); |
| } |
| // add the first cofactor |
| Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); |
| |
| // save the output |
| pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); |
| |
| // create the miter of the two outputs |
| Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pOutput1 ); |
| |
| // make sure that everything is okay |
| if ( !Abc_NtkCheck( pNtkMiter ) ) |
| { |
| printf( "Abc_NtkMiterCofactor: The network check has failed.\n" ); |
| Abc_NtkDelete( pNtkMiter ); |
| return NULL; |
| } |
| return pNtkMiter; |
| } |
| /**Function************************************************************* |
| |
| Synopsis [Derives the miter of two cofactors of one output.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 ) |
| { |
| char Buffer[1000]; |
| Abc_Ntk_t * pNtkMiter; |
| Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter; |
| |
| assert( Abc_NtkIsStrash(pNtk) ); |
| assert( Out < Abc_NtkCoNum(pNtk) ); |
| assert( In1 < Abc_NtkCiNum(pNtk) ); |
| assert( In2 < Abc_NtkCiNum(pNtk) ); |
| assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); |
| |
| // start the new network |
| pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); |
| sprintf( Buffer, "%s_miter", Abc_ObjName(Abc_NtkCo(pNtk, Out)) ); |
| pNtkMiter->pName = Extra_UtilStrsav(Buffer); |
| |
| // get the root output |
| pRoot = Abc_NtkCo( pNtk, Out ); |
| |
| // perform strashing |
| Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1, 0 ); |
| // set the first cofactor |
| Abc_NtkCi(pNtk, In1)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); |
| if ( In2 >= 0 ) |
| Abc_NtkCi(pNtk, In2)->pCopy = Abc_AigConst1(pNtkMiter); |
| // add the first cofactor |
| Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); |
| |
| // save the output |
| pOutput1 = Abc_ObjFanin0(pRoot)->pCopy; |
| |
| // set the second cofactor |
| Abc_NtkCi(pNtk, In1)->pCopy = Abc_AigConst1(pNtkMiter); |
| if ( In2 >= 0 ) |
| Abc_NtkCi(pNtk, In2)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); |
| // add the second cofactor |
| Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); |
| |
| // save the output |
| pOutput2 = Abc_ObjFanin0(pRoot)->pCopy; |
| |
| // create the miter of the two outputs |
| pMiter = Abc_AigXor( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 ); |
| Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); |
| |
| // make sure that everything is okay |
| if ( !Abc_NtkCheck( pNtkMiter ) ) |
| { |
| printf( "Abc_NtkMiter: The network check has failed.\n" ); |
| Abc_NtkDelete( pNtkMiter ); |
| return NULL; |
| } |
| return pNtkMiter; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives the miter of two cofactors of one output.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist ) |
| { |
| Abc_Ntk_t * pNtkMiter; |
| Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter; |
| |
| assert( Abc_NtkIsStrash(pNtk) ); |
| assert( 1 == Abc_NtkCoNum(pNtk) ); |
| assert( In < Abc_NtkCiNum(pNtk) ); |
| assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); |
| |
| // start the new network |
| pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); |
| pNtkMiter->pName = Extra_UtilStrsav( Abc_ObjName(Abc_NtkCo(pNtk, 0)) ); |
| |
| // get the root output |
| pRoot = Abc_NtkCo( pNtk, 0 ); |
| |
| // perform strashing |
| Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1, 0 ); |
| // set the first cofactor |
| Abc_NtkCi(pNtk, In)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); |
| // add the first cofactor |
| Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); |
| // save the output |
| // pOutput1 = Abc_ObjFanin0(pRoot)->pCopy; |
| pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); |
| |
| // set the second cofactor |
| Abc_NtkCi(pNtk, In)->pCopy = Abc_AigConst1(pNtkMiter); |
| // add the second cofactor |
| Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); |
| // save the output |
| // pOutput2 = Abc_ObjFanin0(pRoot)->pCopy; |
| pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); |
| |
| // create the miter of the two outputs |
| if ( fExist ) |
| pMiter = Abc_AigOr( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 ); |
| else |
| pMiter = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 ); |
| Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); |
| |
| // make sure that everything is okay |
| if ( !Abc_NtkCheck( pNtkMiter ) ) |
| { |
| printf( "Abc_NtkMiter: The network check has failed.\n" ); |
| Abc_NtkDelete( pNtkMiter ); |
| return NULL; |
| } |
| return pNtkMiter; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Quantifies all the PIs existentially from the only PO of the network.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk ) |
| { |
| Abc_Ntk_t * pNtkTemp; |
| Abc_Obj_t * pObj; |
| int i; |
| assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); |
| |
| Abc_NtkForEachPi( pNtk, pObj, i ) |
| { |
| if ( Abc_ObjFanoutNum(pObj) == 0 ) |
| continue; |
| pNtk = Abc_NtkMiterQuantify( pNtkTemp = pNtk, i, 1 ); |
| Abc_NtkDelete( pNtkTemp ); |
| } |
| |
| return pNtk; |
| } |
| |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks the status of the miter.] |
| |
| Description [Return 0 if the miter is sat for at least one output. |
| Return 1 if the miter is unsat for all its outputs. Returns -1 if the |
| miter is undecided for some outputs.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter ) |
| { |
| Abc_Obj_t * pNodePo, * pChild; |
| int i; |
| assert( Abc_NtkIsStrash(pMiter) ); |
| Abc_NtkForEachPo( pMiter, pNodePo, i ) |
| { |
| pChild = Abc_ObjChild0( pNodePo ); |
| // check if the output is constant 1 |
| if ( Abc_AigNodeIsConst(pChild) ) |
| { |
| assert( Abc_ObjRegular(pChild) == Abc_AigConst1(pMiter) ); |
| if ( !Abc_ObjIsComplement(pChild) ) |
| { |
| // if the miter is constant 1, return immediately |
| // printf( "MITER IS CONSTANT 1!\n" ); |
| return 0; |
| } |
| } |
| /* |
| // check if the output is not constant 0 |
| else if ( Abc_ObjRegular(pChild)->fPhase != (unsigned)Abc_ObjIsComplement(pChild) ) |
| { |
| return 0; |
| } |
| */ |
| // if the miter is undecided (or satisfiable), return immediately |
| else |
| return -1; |
| } |
| // return 1, meaning all outputs are constant zero |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Reports the status of the miter.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkMiterReport( Abc_Ntk_t * pMiter ) |
| { |
| Abc_Obj_t * pChild, * pNode; |
| int i; |
| if ( Abc_NtkPoNum(pMiter) == 1 ) |
| { |
| pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,0) ); |
| if ( Abc_AigNodeIsConst(pChild) ) |
| { |
| if ( Abc_ObjIsComplement(pChild) ) |
| printf( "Unsatisfiable.\n" ); |
| else |
| printf( "Satisfiable. (Constant 1).\n" ); |
| } |
| else |
| printf( "Satisfiable.\n" ); |
| } |
| else |
| { |
| Abc_NtkForEachPo( pMiter, pNode, i ) |
| { |
| pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) ); |
| printf( "Output #%2d : ", i ); |
| if ( Abc_AigNodeIsConst(pChild) ) |
| { |
| if ( Abc_ObjIsComplement(pChild) ) |
| printf( "Unsatisfiable.\n" ); |
| else |
| printf( "Satisfiable. (Constant 1).\n" ); |
| } |
| else |
| printf( "Satisfiable.\n" ); |
| } |
| } |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives the timeframes of the network.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial, int fVerbose ) |
| { |
| char Buffer[1000]; |
| ProgressBar * pProgress; |
| Abc_Ntk_t * pNtkFrames; |
| Abc_Obj_t * pLatch, * pLatchOut; |
| int i, Counter; |
| assert( nFrames > 0 ); |
| assert( Abc_NtkIsStrash(pNtk) ); |
| assert( Abc_NtkIsDfsOrdered(pNtk) ); |
| assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); |
| // start the new network |
| pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); |
| sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames ); |
| pNtkFrames->pName = Extra_UtilStrsav(Buffer); |
| // map the constant nodes |
| Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkFrames); |
| // create new latches (or their initial values) and remember them in the new latches |
| if ( !fInitial ) |
| { |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) |
| Abc_NtkDupBox( pNtkFrames, pLatch, 1 ); |
| } |
| else |
| { |
| Counter = 0; |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) |
| { |
| pLatchOut = Abc_ObjFanout0(pLatch); |
| if ( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI |
| { |
| pLatchOut->pCopy = Abc_NtkCreatePi(pNtkFrames); |
| Abc_ObjAssignName( pLatchOut->pCopy, Abc_ObjName(pLatchOut), NULL ); |
| Counter++; |
| } |
| else |
| pLatchOut->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) ); |
| } |
| if ( Counter ) |
| printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter ); |
| } |
| |
| // create the timeframes |
| pProgress = Extra_ProgressBarStart( stdout, nFrames ); |
| for ( i = 0; i < nFrames; i++ ) |
| { |
| Extra_ProgressBarUpdate( pProgress, i, NULL ); |
| Abc_NtkAddFrame( pNtkFrames, pNtk, i ); |
| } |
| Extra_ProgressBarStop( pProgress ); |
| |
| // connect the new latches to the outputs of the last frame |
| if ( !fInitial ) |
| { |
| // we cannot use pLatch->pCopy here because pLatch->pCopy is used for temporary storage of strashed values |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) |
| Abc_ObjAddFanin( Abc_ObjFanin0(pLatch)->pCopy, Abc_ObjFanout0(pLatch)->pCopy ); |
| } |
| |
| // remove dangling nodes |
| Abc_AigCleanup( (Abc_Aig_t *)pNtkFrames->pManFunc ); |
| // reorder the latches |
| Abc_NtkOrderCisCos( pNtkFrames ); |
| // make sure that everything is okay |
| if ( !Abc_NtkCheck( pNtkFrames ) ) |
| { |
| printf( "Abc_NtkFrames: The network check has failed.\n" ); |
| Abc_NtkDelete( pNtkFrames ); |
| return NULL; |
| } |
| return pNtkFrames; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds one time frame to the new network.] |
| |
| Description [Assumes that the latches of the old network point |
| to the outputs of the previous frame of the new network (pLatch->pCopy). |
| In the end, updates the latches of the old network to point to the |
| outputs of the current frame of the new network.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame ) |
| { |
| int fVerbose = 0; |
| int NodeBef = Abc_NtkNodeNum(pNtkFrames); |
| char Buffer[10]; |
| Abc_Obj_t * pNode, * pLatch; |
| int i; |
| // create the prefix to be added to the node names |
| sprintf( Buffer, "_%02d", iFrame ); |
| // add the new PI nodes |
| Abc_NtkForEachPi( pNtk, pNode, i ) |
| Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer ); |
| // add the internal nodes |
| Abc_AigForEachAnd( pNtk, pNode, i ) |
| pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); |
| // add the new POs |
| Abc_NtkForEachPo( pNtk, pNode, i ) |
| { |
| Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer ); |
| Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) ); |
| } |
| // transfer the implementation of the latch inputs to the latch outputs |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) |
| pLatch->pCopy = Abc_ObjChild0Copy(Abc_ObjFanin0(pLatch)); |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) |
| Abc_ObjFanout0(pLatch)->pCopy = pLatch->pCopy; |
| // nodes after |
| if ( fVerbose ) |
| printf( "F = %4d : Total = %6d. Nodes = %6d. Prop = %s.\n", |
| iFrame, Abc_NtkNodeNum(pNtk), Abc_NtkNodeNum(pNtkFrames)-NodeBef, |
| Abc_AigNodeIsConst( Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pCopy ) ? "proof" : "unknown" ); |
| } |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives the timeframes of the network.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg ) |
| { |
| /* |
| char Buffer[1000]; |
| ProgressBar * pProgress; |
| Abc_Ntk_t * pNtkFrames; |
| Vec_Ptr_t * vNodes; |
| Abc_Obj_t * pLatch, * pLatchNew; |
| int i, Counter; |
| assert( nFrames > 0 ); |
| assert( Abc_NtkIsStrash(pNtk) ); |
| // start the new network |
| pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); |
| sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames ); |
| pNtkFrames->pName = Extra_UtilStrsav(Buffer); |
| // create new latches (or their initial values) and remember them in the new latches |
| if ( !fInitial ) |
| { |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) { |
| Abc_NtkDupObj( pNtkFrames, pLatch ); |
| if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg); |
| } |
| } |
| else |
| { |
| Counter = 0; |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) |
| { |
| if ( Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI |
| { |
| pLatch->pCopy = Abc_NtkCreatePi(pNtkFrames); |
| Abc_ObjAssignName( pLatch->pCopy, Abc_ObjName(pLatch), NULL ); |
| Counter++; |
| } |
| else { |
| pLatch->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) ); |
| } |
| |
| if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg); |
| } |
| if ( Counter ) |
| printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter ); |
| } |
| |
| // create the timeframes |
| vNodes = Abc_NtkDfs( pNtk, 0 ); |
| pProgress = Extra_ProgressBarStart( stdout, nFrames ); |
| for ( i = 0; i < nFrames; i++ ) |
| { |
| Extra_ProgressBarUpdate( pProgress, i, NULL ); |
| Abc_NtkAddFrame2( pNtkFrames, pNtk, i, vNodes, addFrameMapping, arg ); |
| } |
| Extra_ProgressBarStop( pProgress ); |
| Vec_PtrFree( vNodes ); |
| |
| // connect the new latches to the outputs of the last frame |
| if ( !fInitial ) |
| { |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) |
| { |
| pLatchNew = Abc_NtkBox(pNtkFrames, i); |
| Abc_ObjAddFanin( pLatchNew, pLatch->pCopy ); |
| Abc_ObjAssignName( pLatchNew, Abc_ObjName(pLatch), NULL ); |
| } |
| } |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) |
| pLatch->pNext = NULL; |
| |
| // remove dangling nodes |
| Abc_AigCleanup( pNtkFrames->pManFunc ); |
| |
| // reorder the latches |
| Abc_NtkOrderCisCos( pNtkFrames ); |
| |
| // make sure that everything is okay |
| if ( !Abc_NtkCheck( pNtkFrames ) ) |
| { |
| printf( "Abc_NtkFrames: The network check has failed.\n" ); |
| Abc_NtkDelete( pNtkFrames ); |
| return NULL; |
| } |
| return pNtkFrames; |
| */ |
| return NULL; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds one time frame to the new network.] |
| |
| Description [Assumes that the latches of the old network point |
| to the outputs of the previous frame of the new network (pLatch->pCopy). |
| In the end, updates the latches of the old network to point to the |
| outputs of the current frame of the new network.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg ) |
| { |
| /* |
| char Buffer[10]; |
| Abc_Obj_t * pNode, * pNodeNew, * pLatch; |
| Abc_Obj_t * pConst1, * pConst1New; |
| int i; |
| // get the constant nodes |
| pConst1 = Abc_AigConst1(pNtk); |
| pConst1New = Abc_AigConst1(pNtkFrames); |
| // create the prefix to be added to the node names |
| sprintf( Buffer, "_%02d", iFrame ); |
| // add the new PI nodes |
| Abc_NtkForEachPi( pNtk, pNode, i ) |
| { |
| pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode ); |
| Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer ); |
| if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); |
| } |
| // add the internal nodes |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) |
| { |
| if ( pNode == pConst1 ) |
| pNodeNew = pConst1New; |
| else |
| pNodeNew = Abc_AigAnd( pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); |
| pNode->pCopy = pNodeNew; |
| if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); |
| } |
| // add the new POs |
| Abc_NtkForEachPo( pNtk, pNode, i ) |
| { |
| pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode ); |
| Abc_ObjAddFanin( pNodeNew, Abc_ObjChild0Copy(pNode) ); |
| Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer ); |
| if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); |
| } |
| // transfer the implementation of the latch drivers to the latches |
| |
| // it is important that these two steps are performed it two loops |
| // and not in the same loop |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) |
| pLatch->pNext = Abc_ObjChild0Copy(pLatch); |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) |
| pLatch->pCopy = pLatch->pNext; |
| |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) |
| { |
| if (addFrameMapping) { |
| // don't give Mike complemented pointers because he doesn't like it |
| if (Abc_ObjIsComplement(pLatch->pCopy)) { |
| pNodeNew = Abc_NtkCreateNode( pNtkFrames ); |
| Abc_ObjAddFanin( pNodeNew, pLatch->pCopy ); |
| assert(Abc_ObjFaninNum(pNodeNew) == 1); |
| pNodeNew->Level = 1 + Abc_ObjRegular(pLatch->pCopy)->Level; |
| |
| pLatch->pNext = pNodeNew; |
| pLatch->pCopy = pNodeNew; |
| } |
| addFrameMapping(pLatch->pCopy, pLatch, iFrame+1, arg); |
| } |
| } |
| */ |
| } |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Splits the miter into two logic cones combined by an EXOR] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_NtkDemiter( Abc_Ntk_t * pNtk ) |
| { |
| Abc_Obj_t * pNodeC, * pNodeA, * pNodeB, * pNode; |
| Abc_Obj_t * pPoNew; |
| Vec_Ptr_t * vNodes1, * vNodes2; |
| int nCommon, i; |
| |
| assert( Abc_NtkIsStrash(pNtk) ); |
| assert( Abc_NtkPoNum(pNtk) == 1 ); |
| if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) ) |
| { |
| printf( "The root of the miter is not an EXOR gate.\n" ); |
| return 0; |
| } |
| pNodeC = Abc_NodeRecognizeMux( Abc_ObjFanin0(Abc_NtkPo(pNtk,0)), &pNodeA, &pNodeB ); |
| assert( Abc_ObjRegular(pNodeA) == Abc_ObjRegular(pNodeB) ); |
| if ( Abc_ObjFaninC0(Abc_NtkPo(pNtk,0)) ) |
| { |
| pNodeA = Abc_ObjNot(pNodeA); |
| pNodeB = Abc_ObjNot(pNodeB); |
| } |
| |
| // add the PO corresponding to control input |
| pPoNew = Abc_NtkCreatePo( pNtk ); |
| Abc_ObjAddFanin( pPoNew, pNodeC ); |
| Abc_ObjAssignName( pPoNew, "addOut1", NULL ); |
| |
| // add the PO corresponding to other input |
| pPoNew = Abc_NtkCreatePo( pNtk ); |
| Abc_ObjAddFanin( pPoNew, pNodeB ); |
| Abc_ObjAssignName( pPoNew, "addOut2", NULL ); |
| |
| // mark the nodes in the first cone |
| pNodeB = Abc_ObjRegular(pNodeB); |
| vNodes1 = Abc_NtkDfsNodes( pNtk, &pNodeC, 1 ); |
| vNodes2 = Abc_NtkDfsNodes( pNtk, &pNodeB, 1 ); |
| |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes1, pNode, i ) |
| pNode->fMarkA = 1; |
| nCommon = 0; |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes2, pNode, i ) |
| nCommon += pNode->fMarkA; |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes1, pNode, i ) |
| pNode->fMarkA = 0; |
| |
| printf( "First cone = %6d. Second cone = %6d. Common = %6d.\n", vNodes1->nSize, vNodes2->nSize, nCommon ); |
| Vec_PtrFree( vNodes1 ); |
| Vec_PtrFree( vNodes2 ); |
| |
| // reorder the latches |
| Abc_NtkOrderCisCos( pNtk ); |
| // make sure that everything is okay |
| if ( !Abc_NtkCheck( pNtk ) ) |
| printf( "Abc_NtkDemiter: The network check has failed.\n" ); |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes OR or AND of the POs.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd, int fXor ) |
| { |
| Abc_Obj_t * pNode, * pMiter; |
| int i; |
| assert( Abc_NtkIsStrash(pNtk) ); |
| // assert( Abc_NtkLatchNum(pNtk) == 0 ); |
| if ( Abc_NtkPoNum(pNtk) == 1 ) |
| return 1; |
| // start the result |
| if ( fAnd ) |
| pMiter = Abc_AigConst1(pNtk); |
| else |
| pMiter = Abc_ObjNot( Abc_AigConst1(pNtk) ); |
| // perform operations on the POs |
| Abc_NtkForEachPo( pNtk, pNode, i ) |
| if ( fAnd ) |
| pMiter = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) ); |
| else if ( fXor ) |
| pMiter = Abc_AigXor( (Abc_Aig_t *)pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) ); |
| else |
| pMiter = Abc_AigOr( (Abc_Aig_t *)pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) ); |
| // remove the POs and their names |
| for ( i = Abc_NtkPoNum(pNtk) - 1; i >= 0; i-- ) |
| Abc_NtkDeleteObj( Abc_NtkPo(pNtk, i) ); |
| assert( Abc_NtkPoNum(pNtk) == 0 ); |
| // create the new PO |
| pNode = Abc_NtkCreatePo( pNtk ); |
| Abc_ObjAddFanin( pNode, pMiter ); |
| Abc_ObjAssignName( pNode, "miter", NULL ); |
| Abc_NtkOrderCisCos( pNtk ); |
| // make sure that everything is okay |
| if ( !Abc_NtkCheck( pNtk ) ) |
| { |
| printf( "Abc_NtkOrPos: The network check has failed.\n" ); |
| return 0; |
| } |
| return 1; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |