abcBridge-0.10.0.0: abc-build/src/base/abc/abcHieNew.c
/**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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#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