/**CFile**************************************************************** FileName [wlcNtk.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Network data-structure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: wlcNtk.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "wlc.h" #include "misc/vec/vecWec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // object types static char * Wlc_Names[WLC_OBJ_NUMBER+1] = { NULL, // 00: unknown "pi", // 01: primary input "po", // 02: primary output (unused) "ff", // 03: flop output "bi", // 04: flop input (unused) "ff", // 05: flop (unused) "const", // 06: constant "buf", // 07: buffer "mux", // 08: multiplexer ">>", // 09: shift right ">>>", // 10: shift right (arithmetic) "<<", // 11: shift left "<<<", // 12: shift left (arithmetic) "rotR", // 13: rotate right "rotL", // 14: rotate left "~", // 15: bitwise NOT "&", // 16: bitwise AND "|", // 17: bitwise OR "^", // 18: bitwise XOR "~&", // 19: bitwise NAND "~|", // 20: bitwise NOR "~^", // 21: bitwise NXOR "[:]", // 22: bit selection "{,}", // 23: bit concatenation "zPad", // 24: zero padding "sExt", // 25: sign extension "!", // 26: logic NOT "=>", // 27: logic implication "&&", // 28: logic AND "||", // 29: logic OR "^^", // 30: logic XOR "==", // 31: compare equal "!=", // 32: compare not equal "<", // 33: compare less ">", // 34: compare more "<=", // 35: compare less or equal ">=", // 36: compare more or equal "&", // 37: reduction AND "|", // 38: reduction OR "^", // 39: reduction XOR "~&", // 40: reduction NAND "~|", // 41: reduction NOR "~^", // 42: reduction NXOR "+", // 43: arithmetic addition "-", // 44: arithmetic subtraction "*", // 45: arithmetic multiplier "/", // 46: arithmetic division "%", // 47: arithmetic reminder "mod", // 48: arithmetic modulus "**", // 49: arithmetic power "-", // 50: arithmetic minus "sqrt", // 51: integer square root "squar", // 52: integer square "table", // 53: bit table "READ", // 54: mem read port "WRITE", // 55: mem write port "addsub", // 56: adder/subtractor "sel", // 57: selector "dec", // 58: decoder "LUT", // 59: lookup table NULL // 58: unused }; char * Wlc_ObjTypeName( Wlc_Obj_t * p ) { return p ? (p->Type < WLC_OBJ_NUMBER ? Wlc_Names[p->Type] : (char *)"out_of_bound") : (char *)"no_obj"; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_ManSetDefaultParams( Wlc_Par_t * pPars ) { memset( pPars, 0, sizeof(Wlc_Par_t) ); pPars->nBitsAdd = ABC_INFINITY; // adder bit-width pPars->nBitsMul = ABC_INFINITY; // multiplier bit-widht pPars->nBitsMux = ABC_INFINITY; // MUX bit-width pPars->nBitsFlop = ABC_INFINITY; // flop bit-width pPars->nIterMax = 1000; // the max number of iterations pPars->nLimit = ABC_INFINITY; // the max number of signals pPars->fXorOutput = 1; // XOR outputs of word-level miter pPars->fCheckClauses = 1; // Check clauses in the reloaded trace pPars->fPushClauses = 0; // Push clauses in the reloaded trace pPars->fMFFC = 1; // Refine the entire MFFC of a PPI pPars->fPdra = 0; // Use pdr -nct pPars->fLoadTrace = 1; // Load previous PDR traces pPars->fProofRefine = 0; // Use proof-based refinement pPars->fHybrid = 1; // Use a hybrid of CBR and PBR pPars->fCheckCombUnsat = 0; // Check if ABS becomes comb. unsat pPars->fAbs2 = 0; // Use UFAR style createAbs pPars->fProofUsePPI = 0; // Use PPI values in PBR pPars->fUseBmc3 = 0; // Run BMC3 in parallel pPars->fShrinkAbs = 0; // Shrink Abs with BMC pPars->fShrinkScratch= 0; // Restart pdr from scratch after shrinking pPars->fVerbose = 0; // verbose output` pPars->fPdrVerbose = 0; // show verbose PDR output } /**Function************************************************************* Synopsis [Working with models.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Wlc_Ntk_t * Wlc_NtkAlloc( char * pName, int nObjsAlloc ) { Wlc_Ntk_t * p; p = ABC_CALLOC( Wlc_Ntk_t, 1 ); p->pName = pName ? Extra_FileNameGeneric( pName ) : NULL; Vec_IntGrow( &p->vPis, 111 ); Vec_IntGrow( &p->vPos, 111 ); Vec_IntGrow( &p->vCis, 111 ); Vec_IntGrow( &p->vCos, 111 ); Vec_IntGrow( &p->vFfs, 111 ); p->pMemFanin = Mem_FlexStart(); p->nObjsAlloc = nObjsAlloc; p->pObjs = ABC_CALLOC( Wlc_Obj_t, p->nObjsAlloc ); p->iObj = 1; return p; } void Wlc_ObjSetCi( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) { assert( Wlc_ObjIsCi(pObj) ); assert( Wlc_ObjFaninNum(pObj) == 0 ); if ( Wlc_NtkPiNum(p) == Wlc_NtkCiNum(p) || pObj->Type != WLC_OBJ_PI ) { pObj->Fanins[1] = Vec_IntSize(&p->vCis); Vec_IntPush( &p->vCis, Wlc_ObjId(p, pObj) ); } else // insert in the array of CI at the end of PIs { Wlc_Obj_t * pTemp; int i; Vec_IntInsert( &p->vCis, Wlc_NtkPiNum(p), Wlc_ObjId(p, pObj) ); // other CI IDs are invalidated... naive fix! Wlc_NtkForEachCi( p, pTemp, i ) pTemp->Fanins[1] = i; } if ( pObj->Type == WLC_OBJ_PI ) Vec_IntPush( &p->vPis, Wlc_ObjId(p, pObj) ); } void Wlc_ObjSetCo( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, int fFlopInput ) { // pObj->Fanins[1] = Vec_IntSize(&p->vCos); Vec_IntPush( &p->vCos, Wlc_ObjId(p, pObj) ); if ( !fFlopInput ) Vec_IntPush( &p->vPos, Wlc_ObjId(p, pObj) ); if ( fFlopInput ) pObj->fIsFi = 1; else pObj->fIsPo = 1; } int Wlc_ObjAlloc( Wlc_Ntk_t * p, int Type, int Signed, int End, int Beg ) { Wlc_Obj_t * pObj; assert( Type != WLC_OBJ_PO && Type != WLC_OBJ_FI ); if ( p->iObj == p->nObjsAlloc ) { p->pObjs = ABC_REALLOC( Wlc_Obj_t, p->pObjs, 2 * p->nObjsAlloc ); memset( p->pObjs + p->nObjsAlloc, 0, sizeof(Wlc_Obj_t) * p->nObjsAlloc ); p->nObjsAlloc *= 2; } pObj = Wlc_NtkObj( p, p->iObj ); pObj->Type = Type; pObj->Signed = Signed; pObj->End = End; pObj->Beg = Beg; if ( Wlc_ObjIsCi(pObj) ) Wlc_ObjSetCi( p, pObj ); p->nObjs[Type]++; return p->iObj++; } int Wlc_ObjCreate( Wlc_Ntk_t * p, int Type, int Signed, int End, int Beg, Vec_Int_t * vFanins ) { int iFaninNew = Wlc_ObjAlloc( p, Type, Signed, End, Beg ); Wlc_ObjAddFanins( p, Wlc_NtkObj(p, iFaninNew), vFanins ); return iFaninNew; } char * Wlc_ObjName( Wlc_Ntk_t * p, int iObj ) { static char Buffer[100]; if ( Wlc_NtkHasNameId(p) && Wlc_ObjNameId(p, iObj) ) return Abc_NamStr( p->pManName, Wlc_ObjNameId(p, iObj) ); sprintf( Buffer, "n%d", iObj ); return Buffer; } void Wlc_ObjUpdateType( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, int Type ) { assert( pObj->Type == WLC_OBJ_NONE ); p->nObjs[pObj->Type]--; pObj->Type = Type; p->nObjs[pObj->Type]++; } void Wlc_ObjAddFanins( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Vec_Int_t * vFanins ) { assert( pObj->nFanins == 0 ); pObj->nFanins = Vec_IntSize(vFanins); // special treatment of CONST, SELECT and TABLE if ( pObj->Type == WLC_OBJ_CONST ) pObj->nFanins = 0; else if ( pObj->Type == WLC_OBJ_BIT_SELECT || pObj->Type == WLC_OBJ_TABLE ) pObj->nFanins = 1; if ( Wlc_ObjHasArray(pObj) ) pObj->pFanins[0] = (int *)Mem_FlexEntryFetch( p->pMemFanin, Vec_IntSize(vFanins) * sizeof(int) ); memcpy( Wlc_ObjFanins(pObj), Vec_IntArray(vFanins), sizeof(int) * Vec_IntSize(vFanins) ); } void Wlc_NtkFree( Wlc_Ntk_t * p ) { if ( p->pManName ) Abc_NamStop( p->pManName ); if ( p->pMemFanin ) Mem_FlexStop( p->pMemFanin, 0 ); if ( p->pMemTable ) Mem_FlexStop( p->pMemTable, 0 ); ABC_FREE( p->vPoPairs.pArray ); Vec_PtrFreeP( &p->vTables ); Vec_WrdFreeP( &p->vLutTruths ); ABC_FREE( p->vPis.pArray ); ABC_FREE( p->vPos.pArray ); ABC_FREE( p->vCis.pArray ); ABC_FREE( p->vCos.pArray ); ABC_FREE( p->vFfs.pArray ); ABC_FREE( p->vFfs2.pArray ); Vec_IntFreeP( &p->vInits ); Vec_IntFreeP( &p->vArsts ); ABC_FREE( p->vTravIds.pArray ); ABC_FREE( p->vNameIds.pArray ); ABC_FREE( p->vValues.pArray ); ABC_FREE( p->vCopies.pArray ); ABC_FREE( p->vBits.pArray ); ABC_FREE( p->vLevels.pArray ); ABC_FREE( p->vRefs.pArray ); ABC_FREE( p->pInits ); ABC_FREE( p->pObjs ); ABC_FREE( p->pName ); ABC_FREE( p->pSpec ); ABC_FREE( p ); } int Wlc_NtkMemUsage( Wlc_Ntk_t * p ) { int Mem = sizeof(Wlc_Ntk_t); Mem += 4 * p->vPis.nCap; Mem += 4 * p->vPos.nCap; Mem += 4 * p->vCis.nCap; Mem += 4 * p->vCos.nCap; Mem += 4 * p->vFfs.nCap; Mem += 4 * p->vFfs2.nCap; Mem += sizeof(Wlc_Obj_t) * p->nObjsAlloc; Mem += Abc_NamMemUsed(p->pManName); Mem += Mem_FlexReadMemUsage(p->pMemFanin); return Mem; } /**Function************************************************************* Synopsis [Assigns object levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Wlc_NtkCreateLevels_( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; int i, k, iFanin, Level, LevelMax = 0; Vec_IntFill( &p->vLevels, Wlc_NtkObjNumMax(p), 0 ); Wlc_NtkForEachObj( p, pObj, i ) { Level = 0; Wlc_ObjForEachFanin( pObj, iFanin, k ) Level = Abc_MaxInt( Level, Wlc_ObjLevelId(p, iFanin) + 1 ); Vec_IntWriteEntry( &p->vLevels, i, Level ); LevelMax = Abc_MaxInt( LevelMax, Level ); } return LevelMax; } int Wlc_NtkCreateLevelsRev( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; int i, k, iFanin, Level, LevelMax = 0; Vec_IntFill( &p->vLevels, Wlc_NtkObjNumMax(p), 0 ); Wlc_NtkForEachObjReverse( p, pObj, i ) { if ( Wlc_ObjIsCi(pObj) ) continue; Level = Wlc_ObjLevel(p, pObj) + 1; Wlc_ObjForEachFanin( pObj, iFanin, k ) Vec_IntUpdateEntry( &p->vLevels, iFanin, Level ); LevelMax = Abc_MaxInt( LevelMax, Level ); } // reverse the values Wlc_NtkForEachObj( p, pObj, i ) Vec_IntWriteEntry( &p->vLevels, i, LevelMax - Wlc_ObjLevelId(p, i) ); Wlc_NtkForEachCi( p, pObj, i ) Vec_IntWriteEntry( &p->vLevels, Wlc_ObjId(p, pObj), 0 ); //Wlc_NtkForEachObj( p, pObj, i ) // printf( "%d -> %d\n", i, Wlc_ObjLevelId(p, i) ); return LevelMax; } /**Function************************************************************* Synopsis [Assigns object levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_NtkCreateLevels_rec( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) { int k, iFanin, Level = 0, iObj = Wlc_ObjId(p, pObj); if ( Wlc_ObjIsCi(pObj) || Wlc_ObjIsFf(p, iObj) || Wlc_ObjFaninNum(pObj) == 0 || Wlc_ObjLevel(p, pObj) > 0 ) return; Wlc_ObjForEachFanin( pObj, iFanin, k ) if ( iFanin ) Wlc_NtkCreateLevels_rec( p, Wlc_NtkObj(p, iFanin) ); Wlc_ObjForEachFanin( pObj, iFanin, k ) if ( iFanin ) Level = Abc_MaxInt( Level, Wlc_ObjLevelId(p, iFanin) ); Vec_IntWriteEntry( &p->vLevels, Wlc_ObjId(p, pObj), Level + 1 ); } int Wlc_NtkCreateLevels( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; int i, LeveMax = 0; Vec_IntFill( &p->vLevels, Wlc_NtkObjNumMax(p), 0 ); Wlc_NtkForEachObj( p, pObj, i ) Wlc_NtkCreateLevels_rec( p, pObj ); Wlc_NtkForEachObj( p, pObj, i ) if ( !Wlc_ObjIsCi(pObj) && Wlc_ObjFaninNum(pObj) ) Vec_IntAddToEntry( &p->vLevels, i, 1 ); LeveMax = Vec_IntFindMax( &p->vLevels ); Wlc_NtkForEachFf2( p, pObj, i ) Vec_IntWriteEntry( &p->vLevels, Wlc_ObjId(p, pObj), LeveMax+1 ); //Wlc_NtkPrintObjects( p ); return LeveMax+1; } int Wlc_NtkRemapLevels( Wlc_Ntk_t * p, Vec_Int_t * vObjs, int nLevels ) { int i, k, iFanin, iObj, Entry, Level = 0, Res = nLevels; Vec_Int_t * vMap = Vec_IntStart( nLevels+1 ); Vec_Int_t * vUsed = Vec_IntStart( nLevels+1 ); // mark used levels Vec_IntWriteEntry( vUsed, nLevels, 1 ); Vec_IntForEachEntry( vObjs, iObj, i ) { Vec_IntWriteEntry( vUsed, Wlc_ObjLevelId(p, iObj), 1 ); Wlc_ObjForEachFanin( Wlc_NtkObj(p, iObj), iFanin, k ) if ( iFanin ) Vec_IntWriteEntry( vUsed, Wlc_ObjLevelId(p, iFanin), 1 ); } // create level map Vec_IntForEachEntry( vUsed, Entry, i ) if ( Entry ) Vec_IntWriteEntry( vMap, i, Level++ ); //printf( "Total used levels %d -> %d\n", nLevels, Level ); // remap levels Vec_IntForEachEntry( &p->vLevels, Level, i ) { if ( Vec_IntEntry(vUsed, Level) ) Vec_IntWriteEntry( &p->vLevels, i, Vec_IntEntry(vMap, Level) ); else Vec_IntWriteEntry( &p->vLevels, i, -1 ); } Res = Vec_IntEntry( vMap, nLevels ); Vec_IntFree( vUsed ); Vec_IntFree( vMap ); return Res; } /**Function************************************************************* Synopsis [Collects statistics for each side of the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_NtkCollectStats( Wlc_Ntk_t * p, int nObjs[2][WLC_OBJ_NUMBER] ) { Wlc_Obj_t * pObj; int n, i; if ( Wlc_NtkPoNum(p) != 2 ) return; for ( n = 0; n < 2; n++ ) { Wlc_NtkMarkCone( p, n, 1, 1, 0 ); Wlc_NtkForEachObj( p, pObj, i ) if ( pObj->Mark ) nObjs[n][pObj->Type]++; } Wlc_NtkCleanMarks( p ); } int Wlc_NtkCountRealPis( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; int i, Count = 0; Wlc_NtkMarkCone( p, -1, -1, 1, 0 ); Wlc_NtkForEachPi( p, pObj, i ) Count += pObj->Mark; Wlc_NtkCleanMarks( p ); return Count; } /**Function************************************************************* Synopsis [Prints distribution of operator types.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdSelectSortCost2( word * pArray, int nSize, word * pCosts ) { int i, j, best_i; for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( pCosts[j] < pCosts[best_i] ) best_i = j; ABC_SWAP( word, pArray[i], pArray[best_i] ); ABC_SWAP( word, pCosts[i], pCosts[best_i] ); } } static inline word Wlc_NtkPrintDistribMakeSign( int s, int s0, int s1 ) { return ((word)s1 << 42) | ((word)s0 << 21) | (word)s; } static inline void Wlc_NtkPrintDistribFromSign( word sss, int * s, int * s0, int * s1 ) { *s1 = (int)(sss >> 42); *s0 = (int)(sss >> 21) & 0x1FFFFF; *s = (int)sss & 0x1FFFFF; } static inline void Wlc_NtkPrintDistribAddOne( Vec_Ptr_t * vTypes, Vec_Ptr_t * vOccurs, int Type, word Sign ) { Vec_Wrd_t * vType = (Vec_Wrd_t *)Vec_PtrEntry( vTypes, Type ); Vec_Wrd_t * vOccur = (Vec_Wrd_t *)Vec_PtrEntry( vOccurs, Type ); word Entry; int i; Vec_WrdForEachEntry( vType, Entry, i ) if ( Entry == Sign ) { Vec_WrdAddToEntry( vOccur, i, 1 ); return; } Vec_WrdPush( vType, Sign ); Vec_WrdPush( vOccur, 1 ); } void Wlc_NtkPrintDistribSortOne( Vec_Ptr_t * vTypes, Vec_Ptr_t * vOccurs, int Type ) { Vec_Wrd_t * vType = (Vec_Wrd_t *)Vec_PtrEntry( vTypes, Type ); Vec_Wrd_t * vOccur = (Vec_Wrd_t *)Vec_PtrEntry( vOccurs, Type ); Vec_WrdSelectSortCost2( Vec_WrdArray(vType), Vec_WrdSize(vType), Vec_WrdArray(vOccur) ); Vec_WrdReverseOrder( vType ); Vec_WrdReverseOrder( vOccur ); } void Wlc_NtkPrintDistrib( Wlc_Ntk_t * p, int fTwoSides, int fVerbose ) { int nObjs[2][WLC_OBJ_NUMBER] = {{0}}; // counter of objects of each type Wlc_Obj_t * pObj, * pObjRange = NULL; int nCountRange = 0; Vec_Ptr_t * vTypes, * vOccurs; Vec_Int_t * vAnds = Vec_IntStart( WLC_OBJ_NUMBER ); word Sign = 0; int i, k, s, s0, s1; if ( Wlc_NtkPoNum(p) != 2 ) fTwoSides = 0; if ( fTwoSides ) Wlc_NtkCollectStats( p, nObjs ); // allocate statistics arrays vTypes = Vec_PtrStart( WLC_OBJ_NUMBER ); vOccurs = Vec_PtrStart( WLC_OBJ_NUMBER ); for ( i = 0; i < WLC_OBJ_NUMBER; i++ ) Vec_PtrWriteEntry( vTypes, i, Vec_WrdAlloc(16) ); for ( i = 0; i < WLC_OBJ_NUMBER; i++ ) Vec_PtrWriteEntry( vOccurs, i, Vec_WrdAlloc(16) ); // add nodes Wlc_NtkForEachObj( p, pObj, i ) { // char * pName = Wlc_ObjName(p, i); if ( Wlc_ObjSign(pObj) > 0x1FFFFF ) printf( "Object %6d has range %d, which is reduced to %d in the statistics.\n", i, Wlc_ObjRange(pObj), Wlc_ObjRange(pObj) & 0xFFFFF ); if ( pObj->Beg ) { if ( pObjRange == NULL ) pObjRange = pObj; nCountRange++; } // 0-input types if ( Wlc_ObjIsCi(pObj) || pObj->Type == WLC_OBJ_CONST || pObj->Type == WLC_OBJ_BIT_CONCAT ) Sign = Wlc_NtkPrintDistribMakeSign( Wlc_ObjSign(pObj), 0, 0 ); // 1-input types else if ( pObj->Type == WLC_OBJ_BUF || pObj->Type == WLC_OBJ_BIT_SELECT || pObj->Type == WLC_OBJ_TABLE || pObj->Type == WLC_OBJ_BIT_ZEROPAD || pObj->Type == WLC_OBJ_BIT_SIGNEXT || pObj->Type == WLC_OBJ_BIT_NOT || pObj->Type == WLC_OBJ_LOGIC_NOT || pObj->Type == WLC_OBJ_ARI_MINUS ) Sign = Wlc_NtkPrintDistribMakeSign( Wlc_ObjSign(pObj), Wlc_ObjSign(Wlc_ObjFanin0(p, pObj)), 0 ); // 2-input types (including MUX) else if ( Wlc_ObjFaninNum(pObj) == 0 ) printf( "Object %d with name \"%s\" has type 0. Looks like it was declared by not defined...\n", i, Wlc_ObjName(p, i) ); else if ( Wlc_ObjFaninNum(pObj) == 1 ) Sign = Wlc_NtkPrintDistribMakeSign( Wlc_ObjSign(pObj), Wlc_ObjSign(Wlc_ObjFanin0(p, pObj)), 0 ); else { assert( Wlc_ObjFaninNum(pObj) >= 2 ); Sign = Wlc_NtkPrintDistribMakeSign( Wlc_ObjSign(pObj), Wlc_ObjFaninId(pObj, 0) ? Wlc_ObjSign(Wlc_ObjFanin0(p, pObj)) : 0, Wlc_ObjFaninId(pObj, 1) ? Wlc_ObjSign(Wlc_ObjFanin1(p, pObj)) : 0 ); } // add to storage Wlc_NtkPrintDistribAddOne( vTypes, vOccurs, pObj->Type, Sign ); // count the number of AIG nodes if ( pObj->Type == WLC_OBJ_MUX ) Vec_IntAddToEntry( vAnds, WLC_OBJ_MUX, 3 * Wlc_ObjRange(pObj) * (Wlc_ObjFaninNum(pObj) - 2) ); else if ( pObj->Type == WLC_OBJ_SHIFT_R ) Vec_IntAddToEntry( vAnds, WLC_OBJ_SHIFT_R, Abc_MinInt(Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Abc_Base2Log(Wlc_ObjRange(pObj))) * 3 ); else if ( pObj->Type == WLC_OBJ_SHIFT_RA ) Vec_IntAddToEntry( vAnds, WLC_OBJ_SHIFT_RA, Wlc_ObjRange(pObj) * Abc_MinInt(Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Abc_Base2Log(Wlc_ObjRange(pObj))) * 3 ); else if ( pObj->Type == WLC_OBJ_SHIFT_L ) Vec_IntAddToEntry( vAnds, WLC_OBJ_SHIFT_L, Wlc_ObjRange(pObj) * Abc_MinInt(Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Abc_Base2Log(Wlc_ObjRange(pObj))) * 3 ); else if ( pObj->Type == WLC_OBJ_SHIFT_LA ) Vec_IntAddToEntry( vAnds, WLC_OBJ_SHIFT_LA, Wlc_ObjRange(pObj) * Abc_MinInt(Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Abc_Base2Log(Wlc_ObjRange(pObj))) * 3 ); else if ( pObj->Type == WLC_OBJ_ROTATE_R ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ROTATE_R, Wlc_ObjRange(pObj) * Abc_MinInt(Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Abc_Base2Log(Wlc_ObjRange(pObj))) * 3 ); else if ( pObj->Type == WLC_OBJ_ROTATE_L ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ROTATE_L, Wlc_ObjRange(pObj) * Abc_MinInt(Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Abc_Base2Log(Wlc_ObjRange(pObj))) * 3 ); else if ( pObj->Type == WLC_OBJ_BIT_NOT ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_NOT, 0 ); else if ( pObj->Type == WLC_OBJ_BIT_AND ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_AND, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_OR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_OR, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_XOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_XOR, 3 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_NAND ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_NAND, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_NOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_NOR, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_NXOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_NXOR, 3 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_SELECT ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_SELECT, 0 ); else if ( pObj->Type == WLC_OBJ_BIT_CONCAT ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_CONCAT, 0 ); else if ( pObj->Type == WLC_OBJ_BIT_ZEROPAD ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_ZEROPAD, 0 ); else if ( pObj->Type == WLC_OBJ_BIT_SIGNEXT ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_SIGNEXT, 0 ); else if ( pObj->Type == WLC_OBJ_LOGIC_NOT ) Vec_IntAddToEntry( vAnds, WLC_OBJ_LOGIC_NOT, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_LOGIC_IMPL ) Vec_IntAddToEntry( vAnds, WLC_OBJ_LOGIC_IMPL, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) + Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_LOGIC_AND ) Vec_IntAddToEntry( vAnds, WLC_OBJ_LOGIC_AND, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) + Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_LOGIC_OR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_LOGIC_OR, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) + Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_LOGIC_XOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_LOGIC_XOR, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) + Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)) + 1 ); else if ( pObj->Type == WLC_OBJ_COMP_EQU ) Vec_IntAddToEntry( vAnds, WLC_OBJ_COMP_EQU, 4 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_COMP_NOTEQU ) Vec_IntAddToEntry( vAnds, WLC_OBJ_COMP_NOTEQU, 4 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_COMP_LESS ) Vec_IntAddToEntry( vAnds, WLC_OBJ_COMP_LESS, 6 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 6 ); else if ( pObj->Type == WLC_OBJ_COMP_MORE ) Vec_IntAddToEntry( vAnds, WLC_OBJ_COMP_MORE, 6 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 6 ); else if ( pObj->Type == WLC_OBJ_COMP_LESSEQU ) Vec_IntAddToEntry( vAnds, WLC_OBJ_COMP_LESSEQU, 6 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 6 ); else if ( pObj->Type == WLC_OBJ_COMP_MOREEQU ) Vec_IntAddToEntry( vAnds, WLC_OBJ_COMP_MOREEQU, 6 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 6 ); else if ( pObj->Type == WLC_OBJ_REDUCT_AND ) Vec_IntAddToEntry( vAnds, WLC_OBJ_REDUCT_AND, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_REDUCT_OR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_REDUCT_OR, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_REDUCT_XOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_REDUCT_XOR, 3 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 3 ); else if ( pObj->Type == WLC_OBJ_REDUCT_NAND ) Vec_IntAddToEntry( vAnds, WLC_OBJ_REDUCT_NAND, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_REDUCT_NOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_REDUCT_NOR, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_REDUCT_NXOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_REDUCT_NXOR, 3 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 3 ); else if ( pObj->Type == WLC_OBJ_ARI_ADD ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_ADD, 9 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_ARI_SUB ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_SUB, 9 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_ARI_MULTI ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_MULTI, 9 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) * Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_ARI_DIVIDE ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_DIVIDE, 13 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 19 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) + 10 ); else if ( pObj->Type == WLC_OBJ_ARI_REM ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_REM, 13 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 7 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 2 ); else if ( pObj->Type == WLC_OBJ_ARI_MODULUS ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_MODULUS, 13 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 7 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 2 ); else if ( pObj->Type == WLC_OBJ_ARI_POWER ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_POWER, 10 * (int)pow((double)Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)),(double)Wlc_ObjRange(Wlc_ObjFanin0(p, pObj))) ); else if ( pObj->Type == WLC_OBJ_ARI_MINUS ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_MINUS, 4 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_ARI_SQRT ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_SQRT, 11 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) / 8 + 5 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) / 2 - 5 ); else if ( pObj->Type == WLC_OBJ_ARI_SQUARE ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_SQUARE, 5 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) * Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)) ); } if ( nCountRange && Vec_IntSize(&p->vNameIds) > 0 ) { printf( "Warning: %d objects of the design have non-zero-based ranges.\n", nCountRange ); printf( "In particular, object %6d with name \"%s\" has range %d=[%d:%d]\n", Wlc_ObjId(p, pObjRange), Abc_NamStr(p->pManName, Wlc_ObjNameId(p, Wlc_ObjId(p, pObjRange))), Wlc_ObjRange(pObjRange), pObjRange->End, pObjRange->Beg ); } // print by occurrence printf( "ID : name occurrence%s and2 (occurrence)=. ...\n", fTwoSides ? " Left Share Right":"" ); for ( i = 0; i < WLC_OBJ_NUMBER; i++ ) { Vec_Wrd_t * vType = (Vec_Wrd_t *)Vec_PtrEntry( vTypes, i ); Vec_Wrd_t * vOccur = (Vec_Wrd_t *)Vec_PtrEntry( vOccurs, i ); if ( p->nObjs[i] == 0 ) continue; printf( "%2d : %-8s %6d", i, Wlc_Names[i], p->nObjs[i] ); if ( fTwoSides ) { int nTotal = i == WLC_OBJ_PI ? Wlc_NtkCountRealPis(p) : p->nObjs[i]; printf( " " ); printf( "%6d", nObjs[0][i] ); printf( "%6d", nObjs[0][i]+nObjs[1][i]-nTotal ); printf( "%6d", nObjs[1][i] ); } printf( "%8d ", Vec_IntEntry(vAnds, i) ); // sort by occurence Wlc_NtkPrintDistribSortOne( vTypes, vOccurs, i ); Vec_WrdForEachEntry( vType, Sign, k ) { Wlc_NtkPrintDistribFromSign( Sign, &s, &s0, &s1 ); if ( ((k % 6) == 5 && s1) || ((k % 8) == 7 && !s1) ) { printf( "\n " ); if ( fTwoSides ) printf( " " ); } printf( "(%d)", (int)Vec_WrdEntry( vOccur, k ) ); printf( "%s%d", Abc_LitIsCompl(s)?"-":"", Abc_Lit2Var(s) ); if ( s0 ) printf( "=%s%d", Abc_LitIsCompl(s0)?"-":"", Abc_Lit2Var(s0) ); if ( s1 ) printf( ".%s%d", Abc_LitIsCompl(s1)?"-":"", Abc_Lit2Var(s1) ); printf( " " ); } printf( "\n" ); } Vec_VecFree( (Vec_Vec_t *)vTypes ); Vec_VecFree( (Vec_Vec_t *)vOccurs ); Vec_IntFree( vAnds ); } void Wlc_NtkPrintNode( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) { printf( "%8d : ", Wlc_ObjId(p, pObj) ); if ( Vec_IntSize(&p->vLevels) ) printf( "Lev = %2d ", Vec_IntEntry(&p->vLevels, Wlc_ObjId(p,pObj)) ); printf( "%6d%s = ", Wlc_ObjRange(pObj), Wlc_ObjIsSigned(pObj) ? "s" : " " ); if ( pObj->Type == WLC_OBJ_PI ) { printf( " PI : %-12s\n", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) ); return; } if ( pObj->Type == WLC_OBJ_FO ) { printf( " FO : %-12s = %-12s\n", Wlc_ObjName(p, Wlc_ObjId(p, pObj)), Wlc_ObjName(p, Wlc_ObjId(p, Wlc_ObjFo2Fi(p, pObj))) ); return; } if ( pObj->Type != WLC_OBJ_CONST && Wlc_ObjFaninNum(pObj) == 0 ) { printf( "Unknown object without fanins : %-12s\n", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) ); return; } if ( pObj->Type != WLC_OBJ_CONST ) { printf( "%6d%s %5s ", Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Wlc_ObjIsSigned(Wlc_ObjFanin0(p, pObj)) ? "s" : " ", Wlc_Names[(int)pObj->Type] ); if ( Wlc_ObjFaninNum(pObj) > 1 ) printf( "%6d%s ", Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)), Wlc_ObjIsSigned(Wlc_ObjFanin1(p, pObj)) ? "s" : " " ); else printf( " " ); if ( Wlc_ObjFaninNum(pObj) > 2 ) printf( "%6d%s ", Wlc_ObjRange(Wlc_ObjFanin2(p, pObj)), Wlc_ObjIsSigned(Wlc_ObjFanin2(p, pObj)) ? "s" : " " ); else printf( " " ); } else printf( " " ); printf( " : " ); printf( "%-12s", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) ); if ( pObj->Type == WLC_OBJ_CONST ) { printf( " = %d\'%sh", Wlc_ObjRange(pObj), Wlc_ObjIsSigned(pObj) ? "s":"" ); if ( pObj->fXConst ) { int k; for ( k = 0; k < (Wlc_ObjRange(pObj) + 3) / 4; k++ ) printf( "x" ); } else Abc_TtPrintHexArrayRev( stdout, (word *)Wlc_ObjConstValue(pObj), (Wlc_ObjRange(pObj) + 3) / 4 ); } else { printf( " = %-12s %5s ", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)), Wlc_Names[(int)pObj->Type] ); if ( Wlc_ObjFaninNum(pObj) > 1 ) printf( "%-12s ", Wlc_ObjName(p, Wlc_ObjFaninId1(pObj)) ); else printf( " " ); if ( Wlc_ObjFaninNum(pObj) > 2 ) printf( "%-12s ", Wlc_ObjName(p, Wlc_ObjFaninId2(pObj)) ); } printf( "\n" ); } void Wlc_NtkPrintNodeArray( Wlc_Ntk_t * p, Vec_Int_t * vArray ) { Wlc_Obj_t * pObj; int i; Wlc_NtkForEachObjVec( vArray, p, pObj, i ) Wlc_NtkPrintNode( p, pObj ); } void Wlc_NtkPrintNodes( Wlc_Ntk_t * p, int Type ) { Wlc_Obj_t * pObj; int i, Counter = 0; printf( "Operation %s\n", Wlc_Names[Type] ); Wlc_NtkForEachObj( p, pObj, i ) { if ( (int)pObj->Type != Type ) continue; printf( "%8d :", Counter++ ); Wlc_NtkPrintNode( p, pObj ); } } void Wlc_NtkPrintStats( Wlc_Ntk_t * p, int fDistrib, int fTwoSides, int fVerbose ) { int i; printf( "%-20s : ", p->pName ); printf( "PI = %4d ", Wlc_NtkCountRealPis(p) ); //Wlc_NtkPiNum(p) ); printf( "PO = %4d ", Wlc_NtkPoNum(p) ); printf( "FF = %4d ", Wlc_NtkFfNum(p) ); printf( "Obj = %6d ", Wlc_NtkObjNum(p) - Wlc_NtkPiNum(p) - Wlc_NtkPoNum(p) - Wlc_NtkFfNum(p) ); printf( "Mem = %.3f MB", 1.0*Wlc_NtkMemUsage(p)/(1<<20) ); printf( "\n" ); if ( fDistrib ) { Wlc_NtkPrintDistrib( p, fTwoSides, fVerbose ); return; } if ( !fVerbose ) return; printf( "Node type statistics:\n" ); for ( i = 1; i < WLC_OBJ_NUMBER; i++ ) { if ( !p->nObjs[i] ) continue; if ( p->nAnds[0] && p->nAnds[i] ) printf( "%2d : %-8s %6d %7.2f %%\n", i, Wlc_Names[i], p->nObjs[i], 100.0*p->nAnds[i]/p->nAnds[0] ); else printf( "%2d : %-8s %6d\n", i, Wlc_Names[i], p->nObjs[i] ); } } void Wlc_NtkPrintObjects( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; int i; Wlc_NtkForEachObj( p, pObj, i ) Wlc_NtkPrintNode( p, pObj ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_NtkTransferNames( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p ) { int i; assert( !Wlc_NtkHasCopy(pNew) && Wlc_NtkHasCopy(p) ); assert( !Wlc_NtkHasNameId(pNew) && Wlc_NtkHasNameId(p) ); assert( pNew->pManName == NULL && p->pManName != NULL ); Wlc_NtkCleanNameId( pNew ); for ( i = 0; i < p->nObjsAlloc; i++ ) if ( Wlc_ObjCopy(p, i) > 0 && i < Vec_IntSize(&p->vNameIds) && Wlc_ObjNameId(p, i) ) Wlc_ObjSetNameId( pNew, Wlc_ObjCopy(p, i), Wlc_ObjNameId(p, i) ); pNew->pManName = p->pManName; p->pManName = NULL; Vec_IntErase( &p->vNameIds ); // transfer table pNew->pMemTable = p->pMemTable; p->pMemTable = NULL; pNew->vTables = p->vTables; p->vTables = NULL; } char * Wlc_NtkNewName( Wlc_Ntk_t * p, int iCoId, int fSeq ) { static char pBuffer[1000]; sprintf( pBuffer, "%s_o%d_%s", p->pName, iCoId, fSeq ? "seq": "comb" ); return pBuffer; } /**Function************************************************************* Synopsis [Reduce init vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Wlc_ReduceMarkedInitVec( Wlc_Ntk_t * p, Vec_Int_t * vInit ) { Vec_Int_t * vInitNew = Vec_IntDup( vInit ); Wlc_Obj_t * pObj; int i, k = 0; assert( Vec_IntSize(vInit) == Wlc_NtkCiNum(p) - Wlc_NtkPiNum(p) ); Wlc_NtkForEachCi( p, pObj, i ) if ( !Wlc_ObjIsPi(pObj) && pObj->Mark ) Vec_IntWriteEntry( vInitNew, k++, Vec_IntEntry(vInit, i - Wlc_NtkPiNum(p)) ); Vec_IntShrink( vInitNew, k ); return vInitNew; } char * Wlc_ReduceMarkedInitStr( Wlc_Ntk_t * p, char * pInit ) { char * pInitNew = Abc_UtilStrsav( pInit ); Wlc_Obj_t * pObj; int i, b, nBits = 0, k = 0; Wlc_NtkForEachCi( p, pObj, i ) { if ( !Wlc_ObjIsPi(pObj) && pObj->Mark ) for ( b = 0; b < Wlc_ObjRange(pObj); b++ ) pInitNew[k++] = pInitNew[nBits+b]; if ( !Wlc_ObjIsPi(pObj) ) nBits += Wlc_ObjRange(pObj); } pInitNew[k] = '\0'; assert( nBits == (int)strlen(pInit) ); return pInitNew; } /**Function************************************************************* Synopsis [Duplicates the network in a topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_ObjCollectCopyFanins( Wlc_Ntk_t * p, int iObj, Vec_Int_t * vFanins ) { int i, iFanin; Wlc_Obj_t * pObj = Wlc_NtkObj( p, iObj ); Vec_IntClear( vFanins ); Wlc_ObjForEachFanin( pObj, iFanin, i ) Vec_IntPush( vFanins, Wlc_ObjCopy(p, iFanin) ); // special treatment of CONST and SELECT if ( pObj->Type == WLC_OBJ_CONST ) { int * pInts = Wlc_ObjConstValue( pObj ); int nInts = Abc_BitWordNum( Wlc_ObjRange(pObj) ); for ( i = 0; i < nInts; i++ ) Vec_IntPush( vFanins, pInts[i] ); } else if ( pObj->Type == WLC_OBJ_BIT_SELECT ) { assert( Vec_IntSize(vFanins) == 1 ); Vec_IntPushTwo( vFanins, Wlc_ObjRangeEnd(pObj), Wlc_ObjRangeBeg(pObj) ); } else if ( pObj->Type == WLC_OBJ_TABLE ) { assert( Vec_IntSize(vFanins) == 1 ); Vec_IntPush( vFanins, pObj->Fanins[1] ); } } int Wlc_ObjDup( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p, int iObj, Vec_Int_t * vFanins ) { Wlc_Obj_t * pObj = Wlc_NtkObj( p, iObj ); int iFaninNew = Wlc_ObjAlloc( pNew, pObj->Type, Wlc_ObjIsSigned(pObj), pObj->End, pObj->Beg ); Wlc_Obj_t * pObjNew = Wlc_NtkObj(pNew, iFaninNew); Wlc_ObjCollectCopyFanins( p, iObj, vFanins ); Wlc_ObjAddFanins( pNew, pObjNew, vFanins ); Wlc_ObjSetCopy( p, iObj, iFaninNew ); pObjNew->fXConst = pObj->fXConst; return iFaninNew; } void Wlc_NtkDupDfs_rec( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p, int iObj, Vec_Int_t * vFanins ) { Wlc_Obj_t * pObj; int i, iFanin; if ( iObj == 0 ) return; if ( Wlc_ObjCopy(p, iObj) ) return; pObj = Wlc_NtkObj( p, iObj ); //printf( "Visiting node %16s (ID %6d) of type %5s (type ID %2d)\n", Wlc_ObjName(p, iObj), iObj, Wlc_ObjTypeName(pObj), Wlc_NtkObj(p, iObj)->Type ); assert( pObj->Type != WLC_OBJ_FF ); Wlc_ObjForEachFanin( pObj, iFanin, i ) Wlc_NtkDupDfs_rec( pNew, p, iFanin, vFanins ); Wlc_ObjDup( pNew, p, iObj, vFanins ); } Wlc_Ntk_t * Wlc_NtkDupDfsSimple( Wlc_Ntk_t * p ) { Wlc_Ntk_t * pNew; Wlc_Obj_t * pObj; Vec_Int_t * vFanins; int i; Wlc_NtkCleanCopy( p ); vFanins = Vec_IntAlloc( 100 ); pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc ); pNew->fSmtLib = p->fSmtLib; pNew->fAsyncRst = p->fAsyncRst; pNew->fMemPorts = p->fMemPorts; pNew->fEasyFfs = p->fEasyFfs; Wlc_NtkForEachCi( p, pObj, i ) Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins ); Wlc_NtkForEachCo( p, pObj, i ) Wlc_NtkDupDfs_rec( pNew, p, Wlc_ObjId(p, pObj), vFanins ); Wlc_NtkForEachCo( p, pObj, i ) Wlc_ObjSetCo( pNew, Wlc_ObjCopyObj(pNew, p, pObj), pObj->fIsFi ); if ( p->vInits ) pNew->vInits = Vec_IntDup( p->vInits ); if ( p->pInits ) pNew->pInits = Abc_UtilStrsav( p->pInits ); Vec_IntFree( vFanins ); if ( p->pSpec ) pNew->pSpec = Abc_UtilStrsav( p->pSpec ); return pNew; } Wlc_Ntk_t * Wlc_NtkDupDfs( Wlc_Ntk_t * p, int fMarked, int fSeq ) { Wlc_Ntk_t * pNew; Wlc_Obj_t * pObj, * pObjNew; Vec_Int_t * vFanins; int i, k, iObj, iFanin; vFanins = Vec_IntAlloc( 100 ); Wlc_NtkCleanCopy( p ); pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc ); pNew->fSmtLib = p->fSmtLib; pNew->fAsyncRst = p->fAsyncRst; pNew->fMemPorts = p->fMemPorts; pNew->fEasyFfs = p->fEasyFfs; Wlc_NtkForEachCi( p, pObj, i ) if ( !fMarked || pObj->Mark ) { unsigned Type = pObj->Type; if ( !fSeq ) pObj->Type = WLC_OBJ_PI; Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins ); pObj->Type = Type; } Wlc_NtkForEachFf2( p, pObj, i ) { int iObjNew = Wlc_ObjAlloc( pNew, pObj->Type, Wlc_ObjIsSigned(pObj), pObj->End, pObj->Beg ); Wlc_ObjSetCopy( p, Wlc_ObjId(p, pObj), iObjNew ); Vec_IntPush( &pNew->vFfs2, iObjNew ); } Wlc_NtkForEachCo( p, pObj, i ) if ( !fMarked || pObj->Mark ) Wlc_NtkDupDfs_rec( pNew, p, Wlc_ObjId(p, pObj), vFanins ); Wlc_NtkForEachCo( p, pObj, i ) if ( !fMarked || pObj->Mark ) Wlc_ObjSetCo( pNew, Wlc_ObjCopyObj(pNew, p, pObj), fSeq ? pObj->fIsFi : 0 ); Wlc_NtkForEachFf2( p, pObj, i ) { iObj = Wlc_ObjId(p, pObj); Wlc_ObjForEachFanin( pObj, iFanin, k ) Wlc_NtkDupDfs_rec( pNew, p, iFanin, vFanins ); Wlc_ObjCollectCopyFanins( p, iObj, vFanins ); pObjNew = Wlc_NtkObj( pNew, Wlc_ObjCopy(p, iObj) ); Wlc_ObjAddFanins( pNew, pObjNew, vFanins ); pObjNew->fXConst = pObj->fXConst; } Vec_IntFree( vFanins ); if ( fSeq && p->vInits ) { if ( fMarked ) { if ( p->vInits ) pNew->vInits = Wlc_ReduceMarkedInitVec( p, p->vInits ); if ( p->pInits ) pNew->pInits = Wlc_ReduceMarkedInitStr( p, p->pInits ); } else { if ( p->vInits ) pNew->vInits = Vec_IntDup( p->vInits ); if ( p->pInits ) pNew->pInits = Abc_UtilStrsav( p->pInits ); } } if ( p->pSpec ) pNew->pSpec = Abc_UtilStrsav( p->pSpec ); if ( Wlc_NtkHasNameId(p) ) Wlc_NtkTransferNames( pNew, p ); if ( Vec_IntSize(&p->vPoPairs) ) Vec_IntAppend( &pNew->vPoPairs, &p->vPoPairs ); return pNew; } Wlc_Ntk_t * Wlc_NtkDupDfsAbs( Wlc_Ntk_t * p, Vec_Int_t * vPisOld, Vec_Int_t * vPisNew, Vec_Int_t * vFlops ) { Wlc_Ntk_t * pNew; Wlc_Obj_t * pObj; Vec_Int_t * vFanins; int i; Wlc_NtkCleanCopy( p ); pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc ); pNew->fSmtLib = p->fSmtLib; pNew->fAsyncRst = p->fAsyncRst; pNew->fMemPorts = p->fMemPorts; pNew->fEasyFfs = p->fEasyFfs; // duplicate marked PIs vFanins = Vec_IntAlloc( 100 ); Wlc_NtkForEachObjVec( vPisOld, p, pObj, i ) { assert( Wlc_ObjIsPi(pObj) ); Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins ); } // duplicate additional PIs Wlc_NtkForEachObjVec( vPisNew, p, pObj, i ) { unsigned Type = pObj->Type; int nFanins = Wlc_ObjFaninNum(pObj); assert( !Wlc_ObjIsPi(pObj) ); pObj->Type = WLC_OBJ_PI; pObj->nFanins = 0; Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins ); pObj->Type = Type; pObj->nFanins = (unsigned)nFanins; } // duplicate flop outputs Wlc_NtkForEachObjVec( vFlops, p, pObj, i ) { assert( !Wlc_ObjIsPi(pObj) && Wlc_ObjIsCi(pObj) ); Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins ); } // duplicate logic cones of primary outputs Wlc_NtkForEachPo( p, pObj, i ) Wlc_NtkDupDfs_rec( pNew, p, Wlc_ObjId(p, pObj), vFanins ); // duplidate logic cone of flop inputs Wlc_NtkForEachObjVec( vFlops, p, pObj, i ) Wlc_NtkDupDfs_rec( pNew, p, Wlc_ObjId(p, Wlc_ObjFo2Fi(p, pObj)), vFanins ); // duplicate POs Wlc_NtkForEachPo( p, pObj, i ) Wlc_ObjSetCo( pNew, Wlc_ObjCopyObj(pNew, p, pObj), 0 ); // duplicate flop inputs Wlc_NtkForEachObjVec( vFlops, p, pObj, i ) Wlc_ObjSetCo( pNew, Wlc_ObjCopyObj(pNew, p, Wlc_ObjFo2Fi(p, pObj)), 1 ); Vec_IntFree( vFanins ); // mark flop outputs Wlc_NtkForEachObjVec( vFlops, p, pObj, i ) pObj->Mark = 1; if ( p->vInits ) pNew->vInits = Wlc_ReduceMarkedInitVec( p, p->vInits ); if ( p->pInits ) pNew->pInits = Wlc_ReduceMarkedInitStr( p, p->pInits ); Wlc_NtkCleanMarks( p ); if ( p->pSpec ) pNew->pSpec = Abc_UtilStrsav( p->pSpec ); //Wlc_NtkTransferNames( pNew, p ); return pNew; } /**Function************************************************************* Synopsis [Select the cone of the given output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_NtkCleanMarks( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; int i; Wlc_NtkForEachObj( p, pObj, i ) pObj->Mark = 0; } int Wlc_NtkCountMarked( Wlc_Ntk_t * p, int * pnPis, int * pnFos, int * pnAdders, int * pnMults ) { Wlc_Obj_t * pObj; int i, nNodes = 0; *pnPis = *pnFos = *pnAdders = *pnMults = 0; Wlc_NtkForEachObj( p, pObj, i ) { if ( !pObj->Mark ) continue; if ( Wlc_ObjIsPi(pObj) ) (*pnPis)++; else if ( Wlc_ObjIsCi(pObj) ) (*pnFos)++; else if ( pObj->Mark ) { nNodes++; if ( pObj->Type == WLC_OBJ_ARI_ADD || pObj->Type == WLC_OBJ_ARI_SUB ) (*pnAdders)++; else if ( pObj->Type == WLC_OBJ_ARI_MULTI ) (*pnMults)++; } } return nNodes; } void Wlc_NtkMarkCone_rec( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Vec_Int_t * vFlops ) { int i, iFanin; if ( pObj->Mark ) return; pObj->Mark = 1; if ( Wlc_ObjIsCi(pObj) ) { if ( !Wlc_ObjIsPi(pObj) ) Vec_IntPush( vFlops, Wlc_ObjCiId(pObj) ); return; } Wlc_ObjForEachFanin( pObj, iFanin, i ) if ( iFanin ) Wlc_NtkMarkCone_rec( p, Wlc_NtkObj(p, iFanin), vFlops ); } void Wlc_NtkMarkCone( Wlc_Ntk_t * p, int iCoId, int Range, int fSeq, int fAllPis ) { Vec_Int_t * vFlops; Wlc_Obj_t * pObj; int i, CiId, CoId; Wlc_NtkCleanMarks( p ); if ( fAllPis ) Wlc_NtkForEachPi( p, pObj, i ) pObj->Mark = 1; vFlops = Vec_IntAlloc( 100 ); Wlc_NtkForEachCo( p, pObj, i ) if ( iCoId == -1 || (i >= iCoId && i < iCoId + Range) ) Wlc_NtkMarkCone_rec( p, pObj, vFlops ); if ( fSeq ) Vec_IntForEachEntry( vFlops, CiId, i ) { CoId = Wlc_NtkPoNum(p) + CiId - Wlc_NtkPiNum(p); Wlc_NtkMarkCone_rec( p, Wlc_NtkCo(p, CoId), vFlops ); } Vec_IntFree( vFlops ); } void Wlc_NtkProfileCones( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; int i, nPis, nFos, nNodes, nAdders, nMults; Wlc_NtkForEachCo( p, pObj, i ) { Wlc_NtkMarkCone( p, i, 1, 0, 0 ); nNodes = Wlc_NtkCountMarked( p, &nPis, &nFos, &nAdders, &nMults ); printf( "Cone %5d : ", i ); printf( "PI = %4d ", nPis ); printf( "FO = %4d ", nFos ); printf( "Node = %6d ", nNodes ); printf( "Add/Sub = %4d ", nAdders ); printf( "Mult = %4d ", nMults ); printf( "\n" ); } Wlc_NtkCleanMarks( p ); } /**Function************************************************************* Synopsis [Duplicates the network by copying each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Wlc_Ntk_t * Wlc_NtkDupSingleNodes( Wlc_Ntk_t * p ) { Wlc_Ntk_t * pNew; Vec_Int_t * vFanins; Wlc_Obj_t * pObj, * pObjNew; Wlc_Obj_t * pFanin, * pFaninNew; int i, k, iFanin, iFaninNew, iObjNew, Count = 0; // count objects Wlc_NtkForEachObj( p, pObj, i ) if ( !Wlc_ObjIsCi(pObj) ) Count += 1 + Wlc_ObjFaninNum(pObj); // copy objects Wlc_NtkCleanCopy( p ); vFanins = Vec_IntAlloc( 100 ); pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc ); pNew->fSmtLib = p->fSmtLib; pNew->fAsyncRst = p->fAsyncRst; pNew->fMemPorts = p->fMemPorts; pNew->fEasyFfs = p->fEasyFfs; Wlc_NtkForEachObj( p, pObj, i ) { if ( Wlc_ObjIsCi(pObj) ) continue; if ( pObj->Type == WLC_OBJ_ARI_MULTI ) continue; if ( pObj->Type == WLC_OBJ_MUX && Wlc_ObjFaninNum(pObj) > 3 ) continue; // create CIs for the fanins Wlc_ObjForEachFanin( pObj, iFanin, k ) { pFanin = Wlc_NtkObj(p, iFanin); iFaninNew = Wlc_ObjAlloc( pNew, WLC_OBJ_PI, pFanin->Signed, pFanin->End, pFanin->Beg ); pFaninNew = Wlc_NtkObj(pNew, iFaninNew); Wlc_ObjSetCopy( p, iFanin, iFaninNew ); //Wlc_ObjSetCi( pNew, pFaninNew ); } // create object iObjNew = Wlc_ObjDup( pNew, p, i, vFanins ); pObjNew = Wlc_NtkObj(pNew, iObjNew); pObjNew->fIsPo = 1; Vec_IntPush( &pNew->vPos, iObjNew ); } Vec_IntFree( vFanins ); Wlc_NtkTransferNames( pNew, p ); if ( p->pSpec ) pNew->pSpec = Abc_UtilStrsav( p->pSpec ); return pNew; } /**Function************************************************************* Synopsis [Creates short names for all objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_NtkShortNames( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; char pBuffer[100]; int nDigits, NameId, fFound, i; int nFlops = Wlc_NtkCoNum(p) - Wlc_NtkPoNum(p); nDigits = Abc_Base10Log( nFlops ); Wlc_NtkForEachCo( p, pObj, i ) { if ( Wlc_ObjIsPo(pObj) ) continue; sprintf( pBuffer, "%s%0*d", "fi", nDigits, i - Wlc_NtkPoNum(p) ); NameId = Abc_NamStrFindOrAdd( p->pManName, pBuffer, &fFound ); Wlc_ObjSetNameId( p, Wlc_ObjId(p, pObj), NameId ); } Wlc_NtkForEachCi( p, pObj, i ) { if ( Wlc_ObjIsPi(pObj) ) continue; sprintf( pBuffer, "%s%0*d", "fo", nDigits, i - Wlc_NtkPiNum(p) ); NameId = Abc_NamStrFindOrAdd( p->pManName, pBuffer, &fFound ); Wlc_ObjSetNameId( p, Wlc_ObjId(p, pObj), NameId ); } nDigits = Abc_Base10Log( Wlc_NtkPoNum(p) ); Wlc_NtkForEachPo( p, pObj, i ) { sprintf( pBuffer, "%s%0*d", "po", nDigits, i ); NameId = Abc_NamStrFindOrAdd( p->pManName, pBuffer, &fFound ); Wlc_ObjSetNameId( p, Wlc_ObjId(p, pObj), NameId ); } nDigits = Abc_Base10Log( Wlc_NtkPiNum(p) ); Wlc_NtkForEachPi( p, pObj, i ) { sprintf( pBuffer, "%s%0*d", "pi", nDigits, i ); NameId = Abc_NamStrFindOrAdd( p->pManName, pBuffer, &fFound ); Wlc_ObjSetNameId( p, Wlc_ObjId(p, pObj), NameId ); } nDigits = Abc_Base10Log( Wlc_NtkObjNum(p) ); Wlc_NtkForEachObj( p, pObj, i ) { if ( Wlc_ObjIsCi(pObj) || Wlc_ObjIsCo(pObj) ) continue; sprintf( pBuffer, "%s%0*d", "n", nDigits, i ); NameId = Abc_NamStrFindOrAdd( p->pManName, pBuffer, &fFound ); Wlc_ObjSetNameId( p, Wlc_ObjId(p, pObj), NameId ); } } /**Function************************************************************* Synopsis [Count the number of flops initialized to DC value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Wlc_NtkDcFlopNum( Wlc_Ntk_t * p ) { int i, nFlops, Count = 0; if ( p->pInits == NULL ) return 0; nFlops = strlen(p->pInits); for ( i = 0; i < nFlops; i++ ) Count += (p->pInits[i] == 'x' || p->pInits[i] == 'X'); return Count; } /**Function************************************************************* Synopsis [Create references.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_NtkSetRefs( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; int i, k, Fanin; Vec_IntFill( &p->vRefs, Wlc_NtkObjNumMax(p), 0 ); Wlc_NtkForEachObj( p, pObj, i ) Wlc_ObjForEachFanin( pObj, Fanin, k ) Vec_IntAddToEntry( &p->vRefs, Fanin, 1 ); Wlc_NtkForEachCo( p, pObj, i ) Vec_IntAddToEntry( &p->vRefs, Wlc_ObjId(p, pObj), 1 ); } /**Function************************************************************* Synopsis [This procedure simply count the number of PPI bits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Wlc_NtkCountObjBits( Wlc_Ntk_t * p, Vec_Int_t * vPisNew ) { Wlc_Obj_t * pObj; int i, Count = 0; Wlc_NtkForEachObjVec( vPisNew, p, pObj, i ) Count += Wlc_ObjRange(pObj); return Count; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END