| /**CFile**************************************************************** |
| |
| FileName [abcNtk.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Network and node package.] |
| |
| Synopsis [Network creation/duplication/deletion procedures.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: abcNtk.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "abc.h" |
| #include "abcInt.h" |
| #include "base/main/main.h" |
| #include "map/mio/mio.h" |
| #include "aig/gia/gia.h" |
| |
| #ifdef ABC_USE_CUDD |
| #include "bdd/extrab/extraBdd.h" |
| #endif |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates a new Ntk.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan ) |
| { |
| Abc_Ntk_t * pNtk; |
| pNtk = ABC_ALLOC( Abc_Ntk_t, 1 ); |
| memset( pNtk, 0, sizeof(Abc_Ntk_t) ); |
| pNtk->ntkType = Type; |
| pNtk->ntkFunc = Func; |
| // start the object storage |
| pNtk->vObjs = Vec_PtrAlloc( 100 ); |
| pNtk->vPios = Vec_PtrAlloc( 100 ); |
| pNtk->vPis = Vec_PtrAlloc( 100 ); |
| pNtk->vPos = Vec_PtrAlloc( 100 ); |
| pNtk->vCis = Vec_PtrAlloc( 100 ); |
| pNtk->vCos = Vec_PtrAlloc( 100 ); |
| pNtk->vBoxes = Vec_PtrAlloc( 100 ); |
| pNtk->vLtlProperties = Vec_PtrAlloc( 100 ); |
| // start the memory managers |
| pNtk->pMmObj = fUseMemMan? Mem_FixedStart( sizeof(Abc_Obj_t) ) : NULL; |
| pNtk->pMmStep = fUseMemMan? Mem_StepStart( ABC_NUM_STEPS ) : NULL; |
| // get ready to assign the first Obj ID |
| pNtk->nTravIds = 1; |
| // start the functionality manager |
| if ( !Abc_NtkIsStrash(pNtk) ) |
| Vec_PtrPush( pNtk->vObjs, NULL ); |
| if ( Abc_NtkIsStrash(pNtk) ) |
| pNtk->pManFunc = Abc_AigAlloc( pNtk ); |
| else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) |
| pNtk->pManFunc = Mem_FlexStart(); |
| #ifdef ABC_USE_CUDD |
| else if ( Abc_NtkHasBdd(pNtk) ) |
| pNtk->pManFunc = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); |
| #endif |
| else if ( Abc_NtkHasAig(pNtk) ) |
| pNtk->pManFunc = Hop_ManStart(); |
| else if ( Abc_NtkHasMapping(pNtk) ) |
| pNtk->pManFunc = Abc_FrameReadLibGen(); |
| else if ( !Abc_NtkHasBlackbox(pNtk) ) |
| assert( 0 ); |
| // name manager |
| pNtk->pManName = Nm_ManCreate( 200 ); |
| // attribute manager |
| pNtk->vAttrs = Vec_PtrStart( VEC_ATTR_TOTAL_NUM ); |
| // estimated AndGateDelay |
| pNtk->AndGateDelay = 0.0; |
| return pNtk; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Starts a new network using existing network as a model.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) |
| { |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pObj; |
| int fCopyNames, i; |
| if ( pNtk == NULL ) |
| return NULL; |
| // decide whether to copy the names |
| fCopyNames = ( Type != ABC_NTK_NETLIST ); |
| // start the network |
| pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); |
| pNtkNew->nConstrs = pNtk->nConstrs; |
| pNtkNew->nBarBufs = pNtk->nBarBufs; |
| // duplicate the name and the spec |
| pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); |
| pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); |
| // clean the node copy fields |
| Abc_NtkCleanCopy( pNtk ); |
| // map the constant nodes |
| if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) |
| Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); |
| // clone CIs/CIs/boxes |
| Abc_NtkForEachPi( pNtk, pObj, i ) |
| Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); |
| Abc_NtkForEachPo( pNtk, pObj, i ) |
| Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); |
| Abc_NtkForEachBox( pNtk, pObj, i ) |
| Abc_NtkDupBox( pNtkNew, pObj, fCopyNames ); |
| // transfer logic level |
| Abc_NtkForEachCi( pNtk, pObj, i ) |
| pObj->pCopy->Level = pObj->Level; |
| // transfer the names |
| // Abc_NtkTrasferNames( pNtk, pNtkNew ); |
| Abc_ManTimeDup( pNtk, pNtkNew ); |
| if ( pNtk->vOnehots ) |
| pNtkNew->vOnehots = (Vec_Ptr_t *)Vec_VecDupInt( (Vec_Vec_t *)pNtk->vOnehots ); |
| if ( pNtk->pSeqModel ) |
| pNtkNew->pSeqModel = Abc_CexDup( pNtk->pSeqModel, Abc_NtkLatchNum(pNtk) ); |
| if ( pNtk->vObjPerm ) |
| pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm ); |
| pNtkNew->AndGateDelay = pNtk->AndGateDelay; |
| if ( pNtkNew->pManTime && Abc_FrameReadLibGen() && pNtkNew->AndGateDelay == 0.0 ) |
| pNtkNew->AndGateDelay = Mio_LibraryReadDelayAigNode((Mio_Library_t *)Abc_FrameReadLibGen()); |
| // initialize logic level of the CIs |
| if ( pNtk->AndGateDelay != 0.0 && pNtk->pManTime != NULL && pNtk->ntkType != ABC_NTK_STRASH && Type == ABC_NTK_STRASH ) |
| { |
| Abc_NtkForEachCi( pNtk, pObj, i ) |
| pObj->pCopy->Level = (int)(Abc_MaxFloat(0, Abc_NodeReadArrivalWorst(pObj)) / pNtk->AndGateDelay); |
| } |
| // check that the CI/CO/latches are copied correctly |
| assert( Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkNew) ); |
| assert( Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkNew) ); |
| assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) ); |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Starts a new network using existing network as a model.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkStartFromWithLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func, int nLatches ) |
| { |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pObj, * pNode0, * pNode1; |
| int fCopyNames, i; |
| if ( pNtk == NULL ) |
| return NULL; |
| assert( Abc_NtkLatchNum(pNtk) == 0 ); |
| // decide whether to copy the names |
| fCopyNames = ( Type != ABC_NTK_NETLIST ); |
| // start the network |
| pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); |
| pNtkNew->nConstrs = pNtk->nConstrs; |
| pNtkNew->nBarBufs = pNtk->nBarBufs; |
| // duplicate the name and the spec |
| pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); |
| pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); |
| // clean the node copy fields |
| Abc_NtkCleanCopy( pNtk ); |
| // map the constant nodes |
| if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) |
| Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); |
| // clone CIs/CIs/boxes |
| for ( i = 0; i < Abc_NtkPiNum(pNtk)-nLatches; i++ ) |
| Abc_NtkDupObj( pNtkNew, Abc_NtkPi(pNtk, i), fCopyNames ); |
| for ( i = 0; i < Abc_NtkPoNum(pNtk)-nLatches; i++ ) |
| Abc_NtkDupObj( pNtkNew, Abc_NtkPo(pNtk, i), fCopyNames ); |
| for ( i = 0; i < nLatches; i++ ) |
| { |
| pObj = Abc_NtkCreateLatch(pNtkNew); |
| Abc_LatchSetInit0( pObj ); |
| pNode0 = Abc_NtkCreateBi(pNtkNew); |
| Abc_NtkPo(pNtk, Abc_NtkPoNum(pNtk)-nLatches+i)->pCopy = pNode0; |
| pNode1 = Abc_NtkCreateBo(pNtkNew); |
| Abc_NtkPi(pNtk, Abc_NtkPiNum(pNtk)-nLatches+i)->pCopy = pNode1; |
| Abc_ObjAddFanin( pObj, pNode0 ); |
| Abc_ObjAddFanin( pNode1, pObj ); |
| Abc_ObjAssignName( pNode0, Abc_ObjName(pNode0), NULL ); |
| Abc_ObjAssignName( pNode1, Abc_ObjName(pNode1), NULL ); |
| } |
| // transfer logic level |
| // Abc_NtkForEachCi( pNtk, pObj, i ) |
| // pObj->pCopy->Level = pObj->Level; |
| // transfer the names |
| // Abc_NtkTrasferNames( pNtk, pNtkNew ); |
| Abc_ManTimeDup( pNtk, pNtkNew ); |
| if ( pNtk->vOnehots ) |
| pNtkNew->vOnehots = (Vec_Ptr_t *)Vec_VecDupInt( (Vec_Vec_t *)pNtk->vOnehots ); |
| if ( pNtk->pSeqModel ) |
| pNtkNew->pSeqModel = Abc_CexDup( pNtk->pSeqModel, Abc_NtkLatchNum(pNtk) ); |
| if ( pNtk->vObjPerm ) |
| pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm ); |
| pNtkNew->AndGateDelay = pNtk->AndGateDelay; |
| // initialize logic level of the CIs |
| if ( pNtk->AndGateDelay != 0.0 && pNtk->pManTime != NULL && pNtk->ntkType != ABC_NTK_STRASH && Type == ABC_NTK_STRASH ) |
| { |
| Abc_NtkForEachCi( pNtk, pObj, i ) |
| pObj->pCopy->Level = (int)(Abc_MaxFloat(0, Abc_NodeReadArrivalWorst(pObj)) / pNtk->AndGateDelay); |
| } |
| // check that the CI/CO/latches are copied correctly |
| assert( Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkNew) ); |
| assert( Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkNew) ); |
| assert( nLatches == Abc_NtkLatchNum(pNtkNew) ); |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Starts a new network using existing network as a model.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) |
| { |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pObj; |
| int i; |
| if ( pNtk == NULL ) |
| return NULL; |
| assert( Type != ABC_NTK_NETLIST ); |
| // start the network |
| pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); |
| pNtkNew->nConstrs = pNtk->nConstrs; |
| pNtkNew->nBarBufs = pNtk->nBarBufs; |
| // duplicate the name and the spec |
| pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); |
| pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); |
| // clean the node copy fields |
| Abc_NtkCleanCopy( pNtk ); |
| // map the constant nodes |
| if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) |
| Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); |
| // clone CIs/CIs/boxes |
| Abc_NtkForEachPi( pNtk, pObj, i ) |
| Abc_NtkDupObj( pNtkNew, pObj, 1 ); |
| Abc_NtkForEachPo( pNtk, pObj, i ) |
| Abc_NtkDupObj( pNtkNew, pObj, 1 ); |
| Abc_NtkForEachBox( pNtk, pObj, i ) |
| { |
| if ( Abc_ObjIsLatch(pObj) ) |
| continue; |
| Abc_NtkDupBox(pNtkNew, pObj, 1); |
| } |
| if ( pNtk->vObjPerm ) |
| pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm ); |
| pNtkNew->AndGateDelay = pNtk->AndGateDelay; |
| // transfer the names |
| // Abc_NtkTrasferNamesNoLatches( pNtk, pNtkNew ); |
| Abc_ManTimeDup( pNtk, pNtkNew ); |
| // check that the CI/CO/latches are copied correctly |
| assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); |
| assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Finalizes the network using the existing network as a model.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) |
| { |
| Abc_Obj_t * pObj, * pDriver, * pDriverNew; |
| int i; |
| // set the COs of the strashed network |
| Abc_NtkForEachCo( pNtk, pObj, i ) |
| { |
| pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pObj) ); |
| pDriverNew = Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj)); |
| Abc_ObjAddFanin( pObj->pCopy, pDriverNew ); |
| } |
| // duplicate timing manager |
| if ( pNtk->pManTime ) |
| Abc_NtkTimeInitialize( pNtkNew, pNtk ); |
| if ( pNtk->vPhases ) |
| Abc_NtkTransferPhases( pNtkNew, pNtk ); |
| if ( pNtk->pWLoadUsed ) |
| pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Starts a new network using existing network as a model.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkStartRead( char * pName ) |
| { |
| Abc_Ntk_t * pNtkNew; |
| // allocate the empty network |
| pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); |
| // set the specs |
| pNtkNew->pName = Extra_FileNameGeneric(pName); |
| pNtkNew->pSpec = Extra_UtilStrsav(pName); |
| if ( pNtkNew->pName == NULL || strlen(pNtkNew->pName) == 0 ) |
| { |
| ABC_FREE( pNtkNew->pName ); |
| pNtkNew->pName = Extra_UtilStrsav("unknown"); |
| } |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Finalizes the network using the existing network as a model.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ) |
| { |
| Abc_Obj_t * pBox, * pObj, * pTerm, * pNet; |
| int i; |
| if ( Abc_NtkHasBlackbox(pNtk) && Abc_NtkBoxNum(pNtk) == 0 ) |
| { |
| pBox = Abc_NtkCreateBlackbox(pNtk); |
| Abc_NtkForEachPi( pNtk, pObj, i ) |
| { |
| pTerm = Abc_NtkCreateBi(pNtk); |
| Abc_ObjAddFanin( pTerm, Abc_ObjFanout0(pObj) ); |
| Abc_ObjAddFanin( pBox, pTerm ); |
| } |
| Abc_NtkForEachPo( pNtk, pObj, i ) |
| { |
| pTerm = Abc_NtkCreateBo(pNtk); |
| Abc_ObjAddFanin( pTerm, pBox ); |
| Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pTerm ); |
| } |
| return; |
| } |
| assert( Abc_NtkIsNetlist(pNtk) ); |
| |
| // check if constant 0 net is used |
| pNet = Abc_NtkFindNet( pNtk, "1\'b0" ); |
| if ( pNet ) |
| { |
| if ( Abc_ObjFanoutNum(pNet) == 0 ) |
| Abc_NtkDeleteObj(pNet); |
| else if ( Abc_ObjFaninNum(pNet) == 0 ) |
| Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) ); |
| } |
| // check if constant 1 net is used |
| pNet = Abc_NtkFindNet( pNtk, "1\'b1" ); |
| if ( pNet ) |
| { |
| if ( Abc_ObjFanoutNum(pNet) == 0 ) |
| Abc_NtkDeleteObj(pNet); |
| else if ( Abc_ObjFaninNum(pNet) == 0 ) |
| Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) ); |
| } |
| // fix the net drivers |
| Abc_NtkFixNonDrivenNets( pNtk ); |
| |
| // reorder the CI/COs to PI/POs first |
| Abc_NtkOrderCisCos( pNtk ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Duplicate the network.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) |
| { |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pObj, * pFanin; |
| int i, k; |
| if ( pNtk == NULL ) |
| return NULL; |
| // start the network |
| pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); |
| // copy the internal nodes |
| if ( Abc_NtkIsStrash(pNtk) ) |
| { |
| // copy the AND gates |
| Abc_AigForEachAnd( pNtk, pObj, i ) |
| pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); |
| // relink the choice nodes |
| Abc_AigForEachAnd( pNtk, pObj, i ) |
| if ( pObj->pData ) |
| pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy; |
| // relink the CO nodes |
| Abc_NtkForEachCo( pNtk, pObj, i ) |
| Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); |
| // get the number of nodes before and after |
| if ( Abc_NtkNodeNum(pNtk) != Abc_NtkNodeNum(pNtkNew) ) |
| printf( "Warning: Structural hashing during duplication reduced %d nodes (this is a minor bug).\n", |
| Abc_NtkNodeNum(pNtk) - Abc_NtkNodeNum(pNtkNew) ); |
| } |
| else |
| { |
| // duplicate the nets and nodes (CIs/COs/latches already dupped) |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| if ( pObj->pCopy == NULL ) |
| Abc_NtkDupObj(pNtkNew, pObj, Abc_NtkHasBlackbox(pNtk) && Abc_ObjIsNet(pObj)); |
| // reconnect all objects (no need to transfer attributes on edges) |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) |
| Abc_ObjForEachFanin( pObj, pFanin, k ) |
| Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); |
| } |
| // duplicate the EXDC Ntk |
| if ( pNtk->pExdc ) |
| pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); |
| if ( pNtk->pExcare ) |
| pNtkNew->pExcare = Abc_NtkDup( (Abc_Ntk_t *)pNtk->pExcare ); |
| // duplicate timing manager |
| if ( pNtk->pManTime ) |
| Abc_NtkTimeInitialize( pNtkNew, pNtk ); |
| if ( pNtk->vPhases ) |
| Abc_NtkTransferPhases( pNtkNew, pNtk ); |
| if ( pNtk->pWLoadUsed ) |
| pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed ); |
| // check correctness |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); |
| pNtk->pCopy = pNtkNew; |
| return pNtkNew; |
| } |
| Abc_Ntk_t * Abc_NtkDupDfs( Abc_Ntk_t * pNtk ) |
| { |
| Vec_Ptr_t * vNodes; |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pObj, * pFanin; |
| int i, k; |
| if ( pNtk == NULL ) |
| return NULL; |
| assert( !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsNetlist(pNtk) ); |
| // start the network |
| pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); |
| // copy the internal nodes |
| vNodes = Abc_NtkDfs( pNtk, 0 ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| Abc_NtkDupObj( pNtkNew, pObj, 0 ); |
| Vec_PtrFree( vNodes ); |
| // reconnect all objects (no need to transfer attributes on edges) |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) |
| Abc_ObjForEachFanin( pObj, pFanin, k ) |
| if ( pObj->pCopy && pFanin->pCopy ) |
| Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); |
| // duplicate the EXDC Ntk |
| if ( pNtk->pExdc ) |
| pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); |
| if ( pNtk->pExcare ) |
| pNtkNew->pExcare = Abc_NtkDup( (Abc_Ntk_t *)pNtk->pExcare ); |
| // duplicate timing manager |
| if ( pNtk->pManTime ) |
| Abc_NtkTimeInitialize( pNtkNew, pNtk ); |
| if ( pNtk->vPhases ) |
| Abc_NtkTransferPhases( pNtkNew, pNtk ); |
| if ( pNtk->pWLoadUsed ) |
| pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed ); |
| // check correctness |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); |
| pNtk->pCopy = pNtkNew; |
| return pNtkNew; |
| } |
| Abc_Ntk_t * Abc_NtkDupDfsNoBarBufs( Abc_Ntk_t * pNtk ) |
| { |
| Vec_Ptr_t * vNodes; |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pObj, * pFanin; |
| int i, k; |
| if ( pNtk == NULL ) |
| return NULL; |
| assert( Abc_NtkIsLogic(pNtk) ); |
| assert( pNtk->nBarBufs2 > 0 ); |
| // start the network |
| pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); |
| // copy the internal nodes |
| vNodes = Abc_NtkDfs2( pNtk ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| if ( Abc_ObjIsBarBuf(pObj) ) |
| pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; |
| else |
| Abc_NtkDupObj( pNtkNew, pObj, 0 ); |
| Vec_PtrFree( vNodes ); |
| // reconnect all objects (no need to transfer attributes on edges) |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) && !Abc_ObjIsBarBuf(pObj) ) |
| Abc_ObjForEachFanin( pObj, pFanin, k ) |
| if ( pObj->pCopy && pFanin->pCopy ) |
| Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); |
| // duplicate the EXDC Ntk |
| if ( pNtk->pExdc ) |
| pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); |
| if ( pNtk->pExcare ) |
| pNtkNew->pExcare = Abc_NtkDup( (Abc_Ntk_t *)pNtk->pExcare ); |
| // duplicate timing manager |
| if ( pNtk->pManTime ) |
| Abc_NtkTimeInitialize( pNtkNew, pNtk ); |
| if ( pNtk->vPhases ) |
| Abc_NtkTransferPhases( pNtkNew, pNtk ); |
| if ( pNtk->pWLoadUsed ) |
| pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed ); |
| // check correctness |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); |
| pNtk->pCopy = pNtkNew; |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Duplicate the AIG while adding latches.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkRestrashWithLatches( Abc_Ntk_t * pNtk, int nLatches ) |
| { |
| Abc_Ntk_t * pNtkAig; |
| Abc_Obj_t * pObj; |
| int i; |
| assert( Abc_NtkIsStrash(pNtk) ); |
| // start the new network (constants and CIs of the old network will point to the their counterparts in the new network) |
| pNtkAig = Abc_NtkStartFromWithLatches( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG, nLatches ); |
| // restrash the nodes (assuming a topological order of the old network) |
| Abc_NtkForEachNode( pNtk, pObj, i ) |
| pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); |
| // finalize the network |
| Abc_NtkFinalize( pNtk, pNtkAig ); |
| // make sure everything is okay |
| if ( !Abc_NtkCheck( pNtkAig ) ) |
| { |
| printf( "Abc_NtkStrash: The network check has failed.\n" ); |
| Abc_NtkDelete( pNtkAig ); |
| return NULL; |
| } |
| return pNtkAig; |
| |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Duplicate the network.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkDupTransformMiter( Abc_Ntk_t * pNtk ) |
| { |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pObj, * pObj2, * pMiter; |
| int i; |
| assert( Abc_NtkIsStrash(pNtk) ); |
| // start the network |
| pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); |
| pNtkNew->nConstrs = pNtk->nConstrs; |
| pNtkNew->nBarBufs = pNtk->nBarBufs; |
| // duplicate the name and the spec |
| pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); |
| pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); |
| // clean the node copy fields |
| Abc_NtkCleanCopy( pNtk ); |
| // map the constant nodes |
| Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); |
| // clone CIs/CIs/boxes |
| Abc_NtkForEachPi( pNtk, pObj, i ) |
| Abc_NtkDupObj( pNtkNew, pObj, 1 ); |
| Abc_NtkForEachPo( pNtk, pObj, i ) |
| Abc_NtkDupObj( pNtkNew, pObj, 1 ), i++; |
| Abc_NtkForEachBox( pNtk, pObj, i ) |
| Abc_NtkDupBox( pNtkNew, pObj, 1 ); |
| // copy the AND gates |
| Abc_AigForEachAnd( pNtk, pObj, i ) |
| pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); |
| // create new miters |
| Abc_NtkForEachPo( pNtk, pObj, i ) |
| { |
| pObj2 = Abc_NtkPo( pNtk, ++i ); |
| pMiter = Abc_AigXor( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Copy(pObj2) ); |
| Abc_ObjAddFanin( pObj->pCopy, pMiter ); |
| } |
| Abc_NtkForEachLatchInput( pNtk, pObj, i ) |
| Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); |
| // cleanup |
| Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc ); |
| // check that the CI/CO/latches are copied correctly |
| assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); |
| assert( Abc_NtkPoNum(pNtk) == 2*Abc_NtkPoNum(pNtkNew) ); |
| assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) ); |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Duplicate the network.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk ) |
| { |
| char Buffer[500]; |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pObj, * pFanin; |
| int i, k; |
| assert( Abc_NtkIsLogic(pNtk) ); |
| |
| // start the network |
| pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); |
| sprintf( Buffer, "%s%s", pNtk->pName, "_2x" ); |
| pNtkNew->pName = Extra_UtilStrsav(Buffer); |
| |
| // clean the node copy fields |
| Abc_NtkCleanCopy( pNtk ); |
| // clone CIs/CIs/boxes |
| Abc_NtkForEachPi( pNtk, pObj, i ) |
| Abc_NtkDupObj( pNtkNew, pObj, 0 ); |
| Abc_NtkForEachPo( pNtk, pObj, i ) |
| Abc_NtkDupObj( pNtkNew, pObj, 0 ); |
| Abc_NtkForEachBox( pNtk, pObj, i ) |
| Abc_NtkDupBox( pNtkNew, pObj, 0 ); |
| // copy the internal nodes |
| // duplicate the nets and nodes (CIs/COs/latches already dupped) |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| if ( pObj->pCopy == NULL ) |
| Abc_NtkDupObj(pNtkNew, pObj, 0); |
| // reconnect all objects (no need to transfer attributes on edges) |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) |
| Abc_ObjForEachFanin( pObj, pFanin, k ) |
| Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); |
| |
| // clean the node copy fields |
| Abc_NtkCleanCopy( pNtk ); |
| // clone CIs/CIs/boxes |
| Abc_NtkForEachPi( pNtk, pObj, i ) |
| Abc_NtkDupObj( pNtkNew, pObj, 0 ); |
| Abc_NtkForEachPo( pNtk, pObj, i ) |
| Abc_NtkDupObj( pNtkNew, pObj, 0 ); |
| Abc_NtkForEachBox( pNtk, pObj, i ) |
| Abc_NtkDupBox( pNtkNew, pObj, 0 ); |
| // copy the internal nodes |
| // duplicate the nets and nodes (CIs/COs/latches already dupped) |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| if ( pObj->pCopy == NULL ) |
| Abc_NtkDupObj(pNtkNew, pObj, 0); |
| // reconnect all objects (no need to transfer attributes on edges) |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) |
| Abc_ObjForEachFanin( pObj, pFanin, k ) |
| Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); |
| |
| // assign names |
| Abc_NtkForEachCi( pNtk, pObj, i ) |
| { |
| Abc_ObjAssignName( Abc_NtkCi(pNtkNew, i), "1_", Abc_ObjName(pObj) ); |
| Abc_ObjAssignName( Abc_NtkCi(pNtkNew, Abc_NtkCiNum(pNtk) + i), "2_", Abc_ObjName(pObj) ); |
| } |
| Abc_NtkForEachCo( pNtk, pObj, i ) |
| { |
| Abc_ObjAssignName( Abc_NtkCo(pNtkNew, i), "1_", Abc_ObjName(pObj) ); |
| Abc_ObjAssignName( Abc_NtkCo(pNtkNew, Abc_NtkCoNum(pNtk) + i), "2_", Abc_ObjName(pObj) ); |
| } |
| Abc_NtkOrderCisCos( pNtkNew ); |
| |
| // perform the final check |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Duplicate the bottom levels of the network.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkBottom( Abc_Ntk_t * pNtk, int Level ) |
| { |
| char Buffer[500]; |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pObj, * pFanin; |
| int i, k; |
| assert( Abc_NtkIsLogic(pNtk) ); |
| assert( Abc_NtkLatchNum(pNtk) == 0 ); |
| |
| // start the network |
| pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); |
| sprintf( Buffer, "%s%s", pNtk->pName, "_bot" ); |
| pNtkNew->pName = Extra_UtilStrsav(Buffer); |
| |
| // clean the node copy fields |
| Abc_NtkCleanCopy( pNtk ); |
| // clone CIs/CIs/boxes |
| Abc_NtkForEachPi( pNtk, pObj, i ) |
| Abc_NtkDupObj( pNtkNew, pObj, 1 ); |
| |
| // copy the internal nodes |
| // duplicate the nets and nodes (CIs/COs/latches already dupped) |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| if ( pObj->pCopy == NULL && Abc_ObjIsNode(pObj) && Abc_ObjLevel(pObj) <= Level ) |
| Abc_NtkDupObj(pNtkNew, pObj, 0); |
| // reconnect all objects (no need to transfer attributes on edges) |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| Abc_ObjForEachFanin( pObj, pFanin, k ) |
| if ( pObj->pCopy && pFanin->pCopy ) |
| Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); |
| |
| // create new primary outputs |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| Abc_ObjForEachFanin( pObj, pFanin, k ) |
| if ( !pObj->pCopy && pFanin->pCopy && Abc_ObjIsNode(pFanin) ) |
| { |
| Abc_Obj_t * pNodeNew = Abc_NtkCreatePo(pNtkNew); |
| Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); |
| Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNodeNew), NULL ); |
| } |
| |
| // perform the final check |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkBottom(): Network check has failed.\n" ); |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Attaches the second network at the bottom of the first.] |
| |
| Description [Returns the first network. Deletes the second network.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom ) |
| { |
| Abc_Obj_t * pObj, * pFanin, * pBuffer; |
| Vec_Ptr_t * vNodes; |
| int i, k; |
| assert( pNtkBottom != NULL ); |
| if ( pNtkTop == NULL ) |
| return pNtkBottom; |
| // make sure the networks are combinational |
| assert( Abc_NtkPiNum(pNtkTop) == Abc_NtkCiNum(pNtkTop) ); |
| assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkCiNum(pNtkBottom) ); |
| // make sure the POs of the bottom correspond to the PIs of the top |
| assert( Abc_NtkPoNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) ); |
| assert( Abc_NtkPiNum(pNtkBottom) < Abc_NtkPiNum(pNtkTop) ); |
| // add buffers for the PIs of the top - save results in the POs of the bottom |
| Abc_NtkForEachPi( pNtkTop, pObj, i ) |
| { |
| pBuffer = Abc_NtkCreateNodeBuf( pNtkTop, NULL ); |
| Abc_ObjTransferFanout( pObj, pBuffer ); |
| Abc_NtkPo(pNtkBottom, i)->pCopy = pBuffer; |
| } |
| // remove useless PIs of the top |
| for ( i = Abc_NtkPiNum(pNtkTop) - 1; i >= Abc_NtkPiNum(pNtkBottom); i-- ) |
| Abc_NtkDeleteObj( Abc_NtkPi(pNtkTop, i) ); |
| assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) ); |
| // copy the bottom network |
| Abc_NtkForEachPi( pNtkBottom, pObj, i ) |
| Abc_NtkPi(pNtkBottom, i)->pCopy = Abc_NtkPi(pNtkTop, i); |
| // construct all nodes |
| vNodes = Abc_NtkDfs( pNtkBottom, 0 ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| { |
| Abc_NtkDupObj(pNtkTop, pObj, 0); |
| Abc_ObjForEachFanin( pObj, pFanin, k ) |
| Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); |
| } |
| Vec_PtrFree( vNodes ); |
| // connect the POs |
| Abc_NtkForEachPo( pNtkBottom, pObj, i ) |
| Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy ); |
| // delete old network |
| Abc_NtkDelete( pNtkBottom ); |
| // return the network |
| if ( !Abc_NtkCheck( pNtkTop ) ) |
| fprintf( stdout, "Abc_NtkAttachBottom(): Network check has failed.\n" ); |
| return pNtkTop; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates the network composed of one logic cone.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis ) |
| { |
| Abc_Ntk_t * pNtkNew; |
| Vec_Ptr_t * vNodes; |
| Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; |
| char Buffer[1000]; |
| int i, k; |
| |
| assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); |
| assert( Abc_ObjIsNode(pNode) || (Abc_NtkIsStrash(pNtk) && (Abc_AigNodeIsConst(pNode) || Abc_ObjIsCi(pNode))) ); |
| |
| // start the network |
| pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); |
| // set the name |
| sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); |
| pNtkNew->pName = Extra_UtilStrsav(Buffer); |
| |
| // establish connection between the constant nodes |
| if ( Abc_NtkIsStrash(pNtk) ) |
| Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); |
| |
| // collect the nodes in the TFI of the output (mark the TFI) |
| vNodes = Abc_NtkDfsNodes( pNtk, &pNode, 1 ); |
| // create the PIs |
| Abc_NtkForEachCi( pNtk, pObj, i ) |
| { |
| if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS |
| { |
| pObj->pCopy = Abc_NtkCreatePi(pNtkNew); |
| Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); |
| } |
| } |
| // add the PO corresponding to this output |
| pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); |
| Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL ); |
| // copy the nodes |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| { |
| // if it is an AIG, add to the hash table |
| if ( Abc_NtkIsStrash(pNtk) ) |
| { |
| pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); |
| } |
| else |
| { |
| Abc_NtkDupObj( pNtkNew, pObj, 0 ); |
| Abc_ObjForEachFanin( pObj, pFanin, k ) |
| Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); |
| } |
| } |
| // connect the internal nodes to the new CO |
| Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy ); |
| Vec_PtrFree( vNodes ); |
| |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates the network composed of several logic cones.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis ) |
| { |
| Abc_Ntk_t * pNtkNew; |
| Vec_Ptr_t * vNodes; |
| Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; |
| char Buffer[1000]; |
| int i, k; |
| |
| assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); |
| |
| // start the network |
| pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); |
| // set the name |
| sprintf( Buffer, "%s_part", pNtk->pName ); |
| pNtkNew->pName = Extra_UtilStrsav(Buffer); |
| |
| // establish connection between the constant nodes |
| if ( Abc_NtkIsStrash(pNtk) ) |
| Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); |
| |
| // collect the nodes in the TFI of the output (mark the TFI) |
| vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); |
| |
| // create the PIs |
| Abc_NtkForEachCi( pNtk, pObj, i ) |
| { |
| if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS |
| { |
| pObj->pCopy = Abc_NtkCreatePi(pNtkNew); |
| Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); |
| } |
| } |
| |
| // copy the nodes |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| { |
| // if it is an AIG, add to the hash table |
| if ( Abc_NtkIsStrash(pNtk) ) |
| { |
| pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); |
| } |
| else |
| { |
| Abc_NtkDupObj( pNtkNew, pObj, 0 ); |
| Abc_ObjForEachFanin( pObj, pFanin, k ) |
| Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); |
| } |
| } |
| Vec_PtrFree( vNodes ); |
| |
| // add the POs corresponding to the root nodes |
| Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) |
| { |
| // create the PO node |
| pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); |
| // connect the internal nodes to the new CO |
| if ( Abc_ObjIsCo(pObj) ) |
| Abc_ObjAddFanin( pNodeCoNew, Abc_ObjChild0Copy(pObj) ); |
| else |
| Abc_ObjAddFanin( pNodeCoNew, pObj->pCopy ); |
| // assign the name |
| Abc_ObjAssignName( pNodeCoNew, Abc_ObjName(pObj), NULL ); |
| } |
| |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkCreateConeArray(): Network check has failed.\n" ); |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds new nodes to the cone.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ) |
| { |
| Vec_Ptr_t * vNodes; |
| Abc_Obj_t * pObj; |
| int i, iNodeId; |
| |
| assert( Abc_NtkIsStrash(pNtkNew) ); |
| assert( Abc_NtkIsStrash(pNtk) ); |
| |
| // collect the nodes in the TFI of the output (mark the TFI) |
| vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); |
| |
| // establish connection between the constant nodes |
| Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); |
| |
| // create the PIs |
| Abc_NtkForEachCi( pNtk, pObj, i ) |
| { |
| // skip CIs that are not used |
| if ( !Abc_NodeIsTravIdCurrent(pObj) ) |
| continue; |
| // find the corresponding CI in the new network |
| iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); |
| if ( iNodeId == -1 ) |
| { |
| pObj->pCopy = Abc_NtkCreatePi(pNtkNew); |
| Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); |
| } |
| else |
| pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); |
| } |
| |
| // copy the nodes |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); |
| Vec_PtrFree( vNodes ); |
| |
| // do not add the COs |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkAppendToCone(): Network check has failed.\n" ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates the network composed of MFFC of one node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName ) |
| { |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; |
| Vec_Ptr_t * vCone, * vSupp; |
| char Buffer[1000]; |
| int i, k; |
| |
| assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); |
| assert( Abc_ObjIsNode(pNode) ); |
| |
| // start the network |
| pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); |
| // set the name |
| sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); |
| pNtkNew->pName = Extra_UtilStrsav(Buffer); |
| |
| // establish connection between the constant nodes |
| if ( Abc_NtkIsStrash(pNtk) ) |
| Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); |
| |
| // collect the nodes in MFFC |
| vCone = Vec_PtrAlloc( 100 ); |
| vSupp = Vec_PtrAlloc( 100 ); |
| Abc_NodeDeref_rec( pNode ); |
| Abc_NodeMffcConeSupp( pNode, vCone, vSupp ); |
| Abc_NodeRef_rec( pNode ); |
| // create the PIs |
| Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i ) |
| { |
| pObj->pCopy = Abc_NtkCreatePi(pNtkNew); |
| Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); |
| } |
| // create the PO |
| pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); |
| Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL ); |
| // copy the nodes |
| Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i ) |
| { |
| // if it is an AIG, add to the hash table |
| if ( Abc_NtkIsStrash(pNtk) ) |
| { |
| pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); |
| } |
| else |
| { |
| Abc_NtkDupObj( pNtkNew, pObj, 0 ); |
| Abc_ObjForEachFanin( pObj, pFanin, k ) |
| Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); |
| } |
| } |
| // connect the topmost node |
| Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy ); |
| Vec_PtrFree( vCone ); |
| Vec_PtrFree( vSupp ); |
| |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkCreateMffc(): Network check has failed.\n" ); |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates the miter composed of one multi-output cone.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ) |
| { |
| Vec_Ptr_t * vNodes; |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pObj, * pFinal, * pOther, * pNodePo; |
| int i; |
| |
| assert( Abc_NtkIsLogic(pNtk) ); |
| |
| // start the network |
| Abc_NtkCleanCopy( pNtk ); |
| pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); |
| pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); |
| |
| // collect the nodes in the TFI of the output |
| vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)vRoots->pArray, vRoots->nSize ); |
| // create the PIs |
| Abc_NtkForEachCi( pNtk, pObj, i ) |
| { |
| pObj->pCopy = Abc_NtkCreatePi(pNtkNew); |
| Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); |
| } |
| // copy the nodes |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| pObj->pCopy = Abc_NodeStrash( pNtkNew, pObj, 0 ); |
| Vec_PtrFree( vNodes ); |
| |
| // add the PO |
| pFinal = Abc_AigConst1( pNtkNew ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) |
| { |
| if ( Abc_ObjIsCo(pObj) ) |
| pOther = Abc_ObjFanin0(pObj)->pCopy; |
| else |
| pOther = pObj->pCopy; |
| if ( Vec_IntEntry(vValues, i) == 0 ) |
| pOther = Abc_ObjNot(pOther); |
| pFinal = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pFinal, pOther ); |
| } |
| |
| // add the PO corresponding to this output |
| pNodePo = Abc_NtkCreatePo( pNtkNew ); |
| Abc_ObjAddFanin( pNodePo, pFinal ); |
| Abc_ObjAssignName( pNodePo, "miter", NULL ); |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkCreateTarget(): Network check has failed.\n" ); |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates the network composed of one node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) |
| { |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pFanin, * pNodePo; |
| int i; |
| // start the network |
| pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); |
| pNtkNew->pName = Extra_UtilStrsav(Abc_ObjName(pNode)); |
| // add the PIs corresponding to the fanins of the node |
| Abc_ObjForEachFanin( pNode, pFanin, i ) |
| { |
| pFanin->pCopy = Abc_NtkCreatePi( pNtkNew ); |
| Abc_ObjAssignName( pFanin->pCopy, Abc_ObjName(pFanin), NULL ); |
| } |
| // duplicate and connect the node |
| pNode->pCopy = Abc_NtkDupObj( pNtkNew, pNode, 0 ); |
| Abc_ObjForEachFanin( pNode, pFanin, i ) |
| Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy ); |
| // create the only PO |
| pNodePo = Abc_NtkCreatePo( pNtkNew ); |
| Abc_ObjAddFanin( pNodePo, pNode->pCopy ); |
| Abc_ObjAssignName( pNodePo, Abc_ObjName(pNode), NULL ); |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkCreateFromNode(): Network check has failed.\n" ); |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates the network composed of one node with the given SOP.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ) |
| { |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pFanin, * pNode, * pNodePo; |
| Vec_Ptr_t * vNames; |
| int i, nVars; |
| // start the network |
| pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); |
| pNtkNew->pName = Extra_UtilStrsav("ex"); |
| // create PIs |
| Vec_PtrPush( pNtkNew->vObjs, NULL ); |
| nVars = Abc_SopGetVarNum( pSop ); |
| vNames = Abc_NodeGetFakeNames( nVars ); |
| for ( i = 0; i < nVars; i++ ) |
| Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), (char *)Vec_PtrEntry(vNames, i), NULL ); |
| Abc_NodeFreeNames( vNames ); |
| // create the node, add PIs as fanins, set the function |
| pNode = Abc_NtkCreateNode( pNtkNew ); |
| Abc_NtkForEachPi( pNtkNew, pFanin, i ) |
| Abc_ObjAddFanin( pNode, pFanin ); |
| pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, pSop ); |
| // create the only PO |
| pNodePo = Abc_NtkCreatePo(pNtkNew); |
| Abc_ObjAddFanin( pNodePo, pNode ); |
| Abc_ObjAssignName( pNodePo, "F", NULL ); |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkCreateWithNode(): Network check has failed.\n" ); |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Deletes the Ntk.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkDelete( Abc_Ntk_t * pNtk ) |
| { |
| Abc_Obj_t * pObj; |
| void * pAttrMan; |
| int TotalMemory, i; |
| // int LargePiece = (4 << ABC_NUM_STEPS); |
| if ( pNtk == NULL ) |
| return; |
| // free EXDC Ntk |
| if ( pNtk->pExdc ) |
| Abc_NtkDelete( pNtk->pExdc ); |
| if ( pNtk->pExcare ) |
| Abc_NtkDelete( (Abc_Ntk_t *)pNtk->pExcare ); |
| // dereference the BDDs |
| if ( Abc_NtkHasBdd(pNtk) ) |
| { |
| #ifdef ABC_USE_CUDD |
| Abc_NtkForEachNode( pNtk, pObj, i ) |
| Cudd_RecursiveDeref( (DdManager *)pNtk->pManFunc, (DdNode *)pObj->pData ); |
| #endif |
| } |
| // make sure all the marks are clean |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| { |
| // free large fanout arrays |
| // if ( pNtk->pMmObj && pObj->vFanouts.nCap * 4 > LargePiece ) |
| // ABC_FREE( pObj->vFanouts.pArray ); |
| // these flags should be always zero |
| // if this is not true, something is wrong somewhere |
| assert( pObj->fMarkA == 0 ); |
| assert( pObj->fMarkB == 0 ); |
| assert( pObj->fMarkC == 0 ); |
| } |
| // free the nodes |
| if ( pNtk->pMmStep == NULL ) |
| { |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| { |
| ABC_FREE( pObj->vFanouts.pArray ); |
| ABC_FREE( pObj->vFanins.pArray ); |
| } |
| } |
| if ( pNtk->pMmObj == NULL ) |
| { |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| ABC_FREE( pObj ); |
| } |
| |
| // free the arrays |
| Vec_PtrFree( pNtk->vPios ); |
| Vec_PtrFree( pNtk->vPis ); |
| Vec_PtrFree( pNtk->vPos ); |
| Vec_PtrFree( pNtk->vCis ); |
| Vec_PtrFree( pNtk->vCos ); |
| Vec_PtrFree( pNtk->vObjs ); |
| Vec_PtrFree( pNtk->vBoxes ); |
| ABC_FREE( pNtk->vTravIds.pArray ); |
| if ( pNtk->vLevelsR ) Vec_IntFree( pNtk->vLevelsR ); |
| ABC_FREE( pNtk->pModel ); |
| ABC_FREE( pNtk->pSeqModel ); |
| if ( pNtk->vSeqModelVec ) |
| Vec_PtrFreeFree( pNtk->vSeqModelVec ); |
| TotalMemory = 0; |
| TotalMemory += pNtk->pMmObj? Mem_FixedReadMemUsage(pNtk->pMmObj) : 0; |
| TotalMemory += pNtk->pMmStep? Mem_StepReadMemUsage(pNtk->pMmStep) : 0; |
| // fprintf( stdout, "The total memory allocated internally by the network = %0.2f MB.\n", ((double)TotalMemory)/(1<<20) ); |
| // free the storage |
| if ( pNtk->pMmObj ) |
| Mem_FixedStop( pNtk->pMmObj, 0 ); |
| if ( pNtk->pMmStep ) |
| Mem_StepStop ( pNtk->pMmStep, 0 ); |
| // name manager |
| Nm_ManFree( pNtk->pManName ); |
| // free the timing manager |
| if ( pNtk->pManTime ) |
| Abc_ManTimeStop( pNtk->pManTime ); |
| Vec_IntFreeP( &pNtk->vPhases ); |
| // start the functionality manager |
| if ( Abc_NtkIsStrash(pNtk) ) |
| Abc_AigFree( (Abc_Aig_t *)pNtk->pManFunc ); |
| else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) |
| Mem_FlexStop( (Mem_Flex_t *)pNtk->pManFunc, 0 ); |
| #ifdef ABC_USE_CUDD |
| else if ( Abc_NtkHasBdd(pNtk) ) |
| Extra_StopManager( (DdManager *)pNtk->pManFunc ); |
| #endif |
| else if ( Abc_NtkHasAig(pNtk) ) |
| { if ( pNtk->pManFunc ) Hop_ManStop( (Hop_Man_t *)pNtk->pManFunc ); } |
| else if ( Abc_NtkHasMapping(pNtk) ) |
| pNtk->pManFunc = NULL; |
| else if ( !Abc_NtkHasBlackbox(pNtk) ) |
| assert( 0 ); |
| // free the hierarchy |
| if ( pNtk->pDesign ) |
| { |
| Abc_DesFree( pNtk->pDesign, pNtk ); |
| pNtk->pDesign = NULL; |
| } |
| // if ( pNtk->pBlackBoxes ) |
| // Vec_IntFree( pNtk->pBlackBoxes ); |
| // free node attributes |
| Vec_PtrForEachEntry( Abc_Obj_t *, pNtk->vAttrs, pAttrMan, i ) |
| if ( pAttrMan ) |
| Vec_AttFree( (Vec_Att_t *)pAttrMan, 1 ); |
| assert( pNtk->pSCLib == NULL ); |
| Vec_IntFreeP( &pNtk->vGates ); |
| Vec_PtrFree( pNtk->vAttrs ); |
| Vec_IntFreeP( &pNtk->vNameIds ); |
| ABC_FREE( pNtk->pWLoadUsed ); |
| ABC_FREE( pNtk->pName ); |
| ABC_FREE( pNtk->pSpec ); |
| ABC_FREE( pNtk->pLutTimes ); |
| if ( pNtk->vOnehots ) |
| Vec_VecFree( (Vec_Vec_t *)pNtk->vOnehots ); |
| Vec_PtrFreeP( &pNtk->vLtlProperties ); |
| Vec_IntFreeP( &pNtk->vObjPerm ); |
| Vec_IntFreeP( &pNtk->vTopo ); |
| Vec_IntFreeP( &pNtk->vFins ); |
| ABC_FREE( pNtk ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Reads the verilog file.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ) |
| { |
| Vec_Ptr_t * vNets; |
| Abc_Obj_t * pNet, * pNode; |
| int i; |
| |
| if ( Abc_NtkNodeNum(pNtk) == 0 && Abc_NtkBoxNum(pNtk) == 0 ) |
| return; |
| |
| // special case |
| pNet = Abc_NtkFindNet( pNtk, "[_c1_]" ); |
| if ( pNet != NULL ) |
| { |
| pNode = Abc_NtkCreateNodeConst1( pNtk ); |
| Abc_ObjAddFanin( pNet, pNode ); |
| } |
| |
| // check for non-driven nets |
| vNets = Vec_PtrAlloc( 100 ); |
| Abc_NtkForEachNet( pNtk, pNet, i ) |
| { |
| if ( Abc_ObjFaninNum(pNet) > 0 ) |
| continue; |
| // add the constant 0 driver |
| pNode = Abc_NtkCreateNodeConst0( pNtk ); |
| // add the fanout net |
| Abc_ObjAddFanin( pNet, pNode ); |
| // add the net to those for which the warning will be printed |
| Vec_PtrPush( vNets, pNet ); |
| } |
| |
| // print the warning |
| if ( vNets->nSize > 0 ) |
| { |
| printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pNtk->pName ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNets, pNet, i ) |
| { |
| printf( "%s%s", (i? ", ": ""), Abc_ObjName(pNet) ); |
| if ( i == 3 ) |
| { |
| if ( Vec_PtrSize(vNets) > 3 ) |
| printf( " ..." ); |
| break; |
| } |
| } |
| printf( "\n" ); |
| } |
| Vec_PtrFree( vNets ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Converts the network to combinational.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkMakeComb( Abc_Ntk_t * pNtk, int fRemoveLatches ) |
| { |
| Abc_Obj_t * pObj; |
| int i; |
| |
| if ( Abc_NtkIsComb(pNtk) ) |
| return; |
| |
| assert( !Abc_NtkIsNetlist(pNtk) ); |
| assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); |
| |
| // detach the latches |
| // Abc_NtkForEachLatch( pNtk, pObj, i ) |
| Vec_PtrForEachEntryReverse( Abc_Obj_t *, pNtk->vBoxes, pObj, i ) |
| Abc_NtkDeleteObj( pObj ); |
| assert( Abc_NtkLatchNum(pNtk) == 0 ); |
| assert( Abc_NtkBoxNum(pNtk) == 0 ); |
| |
| // move CIs to become PIs |
| Vec_PtrClear( pNtk->vPis ); |
| Abc_NtkForEachCi( pNtk, pObj, i ) |
| { |
| if ( Abc_ObjIsBo(pObj) ) |
| { |
| pObj->Type = ABC_OBJ_PI; |
| pNtk->nObjCounts[ABC_OBJ_PI]++; |
| pNtk->nObjCounts[ABC_OBJ_BO]--; |
| } |
| Vec_PtrPush( pNtk->vPis, pObj ); |
| } |
| assert( Abc_NtkBoNum(pNtk) == 0 ); |
| |
| if ( fRemoveLatches ) |
| { |
| // remove registers |
| Vec_Ptr_t * vBos; |
| vBos = Vec_PtrAlloc( 100 ); |
| Vec_PtrClear( pNtk->vPos ); |
| Abc_NtkForEachCo( pNtk, pObj, i ) |
| if ( Abc_ObjIsBi(pObj) ) |
| Vec_PtrPush( vBos, pObj ); |
| else |
| Vec_PtrPush( pNtk->vPos, pObj ); |
| // remove COs |
| Vec_PtrFree( pNtk->vCos ); |
| pNtk->vCos = NULL; |
| // remove the BOs |
| Vec_PtrForEachEntry( Abc_Obj_t *, vBos, pObj, i ) |
| Abc_NtkDeleteObj( pObj ); |
| Vec_PtrFree( vBos ); |
| // create COs |
| pNtk->vCos = Vec_PtrDup( pNtk->vPos ); |
| // cleanup |
| if ( Abc_NtkIsLogic(pNtk) ) |
| Abc_NtkCleanup( pNtk, 0 ); |
| else if ( Abc_NtkIsStrash(pNtk) ) |
| Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); |
| else |
| assert( 0 ); |
| } |
| else |
| { |
| // move COs to become POs |
| Vec_PtrClear( pNtk->vPos ); |
| Abc_NtkForEachCo( pNtk, pObj, i ) |
| { |
| if ( Abc_ObjIsBi(pObj) ) |
| { |
| pObj->Type = ABC_OBJ_PO; |
| pNtk->nObjCounts[ABC_OBJ_PO]++; |
| pNtk->nObjCounts[ABC_OBJ_BI]--; |
| } |
| Vec_PtrPush( pNtk->vPos, pObj ); |
| } |
| } |
| assert( Abc_NtkBiNum(pNtk) == 0 ); |
| |
| if ( !Abc_NtkCheck( pNtk ) ) |
| fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Converts the network to sequential.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkMakeSeq( Abc_Ntk_t * pNtk, int nLatchesToAdd ) |
| { |
| Abc_Obj_t * pObjLi, * pObjLo, * pObj; |
| int i; |
| assert( Abc_NtkBoxNum(pNtk) == 0 ); |
| if ( !Abc_NtkIsComb(pNtk) ) |
| { |
| printf( "The network is a not a combinational one.\n" ); |
| return; |
| } |
| if ( nLatchesToAdd >= Abc_NtkPiNum(pNtk) ) |
| { |
| printf( "The number of latches is more or equal than the number of PIs.\n" ); |
| return; |
| } |
| if ( nLatchesToAdd >= Abc_NtkPoNum(pNtk) ) |
| { |
| printf( "The number of latches is more or equal than the number of POs.\n" ); |
| return; |
| } |
| |
| // move the last PIs to become CIs |
| Vec_PtrClear( pNtk->vPis ); |
| Abc_NtkForEachCi( pNtk, pObj, i ) |
| { |
| if ( i < Abc_NtkCiNum(pNtk) - nLatchesToAdd ) |
| { |
| Vec_PtrPush( pNtk->vPis, pObj ); |
| continue; |
| } |
| pObj->Type = ABC_OBJ_BO; |
| pNtk->nObjCounts[ABC_OBJ_PI]--; |
| pNtk->nObjCounts[ABC_OBJ_BO]++; |
| } |
| |
| // move the last POs to become COs |
| Vec_PtrClear( pNtk->vPos ); |
| Abc_NtkForEachCo( pNtk, pObj, i ) |
| { |
| if ( i < Abc_NtkCoNum(pNtk) - nLatchesToAdd ) |
| { |
| Vec_PtrPush( pNtk->vPos, pObj ); |
| continue; |
| } |
| pObj->Type = ABC_OBJ_BI; |
| pNtk->nObjCounts[ABC_OBJ_PO]--; |
| pNtk->nObjCounts[ABC_OBJ_BI]++; |
| } |
| |
| // create latches |
| for ( i = 0; i < nLatchesToAdd; i++ ) |
| { |
| pObjLo = Abc_NtkCi( pNtk, Abc_NtkCiNum(pNtk) - nLatchesToAdd + i ); |
| pObjLi = Abc_NtkCo( pNtk, Abc_NtkCoNum(pNtk) - nLatchesToAdd + i ); |
| pObj = Abc_NtkCreateLatch( pNtk ); |
| Abc_ObjAddFanin( pObj, pObjLi ); |
| Abc_ObjAddFanin( pObjLo, pObj ); |
| Abc_LatchSetInit0( pObj ); |
| } |
| |
| if ( !Abc_NtkCheck( pNtk ) ) |
| fprintf( stdout, "Abc_NtkMakeSeq(): Network check has failed.\n" ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Removes all POs, except one.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkMakeOnePo( Abc_Ntk_t * pNtkInit, int Output, int nRange ) |
| { |
| Abc_Ntk_t * pNtk; |
| Vec_Ptr_t * vPosLeft; |
| Vec_Ptr_t * vCosLeft; |
| Abc_Obj_t * pNodePo; |
| int i; |
| assert( !Abc_NtkIsNetlist(pNtkInit) ); |
| assert( Abc_NtkHasOnlyLatchBoxes(pNtkInit) ); |
| if ( Output < 0 || Output >= Abc_NtkPoNum(pNtkInit) ) |
| { |
| printf( "PO index is incorrect.\n" ); |
| return NULL; |
| } |
| |
| pNtk = Abc_NtkDup( pNtkInit ); |
| if ( Abc_NtkPoNum(pNtk) == 1 ) |
| return pNtk; |
| |
| if ( nRange < 1 ) |
| nRange = 1; |
| |
| // filter POs |
| vPosLeft = Vec_PtrAlloc( nRange ); |
| Abc_NtkForEachPo( pNtk, pNodePo, i ) |
| if ( i < Output || i >= Output + nRange ) |
| Abc_NtkDeleteObjPo( pNodePo ); |
| else |
| Vec_PtrPush( vPosLeft, pNodePo ); |
| // filter COs |
| vCosLeft = Vec_PtrDup( vPosLeft ); |
| for ( i = Abc_NtkPoNum(pNtk); i < Abc_NtkCoNum(pNtk); i++ ) |
| Vec_PtrPush( vCosLeft, Abc_NtkCo(pNtk, i) ); |
| // update arrays |
| Vec_PtrFree( pNtk->vPos ); pNtk->vPos = vPosLeft; |
| Vec_PtrFree( pNtk->vCos ); pNtk->vCos = vCosLeft; |
| |
| // clean the network |
| if ( Abc_NtkIsStrash(pNtk) ) |
| { |
| Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); |
| printf( "Run sequential cleanup (\"scl\") to get rid of dangling logic.\n" ); |
| } |
| else |
| { |
| printf( "Run sequential cleanup (\"st; scl\") to get rid of dangling logic.\n" ); |
| } |
| |
| if ( !Abc_NtkCheck( pNtk ) ) |
| fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" ); |
| return pNtk; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Removes POs with suppsize less than 2 and PIs without fanout.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkTrim( Abc_Ntk_t * pNtk ) |
| { |
| Abc_Obj_t * pObj; |
| int i, k, m; |
| |
| // filter POs |
| k = m = 0; |
| Abc_NtkForEachCo( pNtk, pObj, i ) |
| { |
| if ( Abc_ObjIsPo(pObj) ) |
| { |
| // remove constant nodes and PI pointers |
| if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 0 ) |
| { |
| Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); |
| if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 && !Abc_ObjIsPi(Abc_ObjFanin0(pObj)) ) |
| Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 ); |
| pNtk->vObjs->pArray[pObj->Id] = NULL; |
| pObj->Id = (1<<26)-1; |
| pNtk->nObjCounts[pObj->Type]--; |
| pNtk->nObjs--; |
| Abc_ObjRecycle( pObj ); |
| continue; |
| } |
| // remove buffers/inverters of PIs |
| if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 1 ) |
| { |
| if ( Abc_ObjIsPi(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) ) |
| { |
| Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); |
| if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 ) |
| Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 ); |
| pNtk->vObjs->pArray[pObj->Id] = NULL; |
| pObj->Id = (1<<26)-1; |
| pNtk->nObjCounts[pObj->Type]--; |
| pNtk->nObjs--; |
| Abc_ObjRecycle( pObj ); |
| continue; |
| } |
| } |
| Vec_PtrWriteEntry( pNtk->vPos, m++, pObj ); |
| } |
| Vec_PtrWriteEntry( pNtk->vCos, k++, pObj ); |
| } |
| Vec_PtrShrink( pNtk->vPos, m ); |
| Vec_PtrShrink( pNtk->vCos, k ); |
| |
| // filter PIs |
| k = m = 0; |
| Abc_NtkForEachCi( pNtk, pObj, i ) |
| { |
| if ( Abc_ObjIsPi(pObj) ) |
| { |
| if ( Abc_ObjFanoutNum(pObj) == 0 ) |
| { |
| pNtk->vObjs->pArray[pObj->Id] = NULL; |
| pObj->Id = (1<<26)-1; |
| pNtk->nObjCounts[pObj->Type]--; |
| pNtk->nObjs--; |
| Abc_ObjRecycle( pObj ); |
| continue; |
| } |
| Vec_PtrWriteEntry( pNtk->vPis, m++, pObj ); |
| } |
| Vec_PtrWriteEntry( pNtk->vCis, k++, pObj ); |
| } |
| Vec_PtrShrink( pNtk->vPis, m ); |
| Vec_PtrShrink( pNtk->vCis, k ); |
| |
| return Abc_NtkDup( pNtk ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkDropSatOutputs( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCexes, int fVerbose ) |
| { |
| Abc_Obj_t * pObj, * pConst0, * pFaninNew; |
| int i, Counter = 0; |
| assert( Vec_PtrSize(vCexes) == Abc_NtkPoNum(pNtk) ); |
| pConst0 = Abc_ObjNot( Abc_AigConst1(pNtk) ); |
| Abc_NtkForEachPo( pNtk, pObj, i ) |
| { |
| if ( Vec_PtrEntry( vCexes, i ) == NULL ) |
| continue; |
| Counter++; |
| pFaninNew = Abc_ObjNotCond( pConst0, Abc_ObjFaninC0(pObj) ); |
| Abc_ObjPatchFanin( pObj, Abc_ObjFanin0(pObj), pFaninNew ); |
| assert( Abc_ObjChild0(pObj) == pConst0 ); |
| // if a PO is driven by a latch, they have the same name... |
| // if ( Abc_ObjIsBo(pObj) ) |
| // Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pObj) ); |
| } |
| if ( fVerbose ) |
| printf( "Logic cones of %d POs have been replaced by constant 0.\n", Counter ); |
| Counter = Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); |
| // printf( "Cleanup removed %d nodes.\n", Counter ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkDropOneOutput( Abc_Ntk_t * pNtk, int iOutput, int fSkipSweep, int fUseConst1 ) |
| { |
| Abc_Obj_t * pObj, * pConst0, * pFaninNew; |
| pObj = Abc_NtkPo( pNtk, iOutput ); |
| if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pNtk) ) |
| { |
| if ( !Abc_ObjFaninC0(pObj) ^ fUseConst1 ) |
| Abc_ObjXorFaninC( pObj, 0 ); |
| return; |
| } |
| pConst0 = Abc_ObjNotCond( Abc_AigConst1(pNtk), !fUseConst1 ); |
| pFaninNew = Abc_ObjNotCond( pConst0, Abc_ObjFaninC0(pObj) ); |
| Abc_ObjPatchFanin( pObj, Abc_ObjFanin0(pObj), pFaninNew ); |
| assert( Abc_ObjChild0(pObj) == pConst0 ); |
| if ( fSkipSweep ) |
| return; |
| Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkSwapOneOutput( Abc_Ntk_t * pNtk, int iOutput ) |
| { |
| Abc_Obj_t * pObj1, * pObj2; |
| Abc_Obj_t * pChild1Old, * pChild2Old; |
| Abc_Obj_t * pChild1, * pChild2; |
| if ( iOutput == 0 ) |
| return; |
| pObj1 = Abc_NtkPo( pNtk, 0 ); |
| pObj2 = Abc_NtkPo( pNtk, iOutput ); |
| if ( Abc_ObjFanin0(pObj1) == Abc_ObjFanin0(pObj2) ) |
| { |
| if ( Abc_ObjFaninC0(pObj1) ^ Abc_ObjFaninC0(pObj2) ) |
| { |
| Abc_ObjXorFaninC( pObj1, 0 ); |
| Abc_ObjXorFaninC( pObj2, 0 ); |
| } |
| return; |
| } |
| pChild1Old = Abc_ObjChild0( pObj1 ); |
| pChild2Old = Abc_ObjChild0( pObj2 ); |
| pChild1 = Abc_ObjNotCond( pChild1Old, Abc_ObjFaninC0(pObj2) ); |
| pChild2 = Abc_ObjNotCond( pChild2Old, Abc_ObjFaninC0(pObj1) ); |
| Abc_ObjPatchFanin( pObj1, Abc_ObjFanin0(pObj1), pChild2 ); |
| Abc_ObjPatchFanin( pObj2, Abc_ObjFanin0(pObj2), pChild1 ); |
| assert( Abc_ObjChild0(pObj1) == pChild2Old ); |
| assert( Abc_ObjChild0(pObj2) == pChild1Old ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkRemovePo( Abc_Ntk_t * pNtk, int iOutput, int fRemoveConst0 ) |
| { |
| Abc_Obj_t * pObj = Abc_NtkPo(pNtk, iOutput); |
| if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pNtk) && Abc_ObjFaninC0(pObj) == fRemoveConst0 ) |
| Abc_NtkDeleteObj( pObj ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Abc_NtkReadFlopPerm( char * pFileName, int nFlops ) |
| { |
| char Buffer[1000]; |
| FILE * pFile; |
| Vec_Int_t * vFlops; |
| int iFlop = -1; |
| pFile = fopen( pFileName, "rb" ); |
| if ( pFile == NULL ) |
| { |
| printf( "Cannot open input file \"%s\".\n", pFileName ); |
| return NULL; |
| } |
| vFlops = Vec_IntAlloc( nFlops ); |
| while ( fgets( Buffer, 1000, pFile ) != NULL ) |
| { |
| if ( Buffer[0] == ' ' || Buffer[0] == '\r' || Buffer[0] == '\n' ) |
| continue; |
| iFlop = atoi( Buffer ); |
| if ( iFlop < 0 || iFlop >= nFlops ) |
| { |
| printf( "Flop ID (%d) is out of range.\n", iFlop ); |
| fclose( pFile ); |
| Vec_IntFree( vFlops ); |
| return NULL; |
| } |
| Vec_IntPush( vFlops, iFlop ); |
| } |
| fclose( pFile ); |
| if ( Vec_IntSize(vFlops) != nFlops ) |
| { |
| printf( "The number of flops read in from file (%d) is different from the number of flops in the circuit (%d).\n", iFlop, nFlops ); |
| Vec_IntFree( vFlops ); |
| return NULL; |
| } |
| return vFlops; |
| } |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, char * pFlopPermFile ) |
| { |
| Abc_Obj_t * pTemp; |
| Vec_Int_t * vInputs, * vOutputs, * vFlops, * vTemp; |
| int i, k, Entry; |
| // start permutation arrays |
| if ( pFlopPermFile ) |
| { |
| vFlops = Abc_NtkReadFlopPerm( pFlopPermFile, Abc_NtkLatchNum(pNtk) ); |
| if ( vFlops == NULL ) |
| return; |
| fInputs = 0; |
| fOutputs = 0; |
| fFlops = 0; |
| } |
| else |
| vFlops = Vec_IntStartNatural( Abc_NtkLatchNum(pNtk) ); |
| vInputs = Vec_IntStartNatural( Abc_NtkPiNum(pNtk) ); |
| vOutputs = Vec_IntStartNatural( Abc_NtkPoNum(pNtk) ); |
| // permute inputs |
| if ( fInputs ) |
| for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) |
| { |
| k = rand() % Abc_NtkPiNum(pNtk); |
| // swap indexes |
| Entry = Vec_IntEntry( vInputs, i ); |
| Vec_IntWriteEntry( vInputs, i, Vec_IntEntry(vInputs, k) ); |
| Vec_IntWriteEntry( vInputs, k, Entry ); |
| // swap PIs |
| pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPis, i ); |
| Vec_PtrWriteEntry( pNtk->vPis, i, Vec_PtrEntry(pNtk->vPis, k) ); |
| Vec_PtrWriteEntry( pNtk->vPis, k, pTemp ); |
| // swap CIs |
| pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, i ); |
| Vec_PtrWriteEntry( pNtk->vCis, i, Vec_PtrEntry(pNtk->vCis, k) ); |
| Vec_PtrWriteEntry( pNtk->vCis, k, pTemp ); |
| //printf( "Swapping PIs %d and %d.\n", i, k ); |
| } |
| // permute outputs |
| if ( fOutputs ) |
| for ( i = 0; i < Abc_NtkPoNum(pNtk); i++ ) |
| { |
| k = rand() % Abc_NtkPoNum(pNtk); |
| // swap indexes |
| Entry = Vec_IntEntry( vOutputs, i ); |
| Vec_IntWriteEntry( vOutputs, i, Vec_IntEntry(vOutputs, k) ); |
| Vec_IntWriteEntry( vOutputs, k, Entry ); |
| // swap POs |
| pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPos, i ); |
| Vec_PtrWriteEntry( pNtk->vPos, i, Vec_PtrEntry(pNtk->vPos, k) ); |
| Vec_PtrWriteEntry( pNtk->vPos, k, pTemp ); |
| // swap COs |
| pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i ); |
| Vec_PtrWriteEntry( pNtk->vCos, i, Vec_PtrEntry(pNtk->vCos, k) ); |
| Vec_PtrWriteEntry( pNtk->vCos, k, pTemp ); |
| //printf( "Swapping POs %d and %d.\n", i, k ); |
| } |
| // permute flops |
| assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); |
| if ( fFlops ) |
| for ( i = 0; i < Abc_NtkLatchNum(pNtk); i++ ) |
| { |
| k = rand() % Abc_NtkLatchNum(pNtk); |
| // swap indexes |
| Entry = Vec_IntEntry( vFlops, i ); |
| Vec_IntWriteEntry( vFlops, i, Vec_IntEntry(vFlops, k) ); |
| Vec_IntWriteEntry( vFlops, k, Entry ); |
| // swap flops |
| pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i ); |
| Vec_PtrWriteEntry( pNtk->vBoxes, i, Vec_PtrEntry(pNtk->vBoxes, k) ); |
| Vec_PtrWriteEntry( pNtk->vBoxes, k, pTemp ); |
| // swap CIs |
| pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i ); |
| Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i, Vec_PtrEntry(pNtk->vCis, Abc_NtkPiNum(pNtk)+k) ); |
| Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+k, pTemp ); |
| // swap COs |
| pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i ); |
| Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i, Vec_PtrEntry(pNtk->vCos, Abc_NtkPoNum(pNtk)+k) ); |
| Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+k, pTemp ); |
| |
| //printf( "Swapping flops %d and %d.\n", i, k ); |
| } |
| // invert arrays |
| vInputs = Vec_IntInvert( vTemp = vInputs, -1 ); |
| Vec_IntFree( vTemp ); |
| vOutputs = Vec_IntInvert( vTemp = vOutputs, -1 ); |
| Vec_IntFree( vTemp ); |
| vFlops = Vec_IntInvert( vTemp = vFlops, -1 ); |
| Vec_IntFree( vTemp ); |
| // pack the results into the output array |
| Vec_IntFreeP( &pNtk->vObjPerm ); |
| pNtk->vObjPerm = Vec_IntAlloc( Abc_NtkPiNum(pNtk) + Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) ); |
| Vec_IntForEachEntry( vInputs, Entry, i ) |
| Vec_IntPush( pNtk->vObjPerm, Entry ); |
| Vec_IntForEachEntry( vOutputs, Entry, i ) |
| Vec_IntPush( pNtk->vObjPerm, Entry ); |
| Vec_IntForEachEntry( vFlops, Entry, i ) |
| Vec_IntPush( pNtk->vObjPerm, Entry ); |
| // cleanup |
| Vec_IntFree( vInputs ); |
| Vec_IntFree( vOutputs ); |
| Vec_IntFree( vFlops ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_NodeCompareByFanoutCount( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) |
| { |
| int Diff = Abc_ObjFanoutNum(*pp2) - Abc_ObjFanoutNum(*pp1); |
| if ( Diff < 0 ) |
| return -1; |
| if ( Diff > 0 ) |
| return 1; |
| Diff = strcmp( Abc_ObjName(*pp1), Abc_ObjName(*pp2) ); |
| if ( Diff < 0 ) |
| return -1; |
| if ( Diff > 0 ) |
| return 1; |
| return 0; |
| } |
| void Abc_NtkPermutePiUsingFanout( Abc_Ntk_t * pNtk ) |
| { |
| Abc_Obj_t * pNode; int i; |
| qsort( (void *)Vec_PtrArray(pNtk->vPis), Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *), |
| (int (*)(const void *, const void *)) Abc_NodeCompareByFanoutCount ); |
| Vec_PtrClear( pNtk->vCis ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, pNtk->vPis, pNode, i ) |
| Vec_PtrPush( pNtk->vCis, pNode ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkUnpermute( Abc_Ntk_t * pNtk ) |
| { |
| Vec_Ptr_t * vTemp, * vTemp2, * vLatch; |
| int i, * pInputs, * pOutputs, * pFlops; |
| if ( pNtk->vObjPerm == NULL ) |
| { |
| printf( "Abc_NtkUnpermute(): Initial permutation is not available.\n" ); |
| return; |
| } |
| assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); |
| // get reverve permutation |
| pInputs = Vec_IntArray( pNtk->vObjPerm ); |
| pOutputs = pInputs + Abc_NtkPiNum(pNtk); |
| pFlops = pOutputs + Abc_NtkPoNum(pNtk); |
| // create new PI array |
| vTemp = Vec_PtrAlloc( Abc_NtkPiNum(pNtk) ); |
| for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) |
| Vec_PtrPush( vTemp, Abc_NtkPi(pNtk, pInputs[i]) ); |
| Vec_PtrFreeP( &pNtk->vPis ); |
| pNtk->vPis = vTemp; |
| // create new PO array |
| vTemp = Vec_PtrAlloc( Abc_NtkPoNum(pNtk) ); |
| for ( i = 0; i < Abc_NtkPoNum(pNtk); i++ ) |
| Vec_PtrPush( vTemp, Abc_NtkPo(pNtk, pOutputs[i]) ); |
| Vec_PtrFreeP( &pNtk->vPos ); |
| pNtk->vPos = vTemp; |
| // create new CI/CO arrays |
| vTemp = Vec_PtrDup( pNtk->vPis ); |
| vTemp2 = Vec_PtrDup( pNtk->vPos ); |
| vLatch = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); |
| for ( i = 0; i < Abc_NtkLatchNum(pNtk); i++ ) |
| { |
| //printf( "Setting flop %d to be %d.\n", i, pFlops[i] ); |
| Vec_PtrPush( vTemp, Abc_NtkCi(pNtk, Abc_NtkPiNum(pNtk) + pFlops[i]) ); |
| Vec_PtrPush( vTemp2, Abc_NtkCo(pNtk, Abc_NtkPoNum(pNtk) + pFlops[i]) ); |
| Vec_PtrPush( vLatch, Abc_NtkBox(pNtk, pFlops[i]) ); |
| } |
| Vec_PtrFreeP( &pNtk->vCis ); |
| Vec_PtrFreeP( &pNtk->vCos ); |
| Vec_PtrFreeP( &pNtk->vBoxes ); |
| pNtk->vCis = vTemp; |
| pNtk->vCos = vTemp2; |
| pNtk->vBoxes = vLatch; |
| // cleanup |
| Vec_IntFreeP( &pNtk->vObjPerm ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkNodeDup( Abc_Ntk_t * pNtkInit, int nLimit, int fVerbose ) |
| { |
| Vec_Ptr_t * vNodes, * vFanouts; |
| Abc_Ntk_t * pNtk; |
| Abc_Obj_t * pObj, * pObjNew, * pFanin, * pFanout; |
| int i, k; |
| pNtk = Abc_NtkDup( pNtkInit ); |
| vNodes = Vec_PtrAlloc( 100 ); |
| vFanouts = Vec_PtrAlloc( 100 ); |
| do |
| { |
| Vec_PtrClear( vNodes ); |
| Abc_NtkForEachNode( pNtk, pObj, i ) |
| if ( Abc_ObjFanoutNum(pObj) >= nLimit ) |
| Vec_PtrPush( vNodes, pObj ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| { |
| pObjNew = Abc_NtkDupObj( pNtk, pObj, 0 ); |
| Abc_ObjForEachFanin( pObj, pFanin, k ) |
| Abc_ObjAddFanin( pObjNew, pFanin ); |
| Abc_NodeCollectFanouts( pObj, vFanouts ); |
| Vec_PtrShrink( vFanouts, nLimit / 2 ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, k ) |
| Abc_ObjPatchFanin( pFanout, pObj, pObjNew ); |
| } |
| if ( fVerbose ) |
| printf( "Duplicated %d nodes.\n", Vec_PtrSize(vNodes) ); |
| } |
| while ( Vec_PtrSize(vNodes) > 0 ); |
| Vec_PtrFree( vFanouts ); |
| Vec_PtrFree( vNodes ); |
| return pNtk; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkCreateFromSops( char * pName, Vec_Ptr_t * vSops ) |
| { |
| int i, k, nObjBeg; |
| char * pSop = (char *)Vec_PtrEntry(vSops, 0); |
| Abc_Ntk_t * pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); |
| pNtk->pName = Extra_UtilStrsav( pName ); |
| for ( k = 0; pSop[k] != ' '; k++ ) |
| Abc_NtkCreatePi( pNtk ); |
| nObjBeg = Abc_NtkObjNumMax(pNtk); |
| Vec_PtrForEachEntry( char *, vSops, pSop, i ) |
| { |
| Abc_Obj_t * pObj = Abc_NtkCreateNode( pNtk ); |
| pObj->pData = Abc_SopRegister( (Mem_Flex_t*)pNtk->pManFunc, pSop ); |
| for ( k = 0; pSop[k] != ' '; k++ ) |
| Abc_ObjAddFanin( pObj, Abc_NtkCi(pNtk, k) ); |
| } |
| for ( i = 0; i < Vec_PtrSize(vSops); i++ ) |
| { |
| Abc_Obj_t * pObj = Abc_NtkObj( pNtk, nObjBeg + i ); |
| Abc_Obj_t * pObjPo = Abc_NtkCreatePo( pNtk ); |
| Abc_ObjAddFanin( pObjPo, pObj ); |
| } |
| Abc_NtkAddDummyPiNames( pNtk ); |
| Abc_NtkAddDummyPoNames( pNtk ); |
| return pNtk; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkCreateFromGias( char * pName, Vec_Ptr_t * vGias ) |
| { |
| Gia_Man_t * pGia = (Gia_Man_t *)Vec_PtrEntry(vGias, 0); |
| Abc_Ntk_t * pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); |
| Abc_Obj_t * pAbcObj, * pAbcObjPo; |
| Gia_Obj_t * pObj; int i, k; |
| pNtk->pName = Extra_UtilStrsav( pName ); |
| for ( k = 0; k < Gia_ManCiNum(pGia); k++ ) |
| Abc_NtkCreatePi( pNtk ); |
| Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) |
| { |
| assert( Gia_ManCoNum(pGia) == 1 ); |
| Gia_ManCleanValue(pGia); |
| Gia_ManForEachCi( pGia, pObj, k ) |
| pObj->Value = Abc_ObjId( Abc_NtkCi(pNtk, k) ); |
| Gia_ManForEachAnd( pGia, pObj, k ) |
| { |
| Abc_Obj_t * pAbcObj0 = Abc_NtkObj( pNtk, Gia_ObjFanin0(pObj)->Value ); |
| Abc_Obj_t * pAbcObj1 = Abc_NtkObj( pNtk, Gia_ObjFanin1(pObj)->Value ); |
| pAbcObj0 = Abc_ObjNotCond( pAbcObj0, Gia_ObjFaninC0(pObj) ); |
| pAbcObj1 = Abc_ObjNotCond( pAbcObj1, Gia_ObjFaninC1(pObj) ); |
| pAbcObj = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pAbcObj0, pAbcObj1 ); |
| pObj->Value = Abc_ObjId( pAbcObj ); |
| } |
| pObj = Gia_ManCo(pGia, 0); |
| if ( Gia_ObjFaninId0p(pGia, pObj) == 0 ) |
| pAbcObj = Abc_ObjNot( Abc_AigConst1(pNtk) ); |
| else |
| pAbcObj = Abc_NtkObj( pNtk, Gia_ObjFanin0(pObj)->Value ); |
| pAbcObj = Abc_ObjNotCond( pAbcObj, Gia_ObjFaninC0(pObj) ); |
| pAbcObjPo = Abc_NtkCreatePo( pNtk ); |
| Abc_ObjAddFanin( pAbcObjPo, pAbcObj ); |
| } |
| Abc_NtkAddDummyPiNames( pNtk ); |
| Abc_NtkAddDummyPoNames( pNtk ); |
| return pNtk; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |