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