| /**CFile**************************************************************** |
| |
| FileName [bacNtk.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Hierarchical word-level netlist.] |
| |
| Synopsis [Netlist manipulation.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - November 29, 2014.] |
| |
| Revision [$Id: bacNtk.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "bac.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| typedef struct Bac_Pair_t_ Bac_Pair_t; |
| struct Bac_Pair_t_ |
| { |
| Bac_ObjType_t Type; |
| char * pName; |
| char * pSymb; |
| }; |
| static const char * s_Pref = "ABC_"; |
| static Bac_Pair_t s_Types[BAC_BOX_UNKNOWN] = |
| { |
| { BAC_OBJ_NONE, "NONE", NULL }, |
| { BAC_OBJ_PI, "PI", NULL }, |
| { BAC_OBJ_PO, "PO", NULL }, |
| { BAC_OBJ_BI, "BI", NULL }, |
| { BAC_OBJ_BO, "BO", NULL }, |
| { BAC_OBJ_BOX, "BOX", NULL }, |
| |
| { BAC_BOX_CF, "CF", "o" }, |
| { BAC_BOX_CT, "CT", "o" }, |
| { BAC_BOX_CX, "CX", "o" }, |
| { BAC_BOX_CZ, "CZ", "o" }, |
| { BAC_BOX_BUF, "BUF", "ao" }, |
| { BAC_BOX_INV, "INV", "ao" }, |
| { BAC_BOX_AND, "AND", "abo" }, |
| { BAC_BOX_NAND, "NAND", "abo" }, |
| { BAC_BOX_OR, "OR", "abo" }, |
| { BAC_BOX_NOR, "NOR", "abo" }, |
| { BAC_BOX_XOR, "XOR", "abo" }, |
| { BAC_BOX_XNOR, "XNOR", "abo" }, |
| { BAC_BOX_SHARP, "SHARP", "abo" }, |
| { BAC_BOX_SHARPL, "SHARPL", "abo" }, |
| { BAC_BOX_MUX, "MUX", "cabo" }, |
| { BAC_BOX_MAJ, "MAJ", "abco" }, |
| |
| { BAC_BOX_RAND, "RAND", "ao" }, |
| { BAC_BOX_RNAND, "RNAND", "ao" }, |
| { BAC_BOX_ROR, "ROR", "ao" }, |
| { BAC_BOX_RNOR, "RNOR", "ao" }, |
| { BAC_BOX_RXOR, "RXOR", "ao" }, |
| { BAC_BOX_RXNOR, "RXNOR", "ao" }, |
| |
| { BAC_BOX_LAND, "LAND", "abo" }, |
| { BAC_BOX_LNAND, "LNAND", "abo" }, |
| { BAC_BOX_LOR, "LOR", "abo" }, |
| { BAC_BOX_LNOR, "LNOR", "abo" }, |
| { BAC_BOX_LXOR, "LXOR", "abo" }, |
| { BAC_BOX_LXNOR, "LXNOR", "abo" }, |
| |
| { BAC_BOX_NMUX, "NMUX", "abo" }, |
| { BAC_BOX_SEL, "SEL", "abo" }, |
| { BAC_BOX_PSEL, "PSEL", "iabo" }, |
| { BAC_BOX_ENC, "ENC", "ao" }, |
| { BAC_BOX_PENC, "PENC", "ao" }, |
| { BAC_BOX_DEC, "DEC", "ao" }, |
| { BAC_BOX_EDEC, "EDEC", "abo" }, |
| |
| { BAC_BOX_ADD, "ADD", "iabso" }, |
| { BAC_BOX_SUB, "SUB", "abo" }, |
| { BAC_BOX_MUL, "MUL", "abo" }, |
| { BAC_BOX_DIV, "DIV", "abo" }, |
| { BAC_BOX_MOD, "MOD", "abo" }, |
| { BAC_BOX_REM, "REM", "abo" }, |
| { BAC_BOX_POW, "POW", "abo" }, |
| { BAC_BOX_MIN, "MIN", "ao" }, |
| { BAC_BOX_ABS, "ABS", "ao" }, |
| |
| { BAC_BOX_LTHAN, "LTHAN", "iabo" }, |
| { BAC_BOX_LETHAN, "LETHAN", "abo" }, |
| { BAC_BOX_METHAN, "METHAN", "abo" }, |
| { BAC_BOX_MTHAN, "MTHAN", "abo" }, |
| { BAC_BOX_EQU, "EQU", "abo" }, |
| { BAC_BOX_NEQU, "NEQU", "abo" }, |
| |
| { BAC_BOX_SHIL, "SHIL", "abo" }, |
| { BAC_BOX_SHIR, "SHIR", "abo" }, |
| { BAC_BOX_ROTL, "ROTL", "abo" }, |
| { BAC_BOX_ROTR, "ROTR", "abo" }, |
| |
| { BAC_BOX_GATE, "GATE", "io" }, |
| { BAC_BOX_LUT, "LUT", "io" }, |
| { BAC_BOX_ASSIGN, "ASSIGN", "abo" }, |
| |
| { BAC_BOX_TRI, "TRI", "abo" }, |
| { BAC_BOX_RAM, "RAM", "eadro" }, |
| { BAC_BOX_RAMR, "RAMR", "eamo" }, |
| { BAC_BOX_RAMW, "RAMW", "eado" }, |
| { BAC_BOX_RAMWC, "RAMWC", "ceado" }, |
| { BAC_BOX_RAMBOX, "RAMBOX", "io" }, |
| |
| { BAC_BOX_LATCH, "LATCH", "dvsgq" }, |
| { BAC_BOX_LATCHRS, "LATCHRS", "dsrgq" }, |
| { BAC_BOX_DFF, "DFF", "dvscq" }, |
| { BAC_BOX_DFFRS, "DFFRS", "dsrcq" } |
| }; |
| static inline int Bac_GetTypeId( Bac_ObjType_t Type ) |
| { |
| int i; |
| for ( i = 1; i < BAC_BOX_UNKNOWN; i++ ) |
| if ( s_Types[i].Type == Type ) |
| return i; |
| return -1; |
| } |
| void Bac_ManSetupTypes( char ** pNames, char ** pSymbs ) |
| { |
| int Type; |
| for ( Type = 1; Type < BAC_BOX_UNKNOWN; Type++ ) |
| { |
| int Id = Bac_GetTypeId( (Bac_ObjType_t)Type ); |
| pNames[Type] = s_Types[Id].pName; |
| pSymbs[Type] = s_Types[Id].pSymb; |
| } |
| } |
| |
| char * Bac_NtkGenerateName( Bac_Ntk_t * p, Bac_ObjType_t Type, Vec_Int_t * vBits ) |
| { |
| static char Buffer[100]; |
| char * pTemp; int i, Bits; |
| char * pName = Bac_ManPrimName( p->pDesign, Type ); |
| char * pSymb = Bac_ManPrimSymb( p->pDesign, Type ); |
| assert( Vec_IntSize(vBits) == (int)strlen(pSymb) ); |
| sprintf( Buffer, "%s%s_", s_Pref, pName ); |
| pTemp = Buffer + strlen(Buffer); |
| Vec_IntForEachEntry( vBits, Bits, i ) |
| { |
| sprintf( pTemp, "%c%d", pSymb[i], Bits ); |
| pTemp += strlen(pTemp); |
| } |
| //Vec_IntPrint( vBits ); |
| //printf( "%s\n", Buffer ); |
| return Buffer; |
| } |
| |
| Bac_ObjType_t Bac_NameToType( char * pName ) |
| { |
| int i; |
| if ( strncmp(pName, s_Pref, strlen(s_Pref)) ) |
| return BAC_OBJ_NONE; |
| pName += strlen(s_Pref); |
| for ( i = 1; i < BAC_BOX_UNKNOWN; i++ ) |
| if ( !strncmp(pName, s_Types[i].pName, strlen(s_Types[i].pName)) ) |
| return s_Types[i].Type; |
| return BAC_OBJ_NONE; |
| } |
| Vec_Int_t * Bac_NameToRanges( char * pName ) |
| { |
| static Vec_Int_t Bits, * vBits = &Bits; |
| static int pArray[10]; |
| char * pTemp; |
| int Num = 0, Count = 0; |
| // initialize array |
| vBits->pArray = pArray; |
| vBits->nSize = 0; |
| vBits->nCap = 10; |
| // check the name |
| assert( !strncmp(pName, s_Pref, strlen(s_Pref)) ); |
| for ( pTemp = pName; *pTemp && !Bac_CharIsDigit(*pTemp); pTemp++ ); |
| assert( Bac_CharIsDigit(*pTemp) ); |
| for ( ; *pTemp; pTemp++ ) |
| { |
| if ( Bac_CharIsDigit(*pTemp) ) |
| Num = 10 * Num + *pTemp - '0'; |
| else |
| Vec_IntPush( vBits, Num ), Count += Num, Num = 0; |
| } |
| assert( Num > 0 ); |
| Vec_IntPush( vBits, Num ); Count += Num; |
| assert( Vec_IntSize(vBits) <= 10 ); |
| return vBits; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Replaces fanin iOld by iNew in all fanouts.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Bac_NtkUpdateFanout( Bac_Ntk_t * p, int iOld, int iNew ) |
| { |
| int iCo; |
| assert( Bac_ObjIsCi(p, iOld) ); |
| assert( Bac_ObjIsCi(p, iNew) ); |
| Bac_ObjForEachFanout( p, iOld, iCo ) |
| { |
| assert( Bac_ObjFanin(p, iCo) == iOld ); |
| Bac_ObjCleanFanin( p, iCo ); |
| Bac_ObjSetFanin( p, iCo, iNew ); |
| } |
| Bac_ObjSetFanout( p, iNew, Bac_ObjFanout(p, iOld) ); |
| Bac_ObjSetFanout( p, iOld, 0 ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives fanout.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Bac_NtkDeriveFanout( Bac_Ntk_t * p ) |
| { |
| int iCi, iCo; |
| assert( !Bac_NtkHasFanouts(p) ); |
| Bac_NtkStartFanouts( p ); |
| Bac_NtkForEachCo( p, iCo ) |
| { |
| assert( !Bac_ObjNextFanout(p, iCo) ); |
| iCi = Bac_ObjFanin(p, iCo); |
| if ( Bac_ObjFanout(p, iCi) ) |
| Bac_ObjSetNextFanout( p, Bac_ObjFanout(p, iCi), iCo ); |
| Bac_ObjSetFanout( p, iCi, iCo ); |
| } |
| Bac_NtkForEachCo( p, iCo ) |
| if ( !Bac_ObjNextFanout(p, iCo) ) |
| Bac_ObjSetFanout( p, Bac_ObjFanin(p, iCo), iCo ); |
| } |
| void Bac_ManDeriveFanout( Bac_Man_t * p ) |
| { |
| Bac_Ntk_t * pNtk; int i; |
| Bac_ManForEachNtk( p, pNtk, i ) |
| Bac_NtkDeriveFanout( pNtk ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Assigns word-level names.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Bac_ManAssignInternTwo( Bac_Ntk_t * p, int iNum, int nDigits, char * pPref, Vec_Int_t * vMap ) |
| { |
| char Buffer[16]; int i, NameId = 0; |
| for ( i = 0; !NameId || Vec_IntEntry(vMap, NameId); i++ ) |
| { |
| if ( i == 0 ) |
| sprintf( Buffer, "%s%0*d", pPref, nDigits, iNum ); |
| else |
| sprintf( Buffer, "%s%0*d_%d", pPref, nDigits, iNum, i ); |
| NameId = Abc_NamStrFindOrAdd( p->pDesign->pStrs, Buffer, NULL ); |
| } |
| Vec_IntWriteEntry( vMap, NameId, 1 ); |
| return NameId; |
| } |
| int Bac_ManAssignCountNames( Bac_Ntk_t * p ) |
| { |
| int i, iObj, iBox, Count = 0; |
| Bac_NtkForEachPiMain( p, iObj, i ) |
| if ( !Bac_ObjNameInt(p, iObj) ) |
| Count++; |
| Bac_NtkForEachBox( p, iBox ) |
| Bac_BoxForEachBoMain( p, iBox, iObj, i ) |
| if ( !Bac_ObjNameInt(p, iObj) ) |
| Count++; |
| return Count; |
| } |
| void Bac_ManAssignInternWordNamesNtk( Bac_Ntk_t * p, Vec_Int_t * vMap ) |
| { |
| int k, iObj, iTerm, iName = -1, iBit = -1; |
| int nDigits, nPis = 0, nPos = 0, nNames = 1; |
| // start names |
| if ( !Bac_NtkHasNames(p) ) |
| Bac_NtkStartNames(p); |
| nDigits = Abc_Base10Log( Bac_ManAssignCountNames(p) ); |
| // populate map with the currently used names |
| Bac_NtkForEachCi( p, iObj ) |
| if ( Bac_ObjNameInt(p, iObj) ) |
| Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 1 ); |
| Bac_NtkForEachBox( p, iObj ) |
| if ( Bac_ObjNameInt(p, iObj) ) |
| Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 1 ); |
| // assign CI names |
| Bac_NtkForEachCi( p, iObj ) |
| { |
| if ( Bac_ObjNameInt(p, iObj) ) |
| { |
| iName = -1; |
| iBit = -1; |
| continue; |
| } |
| if ( Bac_ObjBit(p, iObj) ) |
| { |
| assert( iBit > 0 ); |
| Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iBit++, BAC_NAME_INDEX) ); |
| } |
| else |
| { |
| //int Type = Bac_ObjType(p, iObj); |
| int Range = Bac_ObjIsPi(p, iObj) ? Bac_ObjPiRange(p, iObj) : Bac_BoxBoRange(p, iObj); |
| iName = Bac_ManAssignInternTwo( p, nNames++, nDigits, (char*)(Bac_ObjIsPi(p, iObj) ? "i":"n"), vMap ); |
| if ( Range == 1 ) |
| Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iName, BAC_NAME_BIN) ); |
| else |
| Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iName, BAC_NAME_WORD) ); |
| iBit = 1; |
| } |
| } |
| // transfer names to the interface |
| if ( Bac_NtkInfoNum(p) ) |
| { |
| for ( k = 0; k < Bac_NtkInfoNum(p); k++ ) |
| { |
| //char * pName = Bac_NtkName(p); |
| if ( Bac_NtkInfoType(p, k) == 1 ) // PI |
| { |
| iObj = Bac_NtkPi(p, nPis); |
| assert( !Bac_ObjBit(p, iObj) ); |
| assert( Bac_ObjNameType(p, iObj) <= BAC_NAME_WORD ); |
| Bac_NtkSetInfoName( p, k, Abc_Var2Lit2(Bac_ObjNameId(p, iObj), 1) ); |
| nPis += Bac_NtkInfoRange(p, k); |
| } |
| else if ( Bac_NtkInfoType(p, k) == 2 ) // PO |
| { |
| iObj = Bac_NtkPo(p, nPos); |
| assert( !Bac_ObjBit(p, iObj) ); |
| iObj = Bac_ObjFanin(p, iObj); |
| assert( Bac_ObjNameType(p, iObj) <= BAC_NAME_WORD ); |
| Bac_NtkSetInfoName( p, k, Abc_Var2Lit2(Bac_ObjNameId(p, iObj), 2) ); |
| nPos += Bac_NtkInfoRange(p, k); |
| } |
| else assert( 0 ); |
| } |
| assert( nPis == Bac_NtkPiNum(p) ); |
| assert( nPos == Bac_NtkPoNum(p) ); |
| } |
| // assign instance names |
| nDigits = Abc_Base10Log( Bac_NtkObjNum(p) ); |
| Bac_NtkForEachBox( p, iObj ) |
| if ( !Bac_ObjNameInt(p, iObj) ) |
| { |
| iName = Bac_ManAssignInternTwo( p, iObj, nDigits, "g", vMap ); |
| Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iName, BAC_NAME_BIN) ); |
| } |
| // unmark all names |
| Bac_NtkForEachPi( p, iObj, k ) |
| if ( Bac_ObjNameType(p, iObj) <= BAC_NAME_WORD ) |
| Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 0 ); |
| Bac_NtkForEachBox( p, iObj ) |
| { |
| Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 0 ); |
| Bac_BoxForEachBo( p, iObj, iTerm, k ) |
| if ( Bac_ObjNameType(p, iTerm) <= BAC_NAME_WORD ) |
| Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iTerm), 0 ); |
| } |
| // printf( "Generated %d word-level names.\n", nNames-1 ); |
| } |
| void Bac_ManAssignInternWordNames( Bac_Man_t * p ) |
| { |
| Vec_Int_t * vMap = Vec_IntStart( 2*Bac_ManObjNum(p) ); |
| Bac_Ntk_t * pNtk; int i; |
| Bac_ManForEachNtk( p, pNtk, i ) |
| Bac_ManAssignInternWordNamesNtk( pNtk, vMap ); |
| assert( Vec_IntCountEntry(vMap, 0) == Vec_IntSize(vMap) ); |
| Vec_IntFree( vMap ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Count number of objects after collapsing.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Bac_ManClpObjNum_rec( Bac_Ntk_t * p ) |
| { |
| int i, Counter = 0; |
| if ( p->Count >= 0 ) |
| return p->Count; |
| Bac_NtkForEachBox( p, i ) |
| Counter += Bac_ObjIsBoxUser(p, i) ? Bac_ManClpObjNum_rec( Bac_BoxNtk(p, i) ) + 3*Bac_BoxBoNum(p, i) : Bac_BoxSize(p, i); |
| return (p->Count = Counter); |
| } |
| int Bac_ManClpObjNum( Bac_Man_t * p ) |
| { |
| Bac_Ntk_t * pNtk; int i; |
| Bac_ManForEachNtk( p, pNtk, i ) |
| pNtk->Count = -1; |
| return Bac_NtkPioNum( Bac_ManRoot(p) ) + Bac_ManClpObjNum_rec( Bac_ManRoot(p) ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects boxes in the DFS order.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Bac_NtkDfs_rec( Bac_Ntk_t * p, int iObj, Vec_Int_t * vBoxes ) |
| { |
| int k, iFanin; |
| if ( Bac_ObjIsBo(p, iObj) == 1 ) |
| { |
| Bac_NtkDfs_rec( p, Bac_ObjFanin(p, iObj), vBoxes ); |
| return; |
| } |
| assert( Bac_ObjIsPi(p, iObj) || Bac_ObjIsBox(p, iObj) ); |
| if ( Bac_ObjCopy(p, iObj) > 0 ) // visited |
| return; |
| Bac_ObjSetCopy( p, iObj, 1 ); |
| Bac_BoxForEachFanin( p, iObj, iFanin, k ) |
| Bac_NtkDfs_rec( p, iFanin, vBoxes ); |
| Vec_IntPush( vBoxes, iObj ); |
| } |
| Vec_Int_t * Bac_NtkDfs( Bac_Ntk_t * p ) |
| { |
| int i, iObj; |
| Vec_Int_t * vBoxes = Vec_IntAlloc( Bac_NtkBoxNum(p) ); |
| Bac_NtkStartCopies( p ); // -1 = not visited; 1 = finished |
| Bac_NtkForEachPi( p, iObj, i ) |
| Bac_ObjSetCopy( p, iObj, 1 ); |
| Bac_NtkForEachPo( p, iObj, i ) |
| Bac_NtkDfs_rec( p, Bac_ObjFanin(p, iObj), vBoxes ); |
| return vBoxes; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects user boxes in the DFS order.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Bac_NtkDfsUserBoxes_rec( Bac_Ntk_t * p, int iObj, Vec_Int_t * vBoxes ) |
| { |
| int k, iFanin; |
| assert( Bac_ObjIsBoxUser(p, iObj) ); |
| if ( Bac_ObjCopy(p, iObj) == 1 ) // visited |
| return 1; |
| if ( Bac_ObjCopy(p, iObj) == 0 ) // loop |
| return 0; |
| Bac_ObjSetCopy( p, iObj, 0 ); |
| Bac_BoxForEachFanin( p, iObj, iFanin, k ) |
| if ( Bac_ObjIsBo(p, iFanin) && Bac_ObjIsBoxUser(p, Bac_ObjFanin(p, iFanin)) ) |
| if ( !Bac_NtkDfsUserBoxes_rec( p, Bac_ObjFanin(p, iFanin), vBoxes ) ) |
| return 0; |
| Vec_IntPush( vBoxes, iObj ); |
| Bac_ObjSetCopy( p, iObj, 1 ); |
| return 1; |
| } |
| int Bac_NtkDfsUserBoxes( Bac_Ntk_t * p ) |
| { |
| int iObj; |
| Bac_NtkStartCopies( p ); // -1 = not visited; 0 = on the path; 1 = finished |
| Vec_IntClear( &p->vArray ); |
| Bac_NtkForEachBoxUser( p, iObj ) |
| if ( !Bac_NtkDfsUserBoxes_rec( p, iObj, &p->vArray ) ) |
| { |
| printf( "Cyclic dependency of user boxes is detected.\n" ); |
| return 0; |
| } |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Bac_NtkCollapse_rec( Bac_Ntk_t * pNew, Bac_Ntk_t * p, Vec_Int_t * vSigs ) |
| { |
| int i, iObj, iObjNew, iTerm; |
| Bac_NtkStartCopies( p ); |
| // set PI copies |
| assert( Vec_IntSize(vSigs) == Bac_NtkPiNum(p) ); |
| Bac_NtkForEachPi( p, iObj, i ) |
| Bac_ObjSetCopy( p, iObj, Vec_IntEntry(vSigs, i) ); |
| // duplicate internal objects and create buffers for hierarchy instances |
| Bac_NtkForEachBox( p, iObj ) |
| if ( Bac_ObjIsBoxPrim( p, iObj ) ) |
| Bac_BoxDup( pNew, p, iObj ); |
| else |
| { |
| Bac_BoxForEachBo( p, iObj, iTerm, i ) |
| { |
| iObjNew = Bac_ObjAlloc( pNew, BAC_OBJ_BI, -1 ); |
| iObjNew = Bac_ObjAlloc( pNew, BAC_BOX_BUF, -1 ); // buffer |
| iObjNew = Bac_ObjAlloc( pNew, BAC_OBJ_BO, -1 ); |
| Bac_ObjSetCopy( p, iTerm, iObjNew ); |
| } |
| } |
| // duplicate user modules and connect objects |
| Bac_NtkForEachBox( p, iObj ) |
| if ( Bac_ObjIsBoxPrim( p, iObj ) ) |
| { |
| Bac_BoxForEachBi( p, iObj, iTerm, i ) |
| Bac_ObjSetFanin( pNew, Bac_ObjCopy(p, iTerm), Bac_ObjCopy(p, Bac_ObjFanin(p, iTerm)) ); |
| } |
| else |
| { |
| Vec_IntClear( vSigs ); |
| Bac_BoxForEachBi( p, iObj, iTerm, i ) |
| Vec_IntPush( vSigs, Bac_ObjCopy(p, Bac_ObjFanin(p, iTerm)) ); |
| Bac_NtkCollapse_rec( pNew, Bac_BoxNtk(p, iObj), vSigs ); |
| assert( Vec_IntSize(vSigs) == Bac_BoxBoNum(p, iObj) ); |
| Bac_BoxForEachBo( p, iObj, iTerm, i ) |
| Bac_ObjSetFanin( pNew, Bac_ObjCopy(p, iTerm)-2, Vec_IntEntry(vSigs, i) ); |
| } |
| // collect POs |
| Vec_IntClear( vSigs ); |
| Bac_NtkForEachPo( p, iObj, i ) |
| Vec_IntPush( vSigs, Bac_ObjCopy(p, Bac_ObjFanin(p, iObj)) ); |
| } |
| Bac_Man_t * Bac_ManCollapse( Bac_Man_t * p ) |
| { |
| int i, iObj; |
| Vec_Int_t * vSigs = Vec_IntAlloc( 1000 ); |
| Bac_Man_t * pNew = Bac_ManStart( p, 1 ); |
| Bac_Ntk_t * pRoot = Bac_ManRoot( p ); |
| Bac_Ntk_t * pRootNew = Bac_ManRoot( pNew ); |
| Bac_NtkAlloc( pRootNew, Bac_NtkNameId(pRoot), Bac_NtkPiNum(pRoot), Bac_NtkPoNum(pRoot), Bac_ManClpObjNum(p) ); |
| if ( Vec_IntSize(&pRoot->vInfo) ) |
| Vec_IntAppend( &pRootNew->vInfo, &pRoot->vInfo ); |
| Bac_NtkForEachPi( pRoot, iObj, i ) |
| Vec_IntPush( vSigs, Bac_ObjAlloc(pRootNew, BAC_OBJ_PI, -1) ); |
| Bac_NtkCollapse_rec( pRootNew, pRoot, vSigs ); |
| assert( Vec_IntSize(vSigs) == Bac_NtkPoNum(pRoot) ); |
| Bac_NtkForEachPo( pRoot, iObj, i ) |
| Bac_ObjAlloc( pRootNew, BAC_OBJ_PO, Vec_IntEntry(vSigs, i) ); |
| assert( Bac_NtkObjNum(pRootNew) == Bac_NtkObjNumAlloc(pRootNew) ); |
| Vec_IntFree( vSigs ); |
| // transfer PI/PO names |
| if ( Bac_NtkHasNames(pRoot) ) |
| { |
| Bac_NtkStartNames( pRootNew ); |
| Bac_NtkForEachPi( pRoot, iObj, i ) |
| Bac_ObjSetName( pRootNew, Bac_NtkPi(pRootNew, i), Bac_ObjName(pRoot, iObj) ); |
| Bac_NtkForEachPoDriver( pRoot, iObj, i ) |
| if ( !Bac_ObjIsPi(pRoot, iObj) ) |
| Bac_ObjSetName( pRootNew, Bac_ObjCopy(pRoot, iObj), Bac_ObjName(pRoot, iObj) ); |
| } |
| return pNew; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |