/**CFile**************************************************************** FileName [abcHieNew.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [New hierarchy manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcHieNew.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "misc/vec/vec.h" #include "misc/util/utilNam.h" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define AU_MAX_FANINS 0x1FFFFFFF typedef enum { AU_OBJ_NONE, // 0: non-existent object AU_OBJ_CONST0, // 1: constant node AU_OBJ_PI, // 2: primary input AU_OBJ_PO, // 3: primary output AU_OBJ_FAN, // 4: box output AU_OBJ_FLOP, // 5: flip-flop AU_OBJ_BOX, // 6: box AU_OBJ_NODE, // 7: logic node AU_OBJ_VOID // 8: placeholder } Au_Type_t; typedef struct Au_Man_t_ Au_Man_t; typedef struct Au_Ntk_t_ Au_Ntk_t; typedef struct Au_Obj_t_ Au_Obj_t; struct Au_Obj_t_ // 16 bytes { unsigned Func : 30; // functionality unsigned Value : 2; // node value unsigned Type : 3; // object type unsigned nFanins : 29; // fanin count (related to AU_MAX_FANIN_NUM) int Fanins[2]; // fanin literals }; struct Au_Ntk_t_ { char * pName; // model name Au_Man_t * pMan; // model manager int Id; // model ID // objects Vec_Int_t vPis; // primary inputs (CI id -> handle) Vec_Int_t vPos; // primary outputs (CI id -> handle) Vec_Int_t vObjs; // internal nodes (obj id -> handle) int nObjs[AU_OBJ_VOID]; // counter of objects of each type // memory for objects Vec_Ptr_t * vChunks; // memory pages Vec_Ptr_t vPages; // memory pages int iHandle; // currently available ID int nObjsAlloc; // the total number of objects allocated int nObjsUsed; // the number of useful entries // object attributes int nTravIds; // counter of traversal IDs Vec_Int_t vTravIds; // trav IDs of the objects Vec_Int_t vCopies; // object copies // structural hashing int nHTable; // hash table size int * pHTable; // hash table Au_Obj_t * pConst0; // constant node // statistics int fMark; double nBoxes; double nNodes; double nPorts; double nNodeAnds; double nNodeXors; double nNodeMuxs; }; struct Au_Man_t_ { char * pName; // the name of the library Vec_Ptr_t vNtks; // the array of modules Abc_Nam_t * pFuncs; // hashing functions into integers int nRefs; // reference counter // statistics int nGiaObjMax; // max number of GIA objects double nPortsC0; // const ports double nPortsC1; // const ports double nPortsNC; // non-const ports }; static inline int Au_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } static inline int Au_Lit2Var( int Lit ) { return Lit >> 1; } static inline int Au_LitIsCompl( int Lit ) { return Lit & 1; } static inline int Au_LitNot( int Lit ) { return Lit ^ 1; } static inline int Au_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } static inline int Au_LitRegular( int Lit ) { return Lit & ~01; } static inline Au_Obj_t * Au_Regular( Au_Obj_t * p ) { return (Au_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Au_Obj_t * Au_Not( Au_Obj_t * p ) { return (Au_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Au_Obj_t * Au_NotCond( Au_Obj_t * p, int c ) { return (Au_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } static inline int Au_IsComplement( Au_Obj_t * p ) { return (int)((ABC_PTRUINT_T)(p) & 01); } static inline char * Au_UtilStrsav( char * s ) { return s ? strcpy(ABC_ALLOC(char, strlen(s)+1), s) : NULL; } static inline char * Au_ManName( Au_Man_t * p ) { return p->pName; } static inline int Au_ManNtkNum( Au_Man_t * p ) { return Vec_PtrSize(&p->vNtks) - 1; } static inline Au_Ntk_t * Au_ManNtk( Au_Man_t * p, int i ) { return (Au_Ntk_t *)Vec_PtrEntry(&p->vNtks, i); } static inline Au_Ntk_t * Au_ManNtkRoot( Au_Man_t * p ) { return Au_ManNtk( p, 1 ); } static inline char * Au_NtkName( Au_Ntk_t * p ) { return p->pName; } static inline Au_Man_t * Au_NtkMan( Au_Ntk_t * p ) { return p->pMan; } static inline int Au_NtkPiNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_PI]; } static inline int Au_NtkPoNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_PO]; } static inline int Au_NtkFanNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_FAN]; } static inline int Au_NtkFlopNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_FLOP]; } static inline int Au_NtkBoxNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_BOX]; } static inline int Au_NtkNodeNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_NODE]; } static inline int Au_NtkObjNumMax( Au_Ntk_t * p ) { return (Vec_PtrSize(&p->vPages) - 1) * (1 << 12) + p->iHandle; } static inline int Au_NtkObjNum( Au_Ntk_t * p ) { return Vec_IntSize(&p->vObjs); } static inline Au_Obj_t * Au_NtkObj( Au_Ntk_t * p, int h ) { return (Au_Obj_t *)p->vPages.pArray[h >> 12] + (h & 0xFFF); } static inline Au_Obj_t * Au_NtkPi( Au_Ntk_t * p, int i ) { return Au_NtkObj(p, Vec_IntEntry(&p->vPis, i)); } static inline Au_Obj_t * Au_NtkPo( Au_Ntk_t * p, int i ) { return Au_NtkObj(p, Vec_IntEntry(&p->vPos, i)); } static inline Au_Obj_t * Au_NtkObjI( Au_Ntk_t * p, int i ) { return Au_NtkObj(p, Vec_IntEntry(&p->vObjs, i)); } static inline int Au_ObjIsNone( Au_Obj_t * p ) { return p->Type == AU_OBJ_NONE; } static inline int Au_ObjIsConst0( Au_Obj_t * p ) { return p->Type == AU_OBJ_CONST0; } static inline int Au_ObjIsPi( Au_Obj_t * p ) { return p->Type == AU_OBJ_PI; } static inline int Au_ObjIsPo( Au_Obj_t * p ) { return p->Type == AU_OBJ_PO; } static inline int Au_ObjIsFan( Au_Obj_t * p ) { return p->Type == AU_OBJ_FAN; } static inline int Au_ObjIsFlop( Au_Obj_t * p ) { return p->Type == AU_OBJ_FLOP; } static inline int Au_ObjIsBox( Au_Obj_t * p ) { return p->Type == AU_OBJ_BOX; } static inline int Au_ObjIsNode( Au_Obj_t * p ) { return p->Type == AU_OBJ_NODE; } static inline int Au_ObjIsTerm( Au_Obj_t * p ) { return p->Type >= AU_OBJ_PI && p->Type <= AU_OBJ_FLOP; } static inline char * Au_ObjBase( Au_Obj_t * p ) { return (char *)p - ((ABC_PTRINT_T)p & 0x3FF); } static inline Au_Ntk_t * Au_ObjNtk( Au_Obj_t * p ) { return ((Au_Ntk_t **)Au_ObjBase(p))[0]; } static inline int Au_ObjId( Au_Obj_t * p ) { return ((int *)Au_ObjBase(p))[2] | (((ABC_PTRINT_T)p & 0x3FF) >> 4); } static inline int Au_ObjPioNum( Au_Obj_t * p ) { assert(Au_ObjIsTerm(p)); return p->Fanins[p->nFanins]; } static inline int Au_ObjFunc( Au_Obj_t * p ) { return p->Func; } static inline Au_Ntk_t * Au_ObjModel( Au_Obj_t * p ) { assert(Au_ObjIsFan(p)||Au_ObjIsBox(p)); return Au_ManNtk(Au_NtkMan(Au_ObjNtk(p)), p->Func); } static inline int Au_ObjFaninNum( Au_Obj_t * p ) { return p->nFanins; } static inline int Au_ObjFaninId( Au_Obj_t * p, int i ) { assert(i >= 0 && i < (int)p->nFanins && p->Fanins[i]); return Au_Lit2Var(p->Fanins[i]); } static inline int Au_ObjFaninId0( Au_Obj_t * p ) { return Au_ObjFaninId(p, 0); } static inline int Au_ObjFaninId1( Au_Obj_t * p ) { return Au_ObjFaninId(p, 1); } static inline int Au_ObjFaninId2( Au_Obj_t * p ) { return Au_ObjFaninId(p, 2); } static inline Au_Obj_t * Au_ObjFanin( Au_Obj_t * p, int i ) { return Au_NtkObj(Au_ObjNtk(p), Au_ObjFaninId(p, i)); } static inline Au_Obj_t * Au_ObjFanin0( Au_Obj_t * p ) { return Au_ObjFanin( p, 0 ); } static inline Au_Obj_t * Au_ObjFanin1( Au_Obj_t * p ) { return Au_ObjFanin( p, 1 ); } static inline Au_Obj_t * Au_ObjFanin2( Au_Obj_t * p ) { return Au_ObjFanin( p, 2 ); } static inline int Au_ObjFaninC( Au_Obj_t * p, int i ) { assert(i >= 0 && i < (int)p->nFanins && p->Fanins[i]); return Au_LitIsCompl(p->Fanins[i]); } static inline int Au_ObjFaninC0( Au_Obj_t * p ) { return Au_ObjFaninC(p, 0); } static inline int Au_ObjFaninC1( Au_Obj_t * p ) { return Au_ObjFaninC(p, 1); } static inline int Au_ObjFaninC2( Au_Obj_t * p ) { return Au_ObjFaninC(p, 2); } static inline int Au_ObjFaninLit( Au_Obj_t * p, int i ) { assert(i >= 0 && i < (int)p->nFanins && p->Fanins[i]); return p->Fanins[i]; } static inline void Au_ObjSetFanin( Au_Obj_t * p, int i, int f ) { assert(f > 0 && p->Fanins[i] == 0); p->Fanins[i] = Au_Var2Lit(f,0); } static inline void Au_ObjSetFaninLit( Au_Obj_t * p, int i, int f){ assert(f >= 0 && p->Fanins[i] == 0); p->Fanins[i] = f; } static inline int Au_BoxFanoutNum( Au_Obj_t * p ) { assert(Au_ObjIsBox(p)); return p->Fanins[p->nFanins]; } static inline int Au_BoxFanoutId( Au_Obj_t * p, int i ) { assert(i >= 0 && i < Au_BoxFanoutNum(p)); return p->Fanins[p->nFanins+1+i]; } static inline Au_Obj_t * Au_BoxFanout( Au_Obj_t * p, int i ) { return Au_NtkObj(Au_ObjNtk(p), Au_BoxFanoutId(p, i)); } static inline int Au_ObjCopy( Au_Obj_t * p ) { return Vec_IntEntry( &Au_ObjNtk(p)->vCopies, Au_ObjId(p) ); } static inline void Au_ObjSetCopy( Au_Obj_t * p, int c ) { Vec_IntWriteEntry( &Au_ObjNtk(p)->vCopies, Au_ObjId(p), c ); } static inline int Au_ObjFanout( Au_Obj_t * p, int i ) { assert(p->Type == AU_OBJ_BOX && i >= 0 && i < p->Fanins[p->nFanins] && p->Fanins[i]); return p->Fanins[p->nFanins + 1 + i]; } static inline void Au_ObjSetFanout( Au_Obj_t * p, int i, int f ) { assert(p->Type == AU_OBJ_BOX && i >= 0 && i < p->Fanins[p->nFanins] && p->Fanins[i] == 0 && f > 0); p->Fanins[p->nFanins + 1 + i] = f; } static inline void Au_NtkIncrementTravId( Au_Ntk_t * p ) { if (p->vTravIds.pArray == NULL) Vec_IntFill(&p->vTravIds, Au_NtkObjNumMax(p)+500, 0); p->nTravIds++; assert(p->nTravIds < (1<<30)); } static inline void Au_ObjSetTravIdCurrent( Au_Obj_t * p ) { Vec_IntSetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p), Au_ObjNtk(p)->nTravIds ); } static inline void Au_ObjSetTravIdPrevious( Au_Obj_t * p ) { Vec_IntSetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p), Au_ObjNtk(p)->nTravIds-1 ); } static inline int Au_ObjIsTravIdCurrent( Au_Obj_t * p ) { return (Vec_IntGetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p)) == Au_ObjNtk(p)->nTravIds); } static inline int Au_ObjIsTravIdPrevious( Au_Obj_t * p ) { return (Vec_IntGetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p)) == Au_ObjNtk(p)->nTravIds-1); } static inline void Au_ObjSetTravIdCurrentId( Au_Ntk_t * p, int Id ) { Vec_IntSetEntry(&p->vTravIds, Id, p->nTravIds ); } static inline int Au_ObjIsTravIdCurrentId( Au_Ntk_t * p, int Id ) { return (Vec_IntGetEntry(&p->vTravIds, Id) == p->nTravIds); } #define Au_ManForEachNtk( p, pNtk, i ) \ for ( i = 1; (i < Vec_PtrSize(&p->vNtks)) && (((pNtk) = Au_ManNtk(p, i)), 1); i++ ) #define Au_ManForEachNtkReverse( p, pNtk, i ) \ for ( i = Vec_PtrSize(&p->vNtks) - 1;(i>=1) && (((pNtk) = Au_ManNtk(p, i)), 1); i-- ) #define Au_ObjForEachFaninId( pObj, hFanin, i ) \ for ( i = 0; (i < Au_ObjFaninNum(pObj)) && (((hFanin) = Au_ObjFaninId(pObj, i)), 1); i++ ) #define Au_BoxForEachFanoutId( pObj, hFanout, i) \ for ( i = 0; (i < Au_BoxFanoutNum(pObj)) && (((hFanout) = Au_BoxFanoutId(pObj, i)), 1); i++ ) #define Au_ObjForEachFanin( pObj, pFanin, i ) \ for ( i = 0; (i < Au_ObjFaninNum(pObj)) && (((pFanin) = Au_ObjFanin(pObj, i)), 1); i++ ) #define Au_BoxForEachFanout( pObj, pFanout, i) \ for ( i = 0; (i < Au_BoxFanoutNum(pObj)) && (((pFanout) = Au_BoxFanout(pObj, i)), 1); i++ ) #define Au_NtkForEachPi( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vPis)) && (((pObj) = Au_NtkPi(p, i)), 1); i++ ) #define Au_NtkForEachPo( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vPos)) && (((pObj) = Au_NtkPo(p, i)), 1); i++ ) #define Au_NtkForEachObj( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vObjs)) && (((pObj) = Au_NtkObjI(p, i)), 1); i++ ) #define Au_NtkForEachNode( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vObjs)) && (((pObj) = Au_NtkObjI(p, i)), 1); i++ ) if ( !Au_ObjIsNode(pObj) ) {} else #define Au_NtkForEachBox( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vObjs)) && (((pObj) = Au_NtkObjI(p, i)), 1); i++ ) if ( !Au_ObjIsBox(pObj) ) {} else extern void Au_ManAddNtk( Au_Man_t * pMan, Au_Ntk_t * p ); extern void Au_ManFree( Au_Man_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Working with models.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Au_Ntk_t * Au_NtkAlloc( Au_Man_t * pMan, char * pName ) { Au_Ntk_t * p; p = ABC_CALLOC( Au_Ntk_t, 1 ); p->pName = Au_UtilStrsav( pName ); p->vChunks = Vec_PtrAlloc( 111 ); Vec_IntGrow( &p->vPis, 111 ); Vec_IntGrow( &p->vPos, 111 ); Vec_IntGrow( &p->vObjs, 1111 ); Vec_PtrGrow( &p->vPages, 11 ); Au_ManAddNtk( pMan, p ); return p; } void Au_NtkFree( Au_Ntk_t * p ) { Au_ManFree( p->pMan ); Vec_PtrFreeFree( p->vChunks ); ABC_FREE( p->vCopies.pArray ); ABC_FREE( p->vPages.pArray ); ABC_FREE( p->vObjs.pArray ); ABC_FREE( p->vPis.pArray ); ABC_FREE( p->vPos.pArray ); ABC_FREE( p->pHTable ); ABC_FREE( p->pName ); ABC_FREE( p ); } int Au_NtkMemUsage( Au_Ntk_t * p ) { int Mem = sizeof(Au_Ntk_t); Mem += 4 * p->vPis.nCap; Mem += 4 * p->vPos.nCap; Mem += 4 * p->vObjs.nCap; Mem += 16 * p->nObjsAlloc; return Mem; } void Au_NtkPrintStats( Au_Ntk_t * p ) { printf( "%-30s:", Au_NtkName(p) ); printf( " i/o =%6d/%6d", Au_NtkPiNum(p), Au_NtkPoNum(p) ); if ( Au_NtkFlopNum(p) ) printf( " lat =%5d", Au_NtkFlopNum(p) ); printf( " nd =%6d", Au_NtkNodeNum(p) ); // if ( Au_NtkBoxNum(p) ) printf( " box =%5d", Au_NtkBoxNum(p) ); printf( " obj =%7d", Au_NtkObjNum(p) ); // printf( " max =%7d", Au_NtkObjNumMax(p) ); // printf( " use =%7d", p->nObjsUsed ); printf( " %5.1f %%", 100.0 * (Au_NtkObjNumMax(p) - Au_NtkObjNum(p)) / Au_NtkObjNumMax(p) ); printf( " %6.1f MB", 1.0 * Au_NtkMemUsage(p) / (1 << 20) ); printf( " %5.1f %%", 100.0 * (p->nObjsAlloc - p->nObjsUsed) / p->nObjsAlloc ); printf( "\n" ); } void Au_NtkCleanCopy( Au_Ntk_t * p ) { Vec_IntFill( &p->vCopies, Au_NtkObjNumMax(p), -1 ); } int Au_NtkNodeNumFunc( Au_Ntk_t * p, int Func ) { Au_Obj_t * pObj; int i, Counter = 0; if ( p->pMan && p->pMan->pFuncs ) return 0; Au_NtkForEachNode( p, pObj, i ) { Counter += (pObj->Func == (unsigned)Func); // printf( "%d ", pObj->Func ); } // printf( "\n" ); return Counter; } /**Function************************************************************* Synopsis [Working with manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Au_Man_t * Au_ManAlloc( char * pName ) { Au_Man_t * p; p = ABC_CALLOC( Au_Man_t, 1 ); p->pName = Au_UtilStrsav( pName ); Vec_PtrGrow( &p->vNtks, 111 ); Vec_PtrPush( &p->vNtks, NULL ); return p; } void Au_ManFree( Au_Man_t * p ) { assert( p->nRefs > 0 ); if ( --p->nRefs > 0 ) return; if ( p->pFuncs ) Abc_NamStop( p->pFuncs ); ABC_FREE( p->vNtks.pArray ); ABC_FREE( p->pName ); ABC_FREE( p ); } void Au_ManDelete( Au_Man_t * p ) { Au_Ntk_t * pNtk; int i; Au_ManForEachNtk( p, pNtk, i ) Au_NtkFree( pNtk ); } int Au_ManFindNtk( Au_Man_t * p, char * pName ) { Au_Ntk_t * pNtk; int i; Au_ManForEachNtk( p, pNtk, i ) if ( !strcmp(Au_NtkName(pNtk), pName) ) return i; return -1; } Au_Ntk_t * Au_ManFindNtkP( Au_Man_t * p, char * pName ) { int iNtk = Au_ManFindNtk( p, pName ); if ( iNtk == -1 ) return NULL; return Au_ManNtk( p, iNtk ); } void Au_ManAddNtk( Au_Man_t * pMan, Au_Ntk_t * p ) { assert( Au_ManFindNtk(pMan, Au_NtkName(p)) == -1 ); p->pMan = pMan; pMan->nRefs++; p->Id = Vec_PtrSize( &pMan->vNtks ); Vec_PtrPush( &pMan->vNtks, p ); } int Au_ManMemUsage( Au_Man_t * p ) { Au_Ntk_t * pNtk; int i, Mem = 0; Au_ManForEachNtk( p, pNtk, i ) Mem += 16 * pNtk->nObjsAlloc; return Mem; } int Au_ManMemUsageUseful( Au_Man_t * p ) { Au_Ntk_t * pNtk; int i, Mem = 0; Au_ManForEachNtk( p, pNtk, i ) Mem += 16 * pNtk->nObjsUsed; return Mem; } void Au_ManPrintStats( Au_Man_t * p ) { Au_Ntk_t * pNtk; int i; if ( Vec_PtrSize(&p->vNtks) > 2 ) printf( "Design %-13s\n", Au_ManName(p) ); Au_ManForEachNtk( p, pNtk, i ) Au_NtkPrintStats( pNtk ); printf( "Different functions = %d. ", p->pFuncs ? Abc_NamObjNumMax(p->pFuncs) : 0 ); printf( "Memory = %.1f MB", 1.0 * Au_ManMemUsage(p) / (1 << 20) ); printf( " %5.1f %%", 100.0 * (Au_ManMemUsage(p) - Au_ManMemUsageUseful(p)) / Au_ManMemUsage(p) ); printf( "\n" ); // if ( p->pFuncs ) // Abc_NamPrint( p->pFuncs ); } void Au_ManReorderModels_rec( Au_Ntk_t * pNtk, Vec_Int_t * vOrder ) { Au_Ntk_t * pBoxModel; Au_Obj_t * pObj; int k; if ( pNtk->fMark ) return; pNtk->fMark = 1; Au_NtkForEachBox( pNtk, pObj, k ) { pBoxModel = Au_ObjModel(pObj); if ( pBoxModel == NULL || pBoxModel == pNtk ) continue; Au_ManReorderModels_rec( pBoxModel, vOrder ); } Vec_IntPush( vOrder, pNtk->Id ); } void Au_ManReorderModels( Au_Man_t * p, Au_Ntk_t * pRoot ) { Vec_Ptr_t * vNtksNew; Vec_Int_t * vOrder, * vTemp; Au_Ntk_t * pNtk, * pBoxModel; Au_Obj_t * pBox, * pFan; int i, k, j, Entry; Au_ManForEachNtk( p, pNtk, i ) pNtk->fMark = 0; // collect networks in the DFS order vOrder = Vec_IntAlloc( Au_ManNtkNum(p)+1 ); Vec_IntPush( vOrder, 0 ); Au_ManReorderModels_rec( pRoot, vOrder ); assert( Vec_IntEntryLast(vOrder) == pRoot->Id ); // add unconnected ones Vec_IntPop( vOrder ); Au_ManForEachNtk( p, pNtk, i ) if ( pNtk->fMark == 0 ) Vec_IntPush( vOrder, pNtk->Id ); Vec_IntPush( vOrder, pRoot->Id ); assert( Vec_IntSize(vOrder) == Au_ManNtkNum(p)+1 ); // reverse order vOrder->nSize--; vOrder->pArray++; Vec_IntReverseOrder( vOrder ); vOrder->pArray--; vOrder->nSize++; // compute new order vNtksNew = Vec_PtrAlloc( Au_ManNtkNum(p)+1 ); Vec_IntForEachEntry( vOrder, Entry, i ) Vec_PtrPush( vNtksNew, Au_ManNtk(p, Entry) ); // invert order assert( Vec_IntEntry(vOrder, 1) == pRoot->Id ); vOrder = Vec_IntInvert( vTemp = vOrder, 0 ); Vec_IntFree( vTemp ); assert( Vec_IntEntry(vOrder, 1) == pRoot->Id ); // update model numbers Au_ManForEachNtk( p, pNtk, i ) { pNtk->Id = Vec_IntEntry( vOrder, pNtk->Id ); Au_NtkForEachBox( pNtk, pBox, k ) { pBox->Func = Vec_IntEntry( vOrder, pBox->Func ); assert( pBox->Func > 0 ); Au_BoxForEachFanout( pBox, pFan, j ) pFan->Func = pBox->Func; } } // update ABC_FREE( p->vNtks.pArray ); p->vNtks.pArray = vNtksNew->pArray; vNtksNew->pArray = NULL; Vec_PtrFree( vNtksNew ); // verify Au_ManForEachNtk( p, pNtk, i ) Au_NtkForEachBox( pNtk, pBox, k ) { pBoxModel = Au_ObjModel(pBox); if ( pBoxModel == NULL || pBoxModel == pNtk ) continue; assert( !pBox->Func || pBox->Func >= (unsigned)pNtk->Id ); assert( Au_ObjFaninNum(pBox) == Au_NtkPiNum(pBoxModel) ); assert( Au_BoxFanoutNum(pBox) == Au_NtkPoNum(pBoxModel) ); } Vec_IntFree( vOrder ); } void Au_ManCountThings( Au_Man_t * p ) { Au_Ntk_t * pNtk, * pBoxModel; Au_Obj_t * pBox; int i, k;//, clk = Abc_Clock(); Au_ManForEachNtkReverse( p, pNtk, i ) { pNtk->nBoxes = Au_NtkBoxNum(pNtk); pNtk->nNodes = Au_NtkNodeNum(pNtk); pNtk->nPorts = Au_NtkPiNum(pNtk) + Au_NtkPoNum(pNtk); pNtk->nNodeAnds = Au_NtkNodeNumFunc( pNtk, 1 ); pNtk->nNodeXors = Au_NtkNodeNumFunc( pNtk, 2 ); pNtk->nNodeMuxs = Au_NtkNodeNumFunc( pNtk, 3 ); // assert( pNtk->nNodes == pNtk->nNodeAnds + pNtk->nNodeXors + pNtk->nNodeMuxs ); // printf( "adding %.0f nodes of model %s\n", pNtk->nNodes, Au_NtkName(pNtk) ); Au_NtkForEachBox( pNtk, pBox, k ) { pBoxModel = Au_ObjModel(pBox); if ( pBoxModel == NULL || pBoxModel == pNtk ) continue; assert( Au_ObjFaninNum(pBox) == Au_NtkPiNum(pBoxModel) ); assert( Au_BoxFanoutNum(pBox) == Au_NtkPoNum(pBoxModel) ); assert( pBoxModel->Id > pNtk->Id ); assert( pBoxModel->nPorts > 0 ); pNtk->nBoxes += pBoxModel->nBoxes; pNtk->nNodes += pBoxModel->nNodes; pNtk->nPorts += pBoxModel->nPorts; pNtk->nNodeAnds += pBoxModel->nNodeAnds; pNtk->nNodeXors += pBoxModel->nNodeXors; pNtk->nNodeMuxs += pBoxModel->nNodeMuxs; // printf( " adding %.0f nodes of model %s\n", pBoxModel->nNodes, Au_NtkName(pBoxModel) ); } // printf( "total %.0f nodes in model %s\n", pNtk->nNodes, Au_NtkName(pNtk) ); } pNtk = Au_ManNtkRoot(p); printf( "Total nodes = %15.0f. Total instances = %15.0f. Total ports = %15.0f.\n", // printf( "Total nodes = %.2e. Total instances = %.2e. Total ports = %.2e.\n", pNtk->nNodes, pNtk->nBoxes, pNtk->nPorts ); // printf( "Total ANDs = %15.0f. Total XORs = %15.0f. Total MUXes = %15.0f.\n", // printf( "Total ANDs = %.2e. Total XORs = %.2e. Total MUXes = %.2e. ", // pNtk->nNodeAnds, pNtk->nNodeXors, pNtk->nNodeMuxs ); printf( "Total ANDs = %15.0f.\n", pNtk->nNodeAnds ); printf( "Total XORs = %15.0f.\n", pNtk->nNodeXors ); printf( "Total MUXes = %15.0f.\n", pNtk->nNodeMuxs ); // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } int Au_NtkCompareNames( Au_Ntk_t ** p1, Au_Ntk_t ** p2 ) { return strcmp( Au_NtkName(*p1), Au_NtkName(*p2) ); } void Au_ManPrintBoxInfo( Au_Ntk_t * pNtk ) { Vec_Ptr_t * vMods; Au_Ntk_t * pModel, * pBoxModel; Au_Obj_t * pObj; Vec_Int_t * vCounts; int i, k, Num; if ( pNtk->pMan == NULL ) { printf( "There is no hierarchy information.\n" ); return; } vMods = &pNtk->pMan->vNtks; /* vMods->nSize--; vMods->pArray++; // sort models by name Vec_PtrSort( vMods, (int(*)())Au_NtkCompareNames ); // swap the first model Num = Vec_PtrFind( vMods, pNtk ); assert( Num >= 0 && Num < Vec_PtrSize(vMods) ); pBoxModel = (Au_Ntk_t *)Vec_PtrEntry(vMods, 0); Vec_PtrWriteEntry(vMods, 0, (Au_Ntk_t *)Vec_PtrEntry(vMods, Num) ); Vec_PtrWriteEntry(vMods, Num, pBoxModel ); vMods->pArray--; vMods->nSize++; */ // Vec_PtrForEachEntry( Au_Ntk_t *, vMods, pModel, i ) // printf( "%s\n", Au_NtkName(pModel) ); // print models vCounts = Vec_IntStart( Vec_PtrSize(vMods) ); Vec_PtrForEachEntryStart( Au_Ntk_t *, vMods, pModel, i, 1 ) { if ( Au_NtkBoxNum(pModel) == 0 ) continue; Vec_IntFill( vCounts, Vec_IntSize(vCounts), 0 ); Au_NtkForEachBox( pModel, pObj, k ) { pBoxModel = Au_ObjModel(pObj); if ( pBoxModel == NULL || pBoxModel == pModel ) continue; Num = Vec_PtrFind( vMods, pBoxModel ); assert( Num >= 0 && Num < Vec_PtrSize(vMods) ); Vec_IntAddToEntry( vCounts, Num, 1 ); } // Au_NtkPrintStats( pModel, 0, 0, 0, 0, 0, 0, 0 ); printf( "MODULE " ); printf( "%-30s : ", Au_NtkName(pModel) ); printf( "PI=%6d ", Au_NtkPiNum(pModel) ); printf( "PO=%6d ", Au_NtkPoNum(pModel) ); printf( "BB=%6d ", Au_NtkBoxNum(pModel) ); printf( "ND=%6d ", Au_NtkNodeNum(pModel) ); // sans constants // printf( "Lev=%5d ", Au_NtkLevel(pModel) ); printf( "\n" ); Vec_IntForEachEntry( vCounts, Num, k ) if ( Num ) printf( "%15d : %s\n", Num, Au_NtkName((Au_Ntk_t *)Vec_PtrEntry(vMods, k)) ); } Vec_IntFree( vCounts ); Vec_PtrForEachEntryStart( Au_Ntk_t *, vMods, pModel, i, 1 ) { if ( Au_NtkBoxNum(pModel) != 0 ) continue; printf( "MODULE " ); printf( "%-30s : ", Au_NtkName(pModel) ); printf( "PI=%6d ", Au_NtkPiNum(pModel) ); printf( "PO=%6d ", Au_NtkPoNum(pModel) ); printf( "BB=%6d ", Au_NtkBoxNum(pModel) ); printf( "ND=%6d ", Au_NtkNodeNum(pModel) ); // printf( "Lev=%5d ", Au_NtkLevel(pModel) ); printf( "\n" ); } } int Au_NtkCompareSign( Au_Ntk_t ** p1, Au_Ntk_t ** p2 ) { if ( Au_NtkPiNum(*p1) - Au_NtkPiNum(*p2) != 0 ) return Au_NtkPiNum(*p1) - Au_NtkPiNum(*p2); else return Au_NtkPoNum(*p1) - Au_NtkPoNum(*p2); } void Au_ManPrintBoxInfoSorted( Au_Ntk_t * pNtk ) { Vec_Ptr_t * vMods, * vModsNew; Au_Ntk_t * pModel; int i; if ( pNtk->pMan == NULL ) { printf( "There is no hierarchy information.\n" ); return; } vMods = &pNtk->pMan->vNtks; vMods->nSize--; vMods->pArray++; vModsNew = Vec_PtrDup( vMods ); vMods->pArray--; vMods->nSize++; Vec_PtrSort( vModsNew, (int(*)())Au_NtkCompareSign ); Vec_PtrForEachEntryStart( Au_Ntk_t *, vModsNew, pModel, i, 1 ) { printf( "MODULE " ); printf( "%-30s : ", Au_NtkName(pModel) ); printf( "PI=%6d ", Au_NtkPiNum(pModel) ); printf( "PO=%6d ", Au_NtkPoNum(pModel) ); printf( "BB=%6d ", Au_NtkBoxNum(pModel) ); printf( "ND=%6d ", Au_NtkNodeNum(pModel) ); printf( "\n" ); } Vec_PtrFree( vModsNew ); } int Au_NtkCheckRecursive( Au_Ntk_t * pNtk ) { Vec_Ptr_t * vMods; Au_Ntk_t * pModel; Au_Obj_t * pObj; int i, k, RetValue = 0; if ( pNtk->pMan == NULL ) { printf( "There is no hierarchy information.\n" ); return RetValue; } vMods = &pNtk->pMan->vNtks; Vec_PtrForEachEntryStart( Au_Ntk_t *, vMods, pModel, i, 1 ) { Au_NtkForEachObj( pModel, pObj, k ) if ( Au_ObjIsBox(pObj) && Au_ObjModel(pObj) == pModel ) { printf( "WARNING: Model \"%s\" contains a recursive defition.\n", Au_NtkName(pModel) ); RetValue = 1; break; } } return RetValue; } // count the number of support variables int Au_ObjSuppSize_rec( Au_Ntk_t * p, int Id ) { Au_Obj_t * pObj; int i, iFanin, Counter = 0; if ( Au_ObjIsTravIdCurrentId(p, Id) ) return 0; Au_ObjSetTravIdCurrentId(p, Id); pObj = Au_NtkObj( p, Id ); if ( Au_ObjIsPi(pObj) ) return 1; assert( Au_ObjIsNode(pObj) || Au_ObjIsBox(pObj) || Au_ObjIsFan(pObj) ); Au_ObjForEachFaninId( pObj, iFanin, i ) Counter += Au_ObjSuppSize_rec( p, iFanin ); return Counter; } int Au_ObjSuppSize( Au_Obj_t * pObj ) { Au_Ntk_t * p = Au_ObjNtk(pObj); Au_NtkIncrementTravId( p ); return Au_ObjSuppSize_rec( p, Au_ObjId(pObj) ); } /* // this version is 50% slower than above int Au_ObjSuppSize_rec( Au_Obj_t * pObj ) { Au_Obj_t * pFanin; int i, Counter = 0; if ( Au_ObjIsTravIdCurrent(pObj) ) return 0; Au_ObjSetTravIdCurrent(pObj); if ( Au_ObjIsPi(pObj) ) return 1; assert( Au_ObjIsNode(pObj) || Au_ObjIsBox(pObj) || Au_ObjIsFan(pObj) ); Au_ObjForEachFanin( pObj, pFanin, i ) Counter += Au_ObjSuppSize_rec( pFanin ); return Counter; } int Au_ObjSuppSize( Au_Obj_t * pObj ) { Au_NtkIncrementTravId( Au_ObjNtk(pObj) ); return Au_ObjSuppSize_rec( pObj ); } */ int Au_NtkSuppSizeTest( Au_Ntk_t * p ) { Au_Obj_t * pObj; int i, Counter = 0; Au_NtkForEachObj( p, pObj, i ) if ( Au_ObjIsNode(pObj) ) Counter += (Au_ObjSuppSize(pObj) <= 16); printf( "Nodes with small support %d (out of %d)\n", Counter, Au_NtkNodeNum(p) ); return Counter; } /**Function************************************************************* Synopsis [Returns memory for the next object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Au_NtkInsertHeader( Au_Ntk_t * p ) { Au_Obj_t * pMem = (Au_Obj_t *)Vec_PtrEntryLast( &p->vPages ); assert( (((ABC_PTRINT_T)(pMem + p->iHandle) & 0x3FF) >> 4) == 0 ); ((Au_Ntk_t **)(pMem + p->iHandle))[0] = p; ((int *)(pMem + p->iHandle))[2] = ((Vec_PtrSize(&p->vPages) - 1) << 12) | (p->iHandle & 0xFC0); p->iHandle++; } int Au_NtkAllocObj( Au_Ntk_t * p, int nFanins, int Type ) { Au_Obj_t * pMem, * pObj, * pTemp; int nObjInt = ((2+nFanins) >> 2) + (((2+nFanins) & 3) > 0); int Id, nObjIntReal = nObjInt; if ( nObjInt > 63 ) nObjInt = 63 + 64 * (((nObjInt-63) >> 6) + (((nObjInt-63) & 63) > 0)); if ( Vec_PtrSize(&p->vPages) == 0 || p->iHandle + nObjInt > (1 << 12) ) { if ( nObjInt + 64 > (1 << 12) ) pMem = ABC_CALLOC( Au_Obj_t, nObjInt + 64 ), p->nObjsAlloc += nObjInt + 64; else pMem = ABC_CALLOC( Au_Obj_t, (1 << 12) + 64 ), p->nObjsAlloc += (1 << 12) + 64; Vec_PtrPush( p->vChunks, pMem ); if ( ((ABC_PTRINT_T)pMem & 0xF) ) pMem = (Au_Obj_t *)((char *)pMem + 16 - ((ABC_PTRINT_T)pMem & 0xF)); assert( ((ABC_PTRINT_T)pMem & 0xF) == 0 ); p->iHandle = (((ABC_PTRINT_T)pMem & 0x3FF) >> 4); if ( p->iHandle ) { pMem += 64 - (p->iHandle & 63); p->iHandle = 0; } Vec_PtrPush( &p->vPages, pMem ); Au_NtkInsertHeader( p ); } else { pMem = (Au_Obj_t *)Vec_PtrEntryLast( &p->vPages ); if ( (p->iHandle & 63) == 0 || nObjInt > (64 - (p->iHandle & 63)) ) { if ( p->iHandle & 63 ) p->iHandle += 64 - (p->iHandle & 63); Au_NtkInsertHeader( p ); } if ( p->iHandle + nObjInt > (1 << 12) ) return Au_NtkAllocObj( p, nFanins, Type ); } pObj = pMem + p->iHandle; assert( *((int *)pObj) == 0 ); pObj->nFanins = nFanins; p->nObjs[pObj->Type = Type]++; if ( Type == AU_OBJ_PI ) { Au_ObjSetFaninLit( pObj, 0, Vec_IntSize(&p->vPis) ); Vec_IntPush( &p->vPis, Au_ObjId(pObj) ); } else if ( Type == AU_OBJ_PO ) { Au_ObjSetFaninLit( pObj, 1, Vec_IntSize(&p->vPos) ); Vec_IntPush( &p->vPos, Au_ObjId(pObj) ); } p->iHandle += nObjInt; p->nObjsUsed += nObjIntReal; Id = Au_ObjId(pObj); Vec_IntPush( &p->vObjs, Id ); pTemp = Au_NtkObj( p, Id ); assert( pTemp == pObj ); return Id; } int Au_NtkCreateConst0( Au_Ntk_t * pNtk ) { return Au_NtkAllocObj( pNtk, 0, AU_OBJ_CONST0 ); } int Au_NtkCreatePi( Au_Ntk_t * pNtk ) { return Au_NtkAllocObj( pNtk, 0, AU_OBJ_PI ); } int Au_NtkCreatePo( Au_Ntk_t * pNtk, int iFanin ) { int Id = Au_NtkAllocObj( pNtk, 1, AU_OBJ_PO ); if ( iFanin ) Au_ObjSetFaninLit( Au_NtkObj(pNtk, Id), 0, iFanin ); return Id; } int Au_NtkCreateFan( Au_Ntk_t * pNtk, int iFanin, int iFanout, int iModel ) { int Id = Au_NtkAllocObj( pNtk, 1, AU_OBJ_FAN ); Au_Obj_t * p = Au_NtkObj( pNtk, Id ); if ( iFanin ) Au_ObjSetFaninLit( p, 0, iFanin ); Au_ObjSetFaninLit( p, 1, iFanout ); p->Func = iModel; return Id; } int Au_NtkCreateNode( Au_Ntk_t * pNtk, Vec_Int_t * vFanins, int iFunc ) { int i, iFanin; int Id = Au_NtkAllocObj( pNtk, Vec_IntSize(vFanins), AU_OBJ_NODE ); Au_Obj_t * p = Au_NtkObj( pNtk, Id ); Vec_IntForEachEntry( vFanins, iFanin, i ) Au_ObjSetFaninLit( p, i, iFanin ); p->Func = iFunc; return Id; } int Au_NtkCreateBox( Au_Ntk_t * pNtk, Vec_Int_t * vFanins, int nFanouts, int iModel ) { int i, iFanin, nFanins = Vec_IntSize(vFanins); int Id = Au_NtkAllocObj( pNtk, nFanins + 1 + nFanouts, AU_OBJ_BOX ); Au_Obj_t * p = Au_NtkObj( pNtk, Id ); Vec_IntForEachEntry( vFanins, iFanin, i ) Au_ObjSetFaninLit( p, i, iFanin ); Au_ObjSetFaninLit( p, nFanins, nFanouts ); for ( i = 0; i < nFanouts; i++ ) Au_ObjSetFaninLit( p, nFanins + 1 + i, Au_NtkCreateFan(pNtk, Au_Var2Lit(Id,0), i, iModel) ); p->nFanins = nFanins; p->Func = iModel; assert( iModel > 0 ); return Id; } /* * 0/1 would denote false/true respectively. * Signals would be even numbers, and negation would be handled by xor with 1. * The output signal for each gate or subckt could be implicitly generated just use the next signal number. * For ranges, we could use "start:cnt" to denote the sequence "start, start+2, ..., start + 2*(cnt- 1)". - "cnt" seems more intuitive when signals are restricted to even numbers. * We'd have subckts and specialized gates .and, .xor, and .mux. Here is a small example: .model test .inputs 3 # Inputs 2 4 6 .subckt and3 3 1 2:3 # 8 is implicit output .outputs 1 8 .end .model and3 .inputs 3 # Inputs 2 4 6 .and 2 4 # 8 output .and 6 8 # 10 output .outputs 1 10 .end */ /**Function************************************************************* Synopsis [Reads one entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Au_NtkRemapNum( Vec_Int_t * vNum2Obj, int Num ) { return Au_Var2Lit(Vec_IntEntry(vNum2Obj, Au_Lit2Var(Num)), Au_LitIsCompl(Num)); } /**Function************************************************************* Synopsis [Reads one entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Au_NtkParseCBlifNum( Vec_Int_t * vFanins, char * pToken, Vec_Int_t * vNum2Obj ) { char * pCur; int Num1, Num2, i; assert( pToken[0] >= '0' && pToken[0] <= '9' ); Num1 = atoi( pToken ); for ( pCur = pToken; *pCur; pCur++ ) if ( *pCur == ':' ) { Num2 = atoi( pCur+1 ); for ( i = 0; i < Num2; i++ ) Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num1 + i + i) ); return; } else if ( *pCur == '*' ) { Num2 = atoi( pCur+1 ); for ( i = 0; i < Num2; i++ ) Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num1) ); return; } assert( *pCur == 0 ); Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num1) ); } /**Function************************************************************* Synopsis [Parses CBLIF file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Au_Ntk_t * Au_NtkParseCBlif( char * pFileName ) { FILE * pFile; Au_Man_t * pMan; Au_Ntk_t * pRoot = NULL; Au_Obj_t * pBox, * pFan; char * pBuffer, * pCur; Vec_Int_t * vLines, * vNum2Obj, * vFanins; int i, k, j, Id, nInputs, nOutputs; int Line, Num, Func; // read the file pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\".\n", pFileName ); return NULL; } pBuffer = Extra_FileRead( pFile ); fclose( pFile ); // split into lines vLines = Vec_IntAlloc( 1000 ); Vec_IntPush( vLines, 0 ); for ( pCur = pBuffer; *pCur; pCur++ ) if ( *pCur == '\n' ) { *pCur = 0; Vec_IntPush( vLines, pCur - pBuffer + 1 ); } // start the manager pMan = Au_ManAlloc( pFileName ); // parse the lines vNum2Obj = Vec_IntAlloc( 1000 ); vFanins = Vec_IntAlloc( 1000 ); Vec_IntForEachEntry( vLines, Line, i ) { pCur = strtok( pBuffer + Line, " \t\r" ); if ( pCur == NULL || *pCur == '#' ) continue; if ( *pCur != '.' ) { printf( "Cannot read directive in line %d: \"%s\".\n", i, pBuffer + Line ); continue; } Vec_IntClear( vFanins ); if ( !strcmp(pCur, ".and") ) { for ( k = 0; k < 2; k++ ) { pCur = strtok( NULL, " \t\r" ); Num = atoi( pCur ); Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num) ); } Id = Au_NtkCreateNode( pRoot, vFanins, 1 ); Vec_IntPush( vNum2Obj, Id ); } else if ( !strcmp(pCur, ".xor") ) { for ( k = 0; k < 2; k++ ) { pCur = strtok( NULL, " \t\r" ); Num = atoi( pCur ); Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num) ); } Id = Au_NtkCreateNode( pRoot, vFanins, 2 ); Vec_IntPush( vNum2Obj, Id ); } else if ( !strcmp(pCur, ".mux") ) { for ( k = 0; k < 3; k++ ) { pCur = strtok( NULL, " \t\r" ); Num = atoi( pCur ); Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num) ); } Id = Au_NtkCreateNode( pRoot, vFanins, 3 ); Vec_IntPush( vNum2Obj, Id ); } else if ( !strcmp(pCur, ".subckt") ) { pCur = strtok( NULL, " \t\r" ); Func = pCur - pBuffer; pCur = strtok( NULL, " \t\r" ); nInputs = atoi( pCur ); pCur = strtok( NULL, " \t\r" ); nOutputs = atoi( pCur ); while ( 1 ) { pCur = strtok( NULL, " \t\r" ); if ( pCur == NULL || *pCur == '#' ) break; Au_NtkParseCBlifNum( vFanins, pCur, vNum2Obj ); } assert( Vec_IntSize(vFanins) == nInputs ); Id = Au_NtkCreateBox( pRoot, vFanins, nOutputs, Func ); pBox = Au_NtkObj( pRoot, Id ); Au_BoxForEachFanoutId( pBox, Num, k ) Vec_IntPush( vNum2Obj, Num ); } else if ( !strcmp(pCur, ".model") ) { pCur = strtok( NULL, " \t\r" ); pRoot = Au_NtkAlloc( pMan, pCur ); Id = Au_NtkCreateConst0( pRoot ); Vec_IntClear( vNum2Obj ); Vec_IntPush( vNum2Obj, Id ); } else if ( !strcmp(pCur, ".inputs") ) { pCur = strtok( NULL, " \t\r" ); Num = atoi( pCur ); for ( k = 0; k < Num; k++ ) Vec_IntPush( vNum2Obj, Au_NtkCreatePi(pRoot) ); } else if ( !strcmp(pCur, ".outputs") ) { pCur = strtok( NULL, " \t\r" ); nOutputs = atoi( pCur ); while ( 1 ) { pCur = strtok( NULL, " \t\r" ); if ( pCur == NULL || *pCur == '#' ) break; Au_NtkParseCBlifNum( vFanins, pCur, vNum2Obj ); } assert( Vec_IntSize(vFanins) == nOutputs ); Vec_IntForEachEntry( vFanins, Num, k ) Au_NtkCreatePo( pRoot, Num ); } else if ( strcmp(pCur, ".end") ) printf( "Unknown directive in line %d: \"%s\".\n", i, pBuffer + Line ); } Vec_IntFree( vFanins ); Vec_IntFree( vNum2Obj ); Vec_IntFree( vLines ); // set pointers to models Au_ManForEachNtk( pMan, pRoot, i ) Au_NtkForEachBox( pRoot, pBox, k ) { pBox->Func = Au_ManFindNtk( pMan, pBuffer + pBox->Func ); assert( pBox->Func > 0 ); Au_BoxForEachFanout( pBox, pFan, j ) pFan->Func = pBox->Func; } ABC_FREE( pBuffer ); // order models in topological order pRoot = Au_ManNtkRoot( pMan ); Au_ManReorderModels( pMan, pRoot ); return pRoot; } ABC_NAMESPACE_IMPL_END #include "abc.h" #include "aig/gia/gia.h" ABC_NAMESPACE_IMPL_START extern Vec_Ptr_t * Abc_NtkDfsBoxes( Abc_Ntk_t * pNtk ); extern int Abc_NtkDeriveFlatGiaSop( Gia_Man_t * pGia, int * gFanins, char * pSop ); extern int Abc_NtkCheckRecursive( Abc_Ntk_t * pNtk ); /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Au_NtkDeriveFlatGia_rec( Gia_Man_t * pGia, Au_Ntk_t * p ) { Au_Obj_t * pObj, * pTerm; int i, k, Lit; Au_NtkForEachPi( p, pTerm, i ) assert( Au_ObjCopy(pTerm) >= 0 ); if ( strcmp(Au_NtkName(p), "ref_egcd") == 0 ) { printf( "Replacing one instance of recursive model \"%s\" by a black box.\n", "ref_egcd" ); Au_NtkForEachPo( p, pTerm, i ) Au_ObjSetCopy( pTerm, Gia_ManAppendCi(pGia) ); return; } Au_NtkForEachObj( p, pObj, i ) { if ( Au_ObjIsNode(pObj) ) { if ( p->pMan->pFuncs ) { int gFanins[16]; char * pSop = Abc_NamStr( p->pMan->pFuncs, pObj->Func ); assert( Au_ObjFaninNum(pObj) <= 16 ); assert( Au_ObjFaninNum(pObj) == Abc_SopGetVarNum(pSop) ); Au_ObjForEachFanin( pObj, pTerm, k ) { gFanins[k] = Au_ObjCopy(pTerm); assert( gFanins[k] >= 0 ); } Lit = Abc_NtkDeriveFlatGiaSop( pGia, gFanins, pSop ); } else { int Lit0, Lit1, Lit2; assert( pObj->Func >= 1 && pObj->Func <= 3 ); Lit0 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin0(pObj)), Au_ObjFaninC0(pObj) ); Lit1 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin1(pObj)), Au_ObjFaninC1(pObj) ); if ( pObj->Func == 1 ) Lit = Gia_ManHashAnd( pGia, Lit0, Lit1 ); else if ( pObj->Func == 2 ) Lit = Gia_ManHashXor( pGia, Lit0, Lit1 ); else if ( pObj->Func == 3 ) { Lit2 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin2(pObj)), Au_ObjFaninC2(pObj) ); Lit = Gia_ManHashMux( pGia, Lit0, Lit1, Lit2 ); } else assert( 0 ); } assert( Lit >= 0 ); Au_ObjSetCopy( pObj, Lit ); } else if ( Au_ObjIsBox(pObj) ) { Au_Ntk_t * pModel = Au_ObjModel(pObj); Au_NtkCleanCopy( pModel ); // check the match between the number of actual and formal parameters assert( Au_ObjFaninNum(pObj) == Au_NtkPiNum(pModel) ); assert( Au_BoxFanoutNum(pObj) == Au_NtkPoNum(pModel) ); // assign PIs Au_ObjForEachFanin( pObj, pTerm, k ) Au_ObjSetCopy( Au_NtkPi(pModel, k), Au_ObjCopy(pTerm) ); // call recursively Au_NtkDeriveFlatGia_rec( pGia, pModel ); // assign POs Au_BoxForEachFanout( pObj, pTerm, k ) Au_ObjSetCopy( pTerm, Au_ObjCopy(Au_NtkPo(pModel, k)) ); } else if ( Au_ObjIsConst0(pObj) ) Au_ObjSetCopy( pObj, 0 ); } Au_NtkForEachPo( p, pTerm, i ) { Lit = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin0(pTerm)), Au_ObjFaninC0(pTerm) ); Au_ObjSetCopy( pTerm, Lit ); } Au_NtkForEachPo( p, pTerm, i ) assert( Au_ObjCopy(pTerm) >= 0 ); // p->pMan->nGiaObjMax = Abc_MaxInt( p->pMan->nGiaObjMax, Gia_ManObjNum(pGia) ); } /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Au_NtkDeriveFlatGia( Au_Ntk_t * p ) { Gia_Man_t * pTemp, * pGia = NULL; Au_Obj_t * pTerm; int i; printf( "Collapsing model \"%s\"...\n", Au_NtkName(p) ); Au_NtkCleanCopy( p ); // start the network pGia = Gia_ManStart( (1<<16) ); pGia->pName = Abc_UtilStrsav( Au_NtkName(p) ); // pGia->pSpec = Abc_UtilStrsav( Au_NtkSpec(p) ); Gia_ManHashAlloc( pGia ); Gia_ManFlipVerbose( pGia ); // create PIs Au_NtkForEachPi( p, pTerm, i ) Au_ObjSetCopy( pTerm, Gia_ManAppendCi(pGia) ); // recursively flatten hierarchy Au_NtkDeriveFlatGia_rec( pGia, p ); // create POs Au_NtkForEachPo( p, pTerm, i ) Gia_ManAppendCo( pGia, Au_ObjCopy(pTerm) ); // prepare return value // Gia_ManHashProfile( pGia ); Gia_ManHashStop( pGia ); Gia_ManSetRegNum( pGia, 0 ); pGia = Gia_ManCleanup( pTemp = pGia ); Gia_ManStop( pTemp ); return pGia; } // ternary simulation #define AU_VAL0 1 #define AU_VAL1 2 #define AU_VALX 3 static inline void Au_ObjSetXsim( Au_Obj_t * pObj, int Value ) { pObj->Value = Value; } static inline int Au_ObjGetXsim( Au_Obj_t * pObj ) { return pObj->Value; } static inline int Au_XsimInv( int Value ) { if ( Value == AU_VAL0 ) return AU_VAL1; if ( Value == AU_VAL1 ) return AU_VAL0; assert( Value == AU_VALX ); return AU_VALX; } static inline int Au_XsimAnd( int Value0, int Value1 ) { if ( Value0 == AU_VAL0 || Value1 == AU_VAL0 ) return AU_VAL0; if ( Value0 == AU_VALX || Value1 == AU_VALX ) return AU_VALX; assert( Value0 == AU_VAL1 && Value1 == AU_VAL1 ); return AU_VAL1; } static inline int Au_XsimXor( int Value0, int Value1 ) { if ( Value0 == AU_VALX || Value1 == AU_VALX ) return AU_VALX; if ( (Value0 == AU_VAL0) == (Value1 == AU_VAL0) ) return AU_VAL0; return AU_VAL1; } static inline int Au_XsimMux( int ValueC, int Value1, int Value0 ) { if ( ValueC == AU_VAL0 ) return Value0; if ( ValueC == AU_VAL1 ) return Value1; if ( Value0 == AU_VAL0 && Value1 == AU_VAL0 ) return AU_VAL0; if ( Value0 == AU_VAL1 && Value1 == AU_VAL1 ) return AU_VAL1; return AU_VALX; } static inline int Au_ObjGetXsimFan0( Au_Obj_t * pObj ) { int Value = Au_ObjGetXsim( Au_ObjFanin0(pObj) ); return Au_ObjFaninC0(pObj) ? Au_XsimInv(Value) : Value; } static inline int Au_ObjGetXsimFan1( Au_Obj_t * pObj ) { int Value = Au_ObjGetXsim( Au_ObjFanin1(pObj) ); return Au_ObjFaninC1(pObj) ? Au_XsimInv(Value) : Value; } static inline int Au_ObjGetXsimFan2( Au_Obj_t * pObj ) { int Value = Au_ObjGetXsim( Au_ObjFanin2(pObj) ); return Au_ObjFaninC2(pObj) ? Au_XsimInv(Value) : Value; } /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Au_NtkTerSimulate_rec( Au_Ntk_t * p ) { Au_Obj_t * pObj = NULL, * pTerm; int i, k; Au_NtkForEachPi( p, pTerm, i ) { assert( Au_ObjGetXsim(pTerm) > 0 ); if ( Au_ObjGetXsim(pTerm) == AU_VALX ) p->pMan->nPortsNC++; else if ( Au_ObjGetXsim(pTerm) == AU_VAL0 ) p->pMan->nPortsC0++; else p->pMan->nPortsC1++; } if ( strcmp(Au_NtkName(p), "ref_egcd") == 0 ) { printf( "Replacing one instance of recursive model \"%s\" by a black box.\n", "ref_egcd" ); Au_NtkForEachPo( p, pTerm, i ) Au_ObjSetXsim( pTerm, AU_VALX ); return; } Au_NtkForEachObj( p, pObj, i ) { if ( Au_ObjIsNode(pObj) ) { if ( pObj->Func == 1 ) Au_ObjSetXsim( pObj, Au_XsimAnd(Au_ObjGetXsimFan0(pObj), Au_ObjGetXsimFan1(pObj)) ); else if ( pObj->Func == 2 ) Au_ObjSetXsim( pObj, Au_XsimXor(Au_ObjGetXsimFan0(pObj), Au_ObjGetXsimFan1(pObj)) ); else if ( pObj->Func == 3 ) Au_ObjSetXsim( pObj, Au_XsimMux(Au_ObjGetXsimFan0(pObj), Au_ObjGetXsimFan1(pObj), Au_ObjGetXsimFan2(pObj)) ); else assert( 0 ); } else if ( Au_ObjIsBox(pObj) ) { Au_Ntk_t * pModel = Au_ObjModel(pObj); // check the match between the number of actual and formal parameters assert( Au_ObjFaninNum(pObj) == Au_NtkPiNum(pModel) ); assert( Au_BoxFanoutNum(pObj) == Au_NtkPoNum(pModel) ); // assign PIs Au_ObjForEachFanin( pObj, pTerm, k ) Au_ObjSetXsim( Au_NtkPi(pModel, k), Au_ObjGetXsim(pTerm) ); // call recursively Au_NtkTerSimulate_rec( pModel ); // assign POs Au_BoxForEachFanout( pObj, pTerm, k ) Au_ObjSetXsim( pTerm, Au_ObjGetXsim(Au_NtkPo(pModel, k)) ); } else if ( Au_ObjIsConst0(pObj) ) Au_ObjSetXsim( pObj, AU_VAL0 ); } Au_NtkForEachPo( p, pTerm, i ) Au_ObjSetXsim( pTerm, Au_ObjGetXsimFan0(pObj) ); Au_NtkForEachPo( p, pTerm, i ) { assert( Au_ObjGetXsim(pTerm) > 0 ); if ( Au_ObjGetXsim(pTerm) == AU_VALX ) p->pMan->nPortsNC++; else if ( Au_ObjGetXsim(pTerm) == AU_VAL0 ) p->pMan->nPortsC0++; else p->pMan->nPortsC1++; } } /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Au_NtkTerSimulate( Au_Ntk_t * p ) { Au_Obj_t * pTerm; int i, Counter[2] = {0}; assert( p->pMan->pFuncs == NULL ); printf( "Collapsing model \"%s\"...\n", Au_NtkName(p) ); // create PIs Au_NtkForEachPi( p, pTerm, i ) Au_ObjSetXsim( pTerm, AU_VALX ); // recursively flatten hierarchy p->pMan->nPortsC0 = 0; p->pMan->nPortsC1 = 0; p->pMan->nPortsNC = 0; Au_NtkTerSimulate_rec( p ); // analyze outputs Au_NtkForEachPo( p, pTerm, i ) if ( Au_ObjGetXsim(pTerm) == AU_VAL0 ) Counter[0]++; else if ( Au_ObjGetXsim(pTerm) == AU_VAL1 ) Counter[1]++; // print results printf( "Const0 outputs =%15d. Const1 outputs =%15d. Total outputs =%15d.\n", Counter[0], Counter[1], Au_NtkPoNum(p) ); printf( "Const0 ports = %.0f. Const1 ports = %.0f. Non-const ports= %.0f. Total ports = %.0f.\n", p->pMan->nPortsC0, p->pMan->nPortsC1, p->pMan->nPortsNC, p->pMan->nPortsC0 + p->pMan->nPortsC1 + p->pMan->nPortsNC ); } /**Function************************************************************* Synopsis [Duplicates ABC network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Au_Ntk_t * Au_NtkDerive( Au_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vOrder ) { Au_Ntk_t * p; Au_Obj_t * pAuObj; Abc_Obj_t * pObj, * pTerm; // Vec_Ptr_t * vOrder; Vec_Int_t * vFanins; int i, k, iFunc; assert( Abc_NtkIsNetlist(pNtk) ); Abc_NtkCleanCopy( pNtk ); p = Au_NtkAlloc( pMan, Abc_NtkName(pNtk) ); // copy PIs Abc_NtkForEachPi( pNtk, pTerm, i ) Abc_ObjFanout0(pTerm)->iTemp = Au_NtkCreatePi(p); // copy nodes and boxes vFanins = Vec_IntAlloc( 100 ); // vOrder = Abc_NtkDfsBoxes( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) { Vec_IntClear( vFanins ); if ( Abc_ObjIsNode(pObj) ) { Abc_ObjForEachFanin( pObj, pTerm, k ) Vec_IntPush( vFanins, Au_Var2Lit(pTerm->iTemp, 0) ); iFunc = Abc_NamStrFindOrAdd( pMan->pFuncs, (char *)pObj->pData, NULL ); Abc_ObjFanout0(pObj)->iTemp = Au_NtkCreateNode(p, vFanins, iFunc); continue; } assert( Abc_ObjIsBox(pObj) ); Abc_ObjForEachFanin( pObj, pTerm, k ) Vec_IntPush( vFanins, Au_Var2Lit(Abc_ObjFanin0(pTerm)->iTemp, 0) ); pObj->iTemp = Au_NtkCreateBox(p, vFanins, Abc_ObjFanoutNum(pObj), ((Abc_Ntk_t *)pObj->pData)->iStep ); pAuObj = Au_NtkObj(p, pObj->iTemp); Abc_ObjForEachFanout( pObj, pTerm, k ) Abc_ObjFanout0(pTerm)->iTemp = Au_ObjFanout(pAuObj, k); } // Vec_PtrFree( vOrder ); Vec_IntFree( vFanins ); // copy POs Abc_NtkForEachPo( pNtk, pTerm, i ) Au_NtkCreatePo( p, Au_Var2Lit(Abc_ObjFanin0(pTerm)->iTemp, 0) ); // Au_NtkPrintStats( p ); return p; } Gia_Man_t * Au_ManDeriveTest( Abc_Ntk_t * pRoot ) { extern Vec_Ptr_t * Abc_NtkCollectHie( Abc_Ntk_t * pNtk ); // char * pModelName = NULL; char * pModelName = "path_0_r_x_lhs"; Gia_Man_t * pGia = NULL; Vec_Ptr_t * vOrder, * vModels; Abc_Ntk_t * pMod; Au_Man_t * pMan; Au_Ntk_t * pNtk = NULL; abctime clk1, clk2 = 0, clk3 = 0, clk = Abc_Clock(); int i; clk1 = Abc_Clock(); pMan = Au_ManAlloc( pRoot->pDesign ? pRoot->pDesign->pName : pRoot->pName ); pMan->pFuncs = Abc_NamStart( 100, 16 ); clk2 += Abc_Clock() - clk1; vModels = Abc_NtkCollectHie( pRoot ); Vec_PtrForEachEntry( Abc_Ntk_t *, vModels, pMod, i ) { vOrder = Abc_NtkDfsBoxes( pMod ); clk1 = Abc_Clock(); pNtk = Au_NtkDerive( pMan, pMod, vOrder ); pMod->iStep = pNtk->Id; pMod->pData = pNtk; clk2 += Abc_Clock() - clk1; Vec_PtrFree( vOrder ); } Vec_PtrFree( vModels ); // order models in topological order Au_ManReorderModels( pMan, pNtk ); // print statistics Au_ManPrintStats( pMan ); Au_ManCountThings( pNtk->pMan ); // select network if ( pModelName ) { pNtk = Au_ManFindNtkP( pMan, pModelName ); if ( pNtk == NULL ) printf( "Could not find module \"%s\".\n", pModelName ); } if ( pNtk == NULL ) pNtk = (Au_Ntk_t *)pRoot->pData; // if ( !Abc_NtkCheckRecursive(pRoot) ) { clk1 = Abc_Clock(); pGia = Au_NtkDeriveFlatGia( pNtk ); clk3 = Abc_Clock() - clk1; // printf( "GIA objects max = %d.\n", pMan->nGiaObjMax ); } // clk1 = Abc_Clock(); // Au_NtkSuppSizeTest( (Au_Ntk_t *)pRoot->pData ); // clk4 = Abc_Clock() - clk1; clk1 = Abc_Clock(); Au_ManDelete( pMan ); clk2 += Abc_Clock() - clk1; Abc_PrintTime( 1, "Time all ", Abc_Clock() - clk ); Abc_PrintTime( 1, "Time new ", clk2 ); Abc_PrintTime( 1, "Time GIA ", clk3 ); // Abc_PrintTime( 1, "Time supp", clk4 ); return pGia; } /**Function************************************************************* Synopsis [Performs hierarchical equivalence checking.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abc_NtkHieCecTest2( char * pFileName, char * pModelName, int fVerbose ) { int fSimulation = 0; Gia_Man_t * pGia = NULL; Au_Ntk_t * pNtk, * pNtkClp = NULL; abctime clk1 = 0, clk = Abc_Clock(); // read hierarchical netlist pNtk = Au_NtkParseCBlif( pFileName ); if ( pNtk == NULL ) { printf( "Reading CBLIF file has failed.\n" ); return NULL; } if ( pNtk->pMan == NULL || pNtk->pMan->vNtks.pArray == NULL ) { printf( "There is no hierarchy information.\n" ); Au_NtkFree( pNtk ); return NULL; } Abc_PrintTime( 1, "Reading file", Abc_Clock() - clk ); if ( fVerbose ) { Au_ManPrintBoxInfo( pNtk ); // Au_ManPrintBoxInfoSorted( pNtk ); Au_ManPrintStats( pNtk->pMan ); } Au_ManCountThings( pNtk->pMan ); // select network if ( pModelName ) pNtkClp = Au_ManFindNtkP( pNtk->pMan, pModelName ); if ( pNtkClp == NULL ) pNtkClp = pNtk; // check if the model is recursive Au_NtkCheckRecursive( pNtkClp ); // collapse clk1 = Abc_Clock(); if ( fSimulation ) { Au_NtkTerSimulate( pNtkClp ); Abc_PrintTime( 1, "Time sim ", Abc_Clock() - clk1 ); } else { pGia = Au_NtkDeriveFlatGia( pNtkClp ); Abc_PrintTime( 1, "Time GIA ", Abc_Clock() - clk1 ); } // delete Au_ManDelete( pNtk->pMan ); Abc_PrintTime( 1, "Time all ", Abc_Clock() - clk ); return pGia; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END