diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2007-09-30 08:01:00 -0700 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2007-09-30 08:01:00 -0700 |
commit | e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7 (patch) | |
tree | de3ffe87c3e17950351e3b7d97fa18318bd5ea9a /abc70930/src/base | |
parent | 7d7e60f2dc84393cd4c5db22d2eaf7b1fb1a79b2 (diff) | |
download | abc-e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7.tar.gz abc-e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7.tar.bz2 abc-e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7.zip |
Version abc70930
Diffstat (limited to 'abc70930/src/base')
137 files changed, 81467 insertions, 0 deletions
diff --git a/abc70930/src/base/.DS_Store b/abc70930/src/base/.DS_Store Binary files differnew file mode 100644 index 00000000..a4d90d14 --- /dev/null +++ b/abc70930/src/base/.DS_Store diff --git a/abc70930/src/base/abc/abc.h b/abc70930/src/base/abc/abc.h new file mode 100644 index 00000000..2e2b379b --- /dev/null +++ b/abc70930/src/base/abc/abc.h @@ -0,0 +1,929 @@ +/**CFile**************************************************************** + + FileName [abc.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __ABC_H__ +#define __ABC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <time.h> + +#include "cuddInt.h" +#include "hop.h" +#include "extra.h" +#include "vec.h" +#include "stmm.h" +#include "nm.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// network types +typedef enum { + ABC_NTK_NONE = 0, // 0: unknown + ABC_NTK_NETLIST, // 1: network with PIs/POs, latches, nodes, and nets + ABC_NTK_LOGIC, // 2: network with PIs/POs, latches, and nodes + ABC_NTK_STRASH, // 3: structurally hashed AIG (two input AND gates with c-attributes on edges) + ABC_NTK_OTHER // 4: unused +} Abc_NtkType_t; + +// network functionality +typedef enum { + ABC_FUNC_NONE = 0, // 0: unknown + ABC_FUNC_SOP, // 1: sum-of-products + ABC_FUNC_BDD, // 2: binary decision diagrams + ABC_FUNC_AIG, // 3: and-inverter graphs + ABC_FUNC_MAP, // 4: standard cell library + ABC_FUNC_BLIFMV, // 5: BLIF-MV node functions + ABC_FUNC_BLACKBOX, // 6: black box about which nothing is known + ABC_FUNC_OTHER // 7: unused +} Abc_NtkFunc_t; + +// Supported type/functionality combinations: +/*------------------------------------------| +| | SOP | BDD | AIG | Map | +|-----------|-------|-------|-------|-------| +| Netlist | x | | x | x | +|-----------|-------|-------|-------|-------| +| Logic | x | x | x | x | +|-----------|-------|-------|-------|-------| +| Strash | | | x | | +--------------------------------------------|*/ + +// object types +typedef enum { + ABC_OBJ_NONE = 0, // 0: unknown + ABC_OBJ_CONST1, // 1: constant 1 node (AIG only) + ABC_OBJ_PIO, // 2: inout terminal + ABC_OBJ_PI, // 3: primary input terminal + ABC_OBJ_PO, // 4: primary output terminal + ABC_OBJ_BI, // 5: box input terminal + ABC_OBJ_BO, // 6: box output terminal + ABC_OBJ_ASSERT, // 7: assertion terminal + ABC_OBJ_NET, // 8: net + ABC_OBJ_NODE, // 9: node + ABC_OBJ_LATCH, // 10: latch + ABC_OBJ_WHITEBOX, // 11: box with known contents + ABC_OBJ_BLACKBOX, // 12: box with unknown contents + ABC_OBJ_NUMBER // 13: unused +} Abc_ObjType_t; + +// latch initial values +typedef enum { + ABC_INIT_NONE = 0, // 0: unknown + ABC_INIT_ZERO, // 1: zero + ABC_INIT_ONE, // 2: one + ABC_INIT_DC, // 3: don't-care + ABC_INIT_OTHER // 4: unused +} Abc_InitType_t; + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//typedef int bool; +#ifndef __cplusplus +#ifndef bool +#define bool int +#endif +#endif + +#ifndef SINT64 +#define SINT64 + +#ifdef _WIN32 +typedef signed __int64 sint64; // compatible with MS VS 6.0 +#else +typedef long long sint64; +#endif + +#endif + +typedef struct Abc_Lib_t_ Abc_Lib_t; +typedef struct Abc_Ntk_t_ Abc_Ntk_t; +typedef struct Abc_Obj_t_ Abc_Obj_t; +typedef struct Abc_Aig_t_ Abc_Aig_t; +typedef struct Abc_ManTime_t_ Abc_ManTime_t; +typedef struct Abc_ManCut_t_ Abc_ManCut_t; +typedef struct Abc_Time_t_ Abc_Time_t; + +struct Abc_Time_t_ +{ + float Rise; + float Fall; + float Worst; +}; + +struct Abc_Obj_t_ // 12 words +{ + // high-level information + Abc_Ntk_t * pNtk; // the host network + int Id; // the object ID + int TravId; // the traversal ID (if changed, update Abc_NtkIncrementTravId) + // internal information + unsigned Type : 4; // the object type + unsigned fMarkA : 1; // the multipurpose mark + unsigned fMarkB : 1; // the multipurpose mark + unsigned fMarkC : 1; // the multipurpose mark + unsigned fPhase : 1; // the flag to mark the phase of equivalent node + unsigned fExor : 1; // marks AIG node that is a root of EXOR + unsigned fPersist: 1; // marks the persistant AIG node + unsigned fCompl0 : 1; // complemented attribute of the first fanin in the AIG + unsigned fCompl1 : 1; // complemented attribute of the second fanin in the AIG + unsigned Level : 20; // the level of the node + // connectivity + Vec_Int_t vFanins; // the array of fanins + Vec_Int_t vFanouts; // the array of fanouts + // miscellaneous + void * pData; // the network specific data (SOP, BDD, gate, equiv class, etc) + Abc_Obj_t * pNext; // the next pointer in the hash table + Abc_Obj_t * pCopy; // the copy of this object + Hop_Obj_t * pEquiv; // pointer to the HAIG node +}; + +struct Abc_Ntk_t_ +{ + // general information + Abc_NtkType_t ntkType; // type of the network + Abc_NtkFunc_t ntkFunc; // functionality of the network + char * pName; // the network name + char * pSpec; // the name of the spec file if present + Nm_Man_t * pManName; // name manager (stores names of objects) + // components of the network + Vec_Ptr_t * vObjs; // the array of all objects (net, nodes, latches, etc) + Vec_Ptr_t * vPis; // the array of primary inputs + Vec_Ptr_t * vPos; // the array of primary outputs + Vec_Ptr_t * vCis; // the array of combinational inputs (PIs, latches) + Vec_Ptr_t * vCos; // the array of combinational outputs (POs, asserts, latches) + Vec_Ptr_t * vPios; // the array of PIOs + Vec_Ptr_t * vAsserts; // the array of assertions + Vec_Ptr_t * vBoxes; // the array of boxes + // the number of living objects + int nObjs; // the number of live objs + int nObjCounts[ABC_OBJ_NUMBER]; // the number of objects by type + // the backup network and the step number + Abc_Ntk_t * pNetBackup; // the pointer to the previous backup network + int iStep; // the generation number for the given network + // hierarchy + Abc_Lib_t * pDesign; + short fHieVisited; // flag to mark the visited network + short fHiePath; // flag to mark the network on the path + // miscellaneous data members + int nTravIds; // the unique traversal IDs of nodes + Extra_MmFixed_t * pMmObj; // memory manager for objects + Extra_MmStep_t * pMmStep; // memory manager for arrays + void * pManFunc; // functionality manager (AIG manager, BDD manager, or memory manager for SOPs) +// Abc_Lib_t * pVerLib; // for structural verilog designs + Abc_ManTime_t * pManTime; // the timing manager (for mapped networks) stores arrival/required times for all nodes + void * pManCut; // the cut manager (for AIGs) stores information about the cuts computed for the nodes + int LevelMax; // maximum number of levels + Vec_Int_t * vLevelsR; // level in the reverse topological order (for AIGs) + Vec_Ptr_t * vSupps; // CO support information + int * pModel; // counter-example (for miters) + Abc_Ntk_t * pExdc; // the EXDC network (if given) + void * pData; // misc + Abc_Ntk_t * pCopy; + Hop_Man_t * pHaig; // history AIG + // node attributes + Vec_Ptr_t * vAttrs; // managers of various node attributes (node functionality, global BDDs, etc) +}; + +struct Abc_Lib_t_ +{ + char * pName; // the name of the library + void * pManFunc; // functionality manager for the nodes + Vec_Ptr_t * vTops; // the array of top-level modules + Vec_Ptr_t * vModules; // the array of modules + st_table * tModules; // the table hashing module names into their networks + Abc_Lib_t * pLibrary; // the library used to map this design + void * pGenlib; // the genlib library used to map this design +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// maximum/minimum operators +#define ABC_MIN(a,b) (((a) < (b))? (a) : (b)) +#define ABC_MAX(a,b) (((a) > (b))? (a) : (b)) +#define ABC_ABS(a) (((a) >= 0)? (a) :-(a)) +#define ABC_INFINITY (100000000) + +// transforming floats into ints and back +static inline int Abc_Float2Int( float Val ) { return *((int *)&Val); } +static inline float Abc_Int2Float( int Num ) { return *((float *)&Num); } +static inline int Abc_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } +static inline int Abc_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline int Abc_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } +static inline void Abc_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } +static inline void Abc_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } +static inline unsigned Abc_InfoRandomWord() { return ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())); } // #define RAND_MAX 0x7fff +static inline void Abc_InfoRandom( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = Abc_InfoRandomWord(); } +static inline void Abc_InfoClear( unsigned * p, int nWords ) { memset( p, 0, sizeof(unsigned) * nWords ); } +static inline void Abc_InfoFill( unsigned * p, int nWords ) { memset( p, 0xff, sizeof(unsigned) * nWords );} +static inline void Abc_InfoNot( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = ~p[i]; } +static inline int Abc_InfoIsZero( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( p[i] ) return 0; return 1; } +static inline int Abc_InfoIsOne( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~p[i] ) return 0; return 1; } +static inline void Abc_InfoCopy( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = q[i]; } +static inline void Abc_InfoAnd( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] &= q[i]; } +static inline void Abc_InfoOr( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= q[i]; } +static inline void Abc_InfoXor( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] ^= q[i]; } +static inline int Abc_InfoIsOrOne( unsigned * p, unsigned * q, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i]) ) return 0; return 1; } +static inline int Abc_InfoIsOrOne3( unsigned * p, unsigned * q, unsigned * r, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i] | r[i]) ) return 0; return 1; } + +// checking the network type +static inline bool Abc_NtkIsNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_NETLIST; } +static inline bool Abc_NtkIsLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_LOGIC; } +static inline bool Abc_NtkIsStrash( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_STRASH; } + +static inline bool Abc_NtkHasSop( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP; } +static inline bool Abc_NtkHasBdd( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD; } +static inline bool Abc_NtkHasAig( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG; } +static inline bool Abc_NtkHasMapping( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP; } +static inline bool Abc_NtkHasBlifMv( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLIFMV; } +static inline bool Abc_NtkHasBlackbox( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLACKBOX; } + +static inline bool Abc_NtkIsSopNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_NETLIST; } +static inline bool Abc_NtkIsAigNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_NETLIST; } +static inline bool Abc_NtkIsMappedNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_NETLIST; } +static inline bool Abc_NtkIsBlifMvNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLIFMV && pNtk->ntkType == ABC_NTK_NETLIST; } +static inline bool Abc_NtkIsSopLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_LOGIC ; } +static inline bool Abc_NtkIsBddLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD && pNtk->ntkType == ABC_NTK_LOGIC ; } +static inline bool Abc_NtkIsAigLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_LOGIC ; } +static inline bool Abc_NtkIsMappedLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_LOGIC ; } + +// reading data members of the network +static inline char * Abc_NtkName( Abc_Ntk_t * pNtk ) { return pNtk->pName; } +static inline char * Abc_NtkSpec( Abc_Ntk_t * pNtk ) { return pNtk->pSpec; } +static inline int Abc_NtkTravId( Abc_Ntk_t * pNtk ) { return pNtk->nTravIds; } +static inline Abc_Ntk_t * Abc_NtkExdc( Abc_Ntk_t * pNtk ) { return pNtk->pExdc; } +static inline Abc_Ntk_t * Abc_NtkBackup( Abc_Ntk_t * pNtk ) { return pNtk->pNetBackup; } +static inline int Abc_NtkStep ( Abc_Ntk_t * pNtk ) { return pNtk->iStep; } + +// setting data members of the network +static inline void Abc_NtkSetName ( Abc_Ntk_t * pNtk, char * pName ) { pNtk->pName = pName; } +static inline void Abc_NtkSetSpec ( Abc_Ntk_t * pNtk, char * pName ) { pNtk->pSpec = pName; } +static inline void Abc_NtkSetBackup( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNetBackup ) { pNtk->pNetBackup = pNetBackup; } +static inline void Abc_NtkSetStep ( Abc_Ntk_t * pNtk, int iStep ) { pNtk->iStep = iStep; } + +// getting the number of objects +static inline int Abc_NtkObjNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjs; } +static inline int Abc_NtkObjNumMax( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vObjs); } +static inline int Abc_NtkPiNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vPis); } +static inline int Abc_NtkPoNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vPos); } +static inline int Abc_NtkCiNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCis); } +static inline int Abc_NtkCoNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCos); } +static inline int Abc_NtkAssertNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vAsserts); } +static inline int Abc_NtkBoxNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vBoxes); } +static inline int Abc_NtkBiNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BI]; } +static inline int Abc_NtkBoNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BO]; } +static inline int Abc_NtkNetNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_NET]; } +static inline int Abc_NtkNodeNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_NODE]; } +static inline int Abc_NtkLatchNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_LATCH]; } +static inline int Abc_NtkWhiteboxNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_WHITEBOX]; } +static inline int Abc_NtkBlackboxNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BLACKBOX]; } +static inline bool Abc_NtkIsComb( Abc_Ntk_t * pNtk ) { return Abc_NtkLatchNum(pNtk) == 0; } +static inline bool Abc_NtkHasOnlyLatchBoxes(Abc_Ntk_t * pNtk ){ return Abc_NtkLatchNum(pNtk) == Abc_NtkBoxNum(pNtk); } + +// creating simple objects +extern Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); +static inline Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PI ); } +static inline Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PO ); } +static inline Abc_Obj_t * Abc_NtkCreateBi( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BI ); } +static inline Abc_Obj_t * Abc_NtkCreateBo( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BO ); } +static inline Abc_Obj_t * Abc_NtkCreateAssert( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_ASSERT ); } +static inline Abc_Obj_t * Abc_NtkCreateNet( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NET ); } +static inline Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NODE ); } +static inline Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_LATCH ); } +static inline Abc_Obj_t * Abc_NtkCreateWhitebox( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_WHITEBOX ); } +static inline Abc_Obj_t * Abc_NtkCreateBlackbox( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BLACKBOX ); } + +// reading objects +static inline Abc_Obj_t * Abc_NtkObj( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vObjs, i ); } +static inline Abc_Obj_t * Abc_NtkPi( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPis, i ); } +static inline Abc_Obj_t * Abc_NtkPo( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPos, i ); } +static inline Abc_Obj_t * Abc_NtkCi( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, i ); } +static inline Abc_Obj_t * Abc_NtkCo( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i ); } +static inline Abc_Obj_t * Abc_NtkAssert( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vAsserts, i );} +static inline Abc_Obj_t * Abc_NtkBox( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i ); } + +// working with complemented attributes of objects +static inline bool Abc_ObjIsComplement( Abc_Obj_t * p ) { return (bool)((unsigned long)p & (unsigned long)01); } +static inline Abc_Obj_t * Abc_ObjRegular( Abc_Obj_t * p ) { return (Abc_Obj_t *)((unsigned long)p & ~(unsigned long)01); } +static inline Abc_Obj_t * Abc_ObjNot( Abc_Obj_t * p ) { return (Abc_Obj_t *)((unsigned long)p ^ (unsigned long)01); } +static inline Abc_Obj_t * Abc_ObjNotCond( Abc_Obj_t * p, int c ) { return (Abc_Obj_t *)((unsigned long)p ^ (unsigned long)(c!=0)); } + +// reading data members of the object +static inline unsigned Abc_ObjType( Abc_Obj_t * pObj ) { return pObj->Type; } +static inline unsigned Abc_ObjId( Abc_Obj_t * pObj ) { return pObj->Id; } +static inline int Abc_ObjTravId( Abc_Obj_t * pObj ) { return pObj->TravId; } +static inline int Abc_ObjLevel( Abc_Obj_t * pObj ) { return pObj->Level; } +static inline Vec_Int_t * Abc_ObjFaninVec( Abc_Obj_t * pObj ) { return &pObj->vFanins; } +static inline Vec_Int_t * Abc_ObjFanoutVec( Abc_Obj_t * pObj ) { return &pObj->vFanouts; } +static inline Abc_Obj_t * Abc_ObjCopy( Abc_Obj_t * pObj ) { return pObj->pCopy; } +static inline Abc_Ntk_t * Abc_ObjNtk( Abc_Obj_t * pObj ) { return pObj->pNtk; } +static inline void * Abc_ObjData( Abc_Obj_t * pObj ) { return pObj->pData; } +static inline Hop_Obj_t * Abc_ObjEquiv( Abc_Obj_t * pObj ) { return pObj->pEquiv; } +static inline Abc_Obj_t * Abc_ObjCopyCond( Abc_Obj_t * pObj ) { return Abc_ObjRegular(pObj)->pCopy? Abc_ObjNotCond(Abc_ObjRegular(pObj)->pCopy, Abc_ObjIsComplement(pObj)) : NULL; } + +// setting data members of the network +static inline void Abc_ObjSetLevel( Abc_Obj_t * pObj, int Level ) { pObj->Level = Level; } +static inline void Abc_ObjSetCopy( Abc_Obj_t * pObj, Abc_Obj_t * pCopy ) { pObj->pCopy = pCopy; } +static inline void Abc_ObjSetData( Abc_Obj_t * pObj, void * pData ) { pObj->pData = pData; } + +// checking the object type +static inline bool Abc_ObjIsPio( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PIO; } +static inline bool Abc_ObjIsPi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI; } +static inline bool Abc_ObjIsPo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO; } +static inline bool Abc_ObjIsBi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BI; } +static inline bool Abc_ObjIsBo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BO; } +static inline bool Abc_ObjIsAssert( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_ASSERT; } +static inline bool Abc_ObjIsCi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_BO; } +static inline bool Abc_ObjIsCo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO || pObj->Type == ABC_OBJ_BI || pObj->Type == ABC_OBJ_ASSERT; } +static inline bool Abc_ObjIsTerm( Abc_Obj_t * pObj ) { return Abc_ObjIsCi(pObj) || Abc_ObjIsCo(pObj); } +static inline bool Abc_ObjIsNet( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NET; } +static inline bool Abc_ObjIsNode( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NODE; } +static inline bool Abc_ObjIsLatch( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH; } +static inline bool Abc_ObjIsBox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH || pObj->Type == ABC_OBJ_WHITEBOX || pObj->Type == ABC_OBJ_BLACKBOX; } +static inline bool Abc_ObjIsWhitebox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_WHITEBOX;} +static inline bool Abc_ObjIsBlackbox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BLACKBOX;} +static inline void Abc_ObjBlackboxToWhitebox( Abc_Obj_t * pObj ) { assert( Abc_ObjIsBlackbox(pObj) ); pObj->Type = ABC_OBJ_WHITEBOX; pObj->pNtk->nObjCounts[ABC_OBJ_BLACKBOX]--; pObj->pNtk->nObjCounts[ABC_OBJ_WHITEBOX]++; } + +// working with fanin/fanout edges +static inline int Abc_ObjFaninNum( Abc_Obj_t * pObj ) { return pObj->vFanins.nSize; } +static inline int Abc_ObjFanoutNum( Abc_Obj_t * pObj ) { return pObj->vFanouts.nSize; } +static inline int Abc_ObjFaninId( Abc_Obj_t * pObj, int i) { return pObj->vFanins.pArray[i]; } +static inline int Abc_ObjFaninId0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0]; } +static inline int Abc_ObjFaninId1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1]; } +static inline int Abc_ObjFanoutEdgeNum( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) { assert( Abc_NtkHasAig(pObj->pNtk) ); if ( Abc_ObjFaninId0(pFanout) == pObj->Id ) return 0; if ( Abc_ObjFaninId1(pFanout) == pObj->Id ) return 1; assert( 0 ); return -1; } +static inline Abc_Obj_t * Abc_ObjFanout( Abc_Obj_t * pObj, int i ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[i] ]; } +static inline Abc_Obj_t * Abc_ObjFanout0( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[0] ]; } +static inline Abc_Obj_t * Abc_ObjFanin( Abc_Obj_t * pObj, int i ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[i] ]; } +static inline Abc_Obj_t * Abc_ObjFanin0( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[0] ]; } +static inline Abc_Obj_t * Abc_ObjFanin1( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[1] ]; } +static inline Abc_Obj_t * Abc_ObjFanin0Ntk( Abc_Obj_t * pObj ) { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanin0(pObj) : pObj); } +static inline Abc_Obj_t * Abc_ObjFanout0Ntk( Abc_Obj_t * pObj ) { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanout0(pObj) : pObj); } +static inline bool Abc_ObjFaninC0( Abc_Obj_t * pObj ) { return pObj->fCompl0; } +static inline bool Abc_ObjFaninC1( Abc_Obj_t * pObj ) { return pObj->fCompl1; } +static inline bool Abc_ObjFaninC( Abc_Obj_t * pObj, int i ) { assert( i >=0 && i < 2 ); return i? pObj->fCompl1 : pObj->fCompl0; } +static inline void Abc_ObjSetFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1 = 1; else pObj->fCompl0 = 1; } +static inline void Abc_ObjXorFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1^= 1; else pObj->fCompl0^= 1; } +static inline Abc_Obj_t * Abc_ObjChild( Abc_Obj_t * pObj, int i ) { return Abc_ObjNotCond( Abc_ObjFanin(pObj,i), Abc_ObjFaninC(pObj,i) );} +static inline Abc_Obj_t * Abc_ObjChild0( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChild1( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj), Abc_ObjFaninC1(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChildCopy( Abc_Obj_t * pObj, int i ){ return Abc_ObjNotCond( Abc_ObjFanin(pObj,i)->pCopy, Abc_ObjFaninC(pObj,i) ); } +static inline Abc_Obj_t * Abc_ObjChild0Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChild1Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC1(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChild0Data( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin0(pObj)->pData, Abc_ObjFaninC0(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChild1Data( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin1(pObj)->pData, Abc_ObjFaninC1(pObj) ); } +static inline Hop_Obj_t * Abc_ObjChild0Equiv( Abc_Obj_t * pObj ) { return Hop_NotCond( Abc_ObjFanin0(pObj)->pEquiv, Abc_ObjFaninC0(pObj) ); } +static inline Hop_Obj_t * Abc_ObjChild1Equiv( Abc_Obj_t * pObj ) { return Hop_NotCond( Abc_ObjFanin1(pObj)->pEquiv, Abc_ObjFaninC1(pObj) ); } + +// checking the AIG node types +static inline bool Abc_AigNodeIsConst( Abc_Obj_t * pNode ) { assert(Abc_NtkIsStrash(Abc_ObjRegular(pNode)->pNtk)); return Abc_ObjRegular(pNode)->Type == ABC_OBJ_CONST1; } +static inline bool Abc_AigNodeIsAnd( Abc_Obj_t * pNode ) { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return Abc_ObjFaninNum(pNode) == 2; } +static inline bool Abc_AigNodeIsChoice( Abc_Obj_t * pNode ) { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return pNode->pData != NULL && Abc_ObjFanoutNum(pNode) > 0; } + +// handling persistent nodes +static inline int Abc_NodeIsPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); return pNode->fPersist; } +static inline void Abc_NodeSetPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 1; } +static inline void Abc_NodeClearPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 0; } + +// working with the traversal ID +static inline void Abc_NodeSetTravId( Abc_Obj_t * pNode, int TravId ) { pNode->TravId = TravId; } +static inline void Abc_NodeSetTravIdCurrent( Abc_Obj_t * pNode ) { pNode->TravId = pNode->pNtk->nTravIds; } +static inline void Abc_NodeSetTravIdPrevious( Abc_Obj_t * pNode ) { pNode->TravId = pNode->pNtk->nTravIds - 1; } +static inline bool Abc_NodeIsTravIdCurrent( Abc_Obj_t * pNode ) { return (bool)(pNode->TravId == pNode->pNtk->nTravIds); } +static inline bool Abc_NodeIsTravIdPrevious( Abc_Obj_t * pNode ) { return (bool)(pNode->TravId == pNode->pNtk->nTravIds - 1); } + +// checking initial state of the latches +static inline void Abc_LatchSetInitNone( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_NONE; } +static inline void Abc_LatchSetInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ZERO; } +static inline void Abc_LatchSetInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ONE; } +static inline void Abc_LatchSetInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_DC; } +static inline bool Abc_LatchIsInitNone( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_NONE; } +static inline bool Abc_LatchIsInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ZERO; } +static inline bool Abc_LatchIsInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ONE; } +static inline bool Abc_LatchIsInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_DC; } +static inline int Abc_LatchInit( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return (int)pLatch->pData; } + +// global BDDs of the nodes +static inline void * Abc_NtkGlobalBdd( Abc_Ntk_t * pNtk ) { return (void *)Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD); } +static inline DdManager * Abc_NtkGlobalBddMan( Abc_Ntk_t * pNtk ) { return (DdManager *)Vec_AttMan( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) ); } +static inline DdNode ** Abc_NtkGlobalBddArray( Abc_Ntk_t * pNtk ) { return (DdNode **)Vec_AttArray( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) ); } +static inline DdNode * Abc_ObjGlobalBdd( Abc_Obj_t * pObj ) { return (DdNode *)Vec_AttEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id ); } +static inline void Abc_ObjSetGlobalBdd( Abc_Obj_t * pObj, DdNode * bF ) { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id, bF ); } + +// MV variables of the nodes +static inline void * Abc_NtkMvVar( Abc_Ntk_t * pNtk ) { return Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_MVVAR); } +static inline void * Abc_NtkMvVarMan( Abc_Ntk_t * pNtk ) { return Abc_NtkMvVar(pNtk)? Vec_AttMan( (Vec_Att_t *)Abc_NtkMvVar(pNtk) ) : NULL; } +static inline void * Abc_ObjMvVar( Abc_Obj_t * pObj ) { return Abc_NtkMvVar(pObj->pNtk)? Vec_AttEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id ) : NULL; } +static inline int Abc_ObjMvVarNum( Abc_Obj_t * pObj ) { return (Abc_NtkMvVar(pObj->pNtk) && Abc_ObjMvVar(pObj))? *((int*)Abc_ObjMvVar(pObj)) : 2; } +static inline void Abc_ObjSetMvVar( Abc_Obj_t * pObj, void * pV) { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id, pV ); } + +// outputs the runtime in seconds +#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// objects of the network +#define Abc_NtkForEachObj( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pObj) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pObj) == NULL ) {} else +#define Abc_NtkForEachNet( pNtk, pNet, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNet) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNet) == NULL || !Abc_ObjIsNet(pNet) ) {} else +#define Abc_NtkForEachNode( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) ) {} else +#define Abc_NtkForEachGate( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_ObjIsGate(pNode) ) {} else +#define Abc_AigForEachAnd( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_AigNodeIsAnd(pNode) ) {} else +// various boxes +#define Abc_NtkForEachBox( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachLatch( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ + if ( !Abc_ObjIsLatch(pObj) ) {} else +#define Abc_NtkForEachLatchInput( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ ) \ + if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanin0(Abc_NtkBox(pNtk, i))), 1)) ) {} else +#define Abc_NtkForEachLatchOutput( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ ) \ + if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanout0(Abc_NtkBox(pNtk, i))), 1)) ) {} else +#define Abc_NtkForEachWhitebox( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ + if ( !Abc_ObjIsWhitebox(pObj) ) {} else +#define Abc_NtkForEachBlackbox( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ + if ( !Abc_ObjIsBlackbox(pObj) ) {} else +// inputs and outputs +#define Abc_NtkForEachPi( pNtk, pPi, i ) \ + for ( i = 0; (i < Abc_NtkPiNum(pNtk)) && (((pPi) = Abc_NtkPi(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachCi( pNtk, pCi, i ) \ + for ( i = 0; (i < Abc_NtkCiNum(pNtk)) && (((pCi) = Abc_NtkCi(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachPo( pNtk, pPo, i ) \ + for ( i = 0; (i < Abc_NtkPoNum(pNtk)) && (((pPo) = Abc_NtkPo(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachCo( pNtk, pCo, i ) \ + for ( i = 0; (i < Abc_NtkCoNum(pNtk)) && (((pCo) = Abc_NtkCo(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachAssert( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vAsserts)) && (((pObj) = Abc_NtkAssert(pNtk, i)), 1); i++ ) +// fanin and fanouts +#define Abc_ObjForEachFanin( pObj, pFanin, i ) \ + for ( i = 0; (i < Abc_ObjFaninNum(pObj)) && (((pFanin) = Abc_ObjFanin(pObj, i)), 1); i++ ) +#define Abc_ObjForEachFanout( pObj, pFanout, i ) \ + for ( i = 0; (i < Abc_ObjFanoutNum(pObj)) && (((pFanout) = Abc_ObjFanout(pObj, i)), 1); i++ ) +// cubes and literals +#define Abc_SopForEachCube( pSop, nFanins, pCube ) \ + for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 ) +#define Abc_CubeForEachVar( pCube, Value, i ) \ + for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ ) + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== abcAig.c ==========================================================*/ +extern Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtk ); +extern void Abc_AigFree( Abc_Aig_t * pMan ); +extern int Abc_AigCleanup( Abc_Aig_t * pMan ); +extern bool Abc_AigCheck( Abc_Aig_t * pMan ); +extern int Abc_AigLevel( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +extern Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +extern Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType ); +extern Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType ); +extern Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +extern Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +extern Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ); +extern void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool fUpdateLevel ); +extern void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld ); +extern void Abc_AigRehash( Abc_Aig_t * pMan ); +extern bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode ); +extern bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode ); +extern void Abc_AigPrintNode( Abc_Obj_t * pNode ); +extern bool Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot ); +extern void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan ); +extern void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets ); +extern void Abc_AigUpdateStop( Abc_Aig_t * pMan ); +extern void Abc_AigUpdateReset( Abc_Aig_t * pMan ); +/*=== abcAttach.c ==========================================================*/ +extern int Abc_NtkAttach( Abc_Ntk_t * pNtk ); +/*=== abcBlifMv.c ==========================================================*/ +extern void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ); +extern void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk ); +extern void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues ); +extern Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic ); +extern int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk ); +extern char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ); +extern int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ); +/*=== abcBalance.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel ); +/*=== abcCheck.c ==========================================================*/ +extern bool Abc_NtkCheck( Abc_Ntk_t * pNtk ); +extern bool Abc_NtkCheckRead( Abc_Ntk_t * pNtk ); +extern bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ); +extern bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ); +extern bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb ); +extern int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk ); +extern int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ); +extern int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ); +extern int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk ); +/*=== abcCollapse.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ); +/*=== abcCut.c ==========================================================*/ +extern void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ); +extern void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ); +extern void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fFirst ); +extern void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ); +extern void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ); +/*=== abcDfs.c ==========================================================*/ +extern Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll ); +extern Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); +extern Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); +extern Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); +extern Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ); +extern Vec_Ptr_t * Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll ); +extern bool Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); +extern Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos ); +extern Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi ); +extern int Abc_NtkLevel( Abc_Ntk_t * pNtk ); +extern int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk ); +extern bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis ); +/*=== abcFanio.c ==========================================================*/ +extern void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); +extern void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); +extern void Abc_ObjRemoveFanins( Abc_Obj_t * pObj ); +extern void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew ); +extern Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type ); +extern void Abc_ObjTransferFanout( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); +extern void Abc_ObjReplace( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); +extern int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin ); +/*=== abcFraig.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ); +extern void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ); +extern Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk ); +extern int Abc_NtkFraigStore( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkFraigRestore(); +extern void Abc_NtkFraigStoreClean(); +/*=== abcFunc.c ==========================================================*/ +extern int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ); +extern DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop ); +extern char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode ); +extern int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect ); +extern void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ); +extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ); +extern void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ); +extern int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ); +extern int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ); +extern unsigned * Abc_ConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst ); +extern int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ); +extern int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fDirect ); +extern int Abc_NtkToBdd( Abc_Ntk_t * pNtk ); +extern int Abc_NtkToAig( Abc_Ntk_t * pNtk ); +/*=== abcHaig.c ==========================================================*/ +extern int Abc_NtkHaigStart( Abc_Ntk_t * pNtk ); +extern int Abc_NtkHaigStop( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkHaigUse( Abc_Ntk_t * pNtk ); +/*=== abcHie.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL ); +/*=== abcLatch.c ==========================================================*/ +extern bool Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch ); +extern int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk ); +extern int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk ); +extern Vec_Int_t * Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk ); +extern void Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ); +extern Abc_Obj_t * Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init ); +extern void Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk ); + /*=== abcLib.c ==========================================================*/ +extern Abc_Lib_t * Abc_LibCreate( char * pName ); +extern void Abc_LibFree( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk ); +extern void Abc_LibPrint( Abc_Lib_t * pLib ); +extern int Abc_LibAddModel( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_LibFindModelByName( Abc_Lib_t * pLib, char * pName ); +extern int Abc_LibFindTopLevelModels( Abc_Lib_t * pLib ); +extern Abc_Ntk_t * Abc_LibDeriveRoot( Abc_Lib_t * pLib ); +/*=== abcMiter.c ==========================================================*/ +extern int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ); +extern int Abc_NodeMinimumBase( Abc_Obj_t * pNode ); +extern int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ); +extern int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode ); +/*=== abcMiter.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ); +extern void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pNode ); +extern Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 ); +extern Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ); +extern Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 ); +extern Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist ); +extern Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk ); +extern int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter ); +extern void Abc_NtkMiterReport( Abc_Ntk_t * pMiter ); +extern Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial ); +/*=== abcNames.c ====================================================*/ +extern char * Abc_ObjName( Abc_Obj_t * pNode ); +extern char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix ); +extern char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix ); +extern char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits ); +extern void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +extern void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +extern Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode ); +extern Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames ); +extern void Abc_NodeFreeNames( Vec_Ptr_t * vNames ); +extern char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos ); +extern int Abc_NodeCompareNames( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); +extern void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb ); +extern void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk ); +extern void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk ); +extern void Abc_NtkAddDummyAssertNames( Abc_Ntk_t * pNtk ); +extern void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ); +extern void Abc_NtkShortNames( Abc_Ntk_t * pNtk ); +/*=== abcNetlist.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ); +/*=== abcNtbdd.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ); +extern Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ); +extern DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDropInternal, int fReorder, int fVerbose ); +extern DdManager * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ); +extern int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk ); +/*=== abcNtk.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan ); +extern Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ); +extern Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ); +extern void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +extern Abc_Ntk_t * Abc_NtkStartRead( char * pName ); +extern void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis ); +extern Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis ); +extern void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ); +extern Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName ); +extern Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ); +extern Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ); +extern Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ); +extern void Abc_NtkDelete( Abc_Ntk_t * pNtk ); +extern void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ); +extern void Abc_NtkMakeComb( Abc_Ntk_t * pNtk ); +/*=== abcObj.c ==========================================================*/ +extern Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); +extern void Abc_ObjRecycle( Abc_Obj_t * pObj ); +extern Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); +extern void Abc_NtkDeleteObj( Abc_Obj_t * pObj ); +extern void Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes ); +extern void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj ); +extern Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName ); +extern Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName ); +extern Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pNode ); +extern Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ); +extern Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ); +extern Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); +extern Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); +extern Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); +extern Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 ); +extern bool Abc_NodeIsConst( Abc_Obj_t * pNode ); +extern bool Abc_NodeIsConst0( Abc_Obj_t * pNode ); +extern bool Abc_NodeIsConst1( Abc_Obj_t * pNode ); +extern bool Abc_NodeIsBuf( Abc_Obj_t * pNode ); +extern bool Abc_NodeIsInv( Abc_Obj_t * pNode ); +extern void Abc_NodeComplement( Abc_Obj_t * pNode ); +/*=== abcPrint.c ==========================================================*/ +extern void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ); +extern void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk ); +extern void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ); +extern void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk ); +extern void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode ); +extern void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ); +extern void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ); +extern void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes ); +extern void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ); +extern void Abc_NtkPrintSkews( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintAll ); +extern void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj ); +/*=== abcProve.c ==========================================================*/ +extern int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pParams ); +extern int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ); +/*=== abcRec.c ==========================================================*/ +extern void Abc_NtkRecStart( Abc_Ntk_t * pNtk, int nVars, int nCuts ); +extern void Abc_NtkRecStop(); +extern void Abc_NtkRecAdd( Abc_Ntk_t * pNtk ); +extern void Abc_NtkRecPs(); +extern void Abc_NtkRecFilter( int iVar, int iPlus ); +extern Abc_Ntk_t * Abc_NtkRecUse(); +extern int Abc_NtkRecIsRunning(); +extern int Abc_NtkRecVarNum(); +extern Vec_Int_t * Abc_NtkRecMemory(); +extern int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars ); +/*=== abcReconv.c ==========================================================*/ +extern Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ); +extern void Abc_NtkManCutStop( Abc_ManCut_t * p ); +extern Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p ); +extern Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p ); +extern Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p ); +extern Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, bool fContain ); +extern void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited, int fIncludeFanins ); +extern DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited ); +extern DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited ); +extern Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, int LevelMax ); +/*=== abcRefs.c ==========================================================*/ +extern int Abc_NodeMffcSize( Abc_Obj_t * pNode ); +extern int Abc_NodeMffcSizeSupp( Abc_Obj_t * pNode ); +extern int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode ); +extern int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode ); +extern int Abc_NodeMffcLabel( Abc_Obj_t * pNode ); +extern void Abc_NodeMffsConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ); +extern int Abc_NodeDeref_rec( Abc_Obj_t * pNode ); +extern int Abc_NodeRef_rec( Abc_Obj_t * pNode ); +/*=== abcRefactor.c ==========================================================*/ +extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ); +/*=== abcRewrite.c ==========================================================*/ +extern int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable ); +/*=== abcSat.c ==========================================================*/ +extern int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose, sint64 * pNumConfs, sint64 * pNumInspects ); +extern void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes ); +/*=== abcSop.c ==========================================================*/ +extern char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName ); +extern char * Abc_SopStart( Extra_MmFlex_t * pMan, int nCubes, int nVars ); +extern char * Abc_SopCreateConst0( Extra_MmFlex_t * pMan ); +extern char * Abc_SopCreateConst1( Extra_MmFlex_t * pMan ); +extern char * Abc_SopCreateAnd2( Extra_MmFlex_t * pMan, int fCompl0, int fCompl1 ); +extern char * Abc_SopCreateAnd( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ); +extern char * Abc_SopCreateNand( Extra_MmFlex_t * pMan, int nVars ); +extern char * Abc_SopCreateOr( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ); +extern char * Abc_SopCreateOrMultiCube( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ); +extern char * Abc_SopCreateNor( Extra_MmFlex_t * pMan, int nVars ); +extern char * Abc_SopCreateXor( Extra_MmFlex_t * pMan, int nVars ); +extern char * Abc_SopCreateXorSpecial( Extra_MmFlex_t * pMan, int nVars ); +extern char * Abc_SopCreateNxor( Extra_MmFlex_t * pMan, int nVars ); +extern char * Abc_SopCreateMux( Extra_MmFlex_t * pMan ); +extern char * Abc_SopCreateInv( Extra_MmFlex_t * pMan ); +extern char * Abc_SopCreateBuf( Extra_MmFlex_t * pMan ); +extern char * Abc_SopCreateFromTruth( Extra_MmFlex_t * pMan, int nVars, unsigned * pTruth ); +extern char * Abc_SopCreateFromIsop( Extra_MmFlex_t * pMan, int nVars, Vec_Int_t * vCover ); +extern int Abc_SopGetCubeNum( char * pSop ); +extern int Abc_SopGetLitNum( char * pSop ); +extern int Abc_SopGetVarNum( char * pSop ); +extern int Abc_SopGetPhase( char * pSop ); +extern int Abc_SopGetIthCareLit( char * pSop, int i ); +extern void Abc_SopComplement( char * pSop ); +extern bool Abc_SopIsComplement( char * pSop ); +extern bool Abc_SopIsConst0( char * pSop ); +extern bool Abc_SopIsConst1( char * pSop ); +extern bool Abc_SopIsBuf( char * pSop ); +extern bool Abc_SopIsInv( char * pSop ); +extern bool Abc_SopIsAndType( char * pSop ); +extern bool Abc_SopIsOrType( char * pSop ); +extern int Abc_SopIsExorType( char * pSop ); +extern bool Abc_SopCheck( char * pSop, int nFanins ); +extern char * Abc_SopFromTruthBin( char * pTruth ); +extern char * Abc_SopFromTruthHex( char * pTruth ); +extern char * Abc_SopEncoderPos( Extra_MmFlex_t * pMan, int iValue, int nValues ); +extern char * Abc_SopEncoderLog( Extra_MmFlex_t * pMan, int iBit, int nValues ); +extern char * Abc_SopDecoderPos( Extra_MmFlex_t * pMan, int nValues ); +extern char * Abc_SopDecoderLog( Extra_MmFlex_t * pMan, int nValues ); +/*=== abcStrash.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord ); +extern Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int fRecord ); +extern int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos ); +extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); +/*=== abcSweep.c ==========================================================*/ +extern int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ); +extern int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ); +extern int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose ); +/*=== abcTiming.c ==========================================================*/ +extern Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode ); +extern Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode ); +extern Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk ); +extern Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk ); +extern void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall ); +extern void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall ); +extern void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ); +extern void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ); +extern void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk ); +extern void Abc_ManTimeStop( Abc_ManTime_t * p ); +extern void Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ); +extern void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtk ); +extern float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk ); +extern Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk ); +extern float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk ); +extern int Abc_ObjLevelNew( Abc_Obj_t * pObj ); +extern int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj ); +extern int Abc_ObjRequiredLevel( Abc_Obj_t * pObj ); +extern int Abc_ObjReverseLevel( Abc_Obj_t * pObj ); +extern void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR ); +extern void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease ); +extern void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk ); +extern void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); +extern void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); +extern void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); +/*=== abcUtil.c ==========================================================*/ +extern void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan ); +extern void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk ); +extern void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetLitNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetLitFactNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk ); +extern double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk ); +extern void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk ); +extern void Abc_NtkCleanData( Abc_Ntk_t * pNtk ); +extern void Abc_NtkCleanEquiv( Abc_Ntk_t * pNtk ); +extern int Abc_NtkCountCopy( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk ); +extern void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies ); +extern void Abc_NtkCleanNext( Abc_Ntk_t * pNtk ); +extern void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode ); +extern Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode ); +extern Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode ); +extern bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk ); +extern int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, bool fDuplicate ); +extern void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode ); +extern bool Abc_NodeIsExorType( Abc_Obj_t * pNode ); +extern bool Abc_NodeIsMuxType( Abc_Obj_t * pNode ); +extern bool Abc_NodeIsMuxControlType( Abc_Obj_t * pNode ); +extern Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE ); +extern int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2 ); +extern void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); +extern void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); +extern Vec_Ptr_t * Abc_NtkCollectLatches( Abc_Ntk_t * pNtk ); +extern int Abc_NodeCompareLevelsIncrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); +extern int Abc_NodeCompareLevelsDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); +extern Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk ); +extern Vec_Int_t * Abc_NtkGetCiIds( Abc_Ntk_t * pNtk ); +extern void Abc_NtkReassignIds( Abc_Ntk_t * pNtk ); +extern int Abc_ObjPointerCompare( void ** pp1, void ** pp2 ); +extern void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk ); +/*=== abcVerify.c ==========================================================*/ +extern int * Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames ); +extern int * Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/base/abc/abcAig.c b/abc70930/src/base/abc/abcAig.c new file mode 100644 index 00000000..16f66dc6 --- /dev/null +++ b/abc70930/src/base/abc/abcAig.c @@ -0,0 +1,1476 @@ +/**CFile**************************************************************** + + FileName [abcAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Simple structural hashing package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +/* + AIG is an And-Inv Graph with structural hashing. + It is always structurally hashed. It means that at any time: + - for each AND gate, there are no other AND gates with the same children + - the constants are propagated + - there is no single-input nodes (inverters/buffers) + Additionally the following invariants are satisfied: + - there are no dangling nodes (the nodes without fanout) + - the level of each AND gate reflects the levels of this fanins + - the EXOR-status of each node is up-to-date + - the AND nodes are in the topological order + - the constant 1 node has always number 0 in the object list + The operations that are performed on AIGs: + - building new nodes (Abc_AigAnd) + - performing elementary Boolean operations (Abc_AigOr, Abc_AigXor, etc) + - replacing one node by another (Abc_AigReplace) + - propagating constants (Abc_AigReplace) + When AIG is duplicated, the new graph is structurally hashed too. + If this repeated hashing leads to fewer nodes, it means the original + AIG was not strictly hashed (one of the conditions above is violated). +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the simple AIG manager +struct Abc_Aig_t_ +{ + Abc_Ntk_t * pNtkAig; // the AIG network + Abc_Obj_t * pConst1; // the constant 1 object (not a node!) + Abc_Obj_t ** pBins; // the table bins + int nBins; // the size of the table + int nEntries; // the total number of entries in the table + Vec_Ptr_t * vNodes; // the temporary array of nodes + Vec_Ptr_t * vStackReplaceOld; // the nodes to be replaced + Vec_Ptr_t * vStackReplaceNew; // the nodes to be used for replacement + Vec_Vec_t * vLevels; // the nodes to be updated + Vec_Vec_t * vLevelsR; // the nodes to be updated + Vec_Ptr_t * vAddedCells; // the added nodes + Vec_Ptr_t * vUpdatedNets; // the nodes whose fanouts have changed + + int nStrash0; + int nStrash1; + int nStrash5; + int nStrash2; +}; + +// iterators through the entries in the linked lists of nodes +#define Abc_AigBinForEachEntry( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = pEnt->pNext ) +#define Abc_AigBinForEachEntrySafe( pBin, pEnt, pEnt2 ) \ + for ( pEnt = pBin, \ + pEnt2 = pEnt? pEnt->pNext: NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? pEnt->pNext: NULL ) + +// hash key for the structural hash table +//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; } +//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)((a)->Id + (b)->Id) * ((a)->Id + (b)->Id + 1) / 2) % TableSize; } + +// hashing the node +static unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) +{ + unsigned Key = 0; + Key ^= Abc_ObjRegular(p0)->Id * 7937; + Key ^= Abc_ObjRegular(p1)->Id * 2971; + Key ^= Abc_ObjIsComplement(p0) * 911; + Key ^= Abc_ObjIsComplement(p1) * 353; + return Key % TableSize; +} + +// structural hash table procedures +static Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +static Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd ); +static void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis ); +static void Abc_AigResize( Abc_Aig_t * pMan ); +// incremental AIG procedures +static void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ); +static void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan ); +static void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan ); +static void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ); +static void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the local AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig ) +{ + Abc_Aig_t * pMan; + // start the manager + pMan = ALLOC( Abc_Aig_t, 1 ); + memset( pMan, 0, sizeof(Abc_Aig_t) ); + // allocate the table + pMan->nBins = Cudd_PrimeCopy( 10000 ); + pMan->pBins = ALLOC( Abc_Obj_t *, pMan->nBins ); + memset( pMan->pBins, 0, sizeof(Abc_Obj_t *) * pMan->nBins ); + pMan->vNodes = Vec_PtrAlloc( 100 ); + pMan->vLevels = Vec_VecAlloc( 100 ); + pMan->vLevelsR = Vec_VecAlloc( 100 ); + pMan->vStackReplaceOld = Vec_PtrAlloc( 100 ); + pMan->vStackReplaceNew = Vec_PtrAlloc( 100 ); + // create the constant node + assert( pNtkAig->vObjs->nSize == 0 ); + pMan->pConst1 = Abc_NtkCreateObj( pNtkAig, ABC_OBJ_NODE ); + pMan->pConst1->Type = ABC_OBJ_CONST1; + pMan->pConst1->fPhase = 1; + pNtkAig->nObjCounts[ABC_OBJ_NODE]--; + // save the current network + pMan->pNtkAig = pNtkAig; + return pMan; +} + +/**Function************************************************************* + + Synopsis [Deallocates the local AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigFree( Abc_Aig_t * pMan ) +{ + assert( Vec_PtrSize( pMan->vStackReplaceOld ) == 0 ); + assert( Vec_PtrSize( pMan->vStackReplaceNew ) == 0 ); + // free the table + if ( pMan->vAddedCells ) + Vec_PtrFree( pMan->vAddedCells ); + if ( pMan->vUpdatedNets ) + Vec_PtrFree( pMan->vUpdatedNets ); + Vec_VecFree( pMan->vLevels ); + Vec_VecFree( pMan->vLevelsR ); + Vec_PtrFree( pMan->vStackReplaceOld ); + Vec_PtrFree( pMan->vStackReplaceNew ); + Vec_PtrFree( pMan->vNodes ); + free( pMan->pBins ); + free( pMan ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigCleanup( Abc_Aig_t * pMan ) +{ + Vec_Ptr_t * vDangles; + Abc_Obj_t * pAnd; + int i, nNodesOld; +// printf( "Strash0 = %d. Strash1 = %d. Strash100 = %d. StrashM = %d.\n", +// pMan->nStrash0, pMan->nStrash1, pMan->nStrash5, pMan->nStrash2 ); + nNodesOld = pMan->nEntries; + // collect the AND nodes that do not fanout + vDangles = Vec_PtrAlloc( 100 ); + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) + if ( Abc_ObjFanoutNum(pAnd) == 0 ) + Vec_PtrPush( vDangles, pAnd ); + // process the dangling nodes and their MFFCs + Vec_PtrForEachEntry( vDangles, pAnd, i ) + Abc_AigDeleteNode( pMan, pAnd ); + Vec_PtrFree( vDangles ); + return nNodesOld - pMan->nEntries; +} + +/**Function************************************************************* + + Synopsis [Makes sure that every node in the table is in the network and vice versa.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_AigCheck( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pObj, * pAnd; + int i, nFanins, Counter; + Abc_NtkForEachNode( pMan->pNtkAig, pObj, i ) + { + nFanins = Abc_ObjFaninNum(pObj); + if ( nFanins == 0 ) + { + if ( !Abc_AigNodeIsConst(pObj) ) + { + printf( "Abc_AigCheck: The AIG has non-standard constant nodes.\n" ); + return 0; + } + continue; + } + if ( nFanins == 1 ) + { + printf( "Abc_AigCheck: The AIG has single input nodes.\n" ); + return 0; + } + if ( nFanins > 2 ) + { + printf( "Abc_AigCheck: The AIG has non-standard nodes.\n" ); + return 0; + } + if ( pObj->Level != 1 + ABC_MAX( Abc_ObjFanin0(pObj)->Level, Abc_ObjFanin1(pObj)->Level ) ) + printf( "Abc_AigCheck: Node \"%s\" has level that does not agree with the fanin levels.\n", Abc_ObjName(pObj) ); + pAnd = Abc_AigAndLookup( pMan, Abc_ObjChild0(pObj), Abc_ObjChild1(pObj) ); + if ( pAnd != pObj ) + printf( "Abc_AigCheck: Node \"%s\" is not in the structural hashing table.\n", Abc_ObjName(pObj) ); + } + // count the number of nodes in the table + Counter = 0; + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) + Counter++; + if ( Counter != Abc_NtkNodeNum(pMan->pNtkAig) ) + { + printf( "Abc_AigCheck: The number of nodes in the structural hashing table is wrong.\n" ); + return 0; + } + // if the node is a choice node, nodes in its class should not have fanouts + Abc_NtkForEachNode( pMan->pNtkAig, pObj, i ) + if ( Abc_AigNodeIsChoice(pObj) ) + for ( pAnd = pObj->pData; pAnd; pAnd = pAnd->pData ) + if ( Abc_ObjFanoutNum(pAnd) > 0 ) + { + printf( "Abc_AigCheck: Representative %s", Abc_ObjName(pAnd) ); + printf( " of choice node %s has %d fanouts.\n", Abc_ObjName(pObj), Abc_ObjFanoutNum(pAnd) ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigLevel( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, LevelsMax; + assert( Abc_NtkIsStrash(pNtk) ); + // perform the traversal + LevelsMax = 0; + Abc_NtkForEachCo( pNtk, pNode, i ) + if ( LevelsMax < (int)Abc_ObjFanin0(pNode)->Level ) + LevelsMax = (int)Abc_ObjFanin0(pNode)->Level; + return LevelsMax; +} + + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + Abc_Obj_t * pAnd; + unsigned Key; + // check if it is a good time for table resizing + if ( pMan->nEntries > 2 * pMan->nBins ) + Abc_AigResize( pMan ); + // order the arguments + if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) + pAnd = p0, p0 = p1, p1 = pAnd; + // create the new node + pAnd = Abc_NtkCreateNode( pMan->pNtkAig ); + Abc_ObjAddFanin( pAnd, p0 ); + Abc_ObjAddFanin( pAnd, p1 ); + // set the level of the new node + pAnd->Level = 1 + ABC_MAX( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level ); + pAnd->fExor = Abc_NodeIsExorType(pAnd); + pAnd->fPhase = (Abc_ObjIsComplement(p0) ^ Abc_ObjRegular(p0)->fPhase) & (Abc_ObjIsComplement(p1) ^ Abc_ObjRegular(p1)->fPhase); + // add the node to the corresponding linked list in the table + Key = Abc_HashKey2( p0, p1, pMan->nBins ); + pAnd->pNext = pMan->pBins[Key]; + pMan->pBins[Key] = pAnd; + pMan->nEntries++; + // create the cuts if defined +// if ( pAnd->pNtk->pManCut ) +// Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd ); + pAnd->pCopy = NULL; + // add the node to the list of updated nodes + if ( pMan->vAddedCells ) + Vec_PtrPush( pMan->vAddedCells, pAnd ); + // create HAIG + if ( pAnd->pNtk->pHaig ) + pAnd->pEquiv = Hop_And( pAnd->pNtk->pHaig, Abc_ObjChild0Equiv(pAnd), Abc_ObjChild1Equiv(pAnd) ); + return pAnd; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd ) +{ + Abc_Obj_t * pTemp; + unsigned Key; + assert( !Abc_ObjIsComplement(pAnd) ); + // order the arguments + if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) + pTemp = p0, p0 = p1, p1 = pTemp; + // create the new node + Abc_ObjAddFanin( pAnd, p0 ); + Abc_ObjAddFanin( pAnd, p1 ); + // set the level of the new node + pAnd->Level = 1 + ABC_MAX( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level ); + pAnd->fExor = Abc_NodeIsExorType(pAnd); + // add the node to the corresponding linked list in the table + Key = Abc_HashKey2( p0, p1, pMan->nBins ); + pAnd->pNext = pMan->pBins[Key]; + pMan->pBins[Key] = pAnd; + pMan->nEntries++; + // create the cuts if defined +// if ( pAnd->pNtk->pManCut ) +// Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd ); + pAnd->pCopy = NULL; + // add the node to the list of updated nodes +// if ( pMan->vAddedCells ) +// Vec_PtrPush( pMan->vAddedCells, pAnd ); + // create HAIG + if ( pAnd->pNtk->pHaig ) + pAnd->pEquiv = Hop_And( pAnd->pNtk->pHaig, Abc_ObjChild0Equiv(pAnd), Abc_ObjChild1Equiv(pAnd) ); + return pAnd; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + Abc_Obj_t * pAnd, * pConst1; + unsigned Key; + assert( Abc_ObjRegular(p0)->pNtk->pManFunc == pMan ); + assert( Abc_ObjRegular(p1)->pNtk->pManFunc == pMan ); + // check for trivial cases + pConst1 = Abc_AigConst1(pMan->pNtkAig); + if ( p0 == p1 ) + return p0; + if ( p0 == Abc_ObjNot(p1) ) + return Abc_ObjNot(pConst1); + if ( Abc_ObjRegular(p0) == pConst1 ) + { + if ( p0 == pConst1 ) + return p1; + return Abc_ObjNot(pConst1); + } + if ( Abc_ObjRegular(p1) == pConst1 ) + { + if ( p1 == pConst1 ) + return p0; + return Abc_ObjNot(pConst1); + } +/* + { + int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) ); + int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) ); + if ( nFans0 == 0 || nFans1 == 0 ) + pMan->nStrash0++; + else if ( nFans0 == 1 || nFans1 == 1 ) + pMan->nStrash1++; + else if ( nFans0 <= 100 && nFans1 <= 100 ) + pMan->nStrash5++; + else + pMan->nStrash2++; + } +*/ + { + int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) ); + int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) ); + if ( nFans0 == 0 || nFans1 == 0 ) + return NULL; + } + + // order the arguments + if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) + pAnd = p0, p0 = p1, p1 = pAnd; + // get the hash key for these two nodes + Key = Abc_HashKey2( p0, p1, pMan->nBins ); + // find the matching node in the table + Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd ) + if ( p0 == Abc_ObjChild0(pAnd) && p1 == Abc_ObjChild1(pAnd) ) + { +// assert( Abc_ObjFanoutNum(Abc_ObjRegular(p0)) && Abc_ObjFanoutNum(p1) ); + return pAnd; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType ) +{ + Abc_Obj_t * pNode1, * pNode2, * pNode; + // set the flag to zero + if ( pType ) *pType = 0; + // check the case of XOR(a,b) = OR(ab, a'b')' + if ( (pNode1 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), Abc_ObjNot(p1))) && + (pNode2 = Abc_AigAndLookup(pMan, p0, p1)) ) + { + pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + if ( pNode && pType ) *pType = 1; + return pNode; + } + // check the case of XOR(a,b) = OR(a'b, ab') + if ( (pNode1 = Abc_AigAndLookup(pMan, p0, Abc_ObjNot(p1))) && + (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), p1)) ) + { + pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + return pNode? Abc_ObjNot(pNode) : NULL; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType ) +{ + Abc_Obj_t * pNode1, * pNode2, * pNode; + // set the flag to zero + if ( pType ) *pType = 0; + // check the case of MUX(c,t,e) = OR(ct', c'e')' + if ( (pNode1 = Abc_AigAndLookup(pMan, pC, Abc_ObjNot(pT))) && + (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), Abc_ObjNot(pE))) ) + { + pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + if ( pNode && pType ) *pType = 1; + return pNode; + } + // check the case of MUX(c,t,e) = OR(ct, c'e) + if ( (pNode1 = Abc_AigAndLookup(pMan, pC, pT)) && + (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), pE)) ) + { + pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + return pNode? Abc_ObjNot(pNode) : NULL; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Deletes an AIG node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis ) +{ + Abc_Obj_t * pAnd, * pAnd0, * pAnd1, ** ppPlace; + unsigned Key; + assert( !Abc_ObjIsComplement(pThis) ); + assert( Abc_ObjIsNode(pThis) ); + assert( Abc_ObjFaninNum(pThis) == 2 ); + assert( pMan->pNtkAig == pThis->pNtk ); + // get the hash key for these two nodes + pAnd0 = Abc_ObjRegular( Abc_ObjChild0(pThis) ); + pAnd1 = Abc_ObjRegular( Abc_ObjChild1(pThis) ); + Key = Abc_HashKey2( Abc_ObjChild0(pThis), Abc_ObjChild1(pThis), pMan->nBins ); + // find the matching node in the table + ppPlace = pMan->pBins + Key; + Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd ) + { + if ( pAnd != pThis ) + { + ppPlace = &pAnd->pNext; + continue; + } + *ppPlace = pAnd->pNext; + break; + } + assert( pAnd == pThis ); + pMan->nEntries--; + // delete the cuts if defined + if ( pThis->pNtk->pManCut ) + Abc_NodeFreeCuts( pThis->pNtk->pManCut, pThis ); +} + +/**Function************************************************************* + + Synopsis [Resizes the hash table of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigResize( Abc_Aig_t * pMan ) +{ + Abc_Obj_t ** pBinsNew; + Abc_Obj_t * pEnt, * pEnt2; + int nBinsNew, Counter, i, clk; + unsigned Key; + +clk = clock(); + // get the new table size + nBinsNew = Cudd_PrimeCopy( 3 * pMan->nBins ); + // allocate a new array + pBinsNew = ALLOC( Abc_Obj_t *, nBinsNew ); + memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * nBinsNew ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 ) + { + Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), nBinsNew ); + pEnt->pNext = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == pMan->nEntries ); +// printf( "Increasing the structural table size from %6d to %6d. ", pMan->nBins, nBinsNew ); +// PRT( "Time", clock() - clk ); + // replace the table and the parameters + free( pMan->pBins ); + pMan->pBins = pBinsNew; + pMan->nBins = nBinsNew; +} + +/**Function************************************************************* + + Synopsis [Resizes the hash table of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigRehash( Abc_Aig_t * pMan ) +{ + Abc_Obj_t ** pBinsNew; + Abc_Obj_t * pEnt, * pEnt2; + int * pArray; + unsigned Key; + int Counter, Temp, i; + + // allocate a new array + pBinsNew = ALLOC( Abc_Obj_t *, pMan->nBins ); + memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * pMan->nBins ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 ) + { + // swap the fanins if needed + pArray = pEnt->vFanins.pArray; + if ( pArray[0] > pArray[1] ) + { + Temp = pArray[0]; + pArray[0] = pArray[1]; + pArray[1] = Temp; + Temp = pEnt->fCompl0; + pEnt->fCompl0 = pEnt->fCompl1; + pEnt->fCompl1 = Temp; + } + // rehash the node + Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), pMan->nBins ); + pEnt->pNext = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == pMan->nEntries ); + // replace the table and the parameters + free( pMan->pBins ); + pMan->pBins = pBinsNew; +} + + + + + + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk ) +{ + assert( Abc_NtkIsStrash(pNtk) ); + return ((Abc_Aig_t *)pNtk->pManFunc)->pConst1; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + Abc_Obj_t * pAnd; + if ( (pAnd = Abc_AigAndLookup( pMan, p0, p1 )) ) + return pAnd; + return Abc_AigAndCreate( pMan, p0, p1 ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + return Abc_ObjNot( Abc_AigAnd( pMan, Abc_ObjNot(p0), Abc_ObjNot(p1) ) ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + return Abc_AigOr( pMan, Abc_AigAnd(pMan, p0, Abc_ObjNot(p1)), + Abc_AigAnd(pMan, p1, Abc_ObjNot(p0)) ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigMiter_rec( Abc_Aig_t * pMan, Abc_Obj_t ** ppObjs, int nObjs ) +{ + Abc_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Abc_AigMiter_rec( pMan, ppObjs, nObjs/2 ); + pObj2 = Abc_AigMiter_rec( pMan, ppObjs + nObjs/2, nObjs - nObjs/2 ); + return Abc_AigOr( pMan, pObj1, pObj2 ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ) +{ + int i; + if ( vPairs->nSize == 0 ) + return Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) ); + assert( vPairs->nSize % 2 == 0 ); + // go through the cubes of the node's SOP + for ( i = 0; i < vPairs->nSize; i += 2 ) + vPairs->pArray[i/2] = Abc_AigXor( pMan, vPairs->pArray[i], vPairs->pArray[i+1] ); + vPairs->nSize = vPairs->nSize/2; + return Abc_AigMiter_rec( pMan, (Abc_Obj_t **)vPairs->pArray, vPairs->nSize ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigMiter2( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ) +{ + Abc_Obj_t * pMiter, * pXor; + int i; + assert( vPairs->nSize % 2 == 0 ); + // go through the cubes of the node's SOP + pMiter = Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) ); + for ( i = 0; i < vPairs->nSize; i += 2 ) + { + pXor = Abc_AigXor( pMan, vPairs->pArray[i], vPairs->pArray[i+1] ); + pMiter = Abc_AigOr( pMan, pMiter, pXor ); + } + return pMiter; +} + + + + +/**Function************************************************************* + + Synopsis [Replaces one AIG node by the other.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool fUpdateLevel ) +{ + assert( Vec_PtrSize(pMan->vStackReplaceOld) == 0 ); + assert( Vec_PtrSize(pMan->vStackReplaceNew) == 0 ); + Vec_PtrPush( pMan->vStackReplaceOld, pOld ); + Vec_PtrPush( pMan->vStackReplaceNew, pNew ); + assert( !Abc_ObjIsComplement(pOld) ); + // create HAIG + if ( pOld->pNtk->pHaig ) + Hop_ObjCreateChoice( pOld->pEquiv, Abc_ObjRegular(pNew)->pEquiv ); + // process the replacements + while ( Vec_PtrSize(pMan->vStackReplaceOld) ) + { + pOld = Vec_PtrPop( pMan->vStackReplaceOld ); + pNew = Vec_PtrPop( pMan->vStackReplaceNew ); + Abc_AigReplace_int( pMan, pOld, pNew, fUpdateLevel ); + } + if ( fUpdateLevel ) + { + Abc_AigUpdateLevel_int( pMan ); + if ( pMan->pNtkAig->vLevelsR ) + Abc_AigUpdateLevelR_int( pMan ); + } +} + +/**Function************************************************************* + + Synopsis [Performs internal replacement step.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ) +{ + Abc_Obj_t * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout; + int k, v, iFanin; + // make sure the old node is regular and has fanouts + // (the new node can be complemented and can have fanouts) + assert( !Abc_ObjIsComplement(pOld) ); + assert( Abc_ObjFanoutNum(pOld) > 0 ); + // look at the fanouts of old node + Abc_NodeCollectFanouts( pOld, pMan->vNodes ); + Vec_PtrForEachEntry( pMan->vNodes, pFanout, k ) + { + if ( Abc_ObjIsCo(pFanout) ) + { + Abc_ObjPatchFanin( pFanout, pOld, pNew ); + continue; + } + // find the old node as a fanin of this fanout + iFanin = Vec_IntFind( &pFanout->vFanins, pOld->Id ); + assert( iFanin == 0 || iFanin == 1 ); + // get the new fanin + pFanin1 = Abc_ObjNotCond( pNew, Abc_ObjFaninC(pFanout, iFanin) ); + assert( Abc_ObjRegular(pFanin1) != pFanout ); + // get another fanin + pFanin2 = Abc_ObjChild( pFanout, iFanin ^ 1 ); + assert( Abc_ObjRegular(pFanin2) != pFanout ); + // check if the node with these fanins exists + if ( (pFanoutNew = Abc_AigAndLookup( pMan, pFanin1, pFanin2 )) ) + { // such node exists (it may be a constant) + // schedule replacement of the old fanout by the new fanout + Vec_PtrPush( pMan->vStackReplaceOld, pFanout ); + Vec_PtrPush( pMan->vStackReplaceNew, pFanoutNew ); + continue; + } + // such node does not exist - modify the old fanout node + // (this way the change will not propagate all the way to the COs) + assert( Abc_ObjRegular(pFanin1) != Abc_ObjRegular(pFanin2) ); + + // if the node is in the level structure, remove it + if ( pFanout->fMarkA ) + Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout ); + // if the node is in the level structure, remove it + if ( pFanout->fMarkB ) + Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanout ); + + // remove the old fanout node from the structural hashing table + Abc_AigAndDelete( pMan, pFanout ); + // remove the fanins of the old fanout + Abc_ObjRemoveFanins( pFanout ); + // recreate the old fanout with new fanins and add it to the table + Abc_AigAndCreateFrom( pMan, pFanin1, pFanin2, pFanout ); + assert( Abc_AigNodeIsAcyclic(pFanout, pFanout) ); + + if ( fUpdateLevel ) + { + // schedule the updated fanout for updating direct level + assert( pFanout->fMarkA == 0 ); + pFanout->fMarkA = 1; + Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout ); + // schedule the updated fanout for updating reverse level + if ( pMan->pNtkAig->vLevelsR ) + { + assert( pFanout->fMarkB == 0 ); + pFanout->fMarkB = 1; + Vec_VecPush( pMan->vLevelsR, Abc_ObjReverseLevel(pFanout), pFanout ); + } + } + + // the fanout has changed, update EXOR status of its fanouts + Abc_ObjForEachFanout( pFanout, pFanoutFanout, v ) + if ( Abc_AigNodeIsAnd(pFanoutFanout) ) + pFanoutFanout->fExor = Abc_NodeIsExorType(pFanoutFanout); + } + // if the node has no fanouts left, remove its MFFC + if ( Abc_ObjFanoutNum(pOld) == 0 ) + Abc_AigDeleteNode( pMan, pOld ); +} + +/**Function************************************************************* + + Synopsis [Performs internal deletion step.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode0, * pNode1, * pTemp; + int i, k; + + // make sure the node is regular and dangling + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + assert( Abc_ObjFaninNum(pNode) == 2 ); + assert( Abc_ObjFanoutNum(pNode) == 0 ); + + // when deleting an old node that is scheduled for replacement, remove it from the replacement queue + Vec_PtrForEachEntry( pMan->vStackReplaceOld, pTemp, i ) + if ( pNode == pTemp ) + { + // remove the entry from the replacement array + for ( k = i; k < pMan->vStackReplaceOld->nSize - 1; k++ ) + { + pMan->vStackReplaceOld->pArray[k] = pMan->vStackReplaceOld->pArray[k+1]; + pMan->vStackReplaceNew->pArray[k] = pMan->vStackReplaceNew->pArray[k+1]; + } + pMan->vStackReplaceOld->nSize--; + pMan->vStackReplaceNew->nSize--; + } + + // when deleting a new node that should replace another node, do not delete + Vec_PtrForEachEntry( pMan->vStackReplaceNew, pTemp, i ) + if ( pNode == Abc_ObjRegular(pTemp) ) + return; + + // remember the node's fanins + pNode0 = Abc_ObjFanin0( pNode ); + pNode1 = Abc_ObjFanin1( pNode ); + + // add the node to the list of updated nodes + if ( pMan->vUpdatedNets ) + { + Vec_PtrPushUnique( pMan->vUpdatedNets, pNode0 ); + Vec_PtrPushUnique( pMan->vUpdatedNets, pNode1 ); + } + + // remove the node from the table + Abc_AigAndDelete( pMan, pNode ); + // if the node is in the level structure, remove it + if ( pNode->fMarkA ) + Abc_AigRemoveFromLevelStructure( pMan->vLevels, pNode ); + if ( pNode->fMarkB ) + Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pNode ); + // remove the node from the network + Abc_NtkDeleteObj( pNode ); + + // call recursively for the fanins + if ( Abc_ObjIsNode(pNode0) && pNode0->vFanouts.nSize == 0 ) + Abc_AigDeleteNode( pMan, pNode0 ); + if ( Abc_ObjIsNode(pNode1) && pNode1->vFanouts.nSize == 0 ) + Abc_AigDeleteNode( pMan, pNode1 ); +} + + +/**Function************************************************************* + + Synopsis [Updates the level of the node after it has changed.] + + Description [This procedure is based on the observation that + after the node's level has changed, the fanouts levels can change too, + but the new fanout levels are always larger than the node's level. + As a result, we can accumulate the nodes to be updated in the queue + and process them in the increasing order of levels.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pNode, * pFanout; + Vec_Ptr_t * vVec; + int LevelNew, i, k, v; + + // go through the nodes and update the level of their fanouts + Vec_VecForEachLevel( pMan->vLevels, vVec, i ) + { + if ( Vec_PtrSize(vVec) == 0 ) + continue; + Vec_PtrForEachEntry( vVec, pNode, k ) + { + if ( pNode == NULL ) + continue; + assert( Abc_ObjIsNode(pNode) ); + assert( (int)pNode->Level == i ); + // clean the mark + assert( pNode->fMarkA == 1 ); + pNode->fMarkA = 0; + // iterate through the fanouts + Abc_ObjForEachFanout( pNode, pFanout, v ) + { + if ( Abc_ObjIsCo(pFanout) ) + continue; + // get the new level of this fanout + LevelNew = 1 + ABC_MAX( Abc_ObjFanin0(pFanout)->Level, Abc_ObjFanin1(pFanout)->Level ); + assert( LevelNew > i ); + if ( (int)pFanout->Level == LevelNew ) // no change + continue; + // if the fanout is present in the data structure, pull it out + if ( pFanout->fMarkA ) + Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout ); + // update the fanout level + pFanout->Level = LevelNew; + // add the fanout to the data structure to update its fanouts + assert( pFanout->fMarkA == 0 ); + pFanout->fMarkA = 1; + Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout ); + } + } + Vec_PtrClear( vVec ); + } +} + +/**Function************************************************************* + + Synopsis [Updates the level of the node after it has changed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pNode, * pFanin, * pFanout; + Vec_Ptr_t * vVec; + int LevelNew, i, k, v, j; + + // go through the nodes and update the level of their fanouts + Vec_VecForEachLevel( pMan->vLevelsR, vVec, i ) + { + if ( Vec_PtrSize(vVec) == 0 ) + continue; + Vec_PtrForEachEntry( vVec, pNode, k ) + { + if ( pNode == NULL ) + continue; + assert( Abc_ObjIsNode(pNode) ); + assert( Abc_ObjReverseLevel(pNode) == i ); + // clean the mark + assert( pNode->fMarkB == 1 ); + pNode->fMarkB = 0; + // iterate through the fanins + Abc_ObjForEachFanin( pNode, pFanin, v ) + { + if ( Abc_ObjIsCi(pFanin) ) + continue; + // get the new reverse level of this fanin + LevelNew = 0; + Abc_ObjForEachFanout( pFanin, pFanout, j ) + if ( LevelNew < Abc_ObjReverseLevel(pFanout) ) + LevelNew = Abc_ObjReverseLevel(pFanout); + LevelNew += 1; + assert( LevelNew > i ); + if ( Abc_ObjReverseLevel(pFanin) == LevelNew ) // no change + continue; + // if the fanin is present in the data structure, pull it out + if ( pFanin->fMarkB ) + Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanin ); + // update the reverse level + Abc_ObjSetReverseLevel( pFanin, LevelNew ); + // add the fanin to the data structure to update its fanins + assert( pFanin->fMarkB == 0 ); + pFanin->fMarkB = 1; + Vec_VecPush( pMan->vLevelsR, LevelNew, pFanin ); + } + } + Vec_PtrClear( vVec ); + } +} + +/**Function************************************************************* + + Synopsis [Removes the node from the level structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vVecTemp; + Abc_Obj_t * pTemp; + int m; + assert( pNode->fMarkA ); + vVecTemp = Vec_VecEntry( vStruct, pNode->Level ); + Vec_PtrForEachEntry( vVecTemp, pTemp, m ) + { + if ( pTemp != pNode ) + continue; + Vec_PtrWriteEntry( vVecTemp, m, NULL ); + break; + } + assert( m < Vec_PtrSize(vVecTemp) ); // found + pNode->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Removes the node from the level structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vVecTemp; + Abc_Obj_t * pTemp; + int m; + assert( pNode->fMarkB ); + vVecTemp = Vec_VecEntry( vStruct, Abc_ObjReverseLevel(pNode) ); + Vec_PtrForEachEntry( vVecTemp, pTemp, m ) + { + if ( pTemp != pNode ) + continue; + Vec_PtrWriteEntry( vVecTemp, m, NULL ); + break; + } + assert( m < Vec_PtrSize(vVecTemp) ); // found + pNode->fMarkB = 0; +} + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the node has at least one complemented fanout.] + + Description [A fanout is complemented if the fanout's fanin edge pointing + to the given node is complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i, iFanin; + Abc_ObjForEachFanout( pNode, pFanout, i ) + { + iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id ); + assert( iFanin >= 0 ); + if ( Abc_ObjFaninC( pFanout, iFanin ) ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node has at least one complemented fanout.] + + Description [A fanout is complemented if the fanout's fanin edge pointing + to the given node is complemented. Only the fanouts with current TravId + are counted.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i, iFanin; + Abc_ObjForEachFanout( pNode, pFanout, i ) + { + if ( !Abc_NodeIsTravIdCurrent(pFanout) ) + continue; + iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id ); + assert( iFanin >= 0 ); + if ( Abc_ObjFaninC( pFanout, iFanin ) ) + return 1; + } + return 0; +} + + +/**Function************************************************************* + + Synopsis [Prints the AIG node for debugging purposes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigPrintNode( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNodeR = Abc_ObjRegular(pNode); + if ( Abc_ObjIsCi(pNodeR) ) + { + printf( "CI %4s%s.\n", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" ); + return; + } + if ( Abc_AigNodeIsConst(pNodeR) ) + { + printf( "Constant 1 %s.\n", Abc_ObjIsComplement(pNode)? "(complemented)" : "" ); + return; + } + // print the node's function + printf( "%7s%s", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" ); + printf( " = " ); + printf( "%7s%s", Abc_ObjName(Abc_ObjFanin0(pNodeR)), Abc_ObjFaninC0(pNodeR)? "\'" : "" ); + printf( " * " ); + printf( "%7s%s", Abc_ObjName(Abc_ObjFanin1(pNodeR)), Abc_ObjFaninC1(pNodeR)? "\'" : "" ); + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Check if the node has a combination loop of depth 1 or 2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot ) +{ + Abc_Obj_t * pFanin0, * pFanin1; + Abc_Obj_t * pChild00, * pChild01; + Abc_Obj_t * pChild10, * pChild11; + if ( !Abc_AigNodeIsAnd(pNode) ) + return 1; + pFanin0 = Abc_ObjFanin0(pNode); + pFanin1 = Abc_ObjFanin1(pNode); + if ( pRoot == pFanin0 || pRoot == pFanin1 ) + return 0; + if ( Abc_ObjIsCi(pFanin0) ) + { + pChild00 = NULL; + pChild01 = NULL; + } + else + { + pChild00 = Abc_ObjFanin0(pFanin0); + pChild01 = Abc_ObjFanin1(pFanin0); + if ( pRoot == pChild00 || pRoot == pChild01 ) + return 0; + } + if ( Abc_ObjIsCi(pFanin1) ) + { + pChild10 = NULL; + pChild11 = NULL; + } + else + { + pChild10 = Abc_ObjFanin0(pFanin1); + pChild11 = Abc_ObjFanin1(pFanin1); + if ( pRoot == pChild10 || pRoot == pChild11 ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Resizes the hash table of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pEnt; + int i; + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntry( pMan->pBins[i], pEnt ) + { + if ( Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id > Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id ) + { +// int i0 = Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id; +// int i1 = Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id; + printf( "Node %d has incorrect ordering of fanins.\n", pEnt->Id ); + } + } +} + +/**Function************************************************************* + + Synopsis [Sets the correct phase of the nodes.] + + Description [The AIG nodes should be in the DFS order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsDfsOrdered(pNtk) ); + Abc_AigConst1(pNtk)->fPhase = 1; + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->fPhase = 0; + Abc_NtkForEachLatchOutput( pNtk, pObj, i ) + pObj->fPhase = Abc_LatchIsInit1(pObj); + Abc_AigForEachAnd( pNtk, pObj, i ) + pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)) & (Abc_ObjFanin1(pObj)->fPhase ^ Abc_ObjFaninC1(pObj)); + Abc_NtkForEachPo( pNtk, pObj, i ) + pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)); + Abc_NtkForEachLatchInput( pNtk, pObj, i ) + pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)); +} + + + +/**Function************************************************************* + + Synopsis [Start the update list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets ) +{ + assert( pMan->vAddedCells == NULL ); + pMan->vAddedCells = Vec_PtrAlloc( 1000 ); + pMan->vUpdatedNets = Vec_PtrAlloc( 1000 ); + *pvUpdatedNets = pMan->vUpdatedNets; + return pMan->vAddedCells; +} + +/**Function************************************************************* + + Synopsis [Start the update list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigUpdateStop( Abc_Aig_t * pMan ) +{ + assert( pMan->vAddedCells != NULL ); + Vec_PtrFree( pMan->vAddedCells ); + Vec_PtrFree( pMan->vUpdatedNets ); + pMan->vAddedCells = NULL; + pMan->vUpdatedNets = NULL; +} + +/**Function************************************************************* + + Synopsis [Start the update list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigUpdateReset( Abc_Aig_t * pMan ) +{ + assert( pMan->vAddedCells != NULL ); + Vec_PtrClear( pMan->vAddedCells ); + Vec_PtrClear( pMan->vUpdatedNets ); +} + +/**Function************************************************************* + + Synopsis [Start the update list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigCountNext( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pAnd; + int i, Counter = 0, CounterTotal = 0; + // count how many nodes have pNext set + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) + { + Counter += (pAnd->pNext != NULL); + CounterTotal++; + } + printf( "Counter = %d. Nodes = %d. Ave = %6.2f\n", Counter, CounterTotal, 1.0 * CounterTotal/pMan->nBins ); + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcBlifMv.c b/abc70930/src/base/abc/abcBlifMv.c new file mode 100644 index 00000000..48ec58c0 --- /dev/null +++ b/abc70930/src/base/abc/abcBlifMv.c @@ -0,0 +1,970 @@ +/**CFile**************************************************************** + + FileName [abcBlifMv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to process BLIF-MV networks and AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the Mv-Var manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ) +{ + Vec_Att_t * pAttMan; + assert( Abc_NtkMvVar(pNtk) == NULL ); + pAttMan = Vec_AttAlloc( 0, Abc_NtkObjNumMax(pNtk) + 1, Extra_MmFlexStart(), Extra_MmFlexStop, NULL, NULL ); + Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_MVVAR, pAttMan ); +//printf( "allocing attr\n" ); +} + +/**Function************************************************************* + + Synopsis [Stops the Mv-Var manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk ) +{ + void * pUserMan; + pUserMan = Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, 0 ); + Extra_MmFlexStop( pUserMan ); +} + +/**Function************************************************************* + + Synopsis [Duplicate the MV variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues ) +{ + Extra_MmFlex_t * pFlex; + struct temp + { + int nValues; + char ** pNames; + } * pVarStruct; + assert( nValues > 1 ); + // skip binary signals + if ( nValues == 2 ) + return; + // skip already assigned signals + if ( Abc_ObjMvVar(pObj) != NULL ) + return; + // create the structure + pFlex = Abc_NtkMvVarMan( pObj->pNtk ); + pVarStruct = (void *)Extra_MmFlexEntryFetch( pFlex, sizeof(struct temp) ); + pVarStruct->nValues = nValues; + pVarStruct->pNames = NULL; + Abc_ObjSetMvVar( pObj, pVarStruct ); +} + +/**Function************************************************************* + + Synopsis [Strashes the BLIF-MV netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_StringGetNumber( char ** ppStr ) +{ + char * pStr = *ppStr; + int Number = 0; + assert( *pStr >= '0' && *pStr <= '9' ); + for ( ; *pStr >= '0' && *pStr <= '9'; pStr++ ) + Number = 10 * Number + *pStr - '0'; + *ppStr = pStr; + return Number; +} + +/**Function************************************************************* + + Synopsis [Strashes one node in the BLIF-MV netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeStrashBlifMv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ) +{ + char * pSop; + Abc_Obj_t ** pValues, ** pValuesF, ** pValuesF2; + Abc_Obj_t * pTemp, * pTemp2, * pFanin, * pFanin2, * pNet; + int k, v, Def, DefIndex, Index, nValues, nValuesF, nValuesF2; + + // start the output values + assert( Abc_ObjIsNode(pObj) ); + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + pValues = ALLOC( Abc_Obj_t *, nValues ); + for ( k = 0; k < nValues; k++ ) + pValues[k] = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); + + // get the BLIF-MV formula + pSop = pObj->pData; + // skip the value line +// while ( *pSop++ != '\n' ); + + // handle the constant + if ( Abc_ObjFaninNum(pObj) == 0 ) + { + // skip the default if present + if ( *pSop == 'd' ) + while ( *pSop++ != '\n' ); + // skip space if present + if ( *pSop == ' ' ) + pSop++; + Index = Abc_StringGetNumber( &pSop ); + assert( Index < nValues ); + pValues[Index] = Abc_AigConst1(pNtkNew); + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + return 1; + } + + // parse the default line + Def = DefIndex = -1; + if ( *pSop == 'd' ) + { + pSop++; + if ( *pSop == '=' ) + { + pSop++; + DefIndex = Abc_StringGetNumber( &pSop ); + assert( DefIndex < Abc_ObjFaninNum(pObj) ); + } + else if ( *pSop == '-' ) + { + pSop++; + Def = 0; + } + else + { + Def = Abc_StringGetNumber( &pSop ); + assert( Def < nValues ); + } + assert( *pSop == '\n' ); + pSop++; + } + + // convert the values + while ( *pSop ) + { + // extract the values for each cube + pTemp = Abc_AigConst1(pNtkNew); + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + if ( *pSop == '-' ) + { + pSop += 2; + continue; + } + if ( *pSop == '!' ) + { + printf( "Abc_NodeStrashBlifMv(): Cannot handle complement in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) ); + return 0; + } + if ( *pSop == '{' ) + { + printf( "Abc_NodeStrashBlifMv(): Cannot handle braces in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) ); + return 0; + } + // get the value set + nValuesF = Abc_ObjMvVarNum(pFanin); + pValuesF = (Abc_Obj_t **)pFanin->pCopy; + if ( *pSop == '(' ) + { + pSop++; + pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); + while ( *pSop != ')' ) + { + Index = Abc_StringGetNumber( &pSop ); + assert( Index < nValuesF ); + pTemp2 = Abc_AigOr( pNtkNew->pManFunc, pTemp2, pValuesF[Index] ); + assert( *pSop == ')' || *pSop == ',' ); + if ( *pSop == ',' ) + pSop++; + } + assert( *pSop == ')' ); + pSop++; + } + else if ( *pSop == '=' ) + { + pSop++; + // get the fanin index + Index = Abc_StringGetNumber( &pSop ); + assert( Index < Abc_ObjFaninNum(pObj) ); + assert( Index != k ); + // get the fanin + pFanin2 = Abc_ObjFanin( pObj, Index ); + nValuesF2 = Abc_ObjMvVarNum(pFanin2); + pValuesF2 = (Abc_Obj_t **)pFanin2->pCopy; + // create the sum of products of values + assert( nValuesF == nValuesF2 ); + pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); + for ( v = 0; v < nValues; v++ ) + pTemp2 = Abc_AigOr( pNtkNew->pManFunc, pTemp2, Abc_AigAnd(pNtkNew->pManFunc, pValuesF[v], pValuesF2[v]) ); + } + else + { + Index = Abc_StringGetNumber( &pSop ); + assert( Index < nValuesF ); + pTemp2 = pValuesF[Index]; + } + // compute the compute + pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, pTemp2 ); + // advance the reading point + assert( *pSop == ' ' ); + pSop++; + } + // check if the output value is an equal construct + if ( *pSop == '=' ) + { + pSop++; + // get the output value + Index = Abc_StringGetNumber( &pSop ); + assert( Index < Abc_ObjFaninNum(pObj) ); + // add values of the given fanin with the given cube + pFanin = Abc_ObjFanin( pObj, Index ); + nValuesF = Abc_ObjMvVarNum(pFanin); + pValuesF = (Abc_Obj_t **)pFanin->pCopy; + assert( nValuesF == nValues ); // should be guaranteed by the parser + for ( k = 0; k < nValuesF; k++ ) + pValues[k] = Abc_AigOr( pNtkNew->pManFunc, pValues[k], Abc_AigAnd(pNtkNew->pManFunc, pTemp, pValuesF[k]) ); + } + else + { + // get the output value + Index = Abc_StringGetNumber( &pSop ); + assert( Index < nValues ); + pValues[Index] = Abc_AigOr( pNtkNew->pManFunc, pValues[Index], pTemp ); + } + // advance the reading point + assert( *pSop == '\n' ); + pSop++; + } + + // compute the default value + if ( Def >= 0 || DefIndex >= 0 ) + { + pTemp = Abc_AigConst1(pNtkNew); + for ( k = 0; k < nValues; k++ ) + { + if ( k == Def ) + continue; + pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, Abc_ObjNot(pValues[k]) ); + } + + // assign the default value + if ( Def >= 0 ) + pValues[Def] = pTemp; + else + { + assert( DefIndex >= 0 ); + // add values of the given fanin with the given cube + pFanin = Abc_ObjFanin( pObj, DefIndex ); + nValuesF = Abc_ObjMvVarNum(pFanin); + pValuesF = (Abc_Obj_t **)pFanin->pCopy; + assert( nValuesF == nValues ); // should be guaranteed by the parser + for ( k = 0; k < nValuesF; k++ ) + pValues[k] = Abc_AigOr( pNtkNew->pManFunc, pValues[k], Abc_AigAnd(pNtkNew->pManFunc, pTemp, pValuesF[k]) ); + } + + } + + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + return 1; +} + +/**Function************************************************************* + + Synopsis [Assigns name with index.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_NtkConvertAssignName( Abc_Obj_t * pObj, Abc_Obj_t * pNet, int Index ) +{ + char Suffix[16]; + assert( Abc_ObjIsTerm(pObj) ); + assert( Abc_ObjIsNet(pNet) ); + sprintf( Suffix, "[%d]", Index ); + Abc_ObjAssignName( pObj, Abc_ObjName(pNet), Suffix ); +} + +/**Function************************************************************* + + Synopsis [Strashes the BLIF-MV netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ) +{ + int fUsePositional = 0; + Vec_Ptr_t * vNodes; + Abc_Obj_t ** pBits; + Abc_Obj_t ** pValues; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pTemp, * pBit, * pNet; + int i, k, v, nValues, nValuesMax, nBits; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkHasBlifMv(pNtk) ); + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + assert( Abc_NtkBlackboxNum(pNtk) == 0 ); + + // get the largest number of values + nValuesMax = 2; + Abc_NtkForEachNet( pNtk, pObj, i ) + { + nValues = Abc_ObjMvVarNum(pObj); + if ( nValuesMax < nValues ) + nValuesMax = nValues; + } + nBits = Extra_Base2Log( nValuesMax ); + pBits = ALLOC( Abc_Obj_t *, nBits ); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // collect the nodes + vNodes = Abc_NtkDfs( pNtk, 0 ); + + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); +// pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName ); + + // encode the CI nets + Abc_NtkIncrementTravId( pNtk ); + if ( fUsePositional ) + { + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + pValues = ALLOC( Abc_Obj_t *, nValues ); + // create PIs for the values + for ( v = 0; v < nValues; v++ ) + { + pValues[v] = Abc_NtkCreatePi( pNtkNew ); + Abc_NtkConvertAssignName( pValues[v], pNet, v ); + } + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + } + else + { + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + pValues = ALLOC( Abc_Obj_t *, nValues ); + // create PIs for the encoding bits + nBits = Extra_Base2Log( nValues ); + for ( k = 0; k < nBits; k++ ) + { + pBits[k] = Abc_NtkCreatePi( pNtkNew ); + Abc_NtkConvertAssignName( pBits[k], pNet, k ); + } + // encode the values + for ( v = 0; v < nValues; v++ ) + { + pValues[v] = Abc_AigConst1(pNtkNew); + for ( k = 0; k < nBits; k++ ) + { + pBit = Abc_ObjNotCond( pBits[k], (v&(1<<k)) == 0 ); + pValues[v] = Abc_AigAnd( pNtkNew->pManFunc, pValues[v], pBit ); + } + } + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + } + + // process nodes in the topological order + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( !Abc_NodeStrashBlifMv( pNtkNew, pObj ) ) + { + Abc_NtkDelete( pNtkNew ); + return NULL; + } + Vec_PtrFree( vNodes ); + + // encode the CO nets + if ( fUsePositional ) + { + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pNet = Abc_ObjFanin0(pObj); + // skip marked nets + if ( Abc_NodeIsTravIdCurrent(pNet) ) + continue; + Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + pValues = (Abc_Obj_t **)pNet->pCopy; + for ( v = 0; v < nValues; v++ ) + { + pTemp = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pTemp, pValues[v] ); + Abc_NtkConvertAssignName( pTemp, pNet, v ); + } + } + } + else + { + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pNet = Abc_ObjFanin0(pObj); + // skip marked nets + if ( Abc_NodeIsTravIdCurrent(pNet) ) + continue; + Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + pValues = (Abc_Obj_t **)pNet->pCopy; + nBits = Extra_Base2Log( nValues ); + for ( k = 0; k < nBits; k++ ) + { + pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); + for ( v = 0; v < nValues; v++ ) + if ( v & (1<<k) ) + pBit = Abc_AigOr( pNtkNew->pManFunc, pBit, pValues[v] ); + pTemp = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pTemp, pBit ); + Abc_NtkConvertAssignName( pTemp, pNet, k ); + } + } + } + + // cleanup + free( pBits ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy ) + free( pObj->pCopy ); + + // remove dangling nodes + i = Abc_AigCleanup(pNtkNew->pManFunc); +// printf( "Cleanup removed %d nodes.\n", i ); +// Abc_NtkReassignIds( pNtkNew ); + + // check integrity + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkStrashBlifMv(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Extract the MV-skeleton of the BLIF-MV network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkSkeletonBlifMv( Abc_Ntk_t * pNtk ) +{ + int fUsePositional = 0; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pNet, * pNetNew, * pNodeNew, * pTermNew, * pBoxNew; + int i, k, v, nValues, nBits; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkHasBlifMv(pNtk) ); + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + assert( Abc_NtkBlackboxNum(pNtk) == 0 ); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName ); + // create the internal box (it is important to put it first!) + pBoxNew = Abc_NtkCreateWhitebox( pNtkNew ); + // create PIs and their nets + Abc_NtkForEachPi( pNtk, pObj, i ) + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + pNet = Abc_ObjFanout0(pObj); + Abc_NtkDupObj( pNtkNew, pNet, 1 ); + Abc_ObjAddFanin( pNet->pCopy, pObj->pCopy ); + } + // create POs and their nets + Abc_NtkForEachPo( pNtk, pObj, i ) + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + pNet = Abc_ObjFanin0(pObj); + if ( pNet->pCopy == NULL ) + Abc_NtkDupObj( pNtkNew, pNet, 1 ); + Abc_ObjAddFanin( pObj->pCopy, pNet->pCopy ); + } + // create latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + Abc_NtkDupBox( pNtkNew, pObj, 0 ); + // latch outputs + pNet = Abc_ObjFanout0(Abc_ObjFanout0(pObj)); + assert( pNet->pCopy == NULL ); + Abc_NtkDupObj( pNtkNew, pNet, 1 ); + Abc_ObjAddFanin( pNet->pCopy, Abc_ObjFanout0(pObj)->pCopy ); + // latch inputs + pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); + if ( pNet->pCopy == NULL ) + Abc_NtkDupObj( pNtkNew, pNet, 1 ); + Abc_ObjAddFanin( Abc_ObjFanin0(pObj)->pCopy, pNet->pCopy ); + } + + // encode the CI nets + Abc_NtkIncrementTravId( pNtk ); + if ( fUsePositional ) + { + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + for ( v = 0; v < nValues; v++ ) + { + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopEncoderPos( pNtkNew->pManFunc, v, nValues ); + pNetNew = Abc_NtkCreateNet( pNtkNew ); + pTermNew = Abc_NtkCreateBi( pNtkNew ); + Abc_ObjAddFanin( pNodeNew, pNet->pCopy ); + Abc_ObjAddFanin( pNetNew, pNodeNew ); + Abc_ObjAddFanin( pTermNew, pNetNew ); + Abc_ObjAddFanin( pBoxNew, pTermNew ); + } + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + } + else + { + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + nBits = Extra_Base2Log( nValues ); + for ( k = 0; k < nBits; k++ ) + { + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopEncoderLog( pNtkNew->pManFunc, k, nValues ); + pNetNew = Abc_NtkCreateNet( pNtkNew ); + pTermNew = Abc_NtkCreateBi( pNtkNew ); + Abc_ObjAddFanin( pNodeNew, pNet->pCopy ); + Abc_ObjAddFanin( pNetNew, pNodeNew ); + Abc_ObjAddFanin( pTermNew, pNetNew ); + Abc_ObjAddFanin( pBoxNew, pTermNew ); + } + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + } + + // encode the CO nets + if ( fUsePositional ) + { + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pNet = Abc_ObjFanin0(pObj); + // skip marked nets + if ( Abc_NodeIsTravIdCurrent(pNet) ) + continue; + Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopDecoderPos( pNtkNew->pManFunc, nValues ); + for ( v = 0; v < nValues; v++ ) + { + pTermNew = Abc_NtkCreateBo( pNtkNew ); + pNetNew = Abc_NtkCreateNet( pNtkNew ); + Abc_ObjAddFanin( pTermNew, pBoxNew ); + Abc_ObjAddFanin( pNetNew, pTermNew ); + Abc_ObjAddFanin( pNodeNew, pNetNew ); + } + Abc_ObjAddFanin( pNet->pCopy, pNodeNew ); + } + } + else + { + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pNet = Abc_ObjFanin0(pObj); + // skip marked nets + if ( Abc_NodeIsTravIdCurrent(pNet) ) + continue; + Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + nBits = Extra_Base2Log( nValues ); + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopDecoderLog( pNtkNew->pManFunc, nValues ); + for ( k = 0; k < nBits; k++ ) + { + pTermNew = Abc_NtkCreateBo( pNtkNew ); + pNetNew = Abc_NtkCreateNet( pNtkNew ); + Abc_ObjAddFanin( pTermNew, pBoxNew ); + Abc_ObjAddFanin( pNetNew, pTermNew ); + Abc_ObjAddFanin( pNodeNew, pNetNew ); + } + Abc_ObjAddFanin( pNet->pCopy, pNodeNew ); + } + } + + // if it is a BLIF-MV netlist transfer the values of all nets + if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) ) + { + if ( Abc_NtkMvVar( pNtkNew ) == NULL ) + Abc_NtkStartMvVars( pNtkNew ); + Abc_NtkForEachNet( pNtk, pObj, i ) + if ( pObj->pCopy ) + Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) ); + } + + // check integrity + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkSkeletonBlifMv(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Inserts processed network into original base MV network.] + + Description [The original network remembers the interface of combinational + logic (PIs/POs/latches names and values). The processed network may + be binary or multi-valued (currently, multi-value is not supported). + The resulting network has the same interface as the original network + while the internal logic is the same as that of the processed network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic ) +{ + Abc_Ntk_t * pNtkSkel, * pNtkNew; + Abc_Obj_t * pBox; + + assert( Abc_NtkIsNetlist(pNtkBase) ); + assert( Abc_NtkHasBlifMv(pNtkBase) ); + assert( Abc_NtkWhiteboxNum(pNtkBase) == 0 ); + assert( Abc_NtkBlackboxNum(pNtkBase) == 0 ); + + assert( Abc_NtkIsNetlist(pNtkLogic) ); + assert( Abc_NtkHasBlifMv(pNtkLogic) ); + assert( Abc_NtkWhiteboxNum(pNtkLogic) == 0 ); + assert( Abc_NtkBlackboxNum(pNtkLogic) == 0 ); + + // extract the skeleton of the old network + pNtkSkel = Abc_NtkSkeletonBlifMv( pNtkBase ); + + // set the implementation of the box to be the same as the processed network + assert( Abc_NtkWhiteboxNum(pNtkSkel) == 1 ); + pBox = Abc_NtkBox( pNtkSkel, 0 ); + assert( Abc_ObjIsWhitebox(pBox) ); + assert( pBox->pData == NULL ); + assert( Abc_ObjFaninNum(pBox) == Abc_NtkPiNum(pNtkLogic) ); + assert( Abc_ObjFanoutNum(pBox) == Abc_NtkPoNum(pNtkLogic) ); + pBox->pData = pNtkLogic; + + // flatten the hierarchy to insert the processed network + pNtkNew = Abc_NtkFlattenLogicHierarchy( pNtkSkel ); + pBox->pData = NULL; + Abc_NtkDelete( pNtkSkel ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts SOP netlist into BLIF-MV netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk ) +{ + Extra_MmFlex_t * pMmFlex; + Abc_Obj_t * pNode; + Vec_Str_t * vCube; + char * pSop0, * pSop1, * pBlifMv, * pCube, * pCur; + int Value, nCubes, nSize, i, k; + + assert( Abc_NtkIsNetlist(pNtk) ); + if ( !Abc_NtkToBdd(pNtk) ) + { + printf( "Converting logic functions to BDDs has failed.\n" ); + return 0; + } + + pMmFlex = Extra_MmFlexStart(); + vCube = Vec_StrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // convert BDD into cubes for on-set and off-set + Abc_NodeBddToCnf( pNode, pMmFlex, vCube, 0, &pSop0, &pSop1 ); + // allocate room for the MV-SOP + nCubes = Abc_SopGetCubeNum(pSop0) + Abc_SopGetCubeNum(pSop1); + nSize = nCubes*(2*Abc_ObjFaninNum(pNode) + 2)+1; + pBlifMv = Extra_MmFlexEntryFetch( pMmFlex, nSize ); + // add the cubes + pCur = pBlifMv; + Abc_SopForEachCube( pSop0, Abc_ObjFaninNum(pNode), pCube ) + { + Abc_CubeForEachVar( pCube, Value, k ) + { + *pCur++ = Value; + *pCur++ = ' '; + } + *pCur++ = '0'; + *pCur++ = '\n'; + } + Abc_SopForEachCube( pSop1, Abc_ObjFaninNum(pNode), pCube ) + { + Abc_CubeForEachVar( pCube, Value, k ) + { + *pCur++ = Value; + *pCur++ = ' '; + } + *pCur++ = '1'; + *pCur++ = '\n'; + } + *pCur++ = 0; + assert( pCur - pBlifMv == nSize ); + // update the node representation + Cudd_RecursiveDeref( pNtk->pManFunc, pNode->pData ); + pNode->pData = pBlifMv; + } + + // update the functionality type + pNtk->ntkFunc = ABC_FUNC_BLIFMV; + Cudd_Quit( pNtk->pManFunc ); + pNtk->pManFunc = pMmFlex; + + Vec_StrFree( vCube ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Converts SOP into MV-SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ) +{ + char * pMvSop, * pCur; + unsigned uCube; + int nCubes, nSize, Value, i, k; + // consider the case of the constant node + if ( Vec_IntSize(vSop0) == 0 || Vec_IntSize(vSop1) == 0 ) + { + // (temporary) create a tautology cube + pMvSop = ALLOC( char, nVars + 3 ); + for ( k = 0; k < nVars; k++ ) + pMvSop[k] = '-'; + pMvSop[nVars] = '0' + (int)(Vec_IntSize(vSop1) > 0); + pMvSop[nVars+1] = '\n'; + pMvSop[nVars+2] = 0; + return pMvSop; + } + // find the total number of cubes + nCubes = Vec_IntSize(vSop0) + Vec_IntSize(vSop1); + // find the size of the MVSOP represented as a C-string + // (each cube has nVars variables + one output literal + end-of-line, + // and the string is zero-terminated) + nSize = nCubes * (nVars + 2) + 1; + // allocate memory + pMvSop = pCur = ALLOC( char, nSize ); + // fill in the negative polarity cubes + Vec_IntForEachEntry( vSop0, uCube, i ) + { + for ( k = 0; k < nVars; k++ ) + { + Value = (uCube >> (2*k)) & 3; + if ( Value == 1 ) + *pCur++ = '0'; + else if ( Value == 2 ) + *pCur++ = '1'; + else if ( Value == 0 ) + *pCur++ = '-'; + else + assert( 0 ); + } + *pCur++ = '0'; + *pCur++ = '\n'; + } + // fill in the positive polarity cubes + Vec_IntForEachEntry( vSop1, uCube, i ) + { + for ( k = 0; k < nVars; k++ ) + { + Value = (uCube >> (2*k)) & 3; + if ( Value == 1 ) + *pCur++ = '0'; + else if ( Value == 2 ) + *pCur++ = '1'; + else if ( Value == 0 ) + *pCur++ = '-'; + else + assert( 0 ); + } + *pCur++ = '1'; + *pCur++ = '\n'; + } + *pCur++ = 0; + assert( pCur - pMvSop == nSize ); + return pMvSop; +} + + +/**Function************************************************************* + + Synopsis [A prototype of internal cost evaluation procedure.] + + Description [This procedure takes the number of variables (nVars), + the array of values of the inputs and the output (pVarValues) + (note that this array has nVars+1 entries), and an MV-SOP represented + as a C-string with one charater for each literal, including inputs + and output. Each cube is terminated with the new-line character ('\n'). + The string is zero-terminated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeEvalMvCostInternal( int nVars, int * pVarValues, char * pMvSop ) +{ + // for now, return the number of cubes in the MV-SOP + int Counter = 0; + while ( *pMvSop ) Counter += (*pMvSop++ == '\n'); + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Evaluates the cost of the cut.] + + Description [The Boolean function of the cut is specified by two SOPs, + which represent the negative/positive polarities of the cut function. + Converts these two SOPs into a mutually-agreed-upon representation + to be passed to the internal cost-evaluation procedure (see the above + prototype Abc_NodeEvalMvCostInternal).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ) +{ + char * pMvSop; + int * pVarValues; + int i, RetValue; + // collect the input and output values (currently, they are binary) + pVarValues = ALLOC( int, nVars + 1 ); + for ( i = 0; i <= nVars; i++ ) + pVarValues[i] = 2; + // prepare MV-SOP for evaluation + pMvSop = Abc_NodeConvertSopToMvSop( nVars, vSop0, vSop1 ); + // have a look at the MV-SOP: +// printf( "%s\n", pMvSop ); + // get the result of internal cost evaluation + RetValue = Abc_NodeEvalMvCostInternal( nVars, pVarValues, pMvSop ); + // cleanup + free( pVarValues ); + free( pMvSop ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcCheck.c b/abc70930/src/base/abc/abcCheck.c new file mode 100644 index 00000000..3072e40f --- /dev/null +++ b/abc70930/src/base/abc/abcCheck.c @@ -0,0 +1,939 @@ +/**CFile**************************************************************** + + FileName [abcCheck.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Consistency checking procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +//#include "seq.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static bool Abc_NtkCheckNames( Abc_Ntk_t * pNtk ); +static bool Abc_NtkCheckPis( Abc_Ntk_t * pNtk ); +static bool Abc_NtkCheckPos( Abc_Ntk_t * pNtk ); +//static bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ); +static bool Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ); +static bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ); +static bool Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch ); + +static bool Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); +static bool Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); +static bool Abc_NtkCompareLatches( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); + +static inline char * Abc_ObjNameNet( Abc_Obj_t * pObj ) { return (Abc_ObjIsNode(pObj) && Abc_NtkIsNetlist(pObj->pNtk)) ? Abc_ObjName(Abc_ObjFanout0(pObj)) : Abc_ObjName(pObj); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks the integrity of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheck( Abc_Ntk_t * pNtk ) +{ + return !Abc_FrameIsFlagEnabled( "check" ) || Abc_NtkDoCheck( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of the network after reading.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckRead( Abc_Ntk_t * pNtk ) +{ + return !Abc_FrameIsFlagEnabled( "checkread" ) || Abc_NtkDoCheck( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pNet, * pNode; + int i; + + // check network types + if ( !Abc_NtkIsNetlist(pNtk) && !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Unknown network type.\n" ); + return 0; + } + if ( !Abc_NtkHasSop(pNtk) && !Abc_NtkHasBdd(pNtk) && !Abc_NtkHasAig(pNtk) && !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasBlackbox(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Unknown functionality type.\n" ); + return 0; + } + if ( Abc_NtkHasMapping(pNtk) ) + { + if ( pNtk->pManFunc != Abc_FrameReadLibGen() ) + { + fprintf( stdout, "NetworkCheck: The library of the mapped network is not the global library.\n" ); + return 0; + } + } + + if ( Abc_NtkHasOnlyLatchBoxes(pNtk) ) + { + // check CI/CO numbers + if ( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCiNum(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Number of CIs does not match number of PIs and latches.\n" ); + fprintf( stdout, "One possible reason is that latches are added twice:\n" ); + fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" ); + return 0; + } + if ( Abc_NtkPoNum(pNtk) + Abc_NtkAssertNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCoNum(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Number of COs does not match number of POs, asserts, and latches.\n" ); + fprintf( stdout, "One possible reason is that latches are added twice:\n" ); + fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" ); + return 0; + } + } + + // check the names + if ( !Abc_NtkCheckNames( pNtk ) ) + return 0; + + // check PIs and POs + Abc_NtkCleanCopy( pNtk ); + if ( !Abc_NtkCheckPis( pNtk ) ) + return 0; + if ( !Abc_NtkCheckPos( pNtk ) ) + return 0; + + if ( Abc_NtkHasBlackbox(pNtk) ) + return 1; + + // check the connectivity of objects + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NtkCheckObj( pNtk, pObj ) ) + return 0; + + // if it is a netlist change nets and latches + if ( Abc_NtkIsNetlist(pNtk) ) + { + if ( Abc_NtkNetNum(pNtk) == 0 ) + { + fprintf( stdout, "NetworkCheck: Netlist has no nets.\n" ); + return 0; + } + // check the nets + Abc_NtkForEachNet( pNtk, pNet, i ) + if ( !Abc_NtkCheckNet( pNtk, pNet ) ) + return 0; + } + else + { + if ( Abc_NtkNetNum(pNtk) != 0 ) + { + fprintf( stdout, "NetworkCheck: A network that is not a netlist has nets.\n" ); + return 0; + } + } + + // check the nodes + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigCheck( pNtk->pManFunc ); + else + { + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( !Abc_NtkCheckNode( pNtk, pNode ) ) + return 0; + } + + // check the latches + Abc_NtkForEachLatch( pNtk, pNode, i ) + if ( !Abc_NtkCheckLatch( pNtk, pNode ) ) + return 0; + + // finally, check for combinational loops +// clk = clock(); + if ( !Abc_NtkIsAcyclic( pNtk ) ) + { + fprintf( stdout, "NetworkCheck: Network contains a combinational loop.\n" ); + return 0; + } +// PRT( "Acyclic ", clock() - clk ); + + // check the EXDC network if present + if ( pNtk->pExdc ) + Abc_NtkCheck( pNtk->pExdc ); +/* + // check the hierarchy + if ( Abc_NtkIsNetlist(pNtk) && pNtk->tName2Model ) + { + stmm_generator * gen; + Abc_Ntk_t * pNtkTemp; + char * pName; + // check other networks + stmm_foreach_item( pNtk->tName2Model, gen, &pName, (char **)&pNtkTemp ) + { + pNtkTemp->fHiePath = pNtkTemp->fHieVisited = 0; + if ( !Abc_NtkCheck( pNtkTemp ) ) + return 0; + } + // check acyclic dependency of the models + if ( !Abc_NtkIsAcyclicHierarchy( pNtk ) ) + { + fprintf( stdout, "NetworkCheck: Network hierarchical dependences contains a cycle.\n" ); + return 0; + } + } +*/ + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + Vec_Int_t * vNameIds; + char * pName; + int i, NameId; + + if ( Abc_NtkIsNetlist(pNtk) ) + return 1; + + // check that each CI/CO has a name + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pObj = Abc_ObjFanout0Ntk(pObj); + if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL ) + { + fprintf( stdout, "NetworkCheck: CI with ID %d is in the network but not in the name table.\n", pObj->Id ); + return 0; + } + } + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pObj = Abc_ObjFanin0Ntk(pObj); + if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL ) + { + fprintf( stdout, "NetworkCheck: CO with ID %d is in the network but not in the name table.\n", pObj->Id ); + return 0; + } + } + + // return the array of all IDs, which have names + vNameIds = Nm_ManReturnNameIds( pNtk->pManName ); + // make sure that these IDs correspond to live objects + Vec_IntForEachEntry( vNameIds, NameId, i ) + { + if ( Vec_PtrEntry( pNtk->vObjs, NameId ) == NULL ) + { + Vec_IntFree( vNameIds ); + pName = Nm_ManFindNameById(pObj->pNtk->pManName, NameId); + fprintf( stdout, "NetworkCheck: Object with ID %d is deleted but its name \"%s\" remains in the name table.\n", NameId, pName ); + return 0; + } + } + Vec_IntFree( vNameIds ); + + // make sure the CI names are unique + if ( !Abc_NtkCheckUniqueCiNames(pNtk) ) + return 0; + + // make sure the CO names are unique + if ( !Abc_NtkCheckUniqueCoNames(pNtk) ) + return 0; + + // make sure that if a CO has the same name as a CI, they point directly + if ( !Abc_NtkCheckUniqueCioNames(pNtk) ) + return 0; + + return 1; +} + + +/**Function************************************************************* + + Synopsis [Checks the PIs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckPis( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + // check that PIs are indeed PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + { + if ( !Abc_ObjIsPi(pObj) ) + { + fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is in the PI list but is not a PI.\n", Abc_ObjName(pObj), pObj->Id ); + return 0; + } + if ( pObj->pData ) + { + fprintf( stdout, "NetworkCheck: A PI \"%s\" has a logic function.\n", Abc_ObjName(pObj) ); + return 0; + } + if ( Abc_ObjFaninNum(pObj) > 0 ) + { + fprintf( stdout, "NetworkCheck: A PI \"%s\" has fanins.\n", Abc_ObjName(pObj) ); + return 0; + } + pObj->pCopy = (Abc_Obj_t *)1; + } + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->pCopy == NULL && Abc_ObjIsPi(pObj) ) + { + fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is a PI but is not in the PI list.\n", Abc_ObjName(pObj), pObj->Id ); + return 0; + } + pObj->pCopy = NULL; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the POs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckPos( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + // check that POs are indeed POs + Abc_NtkForEachPo( pNtk, pObj, i ) + { + if ( !Abc_ObjIsPo(pObj) ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in the PO list but is not a PO.\n", Abc_ObjName(pObj), pObj->Id ); + return 0; + } + if ( pObj->pData ) + { + fprintf( stdout, "NetworkCheck: A PO \"%s\" has a logic function.\n", Abc_ObjName(pObj) ); + return 0; + } + if ( Abc_ObjFaninNum(pObj) != 1 ) + { + fprintf( stdout, "NetworkCheck: A PO \"%s\" does not have one fanin.\n", Abc_ObjName(pObj) ); + return 0; + } + if ( Abc_ObjFanoutNum(pObj) > 0 ) + { + fprintf( stdout, "NetworkCheck: A PO \"%s\" has fanouts.\n", Abc_ObjName(pObj) ); + return 0; + } + pObj->pCopy = (Abc_Obj_t *)1; + } + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->pCopy == NULL && Abc_ObjIsPo(pObj) ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in a PO but is not in the PO list.\n", Abc_ObjName(pObj), pObj->Id ); + return 0; + } + pObj->pCopy = NULL; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Checks the connectivity of the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin, * pFanout; + int i, Value = 1; + int k; + + // check the network + if ( pObj->pNtk != pNtk ) + { + fprintf( stdout, "NetworkCheck: Object \"%s\" does not belong to the network.\n", Abc_ObjName(pObj) ); + return 0; + } + // check the object ID + if ( pObj->Id < 0 || (int)pObj->Id >= Abc_NtkObjNumMax(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Object \"%s\" has incorrect ID.\n", Abc_ObjName(pObj) ); + return 0; + } + + if ( !Abc_FrameIsFlagEnabled("checkfio") ) + return Value; + + // go through the fanins of the object and make sure fanins have this object as a fanout + Abc_ObjForEachFanin( pObj, pFanin, i ) + { + if ( Vec_IntFind( &pFanin->vFanouts, pObj->Id ) == -1 ) + { + fprintf( stdout, "NodeCheck: Object \"%s\" has fanin ", Abc_ObjName(pObj) ); + fprintf( stdout, "\"%s\" but the fanin does not have it as a fanout.\n", Abc_ObjName(pFanin) ); + Value = 0; + } + } + // go through the fanouts of the object and make sure fanouts have this object as a fanin + Abc_ObjForEachFanout( pObj, pFanout, i ) + { + if ( Vec_IntFind( &pFanout->vFanins, pObj->Id ) == -1 ) + { + fprintf( stdout, "NodeCheck: Object \"%s\" has fanout ", Abc_ObjName(pObj) ); + fprintf( stdout, "\"%s\" but the fanout does not have it as a fanin.\n", Abc_ObjName(pFanout) ); + Value = 0; + } + } + + // make sure fanins are not duplicated + for ( i = 0; i < pObj->vFanins.nSize; i++ ) + for ( k = i + 1; k < pObj->vFanins.nSize; k++ ) + if ( pObj->vFanins.pArray[k] == pObj->vFanins.pArray[i] ) + { + printf( "Warning: Node %s has", Abc_ObjName(pObj) ); + printf( " duplicated fanin %s.\n", Abc_ObjName(Abc_ObjFanin(pObj,k)) ); + } + + // save time: do not check large fanout lists + if ( pObj->vFanouts.nSize > 100 ) + return Value; + + // make sure fanouts are not duplicated + for ( i = 0; i < pObj->vFanouts.nSize; i++ ) + for ( k = i + 1; k < pObj->vFanouts.nSize; k++ ) + if ( pObj->vFanouts.pArray[k] == pObj->vFanouts.pArray[i] ) + { + printf( "Warning: Node %s has", Abc_ObjName(pObj) ); + printf( " duplicated fanout %s.\n", Abc_ObjName(Abc_ObjFanout(pObj,k)) ); + } + + return Value; +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of a net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ) +{ + if ( Abc_ObjFaninNum(pNet) == 0 ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" is not driven.\n", Abc_ObjName(pNet) ); + return 0; + } + if ( Abc_ObjFaninNum(pNet) > 1 ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" has more than one driver.\n", Abc_ObjName(pNet) ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) +{ + // detect internal nodes that do not have nets + if ( Abc_NtkIsNetlist(pNtk) && Abc_ObjFanoutNum(pNode) == 0 ) + { + fprintf( stdout, "Node (id = %d) has no net to drive.\n", pNode->Id ); + return 0; + } + // the node should have a function assigned unless it is an AIG + if ( pNode->pData == NULL ) + { + fprintf( stdout, "NodeCheck: An internal node \"%s\" does not have a logic function.\n", Abc_ObjNameNet(pNode) ); + return 0; + } + // the netlist and SOP logic network should have SOPs + if ( Abc_NtkHasSop(pNtk) ) + { + if ( !Abc_SopCheck( pNode->pData, Abc_ObjFaninNum(pNode) ) ) + { + fprintf( stdout, "NodeCheck: SOP check for node \"%s\" has failed.\n", Abc_ObjNameNet(pNode) ); + return 0; + } + } + else if ( Abc_NtkHasBdd(pNtk) ) + { + int nSuppSize = Cudd_SupportSize(pNtk->pManFunc, pNode->pData); + if ( nSuppSize > Abc_ObjFaninNum(pNode) ) + { + fprintf( stdout, "NodeCheck: BDD of the node \"%s\" has incorrect support size.\n", Abc_ObjNameNet(pNode) ); + return 0; + } + } + else if ( !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasAig(pNtk) ) + { + assert( 0 ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of a latch.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch ) +{ + int Value = 1; + // check whether the object is a latch + if ( !Abc_ObjIsLatch(pLatch) ) + { + fprintf( stdout, "NodeCheck: Latch \"%s\" is in a latch list but is not a latch.\n", Abc_ObjName(pLatch) ); + Value = 0; + } + // make sure the latch has a reasonable return value + if ( (int)pLatch->pData < ABC_INIT_ZERO || (int)pLatch->pData > ABC_INIT_DC ) + { + fprintf( stdout, "NodeCheck: Latch \"%s\" has incorrect reset value (%d).\n", + Abc_ObjName(pLatch), (int)pLatch->pData ); + Value = 0; + } + // make sure the latch has only one fanin + if ( Abc_ObjFaninNum(pLatch) != 1 ) + { + fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanins.\n", Abc_ObjName(pLatch), Abc_ObjFaninNum(pLatch) ); + Value = 0; + } + // make sure the latch has only one fanout + if ( Abc_ObjFanoutNum(pLatch) != 1 ) + { + fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanouts.\n", Abc_ObjName(pLatch), Abc_ObjFanoutNum(pLatch) ); + Value = 0; + } + // make sure the latch input has only one fanin + if ( Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) != 1 ) + { + fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanins.\n", + Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) ); + Value = 0; + } + // make sure the latch input has only one fanout + if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) != 1 ) + { + fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanouts.\n", + Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) ); + Value = 0; + } + // make sure the latch output has only one fanin + if ( Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) != 1 ) + { + fprintf( stdout, "NodeCheck: Output of latch \"%s\" has wrong number (%d) of fanins.\n", + Abc_ObjName(Abc_ObjFanout0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) ); + Value = 0; + } + return Value; +} + + + + +/**Function************************************************************* + + Synopsis [Compares the PIs of the two networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) +{ + Abc_Obj_t * pObj1; + int i; + if ( Abc_NtkPiNum(pNtk1) != Abc_NtkPiNum(pNtk2) ) + { + printf( "Networks have different number of primary inputs.\n" ); + return 0; + } + // for each PI of pNet1 find corresponding PI of pNet2 and reorder them + Abc_NtkForEachPi( pNtk1, pObj1, i ) + { + if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) ) != 0 ) + { + printf( "Primary input #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", + i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Compares the POs of the two networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) +{ + Abc_Obj_t * pObj1; + int i; + if ( Abc_NtkPoNum(pNtk1) != Abc_NtkPoNum(pNtk2) ) + { + printf( "Networks have different number of primary outputs.\n" ); + return 0; + } + // for each PO of pNet1 find corresponding PO of pNet2 and reorder them + Abc_NtkForEachPo( pNtk1, pObj1, i ) + { + if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) ) != 0 ) + { + printf( "Primary output #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", + i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Compares the latches of the two networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCompareBoxes( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) +{ + Abc_Obj_t * pObj1; + int i; + assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); + if ( !fComb ) + return 1; + if ( Abc_NtkBoxNum(pNtk1) != Abc_NtkBoxNum(pNtk2) ) + { + printf( "Networks have different number of latches.\n" ); + return 0; + } + // for each PI of pNet1 find corresponding PI of pNet2 and reorder them + Abc_NtkForEachBox( pNtk1, pObj1, i ) + { + if ( strcmp( Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ) != 0 ) + { + printf( "Box #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", + i, Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Compares the signals of the networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb ) +{ + Abc_NtkOrderObjsByName( pNtk1, fComb ); + Abc_NtkOrderObjsByName( pNtk2, fComb ); + if ( !Abc_NtkComparePis( pNtk1, pNtk2, fComb ) ) + return 0; + if ( !fOnlyPis ) + { + if ( !Abc_NtkCompareBoxes( pNtk1, pNtk2, fComb ) ) + return 0; + if ( !Abc_NtkComparePos( pNtk1, pNtk2, fComb ) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if the network hierachy contains a cycle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsAcyclicHierarchy_rec( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNext; + Abc_Obj_t * pObj; + int i; + // return if visited + if ( pNtk->fHieVisited ) + return 1; + pNtk->fHieVisited = 1; + // return if black box + if ( Abc_NtkHasBlackbox(pNtk) ) + return 1; + assert( Abc_NtkIsNetlist(pNtk) ); + // go through all the children networks + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + pNtkNext = pObj->pData; + assert( pNtkNext != NULL ); + if ( pNtkNext->fHiePath ) + return 0; + pNtk->fHiePath = 1; + if ( !Abc_NtkIsAcyclicHierarchy_rec( pNtkNext ) ) + return 0; + pNtk->fHiePath = 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if the network hierachy contains a cycle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pTemp; + int i, RetValue; + assert( Abc_NtkIsNetlist(pNtk) && pNtk->pDesign ); + // clear the modules + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pTemp, i ) + pTemp->fHieVisited = pTemp->fHiePath = 0; + // traverse + pNtk->fHiePath = 1; + RetValue = Abc_NtkIsAcyclicHierarchy_rec( pNtk ); + pNtk->fHiePath = 0; + // clear the modules + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pTemp, i ) + pTemp->fHieVisited = pTemp->fHiePath = 0; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if CI names are repeated.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkNamesCompare( char ** pName1, char ** pName2 ) +{ + return strcmp( *pName1, *pName2 ); +} + +/**Function************************************************************* + + Synopsis [Returns 0 if CI names are repeated.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNames; + Abc_Obj_t * pObj; + int i, fRetValue = 1; + assert( !Abc_NtkIsNetlist(pNtk) ); + vNames = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Vec_PtrPush( vNames, Abc_ObjName(pObj) ); + Vec_PtrSort( vNames, Abc_NtkNamesCompare ); + for ( i = 1; i < Abc_NtkCiNum(pNtk); i++ ) + if ( !strcmp( Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ) ) + { + printf( "Abc_NtkCheck: Repeated CI names: %s and %s.\n", Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ); + fRetValue = 0; + } + Vec_PtrFree( vNames ); + return fRetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if CO names are repeated.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNames; + Abc_Obj_t * pObj; + int i, fRetValue = 1; + assert( !Abc_NtkIsNetlist(pNtk) ); + vNames = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vNames, Abc_ObjName(pObj) ); + Vec_PtrSort( vNames, Abc_NtkNamesCompare ); + for ( i = 1; i < Abc_NtkCoNum(pNtk); i++ ) + { +// printf( "%s\n", Vec_PtrEntry(vNames,i) ); + if ( !strcmp( Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ) ) + { + printf( "Abc_NtkCheck: Repeated CO names: %s and %s.\n", Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ); + fRetValue = 0; + } + } + Vec_PtrFree( vNames ); + return fRetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if there is a pair of CI/CO with the same name and logic in between.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pObjCi; + int i, nCiId, fRetValue = 1; + assert( !Abc_NtkIsNetlist(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + nCiId = Nm_ManFindIdByNameTwoTypes( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); + if ( nCiId == -1 ) + continue; + pObjCi = Abc_NtkObj( pNtk, nCiId ); + assert( !strcmp( Abc_ObjName(pObj), Abc_ObjName(pObjCi) ) ); + if ( Abc_ObjFanin0(pObj) != pObjCi ) + { + printf( "Abc_NtkCheck: A CI/CO pair share the name (%s) but do not link directly.\n", Abc_ObjName(pObj) ); + fRetValue = 0; + } + } + return fRetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcDfs.c b/abc70930/src/base/abc/abcDfs.c new file mode 100644 index 00000000..39e985c0 --- /dev/null +++ b/abc70930/src/base/abc/abcDfs.c @@ -0,0 +1,1264 @@ +/**CFile**************************************************************** + + FileName [abcDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures that use depth-first search.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + assert( !Abc_ObjIsNet(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the CI + if ( Abc_ObjIsCi(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) ) + return; + assert( Abc_ObjIsNode( pNode ) || Abc_ObjIsBox( pNode ) ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + { +// pFanin = Abc_ObjFanin( pNode, Abc_ObjFaninNum(pNode)-1-i ); + Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); + } + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving CIs and CO. + However it marks with the current TravId both CIs and COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); + } + // collect dangling nodes if asked to + if ( fCollectAll ) + { + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_NtkDfs_rec( pObj, vNodes ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving out PIs, POs and latches.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + // go through the PO nodes and call for each of them + for ( i = 0; i < nNodes; i++ ) + { + if ( Abc_ObjIsCo(ppNodes[i]) ) + { + Abc_NodeSetTravIdCurrent(ppNodes[i]); + Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(ppNodes[i])), vNodes ); + } + else if ( Abc_ObjIsNode(ppNodes[i]) ) + Abc_NtkDfs_rec( ppNodes[i], vNodes ); + } + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + int i; + assert( !Abc_ObjIsNet(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the CI + if ( Abc_ObjIsCo(pNode) ) + return; + assert( Abc_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + pNode = Abc_ObjFanout0Ntk(pNode); + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_NtkDfsReverse_rec( pFanout, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the reverse DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving out CIs/COs. + However it marks both CIs and COs with the current TravId.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanout; + int i, k; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachCi( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + pObj = Abc_ObjFanout0Ntk(pObj); + Abc_ObjForEachFanout( pObj, pFanout, k ) + Abc_NtkDfsReverse_rec( pFanout, vNodes ); + } + // add constant nodes in the end + if ( !Abc_NtkIsStrash(pNtk) ) + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( Abc_NodeIsConst(pObj) ) + Vec_PtrPush( vNodes, pObj ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsReverseNodes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + int i; + assert( !Abc_ObjIsNet(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the CI + if ( Abc_ObjIsCo(pNode) ) + return; + assert( Abc_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + pNode = Abc_ObjFanout0Ntk(pNode); + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_NtkDfsReverseNodes_rec( pFanout, vNodes ); + // add the node after the fanins have been added +// Vec_PtrPush( vNodes, pNode ); + Vec_PtrFillExtra( vNodes, pNode->Level + 1, NULL ); + pNode->pCopy = Vec_PtrEntry( vNodes, pNode->Level ); + Vec_PtrWriteEntry( vNodes, pNode->Level, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the levelized array of TFO nodes.] + + Description [Collects the levelized array of internal nodes, leaving out CIs/COs. + However it marks both CIs and COs with the current TravId.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanout; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrStart( Abc_AigLevel(pNtk) + 1 ); + for ( i = 0; i < nNodes; i++ ) + { + pObj = ppNodes[i]; + assert( Abc_ObjIsCi(pObj) ); + Abc_NodeSetTravIdCurrent( pObj ); + pObj = Abc_ObjFanout0Ntk(pObj); + Abc_ObjForEachFanout( pObj, pFanout, k ) + Abc_NtkDfsReverseNodes_rec( pFanout, vNodes ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the levelized array of TFO nodes.] + + Description [Collects the levelized array of internal nodes, leaving out CIs/COs. + However it marks both CIs and COs with the current TravId. + Collects only the nodes whose support does not exceed the set of given CI nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanout, * pFanin; + int i, k, m, nLevels; + // set the levels + nLevels = Abc_NtkLevel( pNtk ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrStart( nLevels + 2 ); + for ( i = 0; i < nNodes; i++ ) + { + pObj = ppNodes[i]; + assert( Abc_ObjIsCi(pObj) ); + Abc_NodeSetTravIdCurrent( pObj ); + // add to the array + assert( pObj->Level == 0 ); + pObj->pCopy = Vec_PtrEntry( vNodes, pObj->Level ); + Vec_PtrWriteEntry( vNodes, pObj->Level, pObj ); + } + // iterate through the levels + for ( i = 0; i <= nLevels; i++ ) + { + // iterate through the nodes on each level + for ( pObj = Vec_PtrEntry(vNodes, i); pObj; pObj = pObj->pCopy ) + { + // iterate through the fanouts of each node + Abc_ObjForEachFanout( pObj, pFanout, k ) + { + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pFanout) ) + continue; + // visit the fanins of this fanout + Abc_ObjForEachFanin( pFanout, pFanin, m ) + { + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + break; + } + if ( m < Abc_ObjFaninNum(pFanout) ) + continue; + // all fanins are already collected + + // mark the node as visited + Abc_NodeSetTravIdCurrent( pFanout ); + // handle the COs + if ( Abc_ObjIsCo(pFanout) ) + pFanout->Level = nLevels + 1; + // add to the array + pFanout->pCopy = Vec_PtrEntry( vNodes, pFanout->Level ); + Vec_PtrWriteEntry( vNodes, pFanout->Level, pFanout ); + // handle the COs + if ( Abc_ObjIsCo(pFanout) ) + pFanout->Level = 0; + } + } + } + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsSeq_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NtkDfsSeq_rec( pFanin, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes and latches reachable from POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + assert( !Abc_NtkIsNetlist(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDfsSeq_rec( pObj, vNodes ); + // mark the PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDfsSeq_rec( pObj, vNodes ); + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsSeqReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin of the node + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_NtkDfsSeqReverse_rec( pFanout, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes and latches reachable from POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + assert( !Abc_NtkIsNetlist(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDfsSeqReverse_rec( pObj, vNodes ); + // mark the logic feeding into POs + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDfsSeq_rec( pObj, vNodes ); + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Iterative version of the DFS procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfs_iter( Vec_Ptr_t * vStack, Abc_Obj_t * pRoot, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pNode, * pFanin; + int iFanin; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pRoot ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pRoot ); + // skip the CI + if ( Abc_ObjIsCi(pRoot) || (Abc_NtkIsStrash(pRoot->pNtk) && Abc_AigNodeIsConst(pRoot)) ) + return; + // add the CI + Vec_PtrClear( vStack ); + Vec_PtrPush( vStack, pRoot ); + Vec_PtrPush( vStack, (void *)0 ); + while ( Vec_PtrSize(vStack) > 0 ) + { + // get the node and its fanin + iFanin = (int)Vec_PtrPop(vStack); + pNode = Vec_PtrPop(vStack); + assert( !Abc_ObjIsNet(pNode) ); + // add it to the array of nodes if we finished + if ( iFanin == Abc_ObjFaninNum(pNode) ) + { + Vec_PtrPush( vNodes, pNode ); + continue; + } + // explore the next fanin + Vec_PtrPush( vStack, pNode ); + Vec_PtrPush( vStack, (void *)(iFanin+1) ); + // get the fanin + pFanin = Abc_ObjFanin0Ntk( Abc_ObjFanin(pNode,iFanin) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pFanin ) ) + continue; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pFanin ); + // skip the CI + if ( Abc_ObjIsCi(pFanin) || (Abc_NtkIsStrash(pFanin->pNtk) && Abc_AigNodeIsConst(pFanin)) ) + continue; + Vec_PtrPush( vStack, pFanin ); + Vec_PtrPush( vStack, (void *)0 ); + } +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving CIs and CO. + However it marks with the current TravId both CIs and COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ) +{ + Vec_Ptr_t * vNodes, * vStack; + Abc_Obj_t * pObj; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 1000 ); + vStack = Vec_PtrAlloc( 1000 ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + Abc_NtkDfs_iter( vStack, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); + } + // collect dangling nodes if asked to + if ( fCollectAll ) + { + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_NtkDfs_iter( vStack, pObj, vNodes ); + } + Vec_PtrFree( vStack ); + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsHie_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pObj ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_NtkDfsHie_rec( pFanin, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of all objects.] + + Description [This procedure collects everything from POs to PIs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDfsHie_rec( pObj, vNodes ); + // collect dangling nodes if asked to + if ( fCollectAll ) + { + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_NtkDfs_rec( pObj, vNodes ); + } + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the ordering of nodes is DFS.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pFanin; + int i, k; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // mark the CIs + Abc_NtkForEachCi( pNtk, pNode, i ) + Abc_NodeSetTravIdCurrent( pNode ); + // go through the nodes + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // check the fanins of the node + Abc_ObjForEachFanin( pNode, pFanin, k ) + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + return 0; + // check the choices of the node + if ( Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsChoice(pNode) ) + for ( pFanin = pNode->pData; pFanin; pFanin = pFanin->pData ) + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + return 0; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkNodeSupport_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + assert( !Abc_ObjIsNet(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // collect the CI + if ( Abc_ObjIsCi(pNode) || Abc_ObjFaninNum(pNode) == 0 ) + { + Vec_PtrPush( vNodes, pNode ); + return; + } + assert( Abc_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NtkNodeSupport_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); +} + +/**Function************************************************************* + + Synopsis [Returns the set of CI nodes in the support of the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + // go through the PO nodes and call for each of them + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_NtkNodeSupport_rec( Abc_ObjFanin0(pNode), vNodes ); + // add unused CIs + Abc_NtkForEachCi( pNtk, pNode, i ) + if ( !Abc_NodeIsTravIdCurrent( pNode ) ) + Vec_PtrPush( vNodes, pNode ); + assert( Vec_PtrSize(vNodes) == Abc_NtkCiNum(pNtk) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the set of CI nodes in the support of the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + // go through the PO nodes and call for each of them + for ( i = 0; i < nNodes; i++ ) + if ( Abc_ObjIsCo(ppNodes[i]) ) + Abc_NtkNodeSupport_rec( Abc_ObjFanin0(ppNodes[i]), vNodes ); + else + Abc_NtkNodeSupport_rec( ppNodes[i], vNodes ); + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the PI + if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) ) + return; + assert( Abc_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_AigDfs_rec( pFanin, vNodes ); + // visit the equivalent nodes + if ( Abc_AigNodeIsChoice( pNode ) ) + for ( pFanin = pNode->pData; pFanin; pFanin = pFanin->pData ) + Abc_AigDfs_rec( pFanin, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving out CIs/COs. + However it marks both CIs and COs with the current TravId.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + // go through the PO nodes and call for each of them + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes ); + Abc_NodeSetTravIdCurrent( pNode ); + if ( fCollectCos ) + Vec_PtrPush( vNodes, pNode ); + } + // collect dangling nodes if asked to + if ( fCollectAll ) + { + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( !Abc_NodeIsTravIdCurrent(pNode) ) + Abc_AigDfs_rec( pNode, vNodes ); + } + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Collects nodes in the DFS manner by level.] + + Description [The number of levels should be set!!!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels ) +{ + Abc_Obj_t * pFanout; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the terminals + if ( Abc_ObjIsCo(pNode) ) + return; + assert( Abc_ObjIsNode(pNode) ); + // add the node to the structure + Vec_VecPush( vLevels, pNode->Level, pNode ); + // visit the TFO + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_DfsLevelizedTfo_rec( pFanout, vLevels ); +} + +/**Function************************************************************* + + Synopsis [Collects nodes in the DFS manner by level.] + + Description [The number of levels should be set!!!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi ) +{ + Vec_Vec_t * vLevels; + Abc_Obj_t * pFanout; + int i; + assert( fTfi == 0 ); + assert( !Abc_NtkIsNetlist(pNode->pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNode->pNtk ); + vLevels = Vec_VecAlloc( 100 ); + if ( Abc_ObjIsNode(pNode) ) + Abc_DfsLevelizedTfo_rec( pNode, vLevels ); + else + { + assert( Abc_ObjIsCi(pNode) ); + Abc_NodeSetTravIdCurrent( pNode ); + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_DfsLevelizedTfo_rec( pFanout, vLevels ); + } + return vLevels; +} + + +/**Function************************************************************* + + Synopsis [Recursively counts the number of logic levels of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevel_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNext; + int i, Level; + assert( !Abc_ObjIsNet(pNode) ); + // skip the PI + if ( Abc_ObjIsCi(pNode) ) + return pNode->Level; + assert( Abc_ObjIsNode( pNode ) ); + // if this node is already visited, return + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return pNode->Level; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin + pNode->Level = 0; + Abc_ObjForEachFanin( pNode, pNext, i ) + { + Level = Abc_NtkLevel_rec( Abc_ObjFanin0Ntk(pNext) ); + if ( pNode->Level < (unsigned)Level ) + pNode->Level = Level; + } + if ( Abc_ObjFaninNum(pNode) > 0 ) + pNode->Level++; + return pNode->Level; +} + +/**Function************************************************************* + + Synopsis [Recursively counts the number of logic levels of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevelReverse_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNext; + int i, Level; + assert( !Abc_ObjIsNet(pNode) ); + // skip the PI + if ( Abc_ObjIsCo(pNode) ) + return pNode->Level; + assert( Abc_ObjIsNode( pNode ) ); + // if this node is already visited, return + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return pNode->Level; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin + pNode->Level = 0; + Abc_ObjForEachFanout( pNode, pNext, i ) + { + Level = Abc_NtkLevelReverse_rec( Abc_ObjFanout0Ntk(pNext) ); + if ( pNode->Level < (unsigned)Level ) + pNode->Level = Level; + } + if ( Abc_ObjFaninNum(pNode) > 0 ) + pNode->Level++; + return pNode->Level; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevel( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, LevelsMax; + // set the CI levels to zero + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->Level = 0; + // perform the traversal + LevelsMax = 0; + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Abc_NtkLevel_rec( pNode ); + if ( LevelsMax < (int)pNode->Level ) + LevelsMax = (int)pNode->Level; + } + return LevelsMax; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, LevelsMax; + // set the CO levels to zero + Abc_NtkForEachCo( pNtk, pNode, i ) + pNode->Level = 0; + // perform the traversal + LevelsMax = 0; + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Abc_NtkLevelReverse_rec( pNode ); + if ( LevelsMax < (int)pNode->Level ) + LevelsMax = (int)pNode->Level; + } + return LevelsMax; +} + + +/**Function************************************************************* + + Synopsis [Recursively detects combinational loops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + Abc_Obj_t * pFanin; + int fAcyclic, i; + assert( !Abc_ObjIsNet(pNode) ); + if ( Abc_ObjIsCi(pNode) || Abc_ObjIsBox(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) ) + return 1; + assert( Abc_ObjIsNode(pNode) ); + // make sure the node is not visited + assert( !Abc_NodeIsTravIdPrevious(pNode) ); + // check if the node is part of the combinational loop + if ( Abc_NodeIsTravIdCurrent(pNode) ) + { + fprintf( stdout, "Network \"%s\" contains combinational loop!\n", Abc_NtkName(pNtk) ); + fprintf( stdout, "Node \"%s\" is encountered twice on the following path to the COs:\n", Abc_ObjName(pNode) ); + return 0; + } + // mark this node as a node on the current path + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + pFanin = Abc_ObjFanin0Ntk(pFanin); + // make sure there is no mixing of networks + assert( pFanin->pNtk == pNode->pNtk ); + // check if the fanin is visited + if ( Abc_NodeIsTravIdPrevious(pFanin) ) + continue; + // traverse the fanin's cone searching for the loop + if ( fAcyclic = Abc_NtkIsAcyclic_rec(pFanin) ) + continue; + // return as soon as the loop is detected + fprintf( stdout, " %s ->", Abc_ObjName(pFanin) ); + return 0; + } + // visit choices + if ( Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsChoice(pNode) ) + { + for ( pFanin = pNode->pData; pFanin; pFanin = pFanin->pData ) + { + // check if the fanin is visited + if ( Abc_NodeIsTravIdPrevious(pFanin) ) + continue; + // traverse the fanin's cone searching for the loop + if ( fAcyclic = Abc_NtkIsAcyclic_rec(pFanin) ) + continue; + // return as soon as the loop is detected + fprintf( stdout, " %s", Abc_ObjName(pFanin) ); + fprintf( stdout, " (choice of %s) -> ", Abc_ObjName(pNode) ); + return 0; + } + } + // mark this node as a visited node + Abc_NodeSetTravIdPrevious( pNode ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Detects combinational loops.] + + Description [This procedure is based on the idea suggested by Donald Chai. + As we traverse the network and visit the nodes, we need to distinquish + three types of nodes: (1) those that are visited for the first time, + (2) those that have been visited in this traversal but are currently not + on the traversal path, (3) those that have been visited and are currently + on the travesal path. When the node of type (3) is encountered, it means + that there is a combinational loop. To mark the three types of nodes, + two new values of the traversal IDs are used.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int fAcyclic, i; + // set the traversal ID for this DFS ordering + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkIncrementTravId( pNtk ); + // pNode->TravId == pNet->nTravIds means "pNode is on the path" + // pNode->TravId == pNet->nTravIds - 1 means "pNode is visited but is not on the path" + // pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited" + // traverse the network to detect cycles + fAcyclic = 1; + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pNode = Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode)); + if ( Abc_NodeIsTravIdPrevious(pNode) ) + continue; + // traverse the output logic cone + if ( fAcyclic = Abc_NtkIsAcyclic_rec(pNode) ) + continue; + // stop as soon as the first loop is detected + fprintf( stdout, " CO \"%s\"\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + break; + } + return fAcyclic; +} + + +/**Function************************************************************* + + Synopsis [Analyses choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeSetChoiceLevel_rec( Abc_Obj_t * pNode, int fMaximum ) +{ + Abc_Obj_t * pTemp; + int Level1, Level2, Level, LevelE; + // skip the visited node + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return (int)pNode->pCopy; + Abc_NodeSetTravIdCurrent( pNode ); + // compute levels of the children nodes + Level1 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pNode), fMaximum ); + Level2 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin1(pNode), fMaximum ); + Level = 1 + ABC_MAX( Level1, Level2 ); + if ( pNode->pData ) + { + LevelE = Abc_NodeSetChoiceLevel_rec( pNode->pData, fMaximum ); + if ( fMaximum ) + Level = ABC_MAX( Level, LevelE ); + else + Level = ABC_MIN( Level, LevelE ); + // set the level of all equivalent nodes to be the same minimum + for ( pTemp = pNode->pData; pTemp; pTemp = pTemp->pData ) + pTemp->pCopy = (void *)Level; + } + pNode->pCopy = (void *)Level; + return Level; +} + +/**Function************************************************************* + + Synopsis [Resets the levels of the nodes in the choice graph.] + + Description [Makes the level of the choice nodes to be equal to the + maximum of the level of the nodes in the equivalence class. This way + sorting by level leads to the reverse topological order, which is + needed for the required time computation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigSetChoiceLevels( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i, LevelMax, LevelCur; + assert( Abc_NtkIsStrash(pNtk) ); + // set the new travid counter + Abc_NtkIncrementTravId( pNtk ); + // set levels of the CI and constant + Abc_NtkForEachCi( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + pObj->pCopy = NULL; + } + pObj = Abc_AigConst1( pNtk ); + Abc_NodeSetTravIdCurrent( pObj ); + pObj->pCopy = NULL; + // set levels of all other nodes + LevelMax = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + { + LevelCur = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pObj), 1 ); + LevelMax = ABC_MAX( LevelMax, LevelCur ); + } + return LevelMax; +} + +/**Function************************************************************* + + Synopsis [Returns nodes by level from the smallest to the largest.] + + Description [Correctly handles the case of choice nodes, by first + spreading them out across several levels and then collecting.] + + SideEffects [What happens with dangling nodes???] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis ) +{ + Vec_Ptr_t * vNodes, * vLevels; + Abc_Obj_t * pNode, ** ppHead; + int LevelMax, i; + assert( Abc_NtkIsStrash(pNtk) ); + // set the correct levels + Abc_NtkCleanCopy( pNtk ); + LevelMax = Abc_AigSetChoiceLevels( pNtk ); + // relink nodes by level + vLevels = Vec_PtrStart( LevelMax + 1 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + ppHead = ((Abc_Obj_t **)vLevels->pArray) + (int)pNode->pCopy; + pNode->pCopy = *ppHead; + *ppHead = pNode; + } + // recollect nodes + vNodes = Vec_PtrStart( Abc_NtkNodeNum(pNtk) ); + Vec_PtrForEachEntryStart( vLevels, pNode, i, !fCollectCis ) + for ( ; pNode; pNode = pNode->pCopy ) + Vec_PtrPush( vNodes, pNode ); + Vec_PtrFree( vLevels ); + return vNodes; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcFanio.c b/abc70930/src/base/abc/abcFanio.c new file mode 100644 index 00000000..c8536695 --- /dev/null +++ b/abc70930/src/base/abc/abcFanio.c @@ -0,0 +1,336 @@ +/**CFile**************************************************************** + + FileName [abcFanio.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Various procedures to connect fanins/fanouts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntPushMem( Extra_MmStep_t * pMemMan, Vec_Int_t * p, int Entry ) +{ + if ( p->nSize == p->nCap ) + { + int * pArray; + int i; + + if ( p->nSize == 0 ) + p->nCap = 1; + if ( pMemMan ) + pArray = (int *)Extra_MmStepEntryFetch( pMemMan, p->nCap * 8 ); + else + pArray = ALLOC( int, p->nCap * 2 ); + if ( p->pArray ) + { + for ( i = 0; i < p->nSize; i++ ) + pArray[i] = p->pArray[i]; + if ( pMemMan ) + Extra_MmStepEntryRecycle( pMemMan, (char *)p->pArray, p->nCap * 4 ); + else + free( p->pArray ); + } + p->nCap *= 2; + p->pArray = pArray; + } + p->pArray[p->nSize++] = Entry; +} + +/**Function************************************************************* + + Synopsis [Creates fanout/fanin relationship between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pFaninR = Abc_ObjRegular(pFanin); + assert( !Abc_ObjIsComplement(pObj) ); + assert( pObj->pNtk == pFaninR->pNtk ); + assert( pObj->Id >= 0 && pFaninR->Id >= 0 ); + Vec_IntPushMem( pObj->pNtk->pMmStep, &pObj->vFanins, pFaninR->Id ); + Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninR->vFanouts, pObj->Id ); + if ( Abc_ObjIsComplement(pFanin) ) + Abc_ObjSetFaninC( pObj, Abc_ObjFaninNum(pObj)-1 ); + if ( Abc_ObjIsNet(pObj) && Abc_ObjFaninNum(pObj) > 1 ) + { + int x = 0; + } +// printf( "Adding fanin of %s ", Abc_ObjName(pObj) ); +// printf( "to be %s\n", Abc_ObjName(pFanin) ); +} + + +/**Function************************************************************* + + Synopsis [Destroys fanout/fanin relationship between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +{ + assert( !Abc_ObjIsComplement(pObj) ); + assert( !Abc_ObjIsComplement(pFanin) ); + assert( pObj->pNtk == pFanin->pNtk ); + assert( pObj->Id >= 0 && pFanin->Id >= 0 ); + if ( !Vec_IntRemove( &pObj->vFanins, pFanin->Id ) ) + { + printf( "The obj %d is not found among the fanins of obj %d ...\n", pFanin->Id, pObj->Id ); + return; + } + if ( !Vec_IntRemove( &pFanin->vFanouts, pObj->Id ) ) + { + printf( "The obj %d is not found among the fanouts of obj %d ...\n", pObj->Id, pFanin->Id ); + return; + } +} + + +/**Function************************************************************* + + Synopsis [Destroys fanout/fanin relationship between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjRemoveFanins( Abc_Obj_t * pObj ) +{ + Vec_Int_t * vFaninsOld; + Abc_Obj_t * pFanin; + int k; + // remove old fanins + vFaninsOld = &pObj->vFanins; + for ( k = vFaninsOld->nSize - 1; k >= 0; k-- ) + { + pFanin = Abc_NtkObj( pObj->pNtk, vFaninsOld->pArray[k] ); + Abc_ObjDeleteFanin( pObj, pFanin ); + } + pObj->fCompl0 = 0; + pObj->fCompl1 = 0; + assert( vFaninsOld->nSize == 0 ); +} + +/**Function************************************************************* + + Synopsis [Replaces a fanin of the node.] + + Description [The node is pObj. An old fanin of this node (pFaninOld) has to be + replaced by a new fanin (pFaninNew). Assumes that the node and the old fanin + are not complemented. The new fanin can be complemented. In this case, the + polarity of the new fanin will change, compared to the polarity of the old fanin.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew ) +{ + Abc_Obj_t * pFaninNewR = Abc_ObjRegular(pFaninNew); + int iFanin;//, nLats;//, fCompl; + assert( !Abc_ObjIsComplement(pObj) ); + assert( !Abc_ObjIsComplement(pFaninOld) ); + assert( pFaninOld != pFaninNewR ); +// assert( pObj != pFaninOld ); +// assert( pObj != pFaninNewR ); + assert( pObj->pNtk == pFaninOld->pNtk ); + assert( pObj->pNtk == pFaninNewR->pNtk ); + if ( (iFanin = Vec_IntFind( &pObj->vFanins, pFaninOld->Id )) == -1 ) + { + printf( "Node %s is not among", Abc_ObjName(pFaninOld) ); + printf( " the fanins of node %s...\n", Abc_ObjName(pObj) ); + return; + } + + // remember the attributes of the old fanin +// fCompl = Abc_ObjFaninC(pObj, iFanin); + // replace the old fanin entry by the new fanin entry (removes attributes) + Vec_IntWriteEntry( &pObj->vFanins, iFanin, pFaninNewR->Id ); + // set the attributes of the new fanin +// if ( fCompl ^ Abc_ObjIsComplement(pFaninNew) ) +// Abc_ObjSetFaninC( pObj, iFanin ); + if ( Abc_ObjIsComplement(pFaninNew) ) + Abc_ObjXorFaninC( pObj, iFanin ); + +// if ( Abc_NtkIsSeq(pObj->pNtk) && (nLats = Seq_ObjFaninL(pObj, iFanin)) ) +// Seq_ObjSetFaninL( pObj, iFanin, nLats ); + // update the fanout of the fanin + if ( !Vec_IntRemove( &pFaninOld->vFanouts, pObj->Id ) ) + { + printf( "Node %s is not among", Abc_ObjName(pObj) ); + printf( " the fanouts of its old fanin %s...\n", Abc_ObjName(pFaninOld) ); +// return; + } + Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninNewR->vFanouts, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Inserts one-input node of the type specified between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type ) +{ + Abc_Obj_t * pNodeNew; + int iFanoutIndex, iFaninIndex; + // find pNodeOut among the fanouts of pNodeIn + if ( (iFanoutIndex = Vec_IntFind( &pNodeIn->vFanouts, pNodeOut->Id )) == -1 ) + { + printf( "Node %s is not among", Abc_ObjName(pNodeOut) ); + printf( " the fanouts of node %s...\n", Abc_ObjName(pNodeIn) ); + return NULL; + } + // find pNodeIn among the fanins of pNodeOut + if ( (iFaninIndex = Vec_IntFind( &pNodeOut->vFanins, pNodeIn->Id )) == -1 ) + { + printf( "Node %s is not among", Abc_ObjName(pNodeIn) ); + printf( " the fanins of node %s...\n", Abc_ObjName(pNodeOut) ); + return NULL; + } + // create the new node + pNodeNew = Abc_NtkCreateObj( pNodeIn->pNtk, Type ); + // add pNodeIn as fanin and pNodeOut as fanout + Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanins, pNodeIn->Id ); + Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanouts, pNodeOut->Id ); + // update the fanout of pNodeIn + Vec_IntWriteEntry( &pNodeIn->vFanouts, iFanoutIndex, pNodeNew->Id ); + // update the fanin of pNodeOut + Vec_IntWriteEntry( &pNodeOut->vFanins, iFaninIndex, pNodeNew->Id ); + return pNodeNew; +} + +/**Function************************************************************* + + Synopsis [Transfers fanout from the old node to the new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjTransferFanout( Abc_Obj_t * pNodeFrom, Abc_Obj_t * pNodeTo ) +{ + Vec_Ptr_t * vFanouts; + int nFanoutsOld, i; + assert( !Abc_ObjIsComplement(pNodeFrom) ); + assert( !Abc_ObjIsComplement(pNodeTo) ); + assert( !Abc_ObjIsPo(pNodeFrom) && !Abc_ObjIsPo(pNodeTo) ); + assert( pNodeFrom->pNtk == pNodeTo->pNtk ); + assert( pNodeFrom != pNodeTo ); + assert( Abc_ObjFanoutNum(pNodeFrom) > 0 ); + // get the fanouts of the old node + nFanoutsOld = Abc_ObjFanoutNum(pNodeTo); + vFanouts = Vec_PtrAlloc( nFanoutsOld ); + Abc_NodeCollectFanouts( pNodeFrom, vFanouts ); + // patch the fanin of each of them + for ( i = 0; i < vFanouts->nSize; i++ ) + Abc_ObjPatchFanin( vFanouts->pArray[i], pNodeFrom, pNodeTo ); + assert( Abc_ObjFanoutNum(pNodeFrom) == 0 ); + assert( Abc_ObjFanoutNum(pNodeTo) == nFanoutsOld + vFanouts->nSize ); + Vec_PtrFree( vFanouts ); +} + +/**Function************************************************************* + + Synopsis [Replaces the node by a new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjReplace( Abc_Obj_t * pNodeOld, Abc_Obj_t * pNodeNew ) +{ + assert( !Abc_ObjIsComplement(pNodeOld) ); + assert( !Abc_ObjIsComplement(pNodeNew) ); + assert( pNodeOld->pNtk == pNodeNew->pNtk ); + assert( pNodeOld != pNodeNew ); + assert( Abc_ObjFanoutNum(pNodeOld) > 0 ); + // transfer the fanouts to the old node + Abc_ObjTransferFanout( pNodeOld, pNodeNew ); + // remove the old node + Abc_NtkDeleteObj_rec( pNodeOld, 1 ); +} + +/**Function************************************************************* + + Synopsis [Returns the index of the fanin in the fanin list of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pObj; + int i; + Abc_ObjForEachFanin( pFanout, pObj, i ) + if ( pObj == pFanin ) + return i; + return -1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcFunc.c b/abc70930/src/base/abc/abcFunc.c new file mode 100644 index 00000000..f3297d8f --- /dev/null +++ b/abc70930/src/base/abc/abcFunc.c @@ -0,0 +1,1154 @@ +/**CFile**************************************************************** + + FileName [abcFunc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Transformations between different functionality representations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFunc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_MUX_CUBES 100000 + +static int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ); +static DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot); +static Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts the network from SOP to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + DdManager * dd; + int nFaninsMax, i; + + assert( Abc_NtkHasSop(pNtk) ); + + // start the functionality manager + nFaninsMax = Abc_NtkGetFaninMax( pNtk ); + if ( nFaninsMax == 0 ) + printf( "Warning: The network has only constant nodes.\n" ); + + dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + // convert each node from SOP to BDD + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + pNode->pData = Abc_ConvertSopToBdd( dd, pNode->pData ); + if ( pNode->pData == NULL ) + { + printf( "Abc_NtkSopToBdd: Error while converting SOP into BDD.\n" ); + return 0; + } + Cudd_Ref( pNode->pData ); + } + + Extra_MmFlexStop( pNtk->pManFunc ); + pNtk->pManFunc = dd; + + // update the network type + pNtk->ntkFunc = ABC_FUNC_BDD; + return 1; +} + +/**Function************************************************************* + + Synopsis [Converts the node from SOP to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop ) +{ + DdNode * bSum, * bCube, * bTemp, * bVar; + char * pCube; + int nVars, Value, v; + + // start the cover + nVars = Abc_SopGetVarNum(pSop); + bSum = Cudd_ReadLogicZero(dd); Cudd_Ref( bSum ); + if ( Abc_SopIsExorType(pSop) ) + { + for ( v = 0; v < nVars; v++ ) + { + bSum = Cudd_bddXor( dd, bTemp = bSum, Cudd_bddIthVar(dd, v) ); Cudd_Ref( bSum ); + Cudd_RecursiveDeref( dd, bTemp ); + } + } + else + { + // check the logic function of the node + Abc_SopForEachCube( pSop, nVars, pCube ) + { + bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); + Abc_CubeForEachVar( pCube, Value, v ) + { + if ( Value == '0' ) + bVar = Cudd_Not( Cudd_bddIthVar( dd, v ) ); + else if ( Value == '1' ) + bVar = Cudd_bddIthVar( dd, v ); + else + continue; + bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + bSum = Cudd_bddOr( dd, bTemp = bSum, bCube ); + Cudd_Ref( bSum ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + } + // complement the result if necessary + bSum = Cudd_NotCond( bSum, !Abc_SopGetPhase(pSop) ); + Cudd_Deref( bSum ); + return bSum; +} + +/**Function************************************************************* + + Synopsis [Removes complemented SOP covers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) +{ + DdManager * dd; + DdNode * bFunc; + Vec_Str_t * vCube; + Abc_Obj_t * pNode; + int nFaninsMax, fFound, i; + + assert( Abc_NtkHasSop(pNtk) ); + + // check if there are nodes with complemented SOPs + fFound = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( Abc_SopIsComplement(pNode->pData) ) + { + fFound = 1; + break; + } + if ( !fFound ) + return; + + // start the BDD package + nFaninsMax = Abc_NtkGetFaninMax( pNtk ); + if ( nFaninsMax == 0 ) + printf( "Warning: The network has only constant nodes.\n" ); + dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + // change the cover of negated nodes + vCube = Vec_StrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( Abc_SopIsComplement(pNode->pData) ) + { + bFunc = Abc_ConvertSopToBdd( dd, pNode->pData ); Cudd_Ref( bFunc ); + pNode->pData = Abc_ConvertBddToSop( pNtk->pManFunc, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, 1 ); + Cudd_RecursiveDeref( dd, bFunc ); + assert( !Abc_SopIsComplement(pNode->pData) ); + } + Vec_StrFree( vCube ); + Extra_StopManager( dd ); +} + + + + + +/**Function************************************************************* + + Synopsis [Converts the network from BDD to SOP representation.] + + Description [If the flag is set to 1, forces the direct phase of all covers.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect ) +{ + Abc_Obj_t * pNode; + Extra_MmFlex_t * pManNew; + DdManager * dd = pNtk->pManFunc; + DdNode * bFunc; + Vec_Str_t * vCube; + int i, fMode; + + if ( fDirect ) + fMode = 1; + else + fMode = -1; + + assert( Abc_NtkHasBdd(pNtk) ); + if ( dd->size > 0 ) + Cudd_zddVarsFromBddVars( dd, 2 ); + // create the new manager + pManNew = Extra_MmFlexStart(); + + // go through the objects + vCube = Vec_StrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + bFunc = pNode->pData; + pNode->pNext = (Abc_Obj_t *)Abc_ConvertBddToSop( pManNew, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, fMode ); + if ( pNode->pNext == NULL ) + { + Extra_MmFlexStop( pManNew ); + Abc_NtkCleanNext( pNtk ); +// printf( "Converting from BDDs to SOPs has failed.\n" ); + Vec_StrFree( vCube ); + return 0; + } + } + Vec_StrFree( vCube ); + + // update the network type + pNtk->ntkFunc = ABC_FUNC_SOP; + // set the new manager + pNtk->pManFunc = pManNew; + // transfer from next to data + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Cudd_RecursiveDeref( dd, pNode->pData ); + pNode->pData = pNode->pNext; + pNode->pNext = NULL; + } + + // check for remaining references in the package + Extra_StopManager( dd ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Converts the node from BDD to SOP representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode ) +{ + int fVerify = 0; + char * pSop; + DdNode * bFuncNew, * bCover, * zCover, * zCover0, * zCover1; + int nCubes, nCubes0, nCubes1, fPhase; + + assert( bFuncOn == bFuncOnDc || Cudd_bddLeq( dd, bFuncOn, bFuncOnDc ) ); + if ( Cudd_IsConstant(bFuncOn) || Cudd_IsConstant(bFuncOnDc) ) + { + if ( fMode == -1 ) // if the phase is not known, write constant 1 + fMode = 1; + Vec_StrFill( vCube, nFanins, '-' ); + Vec_StrPush( vCube, '\0' ); + if ( pMan ) + pSop = Extra_MmFlexEntryFetch( pMan, nFanins + 4 ); + else + pSop = ALLOC( char, nFanins + 4 ); + if ( bFuncOn == Cudd_ReadOne(dd) ) + sprintf( pSop, "%s %d\n", vCube->pArray, fMode ); + else + sprintf( pSop, "%s %d\n", vCube->pArray, !fMode ); + return pSop; + } + + + if ( fMode == -1 ) + { // try both phases + assert( fAllPrimes == 0 ); + + // get the ZDD of the negative polarity + bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover0 ); + Cudd_Ref( zCover0 ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + nCubes0 = Abc_CountZddCubes( dd, zCover0 ); + + // get the ZDD of the positive polarity + bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover1 ); + Cudd_Ref( zCover1 ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + nCubes1 = Abc_CountZddCubes( dd, zCover1 ); + + // compare the number of cubes + if ( nCubes1 <= nCubes0 ) + { // use positive polarity + nCubes = nCubes1; + zCover = zCover1; + Cudd_RecursiveDerefZdd( dd, zCover0 ); + fPhase = 1; + } + else + { // use negative polarity + nCubes = nCubes0; + zCover = zCover0; + Cudd_RecursiveDerefZdd( dd, zCover1 ); + fPhase = 0; + } + } + else if ( fMode == 0 ) + { + // get the ZDD of the negative polarity + if ( fAllPrimes ) + { + zCover = Extra_zddPrimes( dd, Cudd_Not(bFuncOnDc) ); + Cudd_Ref( zCover ); + } + else + { + bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover ); + Cudd_Ref( zCover ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + } + nCubes = Abc_CountZddCubes( dd, zCover ); + fPhase = 0; + } + else if ( fMode == 1 ) + { + // get the ZDD of the positive polarity + if ( fAllPrimes ) + { + zCover = Extra_zddPrimes( dd, bFuncOnDc ); + Cudd_Ref( zCover ); + } + else + { + bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover ); + Cudd_Ref( zCover ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + } + nCubes = Abc_CountZddCubes( dd, zCover ); + fPhase = 1; + } + else + { + assert( 0 ); + } + + if ( nCubes > ABC_MUX_CUBES ) + { + Cudd_RecursiveDerefZdd( dd, zCover ); + printf( "The number of cubes exceeded the predefined limit (%d).\n", ABC_MUX_CUBES ); + return NULL; + } + + // allocate memory for the cover + if ( pMan ) + pSop = Extra_MmFlexEntryFetch( pMan, (nFanins + 3) * nCubes + 1 ); + else + pSop = ALLOC( char, (nFanins + 3) * nCubes + 1 ); + pSop[(nFanins + 3) * nCubes] = 0; + // create the SOP + Vec_StrFill( vCube, nFanins, '-' ); + Vec_StrPush( vCube, '\0' ); + Abc_ConvertZddToSop( dd, zCover, pSop, nFanins, vCube, fPhase ); + Cudd_RecursiveDerefZdd( dd, zCover ); + + // verify + if ( fVerify ) + { + bFuncNew = Abc_ConvertSopToBdd( dd, pSop ); Cudd_Ref( bFuncNew ); + if ( bFuncOn == bFuncOnDc ) + { + if ( bFuncNew != bFuncOn ) + printf( "Verification failed.\n" ); + } + else + { + if ( !Cudd_bddLeq(dd, bFuncOn, bFuncNew) || !Cudd_bddLeq(dd, bFuncNew, bFuncOnDc) ) + printf( "Verification failed.\n" ); + } + Cudd_RecursiveDeref( dd, bFuncNew ); + } + return pSop; +} + +/**Function************************************************************* + + Synopsis [Derive the SOP from the ZDD representation of the cubes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertZddToSop_rec( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase, int * pnCubes ) +{ + DdNode * zC0, * zC1, * zC2; + int Index; + + if ( zCover == dd->zero ) + return; + if ( zCover == dd->one ) + { + char * pCube; + pCube = pSop + (*pnCubes) * (nFanins + 3); + sprintf( pCube, "%s %d\n", vCube->pArray, fPhase ); + (*pnCubes)++; + return; + } + Index = zCover->index/2; + assert( Index < nFanins ); + extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 ); + vCube->pArray[Index] = '0'; + Abc_ConvertZddToSop_rec( dd, zC0, pSop, nFanins, vCube, fPhase, pnCubes ); + vCube->pArray[Index] = '1'; + Abc_ConvertZddToSop_rec( dd, zC1, pSop, nFanins, vCube, fPhase, pnCubes ); + vCube->pArray[Index] = '-'; + Abc_ConvertZddToSop_rec( dd, zC2, pSop, nFanins, vCube, fPhase, pnCubes ); +} + +/**Function************************************************************* + + Synopsis [Derive the BDD for the function in the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ) +{ + int nCubes = 0; + Abc_ConvertZddToSop_rec( dd, zCover, pSop, nFanins, vCube, fPhase, &nCubes ); + return nCubes; +} + + +/**Function************************************************************* + + Synopsis [Computes the SOPs of the negative and positive phase of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ) +{ + assert( Abc_NtkHasBdd(pNode->pNtk) ); + *ppSop0 = Abc_ConvertBddToSop( pMmMan, pNode->pNtk->pManFunc, pNode->pData, pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 0 ); + *ppSop1 = Abc_ConvertBddToSop( pMmMan, pNode->pNtk->pManFunc, pNode->pData, pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 1 ); +} + + + + +/**Function************************************************************* + + Synopsis [Count the number of paths in the ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_CountZddCubes_rec( DdManager * dd, DdNode * zCover, int * pnCubes ) +{ + DdNode * zC0, * zC1, * zC2; + if ( zCover == dd->zero ) + return; + if ( zCover == dd->one ) + { + (*pnCubes)++; + return; + } + if ( (*pnCubes) > ABC_MUX_CUBES ) + return; + extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 ); + Abc_CountZddCubes_rec( dd, zC0, pnCubes ); + Abc_CountZddCubes_rec( dd, zC1, pnCubes ); + Abc_CountZddCubes_rec( dd, zC2, pnCubes ); +} + +/**Function************************************************************* + + Synopsis [Count the number of paths in the ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ) +{ + int nCubes = 0; + Abc_CountZddCubes_rec( dd, zCover, &nCubes ); + return nCubes; +} + + +/**Function************************************************************* + + Synopsis [Converts the network from SOP to AIG representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + Hop_Man_t * pMan; + int i; + + assert( Abc_NtkHasSop(pNtk) ); + + // start the functionality manager + pMan = Hop_ManStart(); + + // convert each node from SOP to BDD + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + pNode->pData = Abc_ConvertSopToAig( pMan, pNode->pData ); + if ( pNode->pData == NULL ) + { + printf( "Abc_NtkSopToAig: Error while converting SOP into AIG.\n" ); + return 0; + } + } + Extra_MmFlexStop( pNtk->pManFunc ); + pNtk->pManFunc = pMan; + + // update the network type + pNtk->ntkFunc = ABC_FUNC_AIG; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_ConvertSopToAigInternal( Hop_Man_t * pMan, char * pSop ) +{ + Hop_Obj_t * pAnd, * pSum; + int i, Value, nFanins; + char * pCube; + // get the number of variables + nFanins = Abc_SopGetVarNum(pSop); + // go through the cubes of the node's SOP + pSum = Hop_ManConst0(pMan); + Abc_SopForEachCube( pSop, nFanins, pCube ) + { + // create the AND of literals + pAnd = Hop_ManConst1(pMan); + Abc_CubeForEachVar( pCube, Value, i ) + { + if ( Value == '1' ) + pAnd = Hop_And( pMan, pAnd, Hop_IthVar(pMan,i) ); + else if ( Value == '0' ) + pAnd = Hop_And( pMan, pAnd, Hop_Not(Hop_IthVar(pMan,i)) ); + } + // add to the sum of cubes + pSum = Hop_Or( pMan, pSum, pAnd ); + } + // decide whether to complement the result + if ( Abc_SopIsComplement(pSop) ) + pSum = Hop_Not(pSum); + return pSum; +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ) +{ + extern Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop ); + int fUseFactor = 1; + // consider the constant node + if ( Abc_SopGetVarNum(pSop) == 0 ) + return Hop_NotCond( Hop_ManConst1(pMan), Abc_SopIsConst0(pSop) ); + // consider the special case of EXOR function + if ( Abc_SopIsExorType(pSop) ) + return Hop_NotCond( Hop_CreateExor(pMan, Abc_SopGetVarNum(pSop)), Abc_SopIsComplement(pSop) ); + // decide when to use factoring + if ( fUseFactor && Abc_SopGetVarNum(pSop) > 2 && Abc_SopGetCubeNum(pSop) > 1 ) + return Dec_GraphFactorSop( pMan, pSop ); + return Abc_ConvertSopToAigInternal( pMan, pSop ); +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + Hop_Man_t * pMan; + DdManager * dd; + int nFaninsMax, i; + + assert( Abc_NtkHasAig(pNtk) ); + + // start the functionality manager + nFaninsMax = Abc_NtkGetFaninMax( pNtk ); + if ( nFaninsMax == 0 ) + printf( "Warning: The network has only constant nodes.\n" ); + + dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + // set the mapping of elementary AIG nodes into the elementary BDD nodes + pMan = pNtk->pManFunc; + assert( Hop_ManPiNum(pMan) >= nFaninsMax ); + for ( i = 0; i < nFaninsMax; i++ ) + { + Hop_ManPi(pMan, i)->pData = Cudd_bddIthVar(dd, i); + Cudd_Ref( Hop_ManPi(pMan, i)->pData ); + } + + // convert each node from SOP to BDD + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + pNode->pData = Abc_ConvertAigToBdd( dd, pNode->pData ); + if ( pNode->pData == NULL ) + { + printf( "Abc_NtkSopToBdd: Error while converting SOP into BDD.\n" ); + return 0; + } + Cudd_Ref( pNode->pData ); + } + + // dereference intermediate BDD nodes + for ( i = 0; i < nFaninsMax; i++ ) + Cudd_RecursiveDeref( dd, Hop_ManPi(pMan, i)->pData ); + + Hop_ManStop( pNtk->pManFunc ); + pNtk->pManFunc = dd; + + // update the network type + pNtk->ntkFunc = ABC_FUNC_BDD; + return 1; +} + +/**Function************************************************************* + + Synopsis [Construct BDDs and mark AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertAigToBdd_rec1( DdManager * dd, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin0(pObj) ); + Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin1(pObj) ); + pObj->pData = Cudd_bddAnd( dd, (DdNode *)Hop_ObjChild0Copy(pObj), (DdNode *)Hop_ObjChild1Copy(pObj) ); + Cudd_Ref( pObj->pData ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Dereference BDDs and unmark AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertAigToBdd_rec2( DdManager * dd, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) + return; + Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin0(pObj) ); + Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin1(pObj) ); + Cudd_RecursiveDeref( dd, pObj->pData ); + pObj->pData = NULL; + assert( Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjClearMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot ) +{ + DdNode * bFunc; + // check the case of a constant + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + return Cudd_NotCond( Cudd_ReadOne(dd), Hop_IsComplement(pRoot) ); + // construct BDD + Abc_ConvertAigToBdd_rec1( dd, Hop_Regular(pRoot) ); + // hold on to the result + bFunc = Cudd_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); Cudd_Ref( bFunc ); + // dereference BDD + Abc_ConvertAigToBdd_rec2( dd, Hop_Regular(pRoot) ); + // return the result + Cudd_Deref( bFunc ); + return bFunc; +} + + + +/**Function************************************************************* + + Synopsis [Construct BDDs and mark AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ConvertAigToTruth_rec1( Hop_Obj_t * pObj ) +{ + int Counter = 0; + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return 0; + Counter += Abc_ConvertAigToTruth_rec1( Hop_ObjFanin0(pObj) ); + Counter += Abc_ConvertAigToTruth_rec1( Hop_ObjFanin1(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); + return Counter + 1; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Abc_ConvertAigToTruth_rec2( Hop_Obj_t * pObj, Vec_Int_t * vTruth, int nWords ) +{ + unsigned * pTruth, * pTruth0, * pTruth1; + int i; + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) + return pObj->pData; + // compute the truth tables of the fanins + pTruth0 = Abc_ConvertAigToTruth_rec2( Hop_ObjFanin0(pObj), vTruth, nWords ); + pTruth1 = Abc_ConvertAigToTruth_rec2( Hop_ObjFanin1(pObj), vTruth, nWords ); + // creat the truth table of the node + pTruth = Vec_IntFetch( vTruth, nWords ); + if ( Hop_ObjIsExor(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] ^ pTruth1[i]; + else if ( !Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & pTruth1[i]; + else if ( !Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & ~pTruth1[i]; + else if ( Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & pTruth1[i]; + else // if ( Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; + assert( Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjClearMarkA( pObj ); + pObj->pData = pTruth; + return pTruth; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the node.] + + Description [Assumes that the structural support is no more than 8 inputs. + Uses array vTruth to store temporary truth tables. The returned pointer should + be used immediately.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Abc_ConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst ) +{ + static unsigned uTruths[8][8] = { // elementary truth tables + { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, + { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, + { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, + { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, + { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, + { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, + { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, + { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } + }; + Hop_Obj_t * pObj; + unsigned * pTruth, * pTruth2; + int i, nWords, nNodes; + Vec_Ptr_t * vTtElems; + + // if the number of variables is more than 8, allocate truth tables + if ( nVars > 8 ) + vTtElems = Vec_PtrAllocTruthTables( nVars ); + else + vTtElems = NULL; + + // clear the data fields and set marks + nNodes = Abc_ConvertAigToTruth_rec1( pRoot ); + // prepare memory + nWords = Hop_TruthWordNum( nVars ); + Vec_IntClear( vTruth ); + Vec_IntGrow( vTruth, nWords * (nNodes+1) ); + pTruth = Vec_IntFetch( vTruth, nWords ); + // check the case of a constant + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + { + assert( nNodes == 0 ); + if ( Hop_IsComplement(pRoot) ) + Extra_TruthClear( pTruth, nVars ); + else + Extra_TruthFill( pTruth, nVars ); + return pTruth; + } + // set elementary truth tables at the leaves + assert( nVars <= Hop_ManPiNum(p) ); +// assert( Hop_ManPiNum(p) <= 8 ); + if ( fMsbFirst ) + { + Hop_ManForEachPi( p, pObj, i ) + { + if ( vTtElems ) + pObj->pData = Vec_PtrEntry(vTtElems, nVars-1-i); + else + pObj->pData = (void *)uTruths[nVars-1-i]; + } + } + else + { + Hop_ManForEachPi( p, pObj, i ) + { + if ( vTtElems ) + pObj->pData = Vec_PtrEntry(vTtElems, i); + else + pObj->pData = (void *)uTruths[i]; + } + } + // clear the marks and compute the truth table + pTruth2 = Abc_ConvertAigToTruth_rec2( pRoot, vTruth, nWords ); + // copy the result + Extra_TruthCopy( pTruth, pTruth2, nVars ); + if ( vTtElems ) + Vec_PtrFree( vTtElems ); + return pTruth; +} + + +/**Function************************************************************* + + Synopsis [Construct BDDs and mark AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertAigToAig_rec( Abc_Ntk_t * pNtkAig, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin0(pObj) ); + Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin1(pObj) ); + pObj->pData = Abc_AigAnd( pNtkAig->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObjOld ) +{ + Hop_Man_t * pHopMan; + Hop_Obj_t * pRoot; + Abc_Obj_t * pFanin; + int i; + // get the local AIG + pHopMan = pObjOld->pNtk->pManFunc; + pRoot = pObjOld->pData; + // check the case of a constant + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + return Abc_ObjNotCond( Abc_AigConst1(pNtkAig), Hop_IsComplement(pRoot) ); + // assign the fanin nodes + Abc_ObjForEachFanin( pObjOld, pFanin, i ) + { + assert( pFanin->pCopy != NULL ); + Hop_ManPi(pHopMan, i)->pData = pFanin->pCopy; + } + // construct the AIG + Abc_ConvertAigToAig_rec( pNtkAig, Hop_Regular(pRoot) ); + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + // return the result + return Abc_ObjNotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + + +/**Function************************************************************* + + Synopsis [Unmaps the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ) +{ + extern void * Abc_FrameReadLibGen(); + Abc_Obj_t * pNode; + char * pSop; + int i; + + assert( Abc_NtkHasMapping(pNtk) ); + // update the functionality manager + assert( pNtk->pManFunc == Abc_FrameReadLibGen() ); + pNtk->pManFunc = Extra_MmFlexStart(); + pNtk->ntkFunc = ABC_FUNC_SOP; + // update the nodes + Abc_NtkForEachNode( pNtk, pNode, i ) + { + pSop = Mio_GateReadSop(pNode->pData); + assert( Abc_SopGetVarNum(pSop) == Abc_ObjFaninNum(pNode) ); + pNode->pData = Abc_SopRegister( pNtk->pManFunc, pSop ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Converts SOP functions into BLIF-MV functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSopToBlifMv( Abc_Ntk_t * pNtk ) +{ + return 1; +} + +/**Function************************************************************* + + Synopsis [Convers logic network to the SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fDirect ) +{ + assert( !Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkHasSop(pNtk) ) + { + if ( !fDirect ) + return 1; + if ( !Abc_NtkSopToBdd(pNtk) ) + return 0; + return Abc_NtkBddToSop(pNtk, fDirect); + } + if ( Abc_NtkHasMapping(pNtk) ) + return Abc_NtkMapToSop(pNtk); + if ( Abc_NtkHasBdd(pNtk) ) + return Abc_NtkBddToSop(pNtk, fDirect); + if ( Abc_NtkHasAig(pNtk) ) + { + if ( !Abc_NtkAigToBdd(pNtk) ) + return 0; + return Abc_NtkBddToSop(pNtk, fDirect); + } + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Convers logic network to the SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkToBdd( Abc_Ntk_t * pNtk ) +{ + assert( !Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkHasBdd(pNtk) ) + return 1; + if ( Abc_NtkHasMapping(pNtk) ) + { + Abc_NtkMapToSop(pNtk); + return Abc_NtkSopToBdd(pNtk); + } + if ( Abc_NtkHasSop(pNtk) ) + return Abc_NtkSopToBdd(pNtk); + if ( Abc_NtkHasAig(pNtk) ) + return Abc_NtkAigToBdd(pNtk); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Convers logic network to the SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkToAig( Abc_Ntk_t * pNtk ) +{ + assert( !Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkHasAig(pNtk) ) + return 1; + if ( Abc_NtkHasMapping(pNtk) ) + { + Abc_NtkMapToSop(pNtk); + return Abc_NtkSopToAig(pNtk); + } + if ( Abc_NtkHasBdd(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk,0) ) + return 0; + return Abc_NtkSopToAig(pNtk); + } + if ( Abc_NtkHasSop(pNtk) ) + return Abc_NtkSopToAig(pNtk); + assert( 0 ); + return 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcHie.c b/abc70930/src/base/abc/abcHie.c new file mode 100644 index 00000000..56333a36 --- /dev/null +++ b/abc70930/src/base/abc/abcHie.c @@ -0,0 +1,492 @@ +/**CFile**************************************************************** + + FileName [abcHie.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to handle hierarchy.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcHie.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Recursively flattens logic hierarchy of the netlist.] + + Description [When this procedure is called, the PI/PO nets of the old + netlist point to the corresponding nets of the flattened netlist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFlattenLogicHierarchy_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter ) +{ + char Suffix[1000] = {0}; + Abc_Ntk_t * pNtkModel; + Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin; + int i, k; + + // process the blackbox + if ( Abc_NtkHasBlackbox(pNtk) ) + { + // duplicate the blackbox + assert( Abc_NtkBoxNum(pNtk) == 1 ); + pObj = Abc_NtkBox( pNtk, 0 ); + Abc_NtkDupBox( pNtkNew, pObj, 1 ); + pObj->pCopy->pData = pNtk; + + // connect blackbox fanins to the PI nets + assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy ); + + // connect blackbox fanouts to the PO nets + assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) ); + Abc_NtkForEachPo( pNtk, pTerm, i ) + Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) ); + return; + } + + (*pCounter)++; + + // create the prefix, which will be appended to the internal names + if ( *pCounter ) + sprintf( Suffix, "_%s_%d", Abc_NtkName(pNtk), *pCounter ); + + // duplicate nets of all boxes, including latches + Abc_NtkForEachBox( pNtk, pObj, i ) + { + Abc_ObjForEachFanin( pObj, pTerm, k ) + { + pNet = Abc_ObjFanin0(pTerm); + if ( pNet->pCopy ) + continue; + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) ); + } + Abc_ObjForEachFanout( pObj, pTerm, k ) + { + pNet = Abc_ObjFanout0(pTerm); + if ( pNet->pCopy ) + continue; + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) ); + } + } + + // mark objects that will not be used + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_NodeSetTravIdCurrent( pTerm ); + Abc_NtkForEachPo( pNtk, pTerm, i ) + Abc_NodeSetTravIdCurrent( pTerm ); + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + Abc_NodeSetTravIdCurrent( pObj ); + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_NodeSetTravIdCurrent( pTerm ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_NodeSetTravIdCurrent( pTerm ); + } + + // duplicate objects that do not have prototypes yet + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( Abc_NodeIsTravIdCurrent(pObj) ) + continue; + if ( pObj->pCopy ) + continue; + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + } + + // connect objects + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // call recursively + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + pNtkModel = pObj->pData; + // check the match between the number of actual and formal parameters + assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) ); + assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) ); + // clean the node copy fields + Abc_NtkCleanCopy( pNtkModel ); + // map PIs/POs + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy; + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy; + // call recursively + Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtkModel, pCounter ); + } + + // if it is a BLIF-MV netlist transfer the values of all nets + if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) ) + { + if ( Abc_NtkMvVar( pNtkNew ) == NULL ) + Abc_NtkStartMvVars( pNtkNew ); + Abc_NtkForEachNet( pNtk, pObj, i ) + Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) ); + } +} + +/**Function************************************************************* + + Synopsis [Flattens the logic hierarchy of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pTerm, * pNet; + int i, Counter; + extern Abc_Lib_t * Abc_LibDupBlackboxes( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave ); + + assert( Abc_NtkIsNetlist(pNtk) ); + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + + // duplicate PIs/POs and their nets + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + Abc_NtkDupObj( pNtkNew, pTerm, 0 ); + pNet = Abc_ObjFanout0( pTerm ); + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); + Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy ); + } + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + Abc_NtkDupObj( pNtkNew, pTerm, 0 ); + pNet = Abc_ObjFanin0( pTerm ); + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); + Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy ); + } + + // recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes + Counter = -1; + Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtk, &Counter ); + printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n", + Counter, Abc_NtkBlackboxNum(pNtkNew) ); + + if ( pNtk->pDesign ) + { + // pass on the design + assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk ); + pNtkNew->pDesign = Abc_LibDupBlackboxes( pNtk->pDesign, pNtkNew ); + // update the pointers + Abc_NtkForEachBlackbox( pNtkNew, pTerm, i ) + pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy; + } + + // copy the timing information +// Abc_ManTimeDup( pNtk, pNtkNew ); + // duplicate EXDC + if ( pNtk->pExdc ) + printf( "EXDC is not transformed.\n" ); + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkFlattenLogicHierarchy(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Extracts blackboxes by making them into additional PIs/POs.] + + Description [The input netlist has not logic hierarchy. The resulting + netlist has additional PIs/POs for each blackbox input/output.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pNet, * pFanin, * pTerm; + int i, k; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + + // mark the nodes that should not be connected + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachBlackbox( pNtk, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + Abc_NtkForEachCi( pNtk, pTerm, i ) + Abc_NodeSetTravIdCurrent( pTerm ); + Abc_NtkForEachCo( pNtk, pTerm, i ) + Abc_NodeSetTravIdCurrent( pTerm ); + // unmark PIs and LIs/LOs + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_NodeSetTravIdPrevious( pTerm ); + Abc_NtkForEachLatchInput( pNtk, pTerm, i ) + Abc_NodeSetTravIdPrevious( pTerm ); + Abc_NtkForEachLatchOutput( pNtk, pTerm, i ) + Abc_NodeSetTravIdPrevious( pTerm ); + // copy the box outputs + Abc_NtkForEachBlackbox( pNtk, pObj, i ) + Abc_ObjForEachFanout( pObj, pTerm, k ) + pTerm->pCopy = Abc_NtkCreatePi( pNtkNew ); + + // duplicate other objects + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_NtkDupObj( pNtkNew, pObj, Abc_ObjIsNet(pObj) ); + + // connect all objects + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // create unique PO for each net feeding into blackboxes or POs + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pTerm, i ) + { + // skip latch inputs + assert( Abc_ObjFanoutNum(pTerm) <= 1 ); + if ( Abc_ObjFanoutNum(pTerm) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pTerm)) ) + continue; + // check if the net is visited + pNet = Abc_ObjFanin0(pTerm); + if ( Abc_NodeIsTravIdCurrent(pNet) ) + continue; + // create PO + Abc_NodeSetTravIdCurrent( pNet ); + Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNet->pCopy ); + } + + // check integrity + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkConvertBlackboxes(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Inserts blackboxes into the netlist.] + + Description [The first arg is the netlist with blackboxes without logic hierarchy. + The second arg is a non-hierarchical netlist derived from the above netlist after processing. + This procedure create a new netlist, which is comparable to the original netlist with + blackboxes, except that it contains logic nodes from the netlist after processing.] + + SideEffects [This procedure silently assumes that blackboxes appear + only in the top-level model. If they appear in other models as well, + the name of the model and its number were appended to the names of + blackbox inputs/outputs.] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL ) +{ + Abc_Lib_t * pDesign; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjH, * pObjL, * pNetH, * pNetL, * pTermH; + int i, k; + + assert( Abc_NtkIsNetlist(pNtkH) ); + assert( Abc_NtkWhiteboxNum(pNtkH) == 0 ); + assert( Abc_NtkBlackboxNum(pNtkH) > 0 ); + + assert( Abc_NtkIsNetlist(pNtkL) ); + assert( Abc_NtkWhiteboxNum(pNtkL) == 0 ); + assert( Abc_NtkBlackboxNum(pNtkL) == 0 ); + + // prepare the logic network for copying + Abc_NtkCleanCopy( pNtkL ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtkL->ntkType, pNtkL->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( pNtkH->pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtkH->pSpec ); + + // make sure every PI/PO has a PI/PO in the processed network + Abc_NtkForEachPi( pNtkH, pObjH, i ) + { + pNetH = Abc_ObjFanout0(pObjH); + pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); + if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) ) + { + printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the PI %s.\n", Abc_ObjName(pNetH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + if ( pNetL->pCopy ) + { + printf( "Error in Abc_NtkInsertNewLogic(): Primary input %s is repeated twice.\n", Abc_ObjName(pNetH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + // create the new net + pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); + Abc_NtkDupObj( pNtkNew, Abc_ObjFanin0(pNetL), 0 ); + } + + // make sure every BB has a PI/PO in the processed network + Abc_NtkForEachBlackbox( pNtkH, pObjH, i ) + { + // duplicate the box + Abc_NtkDupBox( pNtkNew, pObjH, 0 ); + pObjH->pCopy->pData = pObjH->pData; + // create PIs + Abc_ObjForEachFanout( pObjH, pTermH, k ) + { + pNetH = Abc_ObjFanout0( pTermH ); + pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); + if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) ) + { + printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the inpout %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + if ( pNetL->pCopy ) + { + printf( "Error in Abc_NtkInsertNewLogic(): Box output %s is repeated twice.\n", Abc_ObjName(pNetH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + // create net and map the PI + pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); + Abc_ObjFanin0(pNetL)->pCopy = pTermH->pCopy; + } + } + + Abc_NtkForEachPo( pNtkH, pObjH, i ) + { + pNetH = Abc_ObjFanin0(pObjH); + pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); + if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) ) + { + printf( "Error in Abc_NtkInsertNewLogic(): There is no PO corresponding to the PO %s.\n", Abc_ObjName(pNetH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + if ( pNetL->pCopy ) + continue; + // create the new net + pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); + Abc_NtkDupObj( pNtkNew, Abc_ObjFanout0(pNetL), 0 ); + } + Abc_NtkForEachBlackbox( pNtkH, pObjH, i ) + { + Abc_ObjForEachFanin( pObjH, pTermH, k ) + { + char * pName; + pNetH = Abc_ObjFanin0( pTermH ); + pName = Abc_ObjName(pNetH); + pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); + if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) ) + { + printf( "There is no PO corresponding to the input %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + // create net and map the PO + if ( pNetL->pCopy ) + { + if ( Abc_ObjFanout0(pNetL)->pCopy == NULL ) + Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy; + else + Abc_ObjAddFanin( pTermH->pCopy, pNetL->pCopy ); + continue; + } + pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); + Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy; + } + } + + // duplicate other objects of the logic network + Abc_NtkForEachObj( pNtkL, pObjL, i ) + if ( pObjL->pCopy == NULL && !Abc_ObjIsPo(pObjL) ) // skip POs feeding into PIs + Abc_NtkDupObj( pNtkNew, pObjL, Abc_ObjIsNet(pObjL) ); + + // connect objects + Abc_NtkForEachObj( pNtkL, pObjL, i ) + Abc_ObjForEachFanin( pObjL, pNetL, k ) + if ( pObjL->pCopy ) + Abc_ObjAddFanin( pObjL->pCopy, pNetL->pCopy ); + + // transfer the design + pDesign = pNtkH->pDesign; pNtkH->pDesign = NULL; + assert( Vec_PtrEntry( pDesign->vModules, 0 ) == pNtkH ); + Vec_PtrWriteEntry( pDesign->vModules, 0, pNtkNew ); + pNtkNew->pDesign = pDesign; + +//Abc_NtkPrintStats( stdout, pNtkH, 0 ); +//Abc_NtkPrintStats( stdout, pNtkNew, 0 ); + + // check integrity + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkInsertNewLogic(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcInt.h b/abc70930/src/base/abc/abcInt.h new file mode 100644 index 00000000..0e35e774 --- /dev/null +++ b/abc70930/src/base/abc/abcInt.h @@ -0,0 +1,52 @@ +/**CFile**************************************************************** + + FileName [abcInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __ABC_INT_H__ +#define __ABC_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_NUM_STEPS 10 + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcLatch.c b/abc70930/src/base/abc/abcLatch.c new file mode 100644 index 00000000..d96bbfac --- /dev/null +++ b/abc70930/src/base/abc/abcLatch.c @@ -0,0 +1,326 @@ +/**CFile**************************************************************** + + FileName [abcLatch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures working with latches.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcLatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkLatchIsSelfFeed_rec( Abc_Obj_t * pLatch, Abc_Obj_t * pLatchRoot ) +{ + Abc_Obj_t * pFanin; + assert( Abc_ObjIsLatch(pLatch) ); + if ( pLatch == pLatchRoot ) + return 1; + pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); + if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) + return 0; + return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); +} + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch ) +{ + Abc_Obj_t * pFanin; + assert( Abc_ObjIsLatch(pLatch) ); + pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); + if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) + return 0; + return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); +} + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pLatch; + int i, Counter; + Counter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { +// if ( Abc_NtkLatchIsSelfFeed(pLatch) && Abc_ObjFanoutNum(pLatch) > 1 ) +// printf( "Fanouts = %d.\n", Abc_ObjFanoutNum(pLatch) ); + Counter += Abc_NtkLatchIsSelfFeed( pLatch ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Replaces self-feeding latches by latches with constant inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pLatch, * pConst1; + int i, Counter; + Counter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( Abc_NtkLatchIsSelfFeed( pLatch ) ) + { + if ( Abc_NtkIsStrash(pNtk) ) + pConst1 = Abc_AigConst1(pNtk); + else + pConst1 = Abc_NtkCreateNodeConst1(pNtk); + Abc_ObjPatchFanin( Abc_ObjFanin0(pLatch), Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pConst1 ); + Counter++; + } + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Pipelines the network with latches.] + + Description [] + + SideEffects [Does not check the names of the added latches!!!] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pLatch, * pFanin, * pFanout; + int i, k, nTotal, nDigits; + if ( nLatches < 1 ) + return; + nTotal = nLatches * Abc_NtkPiNum(pNtk); + nDigits = Extra_Base10Log( nTotal ); + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + // remember current fanins of the PI + Abc_NodeCollectFanouts( pObj, vNodes ); + // create the latches + for ( pFanin = pObj, k = 0; k < nLatches; k++, pFanin = pLatch ) + { + pLatch = Abc_NtkCreateLatch( pNtk ); + Abc_ObjAddFanin( pLatch, pFanin ); + Abc_LatchSetInitDc( pLatch ); + // create the name of the new latch + Abc_ObjAssignName( pLatch, Abc_ObjNameDummy("LL", i*nLatches + k, nDigits), NULL ); + } + // patch the PI fanouts + Vec_PtrForEachEntry( vNodes, pFanout, k ) + Abc_ObjPatchFanin( pFanout, pObj, pFanin ); + } + Vec_PtrFree( vNodes ); + Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vValues; + Abc_Obj_t * pLatch; + int i; + vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Vec_IntPush( vValues, Abc_LatchIsInit1(pLatch) ); + return vValues; +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ) +{ + Abc_Obj_t * pLatch; + int i; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + pLatch->pData = (void *)(vValues? (Vec_IntEntry(vValues,i)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC); +} + +/**Function************************************************************* + + Synopsis [Creates latch with the given initial value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init ) +{ + Abc_Obj_t * pLatchOut, * pLatch, * pLatchIn; + pLatchOut = Abc_NtkCreateBo(pNtk); + pLatch = Abc_NtkCreateLatch(pNtk); + pLatchIn = Abc_NtkCreateBi(pNtk); + Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_lo" ); + Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_li" ); + Abc_ObjAddFanin( pLatchOut, pLatch ); + Abc_ObjAddFanin( pLatch, pLatchIn ); + Abc_ObjAddFanin( pLatchIn, pDriver ); + pLatch->pData = (void *)Init; + return pLatchOut; +} + +/**Function************************************************************* + + Synopsis [Creates MUX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkNodeConvertToMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0, Abc_Obj_t * pMux ) +{ + assert( Abc_NtkIsLogic(pNtk) ); + Abc_ObjAddFanin( pMux, pNodeC ); + Abc_ObjAddFanin( pMux, pNode1 ); + Abc_ObjAddFanin( pMux, pNode0 ); + if ( Abc_NtkHasSop(pNtk) ) + pMux->pData = Abc_SopRegister( pNtk->pManFunc, "11- 1\n0-1 1\n" ); + else if ( Abc_NtkHasBdd(pNtk) ) + pMux->pData = Cudd_bddIte(pNtk->pManFunc,Cudd_bddIthVar(pNtk->pManFunc,0),Cudd_bddIthVar(pNtk->pManFunc,1),Cudd_bddIthVar(pNtk->pManFunc,2)), Cudd_Ref( pMux->pData ); + else if ( Abc_NtkHasAig(pNtk) ) + pMux->pData = Hop_Mux(pNtk->pManFunc,Hop_IthVar(pNtk->pManFunc,0),Hop_IthVar(pNtk->pManFunc,1),Hop_IthVar(pNtk->pManFunc,2)); + else + assert( 0 ); +} + +/**Function************************************************************* + + Synopsis [Converts registers with DC values into additional PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pCtrl, * pLatch, * pMux, * pPi; + Abc_InitType_t Init = ABC_INIT_ZERO; + int i, fFound = 0, Counter; + // check if there are latches with DC values + Abc_NtkForEachLatch( pNtk, pLatch, i ) + if ( Abc_LatchIsInitDc(pLatch) ) + { + fFound = 1; + break; + } + if ( !fFound ) + return; + // add control latch + pCtrl = Abc_NtkAddLatch( pNtk, Abc_NtkCreateNodeConst1(pNtk), Init ); + // add fanouts for each latch with DC values + Counter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( !Abc_LatchIsInitDc(pLatch) ) + continue; + // change latch value + pLatch->pData = (void *)Init; + // if the latch output has the same name as a PO, rename it + if ( Abc_NodeFindCoFanout( Abc_ObjFanout0(pLatch) ) ) + { + Nm_ManDeleteIdName( pLatch->pNtk->pManName, Abc_ObjFanout0(pLatch)->Id ); + Abc_ObjAssignName( Abc_ObjFanout0(pLatch), Abc_ObjName(pLatch), "_lo" ); + } + // create new PIs + pPi = Abc_NtkCreatePi( pNtk ); + Abc_ObjAssignName( pPi, Abc_ObjName(pLatch), "_pi" ); + // create a new node and transfer fanout from latch output to the new node + pMux = Abc_NtkCreateNode( pNtk ); + Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pMux ); + // convert the node into a mux + Abc_NtkNodeConvertToMux( pNtk, pCtrl, Abc_ObjFanout0(pLatch), pPi, pMux ); + Counter++; + } + printf( "The number of converted latches with DC values = %d.\n", Counter ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcLib.c b/abc70930/src/base/abc/abcLib.c new file mode 100644 index 00000000..f5b90e90 --- /dev/null +++ b/abc70930/src/base/abc/abcLib.c @@ -0,0 +1,455 @@ +/**CFile**************************************************************** + + FileName [abcLib.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Functions to manipulate verilog libraries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Lib_t * Abc_LibCreate( char * pName ) +{ + Abc_Lib_t * p; + p = ALLOC( Abc_Lib_t, 1 ); + memset( p, 0, sizeof(Abc_Lib_t) ); + p->pName = Extra_UtilStrsav( pName ); + p->tModules = st_init_table( strcmp, st_strhash ); + p->vTops = Vec_PtrAlloc( 100 ); + p->vModules = Vec_PtrAlloc( 100 ); + p->pManFunc = Hop_ManStart(); + p->pLibrary = NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_LibFree( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave ) +{ + Abc_Ntk_t * pNtk; + int i; + if ( pLib->pName ) + free( pLib->pName ); + if ( pLib->pManFunc ) + Hop_ManStop( pLib->pManFunc ); + if ( pLib->tModules ) + st_free_table( pLib->tModules ); + if ( pLib->vModules ) + { + Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) + { +// pNtk->pManFunc = NULL; + if ( pNtk == pNtkSave ) + continue; + pNtk->pManFunc = NULL; + pNtk->pDesign = NULL; + Abc_NtkDelete( pNtk ); + } + Vec_PtrFree( pLib->vModules ); + } + if ( pLib->vTops ) + Vec_PtrFree( pLib->vTops ); + free( pLib ); +} + +/**Function************************************************************* + + Synopsis [Frees the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Lib_t * Abc_LibDupBlackboxes( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave ) +{ + Abc_Lib_t * pLibNew; + Abc_Ntk_t * pNtkTemp; + int i; + assert( Vec_PtrSize(pLib->vTops) > 0 ); + assert( Vec_PtrSize(pLib->vModules) > 1 ); + pLibNew = Abc_LibCreate( pLib->pName ); +// pLibNew->pManFunc = pNtkSave->pManFunc; + Vec_PtrPush( pLibNew->vTops, pNtkSave ); + Vec_PtrPush( pLibNew->vModules, pNtkSave ); + Vec_PtrForEachEntry( pLib->vModules, pNtkTemp, i ) + if ( Abc_NtkHasBlackbox( pNtkTemp ) ) + Vec_PtrPush( pLibNew->vModules, Abc_NtkDup(pNtkTemp) ); + return pLibNew; +} + + +/**Function************************************************************* + + Synopsis [Prints the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_LibPrint( Abc_Lib_t * pLib ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj; + int i, k; + printf( "Models of design %s:\n", pLib->pName ); + Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) + { + printf( "%2d : %20s ", i+1, pNtk->pName ); + printf( "nd = %6d lat = %6d whitebox = %3d blackbox = %3d\n", + Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk), + Abc_NtkWhiteboxNum(pNtk), Abc_NtkBlackboxNum(pNtk) ); + if ( Abc_NtkBlackboxNum(pNtk) == 0 ) + continue; + Abc_NtkForEachWhitebox( pNtk, pObj, k ) + printf( " %20s (whitebox)\n", Abc_NtkName(pObj->pData) ); + Abc_NtkForEachBlackbox( pNtk, pObj, k ) + printf( " %20s (blackbox)\n", Abc_NtkName(pObj->pData) ); + } +} + +/**Function************************************************************* + + Synopsis [Create the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_LibAddModel( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk ) +{ + if ( st_is_member( pLib->tModules, (char *)pNtk->pName ) ) + return 0; + st_insert( pLib->tModules, (char *)pNtk->pName, (char *)pNtk ); + Vec_PtrPush( pLib->vModules, pNtk ); + pNtk->pDesign = pLib; + return 1; +} + +/**Function************************************************************* + + Synopsis [Create the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_LibFindModelByName( Abc_Lib_t * pLib, char * pName ) +{ + Abc_Ntk_t * pNtk; + if ( !st_is_member( pLib->tModules, (char *)pName ) ) + return NULL; + st_lookup( pLib->tModules, (char *)pName, (char **)&pNtk ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Frees the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_LibDeriveRoot( Abc_Lib_t * pLib ) +{ + Abc_Ntk_t * pNtk; + if ( Vec_PtrSize(pLib->vModules) > 1 ) + { + printf( "The design includes more than one module and is currently not used.\n" ); + return NULL; + } + pNtk = Vec_PtrEntry( pLib->vModules, 0 ); Vec_PtrClear( pLib->vModules ); + pNtk->pManFunc = pLib->pManFunc; pLib->pManFunc = NULL; + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Detects the top-level models.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_LibFindTopLevelModels( Abc_Lib_t * pLib ) +{ + Abc_Ntk_t * pNtk, * pNtkBox; + Abc_Obj_t * pObj; + int i, k; + assert( Vec_PtrSize( pLib->vModules ) > 0 ); + // clear the models + Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) + pNtk->fHieVisited = 0; + // mark all the models reachable from other models + Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) + { + Abc_NtkForEachBox( pNtk, pObj, k ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + if ( pObj->pData == NULL ) + continue; + pNtkBox = pObj->pData; + pNtkBox->fHieVisited = 1; + } + } + // collect the models that are not marked + Vec_PtrClear( pLib->vTops ); + Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) + { + if ( pNtk->fHieVisited == 0 ) + Vec_PtrPush( pLib->vTops, pNtk ); + else + pNtk->fHieVisited = 0; + } + return Vec_PtrSize( pLib->vTops ); +} + + +/**Function************************************************************* + + Synopsis [Surround boxes without content (black boxes) with BIs/BOs.] + + Description [Returns the number of black boxes converted.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_LibDeriveBlackBoxes( Abc_Ntk_t * pNtk, Abc_Lib_t * pLib ) +{ +/* + Abc_Obj_t * pObj, * pFanin, * pFanout; + int i, k; + assert( Abc_NtkIsNetlist(pNtk) ); + // collect blackbox nodes + assert( Vec_PtrSize(pNtk->vBoxes) == 0 ); + Vec_PtrClear( pNtk->vBoxes ); + Abc_NtkForEachBox( pNtk, pObj, i ) + if ( Abc_NtkNodeNum(pObj->pData) == 0 ) + Vec_PtrPush( pNtk->vBoxes, pObj ); + // return if there is no black boxes without content + if ( Vec_PtrSize(pNtk->vBoxes) == 0 ) + return 0; + // print the boxes + printf( "Black boxes are: " ); + Abc_NtkForEachBox( pNtk, pObj, i ) + printf( " %s", ((Abc_Ntk_t *)pObj->pData)->pName ); + printf( "\n" ); + // iterate through the boxes and add BIs/BOs + Abc_NtkForEachBox( pNtk, pObj, i ) + { + // go through the fanin nets + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjInsertBetween( pFanin, pObj, ABC_OBJ_BI ); + // go through the fanout nets + Abc_ObjForEachFanout( pObj, pFanout, k ) + { + Abc_ObjInsertBetween( pObj, pFanout, ABC_OBJ_BO ); + // if the name is not given assign name + if ( pFanout->pData == NULL ) + { + pFanout->pData = Abc_ObjName( pFanout ); + Nm_ManStoreIdName( pNtk->pManName, pFanout->Id, pFanout->pData, NULL ); + } + } + } + return Vec_PtrSize(pNtk->vBoxes); +*/ + return 0; +} + +/**Function************************************************************* + + Synopsis [Derive the AIG of the logic in the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeStrashUsingNetwork_rec( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + assert( !Abc_ObjIsNet(pObj) ); + if ( pObj->pCopy ) + return; + // call for the fanins + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) ); + // compute for the node + pObj->pCopy = Abc_NodeStrash( pNtkAig, pObj, 0 ); + // set for the fanout net + Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; +} + +/**Function************************************************************* + + Synopsis [Derive the AIG of the logic in the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeStrashUsingNetwork( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pBox ) +{ + Abc_Ntk_t * pNtkGate; + Abc_Obj_t * pObj; + unsigned * pPolarity; + int i, fCompl; + assert( Abc_ObjIsBox(pBox) ); + pNtkGate = pBox->pData; + pPolarity = (unsigned *)pBox->pNext; + assert( Abc_NtkIsNetlist(pNtkGate) ); + assert( Abc_NtkLatchNum(pNtkGate) == 0 ); + Abc_NtkCleanCopy( pNtkGate ); + // set the PI values + Abc_NtkForEachPi( pNtkGate, pObj, i ) + { + fCompl = (pPolarity && Abc_InfoHasBit(pPolarity, i)); + pObj->pCopy = Abc_ObjNotCond( Abc_ObjFanin(pBox,i)->pCopy, fCompl ); + Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; + } + // build recursively and set the PO values + Abc_NtkForEachPo( pNtkGate, pObj, i ) + { + Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) ); + Abc_ObjFanout(pBox,i)->pCopy = Abc_ObjFanin0(pObj)->pCopy; + } +//printf( "processing %d\n", pBox->Id ); +} + +/**Function************************************************************* + + Synopsis [Derive the AIG of the logic in the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_LibDeriveAig( Abc_Ntk_t * pNtk, Abc_Lib_t * pLib ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkAig; + Abc_Obj_t * pObj; + int i, nBoxes; + // explicitly derive black boxes + assert( Abc_NtkIsNetlist(pNtk) ); + nBoxes = Abc_LibDeriveBlackBoxes( pNtk, pLib ); + if ( nBoxes ) + printf( "Detected and transformed %d black boxes.\n", nBoxes ); + // create the new network with black boxes in place + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transer to the nets + Abc_NtkForEachCi( pNtk, pObj, i ) + Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; + // build the AIG for the remaining logic in the netlist + vNodes = Abc_NtkDfs( pNtk, 0 ); + pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + if ( Abc_ObjIsNode(pObj) ) + { + pObj->pCopy = Abc_NodeStrash( pNtkAig, pObj, 0 ); + Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; + continue; + } + Abc_NodeStrashUsingNetwork( pNtkAig, pObj ); + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + // deallocate memory manager, which remembers the phase + if ( pNtk->pData ) + { + Extra_MmFlexStop( pNtk->pData ); + pNtk->pData = NULL; + } + // set the COs +// Abc_NtkFinalize( pNtk, pNtkAig ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy ); + Abc_AigCleanup( pNtkAig->pManFunc ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_LibDeriveAig: The network check has failed.\n" ); + return 0; + } + return pNtkAig; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcMinBase.c b/abc70930/src/base/abc/abcMinBase.c new file mode 100644 index 00000000..13f422f4 --- /dev/null +++ b/abc70930/src/base/abc/abcMinBase.c @@ -0,0 +1,256 @@ +/**CFile**************************************************************** + + FileName [abcMinBase.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Makes nodes of the network minimum base.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMinBase.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Makes nodes minimum base.] + + Description [Returns the number of changed nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter; + assert( Abc_NtkIsBddLogic(pNtk) ); + Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_NodeMinimumBase( pNode ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Makes one node minimum base.] + + Description [Returns 1 if the node is changed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) +{ + Vec_Str_t * vSupport; + Vec_Ptr_t * vFanins; + DdNode * bTemp; + int i, nVars; + + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + + // compute support + vSupport = Vec_StrAlloc( 10 ); + nVars = Abc_NodeSupport( Cudd_Regular(pNode->pData), vSupport, Abc_ObjFaninNum(pNode) ); + if ( nVars == Abc_ObjFaninNum(pNode) ) + { + Vec_StrFree( vSupport ); + return 0; + } + + // remove unused fanins + vFanins = Vec_PtrAlloc( Abc_ObjFaninNum(pNode) ); + Abc_NodeCollectFanins( pNode, vFanins ); + for ( i = 0; i < vFanins->nSize; i++ ) + if ( vSupport->pArray[i] == 0 ) + Abc_ObjDeleteFanin( pNode, vFanins->pArray[i] ); + assert( nVars == Abc_ObjFaninNum(pNode) ); + + // update the function of the node + pNode->pData = Extra_bddRemapUp( pNode->pNtk->pManFunc, bTemp = pNode->pData ); Cudd_Ref( pNode->pData ); + Cudd_RecursiveDeref( pNode->pNtk->pManFunc, bTemp ); + Vec_PtrFree( vFanins ); + Vec_StrFree( vSupport ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Makes nodes of the network fanin-dup-free.] + + Description [Returns the number of pairs of duplicated fanins.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter; + assert( Abc_NtkIsBddLogic(pNtk) ); + Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_NodeRemoveDupFanins( pNode ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Removes one pair of duplicated fanins if present.] + + Description [Returns 1 if the node is changed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRemoveDupFanins_int( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin1, * pFanin2; + int i, k; + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + // make sure fanins are not duplicated + Abc_ObjForEachFanin( pNode, pFanin2, i ) + { + Abc_ObjForEachFanin( pNode, pFanin1, k ) + { + if ( k >= i ) + break; + if ( pFanin1 == pFanin2 ) + { + DdManager * dd = pNode->pNtk->pManFunc; + DdNode * bVar1 = Cudd_bddIthVar( dd, i ); + DdNode * bVar2 = Cudd_bddIthVar( dd, k ); + DdNode * bTrans, * bTemp; + bTrans = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bTrans ); + pNode->pData = Cudd_bddAndAbstract( dd, bTemp = pNode->pData, bTrans, bVar2 ); Cudd_Ref( pNode->pData ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bTrans ); + Abc_NodeMinimumBase( pNode ); + return 1; + } + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Removes duplicated fanins if present.] + + Description [Returns the number of fanins removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode ) +{ + int Counter = 0; + while ( Abc_NodeRemoveDupFanins_int(pNode) ) + Counter++; + return Counter; +} +/**Function************************************************************* + + Synopsis [Computes support of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSupport_rec( DdNode * bFunc, Vec_Str_t * vSupport ) +{ + if ( cuddIsConstant(bFunc) || Cudd_IsComplement(bFunc->next) ) + return; + vSupport->pArray[ bFunc->index ] = 1; + Abc_NodeSupport_rec( cuddT(bFunc), vSupport ); + Abc_NodeSupport_rec( Cudd_Regular(cuddE(bFunc)), vSupport ); + bFunc->next = Cudd_Not(bFunc->next); +} + +/**Function************************************************************* + + Synopsis [Computes support of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSupportClear_rec( DdNode * bFunc ) +{ + if ( !Cudd_IsComplement(bFunc->next) ) + return; + bFunc->next = Cudd_Regular(bFunc->next); + if ( cuddIsConstant(bFunc) ) + return; + Abc_NodeSupportClear_rec( cuddT(bFunc) ); + Abc_NodeSupportClear_rec( Cudd_Regular(cuddE(bFunc)) ); +} + +/**Function************************************************************* + + Synopsis [Computes support of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars ) +{ + int Counter, i; + // compute the support by marking the BDD + Vec_StrFill( vSupport, nVars, 0 ); + Abc_NodeSupport_rec( bFunc, vSupport ); + // clear the marak + Abc_NodeSupportClear_rec( bFunc ); + // get the number of support variables + Counter = 0; + for ( i = 0; i < nVars; i++ ) + Counter += vSupport->pArray[i]; + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcNames.c b/abc70930/src/base/abc/abcNames.c new file mode 100644 index 00000000..91964dfa --- /dev/null +++ b/abc70930/src/base/abc/abcNames.c @@ -0,0 +1,467 @@ +/**CFile**************************************************************** + + FileName [abcNames.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures working with net and node names.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcNames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the unique name for the object.] + + Description [If the name previously did not exist, creates a new unique + name but does not assign this name to the object. The temporary unique + name is stored in a static buffer inside this procedure. It is important + that the name is used before the function is called again!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjName( Abc_Obj_t * pObj ) +{ + return Nm_ManCreateUniqueName( pObj->pNtk->pManName, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Assigns the given name to the object.] + + Description [The object should not have a name assigned. The same + name may be used for several objects, which they share the same net + in the original netlist. (For example, latch output and primary output + may have the same name.) This procedure returns the pointer to the + internally stored representation of the given name.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix ) +{ + assert( pName != NULL ); + return Nm_ManStoreIdName( pObj->pNtk->pManName, pObj->Id, pObj->Type, pName, pSuffix ); +} + +/**Function************************************************************* + + Synopsis [Gets the long name of the node.] + + Description [This name is the output net's name.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix ) +{ + static char Buffer[500]; + sprintf( Buffer, "%s%s", Abc_ObjName(pObj), pSuffix ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Returns the dummy PI name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits ) +{ + static char Buffer[100]; + sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Tranfers names to the old network.] + + Description [Assumes that the new nodes are attached using pObj->pCopy.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); + assert( Abc_NtkBoxNum(pNtk) == Abc_NtkBoxNum(pNtkNew) ); + assert( Abc_NtkAssertNum(pNtk) == Abc_NtkAssertNum(pNtkNew) ); + assert( Nm_ManNumEntries(pNtk->pManName) > 0 ); + assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 ); + // copy the CI/CO/box names + Abc_NtkForEachCi( pNtk, pObj, i ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); +} + +/**Function************************************************************* + + Synopsis [Tranfers names to the old network.] + + Description [Assumes that the new nodes are attached using pObj->pCopy.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); + assert( Abc_NtkAssertNum(pNtk) == Abc_NtkAssertNum(pNtkNew) ); + assert( Nm_ManNumEntries(pNtk->pManName) > 0 ); + assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 ); + // copy the CI/CO/box name and skip latches and theirs inputs/outputs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFaninNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); + Abc_NtkForEachCo( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); + Abc_NtkForEachBox( pNtk, pObj, i ) + if ( !Abc_ObjIsLatch(pObj) ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); +} + +/**Function************************************************************* + + Synopsis [Gets fanin node names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pFanin; + int i; + vNodes = Vec_PtrAlloc( 100 ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + Vec_PtrPush( vNodes, Extra_UtilStrsav(Abc_ObjName(pFanin)) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Gets fanin node names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames ) +{ + Vec_Ptr_t * vNames; + char Buffer[5]; + int i; + + vNames = Vec_PtrAlloc( nNames ); + for ( i = 0; i < nNames; i++ ) + { + if ( nNames < 26 ) + { + Buffer[0] = 'a' + i; + Buffer[1] = 0; + } + else + { + Buffer[0] = 'a' + i%26; + Buffer[1] = '0' + i/26; + Buffer[2] = 0; + } + Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) ); + } + return vNames; +} + +/**Function************************************************************* + + Synopsis [Gets fanin node names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeFreeNames( Vec_Ptr_t * vNames ) +{ + int i; + if ( vNames == NULL ) + return; + for ( i = 0; i < vNames->nSize; i++ ) + free( vNames->pArray[i] ); + Vec_PtrFree( vNames ); +} + +/**Function************************************************************* + + Synopsis [Collects the CI or CO names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos ) +{ + Abc_Obj_t * pObj; + char ** ppNames; + int i; + if ( fCollectCos ) + { + ppNames = ALLOC( char *, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + ppNames[i] = Abc_ObjName(pObj); + } + else + { + ppNames = ALLOC( char *, Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + ppNames[i] = Abc_ObjName(pObj); + } + return ppNames; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareNames( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) +{ + int Diff = strcmp( (char *)(*pp1)->pCopy, (char *)(*pp2)->pCopy ); + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Orders PIs/POs/latches alphabetically.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkAssertNum(pNtk) == 0 ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + // temporarily store the names in the copy field + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); + Abc_NtkForEachPo( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); + Abc_NtkForEachBox( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(Abc_ObjFanout0(pObj)); + // order objects alphabetically + qsort( (void *)Vec_PtrArray(pNtk->vPis), Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareNames ); + qsort( (void *)Vec_PtrArray(pNtk->vPos), Vec_PtrSize(pNtk->vPos), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareNames ); + // if the comparison if combinational (latches as PIs/POs), order them too + if ( fComb ) + qsort( (void *)Vec_PtrArray(pNtk->vBoxes), Vec_PtrSize(pNtk->vBoxes), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareNames ); + // order CIs/COs first PIs/POs(Asserts) then latches + Abc_NtkOrderCisCos( pNtk ); + // clean the copy fields + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = NULL; + Abc_NtkForEachPo( pNtk, pObj, i ) + pObj->pCopy = NULL; + Abc_NtkForEachBox( pNtk, pObj, i ) + pObj->pCopy = NULL; +} + +/**Function************************************************************* + + Synopsis [Adds dummy names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int nDigits, i; + nDigits = Extra_Base10Log( Abc_NtkPiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjAssignName( pObj, Abc_ObjNameDummy("pi", i, nDigits), NULL ); +} + +/**Function************************************************************* + + Synopsis [Adds dummy names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int nDigits, i; + nDigits = Extra_Base10Log( Abc_NtkPoNum(pNtk) ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_ObjAssignName( pObj, Abc_ObjNameDummy("po", i, nDigits), NULL ); +} + +/**Function************************************************************* + + Synopsis [Adds dummy names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddDummyAssertNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int nDigits, i; + nDigits = Extra_Base10Log( Abc_NtkAssertNum(pNtk) ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Abc_ObjAssignName( pObj, Abc_ObjNameDummy("a", i, nDigits), NULL ); +} + +/**Function************************************************************* + + Synopsis [Adds dummy names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int nDigits, i; + assert( !Abc_NtkIsNetlist(pNtk) ); + nDigits = Extra_Base10Log( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + Abc_ObjAssignName( pObj, Abc_ObjNameDummy("l", i, nDigits), NULL ); + Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjNameDummy("li", i, nDigits), NULL ); + Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjNameDummy("lo", i, nDigits), NULL ); + } +/* + nDigits = Extra_Base10Log( Abc_NtkBlackboxNum(pNtk) ); + Abc_NtkForEachBlackbox( pNtk, pObj, i ) + { + pName = Abc_ObjAssignName( pObj, Abc_ObjNameDummy("B", i, nDigits), NULL ); + nDigitsF = Extra_Base10Log( Abc_ObjFaninNum(pObj) ); + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("i", k, nDigitsF) ); + nDigitsF = Extra_Base10Log( Abc_ObjFanoutNum(pObj) ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("o", k, nDigitsF) ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Replaces names by short names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkShortNames( Abc_Ntk_t * pNtk ) +{ + Nm_ManFree( pNtk->pManName ); + pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk) + Abc_NtkBoxNum(pNtk) ); + Abc_NtkAddDummyPiNames( pNtk ); + Abc_NtkAddDummyPoNames( pNtk ); + Abc_NtkAddDummyAssertNames( pNtk ); + Abc_NtkAddDummyBoxNames( pNtk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcNetlist.c b/abc70930/src/base/abc/abcNetlist.c new file mode 100644 index 00000000..26b88c68 --- /dev/null +++ b/abc70930/src/base/abc/abcNetlist.c @@ -0,0 +1,411 @@ +/**CFile**************************************************************** + + FileName [abcNetlist.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Transforms netlist into a logic network and vice versa.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcNetlist.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +//#include "seq.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transform the netlist into a logic network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k; + // consider the case of the AIG + if ( Abc_NtkIsStrash(pNtk) ) + return Abc_NtkAigToLogicSop( pNtk ); + assert( Abc_NtkIsNetlist(pNtk) ); + // consider simple case when there is hierarchy +// assert( pNtk->pDesign == NULL ); + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + assert( Abc_NtkBlackboxNum(pNtk) == 0 ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, pNtk->ntkFunc ); + // duplicate the nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // reconnect the internal nodes in the new network + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pFanin)->pCopy ); + // collect the CO nodes + Abc_NtkFinalize( pNtk, pNtkNew ); + // fix the problem with CO pointing directly to CIs + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkToLogic( pNtk->pExdc ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkToLogic(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transform the logic network into a netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew, * pNtkTemp; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkIsStrash(pNtk) ) + { + pNtkTemp = Abc_NtkAigToLogicSop(pNtk); + pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp ); + Abc_NtkDelete( pNtkTemp ); + return pNtkNew; + } + return Abc_NtkLogicToNetlist( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Converts the AIG into the netlist.] + + Description [This procedure does not copy the choices.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew, * pNtkTemp; + assert( Abc_NtkIsStrash(pNtk) ); + pNtkTemp = Abc_NtkAigToLogicSopBench( pNtk ); + pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp ); + Abc_NtkDelete( pNtkTemp ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transform the logic network into a netlist.] + + Description [The logic network given to this procedure should + have exactly the same structure as the resulting netlist. The COs + can only point to CIs if they have identical names. Otherwise, + they should have a node between them, even if this node is + inverter or buffer.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pNet, * pDriver, * pFanin; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) ); + + // remove dangling nodes + Abc_NtkCleanup( pNtk, 0 ); + + // make sure the CO names are unique + Abc_NtkCheckUniqueCiNames( pNtk ); + Abc_NtkCheckUniqueCoNames( pNtk ); + Abc_NtkCheckUniqueCioNames( pNtk ); + +// assert( Abc_NtkLogicHasSimpleCos(pNtk) ); + if ( !Abc_NtkLogicHasSimpleCos(pNtk) ) + { + printf( "Abc_NtkLogicToNetlist() warning: The network is converted to have simple COs.\n" ); + Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); + } + + // start the netlist by creating PI/PO/Latch objects + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_NETLIST, pNtk->ntkFunc ); + // create the CI nets and remember them in the new CI nodes + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); + Abc_ObjAddFanin( pNet, pObj->pCopy ); + pObj->pCopy->pCopy = pNet; + } + // duplicate all nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // first add the nets to the CO drivers + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pDriver = Abc_ObjFanin0(pObj); + if ( Abc_ObjIsCi(pDriver) ) + { + assert( !strcmp( Abc_ObjName(pDriver), Abc_ObjName(pObj) ) ); + Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); + continue; + } + assert( Abc_ObjIsNode(pDriver) ); + // if the CO driver has no net, create it + if ( pDriver->pCopy->pCopy == NULL ) + { + // create the CO net and connect it to CO + pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); + Abc_ObjAddFanin( pObj->pCopy, pNet ); + // connect the CO net to the new driver and remember it in the new driver + Abc_ObjAddFanin( pNet, pDriver->pCopy ); + pDriver->pCopy->pCopy = pNet; + } + else + { + assert( !strcmp( Abc_ObjName(pDriver->pCopy->pCopy), Abc_ObjName(pObj) ) ); + Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); + } + } + // create the missing nets + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( pObj->pCopy->pCopy ) // the net of the new object is already created + continue; + // create the new net + pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); // here we create ridiculous names net line "n48", where 48 is the ID of the node + Abc_ObjAddFanin( pNet, pObj->pCopy ); + pObj->pCopy->pCopy = pNet; + } + // connect nodes to the fanins nets + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkToNetlist( pNtk->pExdc ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkLogicToNetlist(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the AIG into the logic network with SOPs.] + + Description [Correctly handles the case of choice nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin, * pNodeNew; + Vec_Int_t * vInts; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + // if the constant node is used, duplicate it + pObj = Abc_AigConst1(pNtk); + if ( Abc_ObjFanoutNum(pObj) > 0 ) + pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew); + // duplicate the nodes and create node functions + Abc_NtkForEachNode( pNtk, pObj, i ) + { + Abc_NtkDupObj(pNtkNew, pObj, 0); + pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); + } + // create the choice nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( !Abc_AigNodeIsChoice(pObj) ) + continue; + // create an OR gate + pNodeNew = Abc_NtkCreateNode(pNtkNew); + // add fanins + vInts = Vec_IntAlloc( 10 ); + for ( pFanin = pObj; pFanin; pFanin = pFanin->pData ) + { + Vec_IntPush( vInts, (int)(pObj->fPhase != pFanin->fPhase) ); + Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); + } + // create the logic function + pNodeNew->pData = Abc_SopCreateOrMultiCube( pNtkNew->pManFunc, Vec_IntSize(vInts), Vec_IntArray(vInts) ); + // set the new node + pObj->pCopy->pCopy = pNodeNew; + Vec_IntFree( vInts ); + } + // connect the internal nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( pFanin->pCopy->pCopy ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + else + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + // connect the COs +// Abc_NtkFinalize( pNtk, pNtkNew ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pFanin = Abc_ObjFanin0(pObj); + if ( pFanin->pCopy->pCopy ) + pNodeNew = Abc_ObjNotCond(pFanin->pCopy->pCopy, Abc_ObjFaninC0(pObj)); + else + pNodeNew = Abc_ObjNotCond(pFanin->pCopy, Abc_ObjFaninC0(pObj)); + Abc_ObjAddFanin( pObj->pCopy, pNodeNew ); + } + + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // duplicate the EXDC Ntk + if ( pNtk->pExdc ) + { + if ( Abc_NtkIsStrash(pNtk->pExdc) ) + pNtkNew->pExdc = Abc_NtkAigToLogicSop( pNtk->pExdc ); + else + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + } + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkAigToLogicSop(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the AIG into the logic network with SOPs for bench writing.] + + Description [This procedure does not copy the choices.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + Vec_Ptr_t * vNodes; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkGetChoiceNum(pNtk) ) + printf( "Warning: Choice nodes are skipped.\n" ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + // collect the nodes to be used (marks all nodes with current TravId) + vNodes = Abc_NtkDfs( pNtk, 0 ); + // create inverters for the CI and remember them + pObj = Abc_AigConst1(pNtk); + if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) + { + pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew); + pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); + } + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) + pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); + // duplicate the nodes, create node functions, and inverters + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + pObj->pCopy->pData = Abc_SopCreateAnd( pNtkNew->pManFunc, 2, NULL ); + if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) + pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); + } + // connect the objects + Vec_PtrForEachEntry( vNodes, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + if ( Abc_ObjFaninC( pObj, k ) ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + else + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + Vec_PtrFree( vNodes ); + // connect the COs + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pFanin = Abc_ObjFanin0(pObj); + if ( Abc_ObjFaninC0( pObj ) ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + else + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // duplicate the EXDC Ntk + if ( pNtk->pExdc ) + printf( "Warning: The EXDc network is skipped.\n" ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkAigToLogicSopBench(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Adds buffers for each PO.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pFanin, * pFaninNew; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pFanin = Abc_ObjChild0(pObj); + pFaninNew = Abc_NtkCreateNode(pNtk); + Abc_ObjAddFanin( pFaninNew, pFanin ); + Abc_ObjPatchFanin( pObj, pFanin, pFaninNew ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcNtk.c b/abc70930/src/base/abc/abcNtk.c new file mode 100644 index 00000000..adaaf7be --- /dev/null +++ b/abc70930/src/base/abc/abcNtk.c @@ -0,0 +1,1235 @@ +/**CFile**************************************************************** + + FileName [abcNtk.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Network creation/duplication/deletion procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcNtk.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "abcInt.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates a new Ntk.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan ) +{ + Abc_Ntk_t * pNtk; + pNtk = ALLOC( Abc_Ntk_t, 1 ); + memset( pNtk, 0, sizeof(Abc_Ntk_t) ); + pNtk->ntkType = Type; + pNtk->ntkFunc = Func; + // start the object storage + pNtk->vObjs = Vec_PtrAlloc( 100 ); + pNtk->vAsserts = Vec_PtrAlloc( 100 ); + pNtk->vPios = Vec_PtrAlloc( 100 ); + pNtk->vPis = Vec_PtrAlloc( 100 ); + pNtk->vPos = Vec_PtrAlloc( 100 ); + pNtk->vCis = Vec_PtrAlloc( 100 ); + pNtk->vCos = Vec_PtrAlloc( 100 ); + pNtk->vBoxes = Vec_PtrAlloc( 100 ); + // start the memory managers + pNtk->pMmObj = fUseMemMan? Extra_MmFixedStart( sizeof(Abc_Obj_t) ) : NULL; + pNtk->pMmStep = fUseMemMan? Extra_MmStepStart( ABC_NUM_STEPS ) : NULL; + // get ready to assign the first Obj ID + pNtk->nTravIds = 1; + // start the functionality manager + if ( Abc_NtkIsStrash(pNtk) ) + pNtk->pManFunc = Abc_AigAlloc( pNtk ); + else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) + pNtk->pManFunc = Extra_MmFlexStart(); + else if ( Abc_NtkHasBdd(pNtk) ) + pNtk->pManFunc = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + else if ( Abc_NtkHasAig(pNtk) ) + pNtk->pManFunc = Hop_ManStart(); + else if ( Abc_NtkHasMapping(pNtk) ) + pNtk->pManFunc = Abc_FrameReadLibGen(); + else if ( !Abc_NtkHasBlackbox(pNtk) ) + assert( 0 ); + // name manager + pNtk->pManName = Nm_ManCreate( 200 ); + // attribute manager + pNtk->vAttrs = Vec_PtrStart( VEC_ATTR_TOTAL_NUM ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Starts a new network using existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj; + int fCopyNames, i; + if ( pNtk == NULL ) + return NULL; + // decide whether to copy the names + fCopyNames = ( Type != ABC_NTK_NETLIST ); + // start the network + pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // map the constant nodes + if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_NtkDupBox( pNtkNew, pObj, fCopyNames ); + // transfer the names +// Abc_NtkTrasferNames( pNtk, pNtkNew ); + Abc_ManTimeDup( pNtk, pNtkNew ); + // check that the CI/CO/latches are copied correctly + assert( Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkNew) ); + assert( Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkNew) ); + assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Starts a new network using existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj; + int i; + if ( pNtk == NULL ) + return NULL; + assert( Type != ABC_NTK_NETLIST ); + // start the network + pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // map the constant nodes + if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + Abc_NtkDupBox(pNtkNew, pObj, 1); + } + // transfer the names +// Abc_NtkTrasferNamesNoLatches( pNtk, pNtkNew ); + Abc_ManTimeDup( pNtk, pNtkNew ); + // check that the CI/CO/latches are copied correctly + assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Finalizes the network using the existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj, * pDriver, * pDriverNew; + int i; + // set the COs of the strashed network + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pObj) ); + pDriverNew = Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj)); + Abc_ObjAddFanin( pObj->pCopy, pDriverNew ); + } +} + +/**Function************************************************************* + + Synopsis [Starts a new network using existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStartRead( char * pName ) +{ + Abc_Ntk_t * pNtkNew; + // allocate the empty network + pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); + // set the specs + pNtkNew->pName = Extra_FileNameGeneric(pName); + pNtkNew->pSpec = Extra_UtilStrsav(pName); + if ( pNtkNew->pName == NULL || strlen(pNtkNew->pName) == 0 ) + { + FREE( pNtkNew->pName ); + pNtkNew->pName = Extra_UtilStrsav("unknown"); + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Finalizes the network using the existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pBox, * pObj, * pTerm, * pNet; + int i; + if ( Abc_NtkHasBlackbox(pNtk) && Abc_NtkBoxNum(pNtk) == 0 ) + { + pBox = Abc_NtkCreateBlackbox(pNtk); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + pTerm = Abc_NtkCreateBi(pNtk); + Abc_ObjAddFanin( pTerm, Abc_ObjFanout0(pObj) ); + Abc_ObjAddFanin( pBox, pTerm ); + } + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pTerm = Abc_NtkCreateBo(pNtk); + Abc_ObjAddFanin( pTerm, pBox ); + Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pTerm ); + } + return; + } + assert( Abc_NtkIsNetlist(pNtk) ); + + // check if constant 0 net is used + pNet = Abc_NtkFindNet( pNtk, "1\'b0" ); + if ( pNet ) + { + if ( Abc_ObjFanoutNum(pNet) == 0 ) + Abc_NtkDeleteObj(pNet); + else if ( Abc_ObjFaninNum(pNet) == 0 ) + Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) ); + } + // check if constant 1 net is used + pNet = Abc_NtkFindNet( pNtk, "1\'b1" ); + if ( pNet ) + { + if ( Abc_ObjFanoutNum(pNet) == 0 ) + Abc_NtkDeleteObj(pNet); + else if ( Abc_ObjFaninNum(pNet) == 0 ) + Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) ); + } + // fix the net drivers + Abc_NtkFixNonDrivenNets( pNtk ); + + // reorder the CI/COs to PI/POs first + Abc_NtkOrderCisCos( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Duplicate the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k; + if ( pNtk == NULL ) + return NULL; + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); + // copy the internal nodes + if ( Abc_NtkIsStrash(pNtk) ) + { + // copy the AND gates + Abc_AigForEachAnd( pNtk, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // relink the choice nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + if ( pObj->pData ) + pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy; + // relink the CO nodes + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); + // get the number of nodes before and after + if ( Abc_NtkNodeNum(pNtk) != Abc_NtkNodeNum(pNtkNew) ) + printf( "Warning: Structural hashing during duplication reduced %d nodes (this is a minor bug).\n", + Abc_NtkNodeNum(pNtk) - Abc_NtkNodeNum(pNtkNew) ); + } + else + { + // duplicate the nets and nodes (CIs/COs/latches already dupped) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy == NULL ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // reconnect all objects (no need to transfer attributes on edges) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + // duplicate the EXDC Ntk + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); + pNtk->pCopy = pNtkNew; + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Duplicate the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk ) +{ + char Buffer[500]; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k; + assert( Abc_NtkIsLogic(pNtk) ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + sprintf( Buffer, "%s%s", pNtk->pName, "_2x" ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_NtkDupBox( pNtkNew, pObj, 0 ); + // copy the internal nodes + // duplicate the nets and nodes (CIs/COs/latches already dupped) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy == NULL ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // reconnect all objects (no need to transfer attributes on edges) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_NtkDupBox( pNtkNew, pObj, 0 ); + // copy the internal nodes + // duplicate the nets and nodes (CIs/COs/latches already dupped) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy == NULL ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // reconnect all objects (no need to transfer attributes on edges) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // assign names + Abc_NtkForEachCi( pNtk, pObj, i ) + { + Abc_ObjAssignName( Abc_NtkCi(pNtkNew, i), "1_", Abc_ObjName(pObj) ); + Abc_ObjAssignName( Abc_NtkCi(pNtkNew, Abc_NtkCiNum(pNtk) + i), "2_", Abc_ObjName(pObj) ); + } + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_ObjAssignName( Abc_NtkCo(pNtkNew, i), "1_", Abc_ObjName(pObj) ); + Abc_ObjAssignName( Abc_NtkCo(pNtkNew, Abc_NtkCoNum(pNtk) + i), "2_", Abc_ObjName(pObj) ); + } + + // perform the final check + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Attaches the second network at the bottom of the first.] + + Description [Returns the first network. Deletes the second network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom ) +{ + Abc_Obj_t * pObj, * pFanin, * pBuffer; + Vec_Ptr_t * vNodes; + int i, k; + assert( pNtkBottom != NULL ); + if ( pNtkTop == NULL ) + return pNtkBottom; + // make sure the networks are combinational + assert( Abc_NtkPiNum(pNtkTop) == Abc_NtkCiNum(pNtkTop) ); + assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkCiNum(pNtkBottom) ); + // make sure the POs of the bottom correspond to the PIs of the top + assert( Abc_NtkPoNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) ); + assert( Abc_NtkPiNum(pNtkBottom) < Abc_NtkPiNum(pNtkTop) ); + // add buffers for the PIs of the top - save results in the POs of the bottom + Abc_NtkForEachPi( pNtkTop, pObj, i ) + { + pBuffer = Abc_NtkCreateNodeBuf( pNtkTop, NULL ); + Abc_ObjTransferFanout( pObj, pBuffer ); + Abc_NtkPo(pNtkBottom, i)->pCopy = pBuffer; + } + // remove useless PIs of the top + for ( i = Abc_NtkPiNum(pNtkTop) - 1; i >= Abc_NtkPiNum(pNtkBottom); i-- ) + Abc_NtkDeleteObj( Abc_NtkPi(pNtkTop, i) ); + assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) ); + // copy the bottom network + Abc_NtkForEachPi( pNtkBottom, pObj, i ) + Abc_NtkPi(pNtkBottom, i)->pCopy = Abc_NtkPi(pNtkTop, i); + // construct all nodes + vNodes = Abc_NtkDfs( pNtkBottom, 0 ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + Abc_NtkDupObj(pNtkTop, pObj, 0); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + Vec_PtrFree( vNodes ); + // connect the POs + Abc_NtkForEachPo( pNtkBottom, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy ); + // delete old network + Abc_NtkDelete( pNtkBottom ); + // return the network + if ( !Abc_NtkCheck( pNtkTop ) ) + fprintf( stdout, "Abc_NtkAttachBottom(): Network check has failed.\n" ); + return pNtkTop; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of one logic cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis ) +{ + Abc_Ntk_t * pNtkNew; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; + char Buffer[1000]; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // set the name + sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // establish connection between the constant nodes + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + + // collect the nodes in the TFI of the output (mark the TFI) + vNodes = Abc_NtkDfsNodes( pNtk, &pNode, 1 ); + // create the PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + } + // add the PO corresponding to this output + pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL ); + // copy the nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // if it is an AIG, add to the hash table + if ( Abc_NtkIsStrash(pNtk) ) + { + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + } + else + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + } + // connect the internal nodes to the new CO + Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy ); + Vec_PtrFree( vNodes ); + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of several logic cones.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis ) +{ + Abc_Ntk_t * pNtkNew; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; + char Buffer[1000]; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // set the name + sprintf( Buffer, "%s_part", pNtk->pName ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // establish connection between the constant nodes + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + + // collect the nodes in the TFI of the output (mark the TFI) + vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); + + // create the PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + } + + // copy the nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // if it is an AIG, add to the hash table + if ( Abc_NtkIsStrash(pNtk) ) + { + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + } + else + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + } + Vec_PtrFree( vNodes ); + + // add the POs corresponding to the root nodes + Vec_PtrForEachEntry( vRoots, pObj, i ) + { + // create the PO node + pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); + // connect the internal nodes to the new CO + if ( Abc_ObjIsCo(pObj) ) + Abc_ObjAddFanin( pNodeCoNew, Abc_ObjChild0Copy(pObj) ); + else + Abc_ObjAddFanin( pNodeCoNew, pObj->pCopy ); + // assign the name + Abc_ObjAssignName( pNodeCoNew, Abc_ObjName(pObj), NULL ); + } + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateConeArray(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Adds new nodes to the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i, iNodeId; + + assert( Abc_NtkIsStrash(pNtkNew) ); + assert( Abc_NtkIsStrash(pNtk) ); + + // collect the nodes in the TFI of the output (mark the TFI) + vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); + + // establish connection between the constant nodes + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + + // create the PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + { + // skip CIs that are not used + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + continue; + // find the corresponding CI in the new network + iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); + if ( iNodeId == -1 ) + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + else + pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); + } + + // copy the nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + Vec_PtrFree( vNodes ); + + // do not add the COs + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkAppendToCone(): Network check has failed.\n" ); +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of MFFC of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; + Vec_Ptr_t * vCone, * vSupp; + char Buffer[1000]; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // set the name + sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // establish connection between the constant nodes + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + + // collect the nodes in MFFC + vCone = Vec_PtrAlloc( 100 ); + vSupp = Vec_PtrAlloc( 100 ); + Abc_NodeDeref_rec( pNode ); + Abc_NodeMffsConeSupp( pNode, vCone, vSupp ); + Abc_NodeRef_rec( pNode ); + // create the PIs + Vec_PtrForEachEntry( vSupp, pObj, i ) + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + // create the PO + pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL ); + // copy the nodes + Vec_PtrForEachEntry( vCone, pObj, i ) + { + // if it is an AIG, add to the hash table + if ( Abc_NtkIsStrash(pNtk) ) + { + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + } + else + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + } + // connect the topmost node + Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy ); + Vec_PtrFree( vCone ); + Vec_PtrFree( vSupp ); + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateMffc(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the miter composed of one multi-output cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFinal, * pOther, * pNodePo; + int i; + + assert( Abc_NtkIsLogic(pNtk) ); + + // start the network + Abc_NtkCleanCopy( pNtk ); + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + + // collect the nodes in the TFI of the output + vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)vRoots->pArray, vRoots->nSize ); + // create the PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + // copy the nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pCopy = Abc_NodeStrash( pNtkNew, pObj, 0 ); + Vec_PtrFree( vNodes ); + + // add the PO + pFinal = Abc_AigConst1( pNtkNew ); + Vec_PtrForEachEntry( vRoots, pObj, i ) + { + if ( Abc_ObjIsCo(pObj) ) + pOther = Abc_ObjFanin0(pObj)->pCopy; + else + pOther = pObj->pCopy; + if ( Vec_IntEntry(vValues, i) == 0 ) + pOther = Abc_ObjNot(pOther); + pFinal = Abc_AigAnd( pNtkNew->pManFunc, pFinal, pOther ); + } + + // add the PO corresponding to this output + pNodePo = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pNodePo, pFinal ); + Abc_ObjAssignName( pNodePo, "miter", NULL ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateTarget(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pFanin, * pNodePo; + int i; + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + pNtkNew->pName = Extra_UtilStrsav(Abc_ObjName(pNode)); + // add the PIs corresponding to the fanins of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + pFanin->pCopy = Abc_NtkCreatePi( pNtkNew ); + Abc_ObjAssignName( pFanin->pCopy, Abc_ObjName(pFanin), NULL ); + } + // duplicate and connect the node + pNode->pCopy = Abc_NtkDupObj( pNtkNew, pNode, 0 ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy ); + // create the only PO + pNodePo = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pNodePo, pNode->pCopy ); + Abc_ObjAssignName( pNodePo, Abc_ObjName(pNode), NULL ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateFromNode(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of one node with the given SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pFanin, * pNode, * pNodePo; + Vec_Ptr_t * vNames; + int i, nVars; + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtkNew->pName = Extra_UtilStrsav("ex"); + // create PIs + Vec_PtrPush( pNtkNew->vObjs, NULL ); + nVars = Abc_SopGetVarNum( pSop ); + vNames = Abc_NodeGetFakeNames( nVars ); + for ( i = 0; i < nVars; i++ ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Vec_PtrEntry(vNames, i), NULL ); + Abc_NodeFreeNames( vNames ); + // create the node, add PIs as fanins, set the function + pNode = Abc_NtkCreateNode( pNtkNew ); + Abc_NtkForEachPi( pNtkNew, pFanin, i ) + Abc_ObjAddFanin( pNode, pFanin ); + pNode->pData = Abc_SopRegister( pNtkNew->pManFunc, pSop ); + // create the only PO + pNodePo = Abc_NtkCreatePo(pNtkNew); + Abc_ObjAddFanin( pNodePo, pNode ); + Abc_ObjAssignName( pNodePo, "F", NULL ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateWithNode(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Deletes the Ntk.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDelete( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + void * pAttrMan; + int TotalMemory, i; + int LargePiece = (4 << ABC_NUM_STEPS); + if ( pNtk == NULL ) + return; + // free the HAIG + if ( pNtk->pHaig ) + Abc_NtkHaigStop( pNtk ); + // free EXDC Ntk + if ( pNtk->pExdc ) + Abc_NtkDelete( pNtk->pExdc ); + // dereference the BDDs + if ( Abc_NtkHasBdd(pNtk) ) + { + Abc_NtkForEachNode( pNtk, pObj, i ) + Cudd_RecursiveDeref( pNtk->pManFunc, pObj->pData ); + } + // make sure all the marks are clean + Abc_NtkForEachObj( pNtk, pObj, i ) + { + // free large fanout arrays + if ( pNtk->pMmObj && pObj->vFanouts.nCap * 4 > LargePiece ) + FREE( pObj->vFanouts.pArray ); + // these flags should be always zero + // if this is not true, something is wrong somewhere + assert( pObj->fMarkA == 0 ); + assert( pObj->fMarkB == 0 ); + assert( pObj->fMarkC == 0 ); + } + // free the nodes + if ( pNtk->pMmStep == NULL ) + { + Abc_NtkForEachObj( pNtk, pObj, i ) + { + FREE( pObj->vFanouts.pArray ); + FREE( pObj->vFanins.pArray ); + } + } + if ( pNtk->pMmObj == NULL ) + { + Abc_NtkForEachObj( pNtk, pObj, i ) + free( pObj ); + } + + // free the arrays + Vec_PtrFree( pNtk->vPios ); + Vec_PtrFree( pNtk->vPis ); + Vec_PtrFree( pNtk->vPos ); + Vec_PtrFree( pNtk->vCis ); + Vec_PtrFree( pNtk->vCos ); + Vec_PtrFree( pNtk->vAsserts ); + Vec_PtrFree( pNtk->vObjs ); + Vec_PtrFree( pNtk->vBoxes ); + if ( pNtk->vLevelsR ) Vec_IntFree( pNtk->vLevelsR ); + if ( pNtk->pModel ) free( pNtk->pModel ); + TotalMemory = 0; + TotalMemory += pNtk->pMmObj? Extra_MmFixedReadMemUsage(pNtk->pMmObj) : 0; + TotalMemory += pNtk->pMmStep? Extra_MmStepReadMemUsage(pNtk->pMmStep) : 0; +// fprintf( stdout, "The total memory allocated internally by the network = %0.2f Mb.\n", ((double)TotalMemory)/(1<<20) ); + // free the storage + if ( pNtk->pMmObj ) + Extra_MmFixedStop( pNtk->pMmObj ); + if ( pNtk->pMmStep ) + Extra_MmStepStop ( pNtk->pMmStep ); + // name manager + Nm_ManFree( pNtk->pManName ); + // free the timing manager + if ( pNtk->pManTime ) + Abc_ManTimeStop( pNtk->pManTime ); + // start the functionality manager + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigFree( pNtk->pManFunc ); + else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) + Extra_MmFlexStop( pNtk->pManFunc ); + else if ( Abc_NtkHasBdd(pNtk) ) + Extra_StopManager( pNtk->pManFunc ); + else if ( Abc_NtkHasAig(pNtk) ) + { if ( pNtk->pManFunc ) Hop_ManStop( pNtk->pManFunc ); } + else if ( Abc_NtkHasMapping(pNtk) ) + pNtk->pManFunc = NULL; + else if ( !Abc_NtkHasBlackbox(pNtk) ) + assert( 0 ); + // free the hierarchy + if ( pNtk->pDesign ) + { + Abc_LibFree( pNtk->pDesign, pNtk ); + pNtk->pDesign = NULL; + } +// if ( pNtk->pBlackBoxes ) +// Vec_IntFree( pNtk->pBlackBoxes ); + // free node attributes + Vec_PtrForEachEntry( pNtk->vAttrs, pAttrMan, i ) + if ( pAttrMan ) + { +//printf( "deleting attr\n" ); + Vec_AttFree( pAttrMan, 1 ); + } + Vec_PtrFree( pNtk->vAttrs ); + FREE( pNtk->pName ); + FREE( pNtk->pSpec ); + free( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Reads the verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNets; + Abc_Obj_t * pNet, * pNode; + int i; + + if ( Abc_NtkNodeNum(pNtk) == 0 && Abc_NtkBoxNum(pNtk) == 0 ) + return; + + // check for non-driven nets + vNets = Vec_PtrAlloc( 100 ); + Abc_NtkForEachNet( pNtk, pNet, i ) + { + if ( Abc_ObjFaninNum(pNet) > 0 ) + continue; + // add the constant 0 driver + pNode = Abc_NtkCreateNodeConst0( pNtk ); + // add the fanout net + Abc_ObjAddFanin( pNet, pNode ); + // add the net to those for which the warning will be printed + Vec_PtrPush( vNets, pNet ); + } + + // print the warning + if ( vNets->nSize > 0 ) + { + printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pNtk->pName ); + Vec_PtrForEachEntry( vNets, pNet, i ) + { + printf( "%s%s", (i? ", ": ""), Abc_ObjName(pNet) ); + if ( i == 3 ) + { + if ( Vec_PtrSize(vNets) > 3 ) + printf( " ..." ); + break; + } + } + printf( "\n" ); + } + Vec_PtrFree( vNets ); +} + + +/**Function************************************************************* + + Synopsis [Converts the network to combinational.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMakeComb( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + if ( Abc_NtkIsComb(pNtk) ) + return; + + assert( !Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + + // detach the latches +// Abc_NtkForEachLatch( pNtk, pObj, i ) + Vec_PtrForEachEntryReverse( pNtk->vBoxes, pObj, i ) + Abc_NtkDeleteObj( pObj ); + assert( Abc_NtkLatchNum(pNtk) == 0 ); + assert( Abc_NtkBoxNum(pNtk) == 0 ); + + // move CIs to become PIs + Vec_PtrClear( pNtk->vPis ); + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( Abc_ObjIsBo(pObj) ) + { + pObj->Type = ABC_OBJ_PI; + pNtk->nObjCounts[ABC_OBJ_PI]++; + pNtk->nObjCounts[ABC_OBJ_BO]--; + } + Vec_PtrPush( pNtk->vPis, pObj ); + } + assert( Abc_NtkBoNum(pNtk) == 0 ); + + // move COs to become POs + Vec_PtrClear( pNtk->vPos ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( Abc_ObjIsBi(pObj) ) + { + pObj->Type = ABC_OBJ_PO; + pNtk->nObjCounts[ABC_OBJ_PO]++; + pNtk->nObjCounts[ABC_OBJ_BI]--; + } + Vec_PtrPush( pNtk->vPos, pObj ); + } + assert( Abc_NtkBiNum(pNtk) == 0 ); + + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" ); +} + + +/**Function************************************************************* + + Synopsis [Removes POs with suppsize less than 2 and PIs without fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkTrim( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i, k, m; + + // filter POs + k = m = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( Abc_ObjIsPo(pObj) ) + { + // remove constant nodes and PI pointers + if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 0 ) + { + Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); + if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 && !Abc_ObjIsPi(Abc_ObjFanin0(pObj)) ) + Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 ); + pNtk->vObjs->pArray[pObj->Id] = NULL; + pObj->Id = (1<<26)-1; + pNtk->nObjCounts[pObj->Type]--; + pNtk->nObjs--; + Abc_ObjRecycle( pObj ); + continue; + } + // remove buffers/inverters of PIs + if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 1 ) + { + if ( Abc_ObjIsPi(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) ) + { + Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); + if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 ) + Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 ); + pNtk->vObjs->pArray[pObj->Id] = NULL; + pObj->Id = (1<<26)-1; + pNtk->nObjCounts[pObj->Type]--; + pNtk->nObjs--; + Abc_ObjRecycle( pObj ); + continue; + } + } + Vec_PtrWriteEntry( pNtk->vPos, m++, pObj ); + } + Vec_PtrWriteEntry( pNtk->vCos, k++, pObj ); + } + Vec_PtrShrink( pNtk->vPos, m ); + Vec_PtrShrink( pNtk->vCos, k ); + + // filter PIs + k = m = 0; + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( Abc_ObjIsPi(pObj) ) + { + if ( Abc_ObjFanoutNum(pObj) == 0 ) + { + pNtk->vObjs->pArray[pObj->Id] = NULL; + pObj->Id = (1<<26)-1; + pNtk->nObjCounts[pObj->Type]--; + pNtk->nObjs--; + Abc_ObjRecycle( pObj ); + continue; + } + Vec_PtrWriteEntry( pNtk->vPis, m++, pObj ); + } + Vec_PtrWriteEntry( pNtk->vCis, k++, pObj ); + } + Vec_PtrShrink( pNtk->vPis, m ); + Vec_PtrShrink( pNtk->vCis, k ); + + return Abc_NtkDup( pNtk ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcObj.c b/abc70930/src/base/abc/abcObj.c new file mode 100644 index 00000000..7a995c71 --- /dev/null +++ b/abc70930/src/base/abc/abcObj.c @@ -0,0 +1,976 @@ +/**CFile**************************************************************** + + FileName [abcObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Object creation/duplication/deletion procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcObj.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "abcInt.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates a new object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ) +{ + Abc_Obj_t * pObj; + if ( pNtk->pMmObj ) + pObj = (Abc_Obj_t *)Extra_MmFixedEntryFetch( pNtk->pMmObj ); + else + pObj = (Abc_Obj_t *)ALLOC( Abc_Obj_t, 1 ); + memset( pObj, 0, sizeof(Abc_Obj_t) ); + pObj->pNtk = pNtk; + pObj->Type = Type; + pObj->Id = -1; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Recycles the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjRecycle( Abc_Obj_t * pObj ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + int LargePiece = (4 << ABC_NUM_STEPS); + // free large fanout arrays + if ( pNtk->pMmStep && pObj->vFanouts.nCap * 4 > LargePiece ) + FREE( pObj->vFanouts.pArray ); + if ( pNtk->pMmStep == NULL ) + { + FREE( pObj->vFanouts.pArray ); + FREE( pObj->vFanins.pArray ); + } + // clean the memory to make deleted object distinct from the live one + memset( pObj, 0, sizeof(Abc_Obj_t) ); + // recycle the object + if ( pNtk->pMmObj ) + Extra_MmFixedEntryRecycle( pNtk->pMmObj, (char *)pObj ); + else + free( pObj ); +} + +/**Function************************************************************* + + Synopsis [Adds the node to the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ) +{ + Abc_Obj_t * pObj; + // create new object, assign ID, and add to the array + pObj = Abc_ObjAlloc( pNtk, Type ); + pObj->Id = pNtk->vObjs->nSize; + Vec_PtrPush( pNtk->vObjs, pObj ); + pNtk->nObjCounts[Type]++; + pNtk->nObjs++; + // perform specialized operations depending on the object type + switch (Type) + { + case ABC_OBJ_NONE: + assert(0); + break; + case ABC_OBJ_CONST1: + assert(0); + break; + case ABC_OBJ_PIO: + assert(0); + break; + case ABC_OBJ_PI: + Vec_PtrPush( pNtk->vPis, pObj ); + Vec_PtrPush( pNtk->vCis, pObj ); + break; + case ABC_OBJ_PO: + Vec_PtrPush( pNtk->vPos, pObj ); + Vec_PtrPush( pNtk->vCos, pObj ); + break; + case ABC_OBJ_BI: + if ( pNtk->vCos ) Vec_PtrPush( pNtk->vCos, pObj ); + break; + case ABC_OBJ_BO: + if ( pNtk->vCis ) Vec_PtrPush( pNtk->vCis, pObj ); + break; + case ABC_OBJ_ASSERT: + Vec_PtrPush( pNtk->vAsserts, pObj ); + Vec_PtrPush( pNtk->vCos, pObj ); + break; + case ABC_OBJ_NET: + case ABC_OBJ_NODE: + break; + case ABC_OBJ_LATCH: + pObj->pData = (void *)ABC_INIT_NONE; + case ABC_OBJ_WHITEBOX: + case ABC_OBJ_BLACKBOX: + if ( pNtk->vBoxes ) Vec_PtrPush( pNtk->vBoxes, pObj ); + break; + default: + assert(0); + break; + } + return pObj; +} + +/**Function************************************************************* + + Synopsis [Deletes the object from the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDeleteObj( Abc_Obj_t * pObj ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + Vec_Ptr_t * vNodes; + int i; + assert( !Abc_ObjIsComplement(pObj) ); + // remove from the table of names + if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) ) + Nm_ManDeleteIdName(pObj->pNtk->pManName, pObj->Id); + // delete fanins and fanouts + vNodes = Vec_PtrAlloc( 100 ); + Abc_NodeCollectFanouts( pObj, vNodes ); + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_ObjDeleteFanin( vNodes->pArray[i], pObj ); + Abc_NodeCollectFanins( pObj, vNodes ); + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_ObjDeleteFanin( pObj, vNodes->pArray[i] ); + Vec_PtrFree( vNodes ); + // remove from the list of objects + Vec_PtrWriteEntry( pNtk->vObjs, pObj->Id, NULL ); + pObj->Id = (1<<26)-1; + pNtk->nObjCounts[pObj->Type]--; + pNtk->nObjs--; + // perform specialized operations depending on the object type + switch (pObj->Type) + { + case ABC_OBJ_NONE: + assert(0); + break; + case ABC_OBJ_CONST1: + assert(0); + break; + case ABC_OBJ_PIO: + assert(0); + break; + case ABC_OBJ_PI: + Vec_PtrRemove( pNtk->vPis, pObj ); + Vec_PtrRemove( pNtk->vCis, pObj ); + break; + case ABC_OBJ_PO: + Vec_PtrRemove( pNtk->vPos, pObj ); + Vec_PtrRemove( pNtk->vCos, pObj ); + break; + case ABC_OBJ_BI: + if ( pNtk->vCos ) Vec_PtrRemove( pNtk->vCos, pObj ); + break; + case ABC_OBJ_BO: + if ( pNtk->vCis ) Vec_PtrRemove( pNtk->vCis, pObj ); + break; + case ABC_OBJ_ASSERT: + Vec_PtrRemove( pNtk->vAsserts, pObj ); + Vec_PtrRemove( pNtk->vCos, pObj ); + break; + case ABC_OBJ_NET: + break; + case ABC_OBJ_NODE: + if ( Abc_NtkHasBdd(pNtk) ) + Cudd_RecursiveDeref( pNtk->pManFunc, pObj->pData ); + pObj->pData = NULL; + break; + case ABC_OBJ_LATCH: + case ABC_OBJ_WHITEBOX: + case ABC_OBJ_BLACKBOX: + if ( pNtk->vBoxes ) Vec_PtrRemove( pNtk->vBoxes, pObj ); + break; + default: + assert(0); + break; + } + // recycle the object memory + Abc_ObjRecycle( pObj ); +} + +/**Function************************************************************* + + Synopsis [Deletes the node and MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes ) +{ + Vec_Ptr_t * vNodes; + int i; + assert( !Abc_ObjIsComplement(pObj) ); + assert( !Abc_ObjIsPi(pObj) ); + assert( Abc_ObjFanoutNum(pObj) == 0 ); + // delete fanins and fanouts + vNodes = Vec_PtrAlloc( 100 ); + Abc_NodeCollectFanins( pObj, vNodes ); + Abc_NtkDeleteObj( pObj ); + if ( fOnlyNodes ) + { + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) + Abc_NtkDeleteObj_rec( pObj, fOnlyNodes ); + } + else + { + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( !Abc_ObjIsPi(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) + Abc_NtkDeleteObj_rec( pObj, fOnlyNodes ); + } + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Deletes the node and MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj ) +{ + Vec_Ptr_t * vNodes; + int i; + assert( !Abc_ObjIsComplement(pObj) ); + assert( Abc_ObjFanoutNum(pObj) == 0 ); + // delete fanins and fanouts + vNodes = Vec_PtrAlloc( 100 ); + Abc_NodeCollectFanins( pObj, vNodes ); + Abc_NtkDeleteObj( pObj ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( !Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) + Abc_NtkDeleteAll_rec( pObj ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Duplicate the Obj.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName ) +{ + Abc_Obj_t * pObjNew; + // create the new object + pObjNew = Abc_NtkCreateObj( pNtkNew, pObj->Type ); + // transfer names of the terminal objects + if ( fCopyName ) + { + if ( Abc_ObjIsCi(pObj) ) + { + if ( !Abc_NtkIsNetlist(pNtkNew) ) + Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); + } + else if ( Abc_ObjIsCo(pObj) ) + { + if ( !Abc_NtkIsNetlist(pNtkNew) ) + { + if ( Abc_ObjIsPo(pObj) ) + Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); + else + { + assert( Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ); + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); + } + } + } + else if ( Abc_ObjIsBox(pObj) || Abc_ObjIsNet(pObj) ) + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); + } + // copy functionality/names + if ( Abc_ObjIsNode(pObj) ) // copy the function if functionality is compatible + { + if ( pNtkNew->ntkFunc == pObj->pNtk->ntkFunc ) + { + if ( Abc_NtkIsStrash(pNtkNew) ) + {} + else if ( Abc_NtkHasSop(pNtkNew) || Abc_NtkHasBlifMv(pNtkNew) ) + pObjNew->pData = Abc_SopRegister( pNtkNew->pManFunc, pObj->pData ); + else if ( Abc_NtkHasBdd(pNtkNew) ) + pObjNew->pData = Cudd_bddTransfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData), Cudd_Ref(pObjNew->pData); + else if ( Abc_NtkHasAig(pNtkNew) ) + pObjNew->pData = Hop_Transfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData, Abc_ObjFaninNum(pObj)); + else if ( Abc_NtkHasMapping(pNtkNew) ) + pObjNew->pData = pObj->pData; + else assert( 0 ); + } + } + else if ( Abc_ObjIsNet(pObj) ) // copy the name + { + } + else if ( Abc_ObjIsLatch(pObj) ) // copy the reset value + pObjNew->pData = pObj->pData; + // transfer HAIG +// pObjNew->pEquiv = pObj->pEquiv; + // remember the new node in the old node + pObj->pCopy = pObjNew; + return pObjNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the latch with its input/output terminals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName ) +{ + Abc_Obj_t * pTerm, * pBoxNew; + int i; + assert( Abc_ObjIsBox(pBox) ); + // duplicate the box + pBoxNew = Abc_NtkDupObj( pNtkNew, pBox, fCopyName ); + // duplicate the fanins and connect them + Abc_ObjForEachFanin( pBox, pTerm, i ) + Abc_ObjAddFanin( pBoxNew, Abc_NtkDupObj(pNtkNew, pTerm, fCopyName) ); + // duplicate the fanouts and connect them + Abc_ObjForEachFanout( pBox, pTerm, i ) + Abc_ObjAddFanin( Abc_NtkDupObj(pNtkNew, pTerm, fCopyName), pBoxNew ); + return pBoxNew; +} + +/**Function************************************************************* + + Synopsis [Clones the objects in the same network but does not assign its function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pClone, * pFanin; + int i; + pClone = Abc_NtkCreateObj( pObj->pNtk, pObj->Type ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_ObjAddFanin( pClone, pFanin ); + return pClone; +} + + +/**Function************************************************************* + + Synopsis [Returns the net with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pObj; + int Num; + // try to find the terminal + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO ); + if ( Num >= 0 ) + return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI ); + if ( Num >= 0 ) + return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NODE ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + // find the internal node + if ( pName[0] != 'n' ) + { + printf( "Name \"%s\" is not found among CO or node names (internal names often look as \"n<num>\").\n", pName ); + return NULL; + } + Num = atoi( pName + 1 ); + if ( Num < 0 || Num >= Abc_NtkObjNumMax(pNtk) ) + { + printf( "The node \"%s\" with ID %d is not in the current network.\n", pName, Num ); + return NULL; + } + pObj = Abc_NtkObj( pNtk, Num ); + if ( pObj == NULL ) + { + printf( "The node \"%s\" with ID %d has been removed from the current network.\n", pName, Num ); + return NULL; + } + if ( !Abc_ObjIsNode(pObj) ) + { + printf( "Object with ID %d is not a node.\n", Num ); + return NULL; + } + return pObj; +} + +/**Function************************************************************* + + Synopsis [Returns the net with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet; + int ObjId; + assert( Abc_NtkIsNetlist(pNtk) ); + ObjId = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NET ); + if ( ObjId == -1 ) + return NULL; + pNet = Abc_NtkObj( pNtk, ObjId ); + return pNet; +} + +/**Function************************************************************* + + Synopsis [Returns CI with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName ) +{ + int Num; + assert( !Abc_NtkIsNetlist(pNtk) ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PI ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BO ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns CO with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ) +{ + int Num; + assert( !Abc_NtkIsNetlist(pNtk) ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Finds or creates the net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet; + assert( Abc_NtkIsNetlist(pNtk) ); + if ( pName && (pNet = Abc_NtkFindNet( pNtk, pName )) ) + return pNet; +//printf( "Creating net %s.\n", pName ); + // create a new net + pNet = Abc_NtkCreateNet( pNtk ); + if ( pName ) + Nm_ManStoreIdName( pNtk->pManName, pNet->Id, pNet->Type, pName, NULL ); + return pNet; +} + +/**Function************************************************************* + + Synopsis [Creates constant 0 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) + pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\n" ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_ReadLogicZero(pNtk->pManFunc), Cudd_Ref( pNode->pData ); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_ManConst0(pNtk->pManFunc); + else if ( Abc_NtkHasMapping(pNtk) ) + pNode->pData = Mio_LibraryReadConst0(Abc_FrameReadLibGen()); + else if ( !Abc_NtkHasBlackbox(pNtk) ) + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) + pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 1\n" ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_ReadOne(pNtk->pManFunc), Cudd_Ref( pNode->pData ); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_ManConst1(pNtk->pManFunc); + else if ( Abc_NtkHasMapping(pNtk) ) + pNode->pData = Mio_LibraryReadConst1(Abc_FrameReadLibGen()); + else if ( !Abc_NtkHasBlackbox(pNtk) ) + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates inverter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopRegister( pNtk->pManFunc, "0 1\n" ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_Not(Cudd_bddIthVar(pNtk->pManFunc,0)), Cudd_Ref( pNode->pData ); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_Not(Hop_IthVar(pNtk->pManFunc,0)); + else if ( Abc_NtkHasMapping(pNtk) ) + pNode->pData = Mio_LibraryReadInv(Abc_FrameReadLibGen()); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopRegister( pNtk->pManFunc, "1 1\n" ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_bddIthVar(pNtk->pManFunc,0), Cudd_Ref( pNode->pData ); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_IthVar(pNtk->pManFunc,0); + else if ( Abc_NtkHasMapping(pNtk) ) + pNode->pData = Mio_LibraryReadBuf(Abc_FrameReadLibGen()); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates AND.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + for ( i = 0; i < vFanins->nSize; i++ ) + Abc_ObjAddFanin( pNode, vFanins->pArray[i] ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopCreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins), NULL ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Extra_bddCreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_CreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins) ); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + for ( i = 0; i < vFanins->nSize; i++ ) + Abc_ObjAddFanin( pNode, vFanins->pArray[i] ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopCreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins), NULL ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Extra_bddCreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_CreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins) ); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates EXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + for ( i = 0; i < vFanins->nSize; i++ ) + Abc_ObjAddFanin( pNode, vFanins->pArray[i] ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopCreateXorSpecial( pNtk->pManFunc, Vec_PtrSize(vFanins) ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Extra_bddCreateExor( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_CreateExor( pNtk->pManFunc, Vec_PtrSize(vFanins) ); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates MUX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + Abc_ObjAddFanin( pNode, pNodeC ); + Abc_ObjAddFanin( pNode, pNode1 ); + Abc_ObjAddFanin( pNode, pNode0 ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopRegister( pNtk->pManFunc, "11- 1\n0-1 1\n" ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_bddIte(pNtk->pManFunc,Cudd_bddIthVar(pNtk->pManFunc,0),Cudd_bddIthVar(pNtk->pManFunc,1),Cudd_bddIthVar(pNtk->pManFunc,2)), Cudd_Ref( pNode->pData ); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_Mux(pNtk->pManFunc,Hop_IthVar(pNtk->pManFunc,0),Hop_IthVar(pNtk->pManFunc,1),Hop_IthVar(pNtk->pManFunc,2)); + else + assert( 0 ); + return pNode; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is a constant 0 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsConst( Abc_Obj_t * pNode ) +{ + assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) ); + return Abc_ObjIsNode(pNode) && Abc_ObjFaninNum(pNode) == 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is a constant 0 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsConst0( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( !Abc_NodeIsConst(pNode) ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return Abc_SopIsConst0(pNode->pData); + if ( Abc_NtkHasBdd(pNtk) ) + return Cudd_IsComplement(pNode->pData); + if ( Abc_NtkHasAig(pNtk) ) + return Hop_IsComplement(pNode->pData); + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadConst0(Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is a constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsConst1( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( !Abc_NodeIsConst(pNode) ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return Abc_SopIsConst1(pNode->pData); + if ( Abc_NtkHasBdd(pNtk) ) + return !Cudd_IsComplement(pNode->pData); + if ( Abc_NtkHasAig(pNtk) ) + return !Hop_IsComplement(pNode->pData); + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadConst1(Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is a buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsBuf( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_ObjFaninNum(pNode) != 1 ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return Abc_SopIsBuf(pNode->pData); + if ( Abc_NtkHasBdd(pNtk) ) + return !Cudd_IsComplement(pNode->pData); + if ( Abc_NtkHasAig(pNtk) ) + return !Hop_IsComplement(pNode->pData); + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadBuf(Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is an inverter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsInv( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_ObjFaninNum(pNode) != 1 ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return Abc_SopIsInv(pNode->pData); + if ( Abc_NtkHasBdd(pNtk) ) + return Cudd_IsComplement(pNode->pData); + if ( Abc_NtkHasAig(pNtk) ) + return Hop_IsComplement(pNode->pData); + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadInv(Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Complements the local functions of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeComplement( Abc_Obj_t * pNode ) +{ + assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_NtkHasSop(pNode->pNtk) ) + Abc_SopComplement( pNode->pData ); + else if ( Abc_NtkHasBdd(pNode->pNtk) ) + pNode->pData = Cudd_Not( pNode->pData ); + else if ( Abc_NtkHasAig(pNode->pNtk) ) + pNode->pData = Hop_Not( pNode->pData ); + else + assert( 0 ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/base/abc/abcRefs.c b/abc70930/src/base/abc/abcRefs.c new file mode 100644 index 00000000..604c5ffa --- /dev/null +++ b/abc70930/src/base/abc/abcRefs.c @@ -0,0 +1,452 @@ +/**CFile**************************************************************** + + FileName [abcRefs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures using reference counting of the AIG nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRefs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel ); +static int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the MFFC size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffcSize( Abc_Obj_t * pNode ) +{ + int nConeSize1, nConeSize2; +// assert( Abc_NtkIsStrash(pNode->pNtk) ); +// assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_ObjIsNode( pNode ) ); + if ( Abc_ObjFaninNum(pNode) == 0 ) + return 0; + nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference + nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference + assert( nConeSize1 == nConeSize2 ); + assert( nConeSize1 > 0 ); + return nConeSize1; +} + +/**Function************************************************************* + + Synopsis [Returns the MFFC size while stopping at the complemented edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode ) +{ + int nConeSize1, nConeSize2; + assert( Abc_NtkIsStrash(pNode->pNtk) ); + assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_ObjIsNode( pNode ) ); + if ( Abc_ObjFaninNum(pNode) == 0 ) + return 0; + nConeSize1 = Abc_NodeRefDerefStop( pNode, 0 ); // dereference + nConeSize2 = Abc_NodeRefDerefStop( pNode, 1 ); // reference + assert( nConeSize1 == nConeSize2 ); + assert( nConeSize1 > 0 ); + return nConeSize1; +} + +/**Function************************************************************* + + Synopsis [Labels MFFC with the current traversal ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode ) +{ + int nConeSize1, nConeSize2; + assert( Abc_NtkIsStrash(pNode->pNtk) ); + assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_ObjIsNode( pNode ) ); + if ( Abc_ObjFaninNum(pNode) == 0 ) + return 0; + nConeSize1 = Abc_NodeRefDeref( pNode, 0, 1 ); // dereference + nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference + assert( nConeSize1 == nConeSize2 ); + assert( nConeSize1 > 0 ); + return nConeSize1; +} + +/**Function************************************************************* + + Synopsis [References/references the node and returns MFFC size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel ) +{ + Abc_Obj_t * pNode0, * pNode1; + int Counter; + // label visited nodes + if ( fLabel ) + Abc_NodeSetTravIdCurrent( pNode ); + // skip the CI + if ( Abc_ObjIsCi(pNode) ) + return 0; + // process the internal node + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + Counter = 1; + if ( fReference ) + { + if ( pNode0->vFanouts.nSize++ == 0 ) + Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel ); + if ( pNode1->vFanouts.nSize++ == 0 ) + Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel ); + } + else + { + assert( pNode0->vFanouts.nSize > 0 ); + assert( pNode1->vFanouts.nSize > 0 ); + if ( --pNode0->vFanouts.nSize == 0 ) + Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel ); + if ( --pNode1->vFanouts.nSize == 0 ) + Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel ); + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [References/references the node and returns MFFC size.] + + Description [Stops at the complemented edges.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference ) +{ + Abc_Obj_t * pNode0, * pNode1; + int Counter; + // skip the CI + if ( Abc_ObjIsCi(pNode) ) + return 0; + // process the internal node + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + Counter = 1; + if ( fReference ) + { + if ( pNode0->vFanouts.nSize++ == 0 && !Abc_ObjFaninC0(pNode) ) + Counter += Abc_NodeRefDerefStop( pNode0, fReference ); + if ( pNode1->vFanouts.nSize++ == 0 && !Abc_ObjFaninC1(pNode) ) + Counter += Abc_NodeRefDerefStop( pNode1, fReference ); + } + else + { + assert( pNode0->vFanouts.nSize > 0 ); + assert( pNode1->vFanouts.nSize > 0 ); + if ( --pNode0->vFanouts.nSize == 0 && !Abc_ObjFaninC0(pNode) ) + Counter += Abc_NodeRefDerefStop( pNode0, fReference ); + if ( --pNode1->vFanouts.nSize == 0 && !Abc_ObjFaninC1(pNode) ) + Counter += Abc_NodeRefDerefStop( pNode1, fReference ); + } + return Counter; +} + + + + +/**Function************************************************************* + + Synopsis [Dereferences the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeDeref_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + int i, Counter = 1; + if ( Abc_ObjIsCi(pNode) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + assert( pFanin->vFanouts.nSize > 0 ); + if ( --pFanin->vFanouts.nSize == 0 ) + Counter += Abc_NodeDeref_rec( pFanin ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [References the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRef_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + int i, Counter = 1; + if ( Abc_ObjIsCi(pNode) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pFanin->vFanouts.nSize++ == 0 ) + Counter += Abc_NodeRef_rec( pFanin ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffsConeSupp_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int fTopmost ) +{ + Abc_Obj_t * pFanin; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return; + Abc_NodeSetTravIdCurrent(pNode); + // add to the new support nodes + if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) ) + { + if ( vSupp ) Vec_PtrPush( vSupp, pNode ); + return; + } + // recur on the children + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NodeMffsConeSupp_rec( pFanin, vCone, vSupp, 0 ); + // collect the internal node + if ( vCone ) Vec_PtrPush( vCone, pNode ); +// printf( "%d ", pNode->Id ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffsConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ) +{ + assert( Abc_ObjIsNode(pNode) ); + assert( !Abc_ObjIsComplement(pNode) ); + if ( vCone ) Vec_PtrClear( vCone ); + if ( vSupp ) Vec_PtrClear( vSupp ); + Abc_NtkIncrementTravId( pNode->pNtk ); + Abc_NodeMffsConeSupp_rec( pNode, vCone, vSupp, 1 ); +// printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffsConeSuppPrint( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vCone, * vSupp; + Abc_Obj_t * pObj; + int i; + vCone = Vec_PtrAlloc( 100 ); + vSupp = Vec_PtrAlloc( 100 ); + Abc_NodeDeref_rec( pNode ); + Abc_NodeMffsConeSupp( pNode, vCone, vSupp ); + Abc_NodeRef_rec( pNode ); + printf( "Node = %6s : Supp = %3d Cone = %3d (", + Abc_ObjName(pNode), Vec_PtrSize(vSupp), Vec_PtrSize(vCone) ); + Vec_PtrForEachEntry( vCone, pObj, i ) + printf( " %s", Abc_ObjName(pObj) ); + printf( " )\n" ); + Vec_PtrFree( vCone ); + Vec_PtrFree( vSupp ); +} + +/**Function************************************************************* + + Synopsis [Collects the internal nodes of the MFFC limited by cut.] + + Description [] + + SideEffects [Increments the trav ID and marks visited nodes.] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffsInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside ) +{ + Abc_Obj_t * pObj; + int i, Count1, Count2; + // increment the fanout counters for the leaves + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->vFanouts.nSize++; + // dereference the node + Count1 = Abc_NodeDeref_rec( pNode ); + // collect the nodes inside the MFFC + Abc_NodeMffsConeSupp( pNode, vInside, NULL ); + // reference it back + Count2 = Abc_NodeRef_rec( pNode ); + assert( Count1 == Count2 ); + // remove the extra counters + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->vFanouts.nSize--; + return Count1; +} + +/**Function************************************************************* + + Synopsis [Collects the internal nodes of the MFFC limited by cut.] + + Description [] + + SideEffects [Increments the trav ID and marks visited nodes.] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeMffsInsideCollect( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vInside; + int Count1, Count2; + // dereference the node + Count1 = Abc_NodeDeref_rec( pNode ); + // collect the nodes inside the MFFC + vInside = Vec_PtrAlloc( 10 ); + Abc_NodeMffsConeSupp( pNode, vInside, NULL ); + // reference it back + Count2 = Abc_NodeRef_rec( pNode ); + assert( Count1 == Count2 ); + return vInside; +} + +/**Function************************************************************* + + Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffcLabel_rec( Abc_Obj_t * pNode, int fTopmost ) +{ + Abc_Obj_t * pFanin; + int i; + // add to the new support nodes + if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) ) + return; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return; + Abc_NodeSetTravIdCurrent(pNode); + // recur on the children + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NodeMffcLabel_rec( pFanin, 0 ); + // collect the internal node +// printf( "%d ", pNode->Id ); +} + +/**Function************************************************************* + + Synopsis [Collects the internal nodes of the MFFC limited by cut.] + + Description [] + + SideEffects [Increments the trav ID and marks visited nodes.] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffcLabel( Abc_Obj_t * pNode ) +{ + int Count1, Count2; + // dereference the node + Count1 = Abc_NodeDeref_rec( pNode ); + // collect the nodes inside the MFFC + Abc_NtkIncrementTravId( pNode->pNtk ); + Abc_NodeMffcLabel_rec( pNode, 1 ); + // reference it back + Count2 = Abc_NodeRef_rec( pNode ); + assert( Count1 == Count2 ); + return Count1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcShow.c b/abc70930/src/base/abc/abcShow.c new file mode 100644 index 00000000..40d1dcad --- /dev/null +++ b/abc70930/src/base/abc/abcShow.c @@ -0,0 +1,318 @@ +/**CFile**************************************************************** + + FileName [abcShow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Visualization procedures using DOT software and GSView.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcShow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifdef WIN32 +#include <process.h> +#endif + +#include "abc.h" +#include "main.h" +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Abc_ShowFile( char * FileNameDot ); +static void Abc_ShowGetFileName( char * pName, char * pBuffer ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Visualizes BDD of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeShowBdd( Abc_Obj_t * pNode ) +{ + FILE * pFile; + Vec_Ptr_t * vNamesIn; + char FileNameDot[200]; + char * pNameOut; + + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + // create the file name + Abc_ShowGetFileName( Abc_ObjName(pNode), FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + + // set the node names + vNamesIn = Abc_NodeGetFaninNames( pNode ); + pNameOut = Abc_ObjName(pNode); + Cudd_DumpDot( pNode->pNtk->pManFunc, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); + Abc_NodeFreeNames( vNamesIn ); + Abc_NtkCleanCopy( pNode->pNtk ); + fclose( pFile ); + + // visualize the file + Abc_ShowFile( FileNameDot ); +} + +/**Function************************************************************* + + Synopsis [Visualizes a reconvergence driven cut at the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) +{ + FILE * pFile; + char FileNameDot[200]; + Abc_ManCut_t * p; + Vec_Ptr_t * vCutSmall; + Vec_Ptr_t * vCutLarge; + Vec_Ptr_t * vInside; + Vec_Ptr_t * vNodesTfo; + Abc_Obj_t * pTemp; + int i; + + assert( Abc_NtkIsStrash(pNode->pNtk) ); + + // start the cut computation manager + p = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, ABC_INFINITY ); + // get the recovergence driven cut + vCutSmall = Abc_NodeFindCut( p, pNode, 1 ); + // get the containing cut + vCutLarge = Abc_NtkManCutReadCutLarge( p ); + // get the array for the inside nodes + vInside = Abc_NtkManCutReadVisited( p ); + // get the inside nodes of the containing cone + Abc_NodeConeCollect( &pNode, 1, vCutLarge, vInside, 1 ); + + // add the nodes in the TFO + vNodesTfo = Abc_NodeCollectTfoCands( p, pNode, vCutSmall, ABC_INFINITY ); + Vec_PtrForEachEntry( vNodesTfo, pTemp, i ) + Vec_PtrPushUnique( vInside, pTemp ); + + // create the file name + Abc_ShowGetFileName( Abc_ObjName(pNode), FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + // add the root node to the cone (for visualization) + Vec_PtrPush( vCutSmall, pNode ); + // write the DOT file + Io_WriteDotNtk( pNode->pNtk, vInside, vCutSmall, FileNameDot, 0, 0 ); + // stop the cut computation manager + Abc_NtkManCutStop( p ); + + // visualize the file + Abc_ShowFile( FileNameDot ); +} + +/**Function************************************************************* + + Synopsis [Visualizes AIG with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse ) +{ + FILE * pFile; + Abc_Obj_t * pNode; + Vec_Ptr_t * vNodes; + char FileNameDot[200]; + int i; + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + if ( Abc_NtkIsStrash(pNtk) && Abc_NtkGetChoiceNum(pNtk) ) + { + printf( "Temporarily visualization of AIGs with choice nodes is disabled.\n" ); + return; + } + // convert to logic SOP + if ( Abc_NtkIsLogic(pNtk) ) + Abc_NtkToSop( pNtk, 0 ); + // create the file name + Abc_ShowGetFileName( pNtk->pName, FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + fclose( pFile ); + + // collect all nodes in the network + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachObj( pNtk, pNode, i ) + Vec_PtrPush( vNodes, pNode ); + // write the DOT file + if ( fSeq ) + Io_WriteDotSeq( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse ); + else + Io_WriteDotNtk( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse ); + Vec_PtrFree( vNodes ); + + // visualize the file + Abc_ShowFile( FileNameDot ); +} + + +/**Function************************************************************* + + Synopsis [Shows the given DOT file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ShowFile( char * FileNameDot ) +{ + FILE * pFile; + char * FileGeneric; + char FileNamePs[200]; + char CommandDot[1000]; + char * pDotName; + char * pDotNameWin = "dot.exe"; + char * pDotNameUnix = "dot"; + char * pGsNameWin = "gsview32.exe"; + char * pGsNameUnix = "gv"; + int RetValue; + + // get DOT names from the resource file + if ( Abc_FrameReadFlag("dotwin") ) + pDotNameWin = Abc_FrameReadFlag("dotwin"); + if ( Abc_FrameReadFlag("dotunix") ) + pDotNameUnix = Abc_FrameReadFlag("dotunix"); + +#ifdef WIN32 + pDotName = pDotNameWin; +#else + pDotName = pDotNameUnix; +#endif + + // check if the input DOT file is okay + if ( (pFile = fopen( FileNameDot, "r" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + fclose( pFile ); + + // create the PostScript file name + FileGeneric = Extra_FileNameGeneric( FileNameDot ); + sprintf( FileNamePs, "%s.ps", FileGeneric ); + free( FileGeneric ); + + // generate the PostScript file using DOT + sprintf( CommandDot, "%s -Tps -o %s %s", pDotName, FileNamePs, FileNameDot ); + RetValue = system( CommandDot ); + if ( RetValue == -1 ) + { + fprintf( stdout, "Command \"%s\" did not succeed.\n", CommandDot ); + return; + } + // check that the input PostScript file is okay + if ( (pFile = fopen( FileNamePs, "r" )) == NULL ) + { + fprintf( stdout, "Cannot open intermediate file \"%s\".\n", FileNamePs ); + return; + } + fclose( pFile ); + + + // get GSVIEW names from the resource file + if ( Abc_FrameReadFlag("gsviewwin") ) + pGsNameWin = Abc_FrameReadFlag("gsviewwin"); + if ( Abc_FrameReadFlag("gsviewunix") ) + pGsNameUnix = Abc_FrameReadFlag("gsviewunix"); + + // spawn the viewer +#ifdef WIN32 + _unlink( FileNameDot ); + if ( _spawnl( _P_NOWAIT, pGsNameWin, pGsNameWin, FileNamePs, NULL ) == -1 ) + if ( _spawnl( _P_NOWAIT, "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", + "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", FileNamePs, NULL ) == -1 ) + { + fprintf( stdout, "Cannot find \"%s\".\n", pGsNameWin ); + return; + } +#else + { + char CommandPs[1000]; + unlink( FileNameDot ); + sprintf( CommandPs, "%s %s &", pGsNameUnix, FileNamePs ); + if ( system( CommandPs ) == -1 ) + { + fprintf( stdout, "Cannot execute \"%s\".\n", CommandPs ); + return; + } + } +#endif +} + +/**Function************************************************************* + + Synopsis [Derives the DOT file name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ShowGetFileName( char * pName, char * pBuffer ) +{ + char * pCur; + // creat the file name + sprintf( pBuffer, "%s.dot", pName ); + // get rid of not-alpha-numeric characters + for ( pCur = pBuffer; *pCur; pCur++ ) + if ( !((*pCur >= '0' && *pCur <= '9') || (*pCur >= 'a' && *pCur <= 'z') || + (*pCur >= 'A' && *pCur <= 'Z') || (*pCur == '.')) ) + *pCur = '_'; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcSop.c b/abc70930/src/base/abc/abcSop.c new file mode 100644 index 00000000..106901ab --- /dev/null +++ b/abc70930/src/base/abc/abcSop.c @@ -0,0 +1,1075 @@ +/**CFile**************************************************************** + + FileName [abcSop.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Implementation of a simple SOP representation of nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcSop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +/* + The SOPs in this package are represented using char * strings. + For example, the SOP of the node: + + .names c d0 d1 MUX + 01- 1 + 1-1 1 + + is the string: "01- 1\n1-1 1\n" where '\n' is a single char. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Registers the cube string with the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName ) +{ + char * pRegName; + if ( pName == NULL ) return NULL; + pRegName = Extra_MmFlexEntryFetch( pMan, strlen(pName) + 1 ); + strcpy( pRegName, pName ); + return pRegName; +} + +/**Function************************************************************* + + Synopsis [Creates the constant 1 cover with the given number of variables and cubes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopStart( Extra_MmFlex_t * pMan, int nCubes, int nVars ) +{ + char * pSopCover, * pCube; + int i, Length; + + Length = nCubes * (nVars + 3); + pSopCover = Extra_MmFlexEntryFetch( pMan, Length + 1 ); + memset( pSopCover, '-', Length ); + pSopCover[Length] = 0; + + for ( i = 0; i < nCubes; i++ ) + { + pCube = pSopCover + i * (nVars + 3); + pCube[nVars + 0] = ' '; + pCube[nVars + 1] = '1'; + pCube[nVars + 2] = '\n'; + } + return pSopCover; +} + +/**Function************************************************************* + + Synopsis [Creates the constant 1 cover with 0 variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateConst1( Extra_MmFlex_t * pMan ) +{ + return Abc_SopRegister( pMan, " 1\n" ); +} + +/**Function************************************************************* + + Synopsis [Creates the constant 1 cover with 0 variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateConst0( Extra_MmFlex_t * pMan ) +{ + return Abc_SopRegister( pMan, " 0\n" ); +} + +/**Function************************************************************* + + Synopsis [Creates the AND2 cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateAnd2( Extra_MmFlex_t * pMan, int fCompl0, int fCompl1 ) +{ + char Buffer[6]; + Buffer[0] = '1' - fCompl0; + Buffer[1] = '1' - fCompl1; + Buffer[2] = ' '; + Buffer[3] = '1'; + Buffer[4] = '\n'; + Buffer[5] = 0; + return Abc_SopRegister( pMan, Buffer ); +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input AND cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateAnd( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ) +{ + char * pSop; + int i; + pSop = Abc_SopStart( pMan, 1, nVars ); + for ( i = 0; i < nVars; i++ ) + pSop[i] = '1' - (pfCompl? pfCompl[i] : 0); + pSop[nVars + 1] = '1'; + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input NAND cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateNand( Extra_MmFlex_t * pMan, int nVars ) +{ + char * pSop; + int i; + pSop = Abc_SopStart( pMan, 1, nVars ); + for ( i = 0; i < nVars; i++ ) + pSop[i] = '1'; + pSop[nVars + 1] = '0'; + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input OR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateOr( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ) +{ + char * pSop; + int i; + pSop = Abc_SopStart( pMan, 1, nVars ); + for ( i = 0; i < nVars; i++ ) + pSop[i] = '0' + (pfCompl? pfCompl[i] : 0); + pSop[nVars + 1] = '0'; + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input OR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateOrMultiCube( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ) +{ + char * pSop, * pCube; + int i; + pSop = Abc_SopStart( pMan, nVars, nVars ); + i = 0; + Abc_SopForEachCube( pSop, nVars, pCube ) + { + pCube[i] = '1' - (pfCompl? pfCompl[i] : 0); + i++; + } + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input NOR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateNor( Extra_MmFlex_t * pMan, int nVars ) +{ + char * pSop; + int i; + pSop = Abc_SopStart( pMan, 1, nVars ); + for ( i = 0; i < nVars; i++ ) + pSop[i] = '0'; + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input XOR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateXor( Extra_MmFlex_t * pMan, int nVars ) +{ + assert( nVars == 2 ); + return Abc_SopRegister(pMan, "01 1\n10 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input XOR cover (special case).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateXorSpecial( Extra_MmFlex_t * pMan, int nVars ) +{ + char * pSop; + pSop = Abc_SopCreateAnd( pMan, nVars, NULL ); + pSop[nVars+1] = 'x'; + assert( pSop[nVars+2] == '\n' ); + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input XNOR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateNxor( Extra_MmFlex_t * pMan, int nVars ) +{ + assert( nVars == 2 ); + return Abc_SopRegister(pMan, "11 1\n00 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the MUX cover.] + + Description [The first input of MUX is the control. The second input + is DATA1. The third input is DATA0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateMux( Extra_MmFlex_t * pMan ) +{ + return Abc_SopRegister(pMan, "11- 1\n0-1 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the inv cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateInv( Extra_MmFlex_t * pMan ) +{ + return Abc_SopRegister(pMan, "0 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the buf cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateBuf( Extra_MmFlex_t * pMan ) +{ + return Abc_SopRegister(pMan, "1 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the arbitrary cover from the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateFromTruth( Extra_MmFlex_t * pMan, int nVars, unsigned * pTruth ) +{ + char * pSop, * pCube; + int nMints, Counter, i, k; + // count the number of true minterms + Counter = 0; + nMints = (1 << nVars); + for ( i = 0; i < nMints; i++ ) + Counter += ((pTruth[i>>5] & (1 << (i&31))) > 0); + // SOP is not well-defined if the truth table is constant 0 + assert( Counter > 0 ); + if ( Counter == 0 ) + return NULL; + // start the cover + pSop = Abc_SopStart( pMan, Counter, nVars ); + // create true minterms + Counter = 0; + for ( i = 0; i < nMints; i++ ) + if ( (pTruth[i>>5] & (1 << (i&31))) > 0 ) + { + pCube = pSop + Counter * (nVars + 3); + for ( k = 0; k < nVars; k++ ) + pCube[k] = '0' + ((i & (1 << k)) > 0); + Counter++; + } + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the cover from the ISOP computed from TT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateFromIsop( Extra_MmFlex_t * pMan, int nVars, Vec_Int_t * vCover ) +{ + char * pSop, * pCube; + int i, k, Entry, Literal; + assert( Vec_IntSize(vCover) > 0 ); + if ( Vec_IntSize(vCover) == 0 ) + return NULL; + // start the cover + pSop = Abc_SopStart( pMan, Vec_IntSize(vCover), nVars ); + // create cubes + Vec_IntForEachEntry( vCover, Entry, i ) + { + pCube = pSop + i * (nVars + 3); + for ( k = 0; k < nVars; k++ ) + { + Literal = 3 & (Entry >> (k << 1)); + if ( Literal == 1 ) + pCube[k] = '0'; + else if ( Literal == 2 ) + pCube[k] = '1'; + else if ( Literal != 0 ) + assert( 0 ); + } + } + return pSop; +} + +/**Function************************************************************* + + Synopsis [Reads the number of cubes in the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetCubeNum( char * pSop ) +{ + char * pCur; + int nCubes = 0; + if ( pSop == NULL ) + return 0; + for ( pCur = pSop; *pCur; pCur++ ) + nCubes += (*pCur == '\n'); + return nCubes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of SOP literals in the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetLitNum( char * pSop ) +{ + char * pCur; + int nLits = 0; + if ( pSop == NULL ) + return 0; + for ( pCur = pSop; *pCur; pCur++ ) + { + nLits -= (*pCur == '\n'); + nLits += (*pCur == '0' || *pCur == '1'); + } + return nLits; +} + +/**Function************************************************************* + + Synopsis [Reads the number of variables in the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetVarNum( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur != '\n'; pCur++ ); + return pCur - pSop - 2; +} + +/**Function************************************************************* + + Synopsis [Reads the phase of the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetPhase( char * pSop ) +{ + int nVars = Abc_SopGetVarNum( pSop ); + if ( pSop[nVars+1] == '0' || pSop[nVars+1] == 'n' ) + return 0; + if ( pSop[nVars+1] == '1' || pSop[nVars+1] == 'x' ) + return 1; + assert( 0 ); + return -1; +} + +/**Function************************************************************* + + Synopsis [Returns the i-th literal of the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetIthCareLit( char * pSop, int i ) +{ + char * pCube; + int nVars; + nVars = Abc_SopGetVarNum( pSop ); + Abc_SopForEachCube( pSop, nVars, pCube ) + if ( pCube[i] != '-' ) + return pCube[i] - '0'; + return -1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SopComplement( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur; pCur++ ) + if ( *pCur == '\n' ) + { + if ( *(pCur - 1) == '0' ) + *(pCur - 1) = '1'; + else if ( *(pCur - 1) == '1' ) + *(pCur - 1) = '0'; + else if ( *(pCur - 1) == 'x' ) + *(pCur - 1) = 'n'; + else if ( *(pCur - 1) == 'n' ) + *(pCur - 1) = 'x'; + else + assert( 0 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsComplement( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur; pCur++ ) + if ( *pCur == '\n' ) + return (int)(*(pCur - 1) == '0' || *(pCur - 1) == 'n'); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsConst0( char * pSop ) +{ + return pSop[0] == ' ' && pSop[1] == '0'; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsConst1( char * pSop ) +{ + return pSop[0] == ' ' && pSop[1] == '1'; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsBuf( char * pSop ) +{ + if ( pSop[4] != 0 ) + return 0; + if ( (pSop[0] == '1' && pSop[2] == '1') || (pSop[0] == '0' && pSop[2] == '0') ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsInv( char * pSop ) +{ + if ( pSop[4] != 0 ) + return 0; + if ( (pSop[0] == '0' && pSop[2] == '1') || (pSop[0] == '1' && pSop[2] == '0') ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is AND with possibly complemented inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsAndType( char * pSop ) +{ + char * pCur; + if ( Abc_SopGetCubeNum(pSop) != 1 ) + return 0; + for ( pCur = pSop; *pCur != ' '; pCur++ ) + if ( *pCur == '-' ) + return 0; + if ( pCur[1] != '1' ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is OR with possibly complemented inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsOrType( char * pSop ) +{ + char * pCube, * pCur; + int nVars, nLits; + nVars = Abc_SopGetVarNum( pSop ); + if ( nVars != Abc_SopGetCubeNum(pSop) ) + return 0; + Abc_SopForEachCube( pSop, nVars, pCube ) + { + // count the number of literals in the cube + nLits = 0; + for ( pCur = pCube; *pCur != ' '; pCur++ ) + nLits += ( *pCur != '-' ); + if ( nLits != 1 ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopIsExorType( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur; pCur++ ) + if ( *pCur == '\n' ) + return (int)(*(pCur - 1) == 'x' || *(pCur - 1) == 'n'); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopCheck( char * pSop, int nFanins ) +{ + char * pCubes, * pCubesOld; + int fFound0 = 0, fFound1 = 0; + + // check the logic function of the node + for ( pCubes = pSop; *pCubes; pCubes++ ) + { + // get the end of the next cube + for ( pCubesOld = pCubes; *pCubes != ' '; pCubes++ ); + // compare the distance + if ( pCubes - pCubesOld != nFanins ) + { + fprintf( stdout, "Abc_SopCheck: SOP has a mismatch between its cover size (%d) and its fanin number (%d).\n", + pCubes - pCubesOld, nFanins ); + return 0; + } + // check the output values for this cube + pCubes++; + if ( *pCubes == '0' ) + fFound0 = 1; + else if ( *pCubes == '1' ) + fFound1 = 1; + else if ( *pCubes != 'x' && *pCubes != 'n' ) + { + fprintf( stdout, "Abc_SopCheck: SOP has a strange character (%c) in the output part of its cube.\n", *pCubes ); + return 0; + } + // check the last symbol (new line) + pCubes++; + if ( *pCubes != '\n' ) + { + fprintf( stdout, "Abc_SopCheck: SOP has a cube without new line in the end.\n" ); + return 0; + } + } + if ( fFound0 && fFound1 ) + { + fprintf( stdout, "Abc_SopCheck: SOP has cubes in both phases.\n" ); + return 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Derives SOP from the truth table representation.] + + Description [Truth table is expected to be in the hexadecimal notation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopFromTruthBin( char * pTruth ) +{ + char * pSopCover, * pCube; + int nTruthSize, nVars, Digit, Length, Mint, i, b; + Vec_Int_t * vMints; + + // get the number of variables + nTruthSize = strlen(pTruth); + nVars = Extra_Base2Log( nTruthSize ); + if ( nTruthSize != (1 << (nVars)) ) + { + printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars ); + return NULL; + } + + // collect the on-set minterms + vMints = Vec_IntAlloc( 100 ); + for ( i = 0; i < nTruthSize; i++ ) + { + if ( pTruth[i] >= '0' && pTruth[i] <= '1' ) + Digit = pTruth[i] - '0'; + else + { + printf( "String %s does not look like a binary representation of the truth table.\n", pTruth ); + return NULL; + } + if ( Digit == 1 ) + Vec_IntPush( vMints, nTruthSize - 1 - i ); + } + if ( Vec_IntSize( vMints ) == 0 || Vec_IntSize( vMints ) == nTruthSize ) + { + Vec_IntFree( vMints ); + printf( "Cannot create constant function.\n" ); + return NULL; + } + + // create the SOP representation of the minterms + Length = Vec_IntSize(vMints) * (nVars + 3); + pSopCover = ALLOC( char, Length + 1 ); + pSopCover[Length] = 0; + Vec_IntForEachEntry( vMints, Mint, i ) + { + pCube = pSopCover + i * (nVars + 3); + for ( b = 0; b < nVars; b++ ) + if ( Mint & (1 << (nVars-1-b)) ) +// if ( Mint & (1 << b) ) + pCube[b] = '1'; + else + pCube[b] = '0'; + pCube[nVars + 0] = ' '; + pCube[nVars + 1] = '1'; + pCube[nVars + 2] = '\n'; + } + Vec_IntFree( vMints ); + return pSopCover; +} + +/**Function************************************************************* + + Synopsis [Derives SOP from the truth table representation.] + + Description [Truth table is expected to be in the hexadecimal notation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopFromTruthHex( char * pTruth ) +{ + char * pSopCover, * pCube; + int nTruthSize, nVars, Digit, Length, Mint, i, b; + Vec_Int_t * vMints; + + // get the number of variables + nTruthSize = strlen(pTruth); + nVars = Extra_Base2Log( nTruthSize ) + 2; + if ( nTruthSize != (1 << (nVars-2)) ) + { + printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars ); + return NULL; + } + + // collect the on-set minterms + vMints = Vec_IntAlloc( 100 ); + for ( i = 0; i < nTruthSize; i++ ) + { + if ( pTruth[i] >= '0' && pTruth[i] <= '9' ) + Digit = pTruth[i] - '0'; + else if ( pTruth[i] >= 'a' && pTruth[i] <= 'f' ) + Digit = 10 + pTruth[i] - 'a'; + else if ( pTruth[i] >= 'A' && pTruth[i] <= 'F' ) + Digit = 10 + pTruth[i] - 'A'; + else + { + printf( "String %s does not look like a hexadecimal representation of the truth table.\n", pTruth ); + return NULL; + } + for ( b = 0; b < 4; b++ ) + if ( Digit & (1 << b) ) + Vec_IntPush( vMints, 4*(nTruthSize-1-i)+b ); + } + + // create the SOP representation of the minterms + Length = Vec_IntSize(vMints) * (nVars + 3); + pSopCover = ALLOC( char, Length + 1 ); + pSopCover[Length] = 0; + Vec_IntForEachEntry( vMints, Mint, i ) + { + pCube = pSopCover + i * (nVars + 3); + for ( b = 0; b < nVars; b++ ) +// if ( Mint & (1 << (nVars-1-b)) ) + if ( Mint & (1 << b) ) + pCube[b] = '1'; + else + pCube[b] = '0'; + pCube[nVars + 0] = ' '; + pCube[nVars + 1] = '1'; + pCube[nVars + 2] = '\n'; + } + Vec_IntFree( vMints ); + return pSopCover; +} + +/**Function************************************************************* + + Synopsis [Creates one encoder node.] + + Description [Produces MV-SOP for BLIF-MV representation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopEncoderPos( Extra_MmFlex_t * pMan, int iValue, int nValues ) +{ + char Buffer[32]; + assert( iValue < nValues ); + sprintf( Buffer, "d0\n%d 1\n", iValue ); + return Abc_SopRegister( pMan, Buffer ); +} + +/**Function************************************************************* + + Synopsis [Creates one encoder node.] + + Description [Produces MV-SOP for BLIF-MV representation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopEncoderLog( Extra_MmFlex_t * pMan, int iBit, int nValues ) +{ + char * pResult; + Vec_Str_t * vSop; + int v, Counter, fFirst = 1, nBits = Extra_Base2Log(nValues); + assert( iBit < nBits ); + // count the number of literals + Counter = 0; + for ( v = 0; v < nValues; v++ ) + Counter += ( (v & (1 << iBit)) > 0 ); + // create the cover + vSop = Vec_StrAlloc( 100 ); + Vec_StrPrintStr( vSop, "d0\n" ); + if ( Counter > 1 ) + Vec_StrPrintStr( vSop, "(" ); + for ( v = 0; v < nValues; v++ ) + if ( v & (1 << iBit) ) + { + if ( fFirst ) + fFirst = 0; + else + Vec_StrPush( vSop, ',' ); + Vec_StrPrintNum( vSop, v ); + } + if ( Counter > 1 ) + Vec_StrPrintStr( vSop, ")" ); + Vec_StrPrintStr( vSop, " 1\n" ); + Vec_StrPush( vSop, 0 ); + pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); + Vec_StrFree( vSop ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Creates the decoder node.] + + Description [Produces MV-SOP for BLIF-MV representation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopDecoderPos( Extra_MmFlex_t * pMan, int nValues ) +{ + char * pResult; + Vec_Str_t * vSop; + int i, k; + assert( nValues > 1 ); + vSop = Vec_StrAlloc( 100 ); + for ( i = 0; i < nValues; i++ ) + { + for ( k = 0; k < nValues; k++ ) + { + if ( k == i ) + Vec_StrPrintStr( vSop, "1 " ); + else + Vec_StrPrintStr( vSop, "- " ); + } + Vec_StrPrintNum( vSop, i ); + Vec_StrPush( vSop, '\n' ); + } + Vec_StrPush( vSop, 0 ); + pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); + Vec_StrFree( vSop ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Creates the decover node.] + + Description [Produces MV-SOP for BLIF-MV representation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopDecoderLog( Extra_MmFlex_t * pMan, int nValues ) +{ + char * pResult; + Vec_Str_t * vSop; + int i, b, nBits = Extra_Base2Log(nValues); + assert( nValues > 1 && nValues <= (1<<nBits) ); + vSop = Vec_StrAlloc( 100 ); + for ( i = 0; i < nValues; i++ ) + { + for ( b = 0; b < nBits; b++ ) + { + Vec_StrPrintNum( vSop, (int)((i & (1 << b)) > 0) ); + Vec_StrPush( vSop, ' ' ); + } + Vec_StrPrintNum( vSop, i ); + Vec_StrPush( vSop, '\n' ); + } + Vec_StrPush( vSop, 0 ); + pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); + Vec_StrFree( vSop ); + return pResult; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcUtil.c b/abc70930/src/base/abc/abcUtil.c new file mode 100644 index 00000000..b4a97223 --- /dev/null +++ b/abc70930/src/base/abc/abcUtil.c @@ -0,0 +1,1764 @@ +/**CFile**************************************************************** + + FileName [abcUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +#include "mio.h" +#include "dec.h" +//#include "seq.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Frees one attribute manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan ) +{ + void * pUserMan; + Vec_Att_t * pAttrMan; + pAttrMan = Vec_PtrEntry( pNtk->vAttrs, Attr ); + Vec_PtrWriteEntry( pNtk->vAttrs, Attr, NULL ); + pUserMan = Vec_AttFree( pAttrMan, fFreeMan ); + return pUserMan; +} + +/**Function************************************************************* + + Synopsis [Increments the current traversal ID of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + if ( pNtk->nTravIds >= (1<<30)-1 ) + { + pNtk->nTravIds = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->TravId = 0; + } + pNtk->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Order CI/COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pTerm; + int i, k; + Vec_PtrClear( pNtk->vCis ); + Vec_PtrClear( pNtk->vCos ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Vec_PtrPush( pNtk->vCis, pObj ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Vec_PtrPush( pNtk->vCos, pObj ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Vec_PtrPush( pNtk->vCos, pObj ); + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + Abc_ObjForEachFanin( pObj, pTerm, k ) + Vec_PtrPush( pNtk->vCos, pTerm ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Vec_PtrPush( pNtk->vCis, pTerm ); + } + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( !Abc_ObjIsLatch(pObj) ) + continue; + Abc_ObjForEachFanin( pObj, pTerm, k ) + Vec_PtrPush( pNtk->vCos, pTerm ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Vec_PtrPush( pNtk->vCis, pTerm ); + } +} + +/**Function************************************************************* + + Synopsis [Reads the number of cubes of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nCubes = 0; + assert( Abc_NtkHasSop(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsConst(pNode) ) + continue; + assert( pNode->pData ); + nCubes += Abc_SopGetCubeNum( pNode->pData ); + } + return nCubes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of cubes of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nCubes, nCubePairs = 0; + assert( Abc_NtkHasSop(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsConst(pNode) ) + continue; + assert( pNode->pData ); + nCubes = Abc_SopGetCubeNum( pNode->pData ); + nCubePairs += nCubes * (nCubes - 1) / 2; + } + return nCubePairs; +} + +/**Function************************************************************* + + Synopsis [Reads the number of literals in the SOPs of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetLitNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nLits = 0; + assert( Abc_NtkHasSop(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + nLits += Abc_SopGetLitNum( pNode->pData ); + } + return nLits; +} + +/**Function************************************************************* + + Synopsis [Counts the number of literals in the factored forms.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetLitFactNum( Abc_Ntk_t * pNtk ) +{ + Dec_Graph_t * pFactor; + Abc_Obj_t * pNode; + int nNodes, i; + assert( Abc_NtkHasSop(pNtk) ); + nNodes = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsConst(pNode) ) + continue; + pFactor = Dec_Factor( pNode->pData ); + nNodes += 1 + Dec_GraphNodeNum(pFactor); + Dec_GraphFree( pFactor ); + } + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of BDD nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nNodes = 0; + assert( Abc_NtkIsBddLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + if ( Abc_ObjFaninNum(pNode) < 2 ) + continue; + nNodes += pNode->pData? -1 + Cudd_DagSize( pNode->pData ) : 0; + } + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of BDD nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nNodes = 0; + assert( Abc_NtkIsAigLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + if ( Abc_ObjFaninNum(pNode) < 2 ) + continue; +//printf( "%d ", Hop_DagSize( pNode->pData ) ); + nNodes += pNode->pData? Hop_DagSize( pNode->pData ) : 0; + } + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of BDD nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + DdNode * bCover, * zCover, * bFunc; + DdManager * dd = pNtk->pManFunc; + int i, nClauses = 0; + assert( Abc_NtkIsBddLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + bFunc = pNode->pData; + + bCover = Cudd_zddIsop( dd, bFunc, bFunc, &zCover ); + Cudd_Ref( bCover ); + Cudd_Ref( zCover ); + nClauses += Abc_CountZddCubes( dd, zCover ); + Cudd_RecursiveDeref( dd, bCover ); + Cudd_RecursiveDerefZdd( dd, zCover ); + + bCover = Cudd_zddIsop( dd, Cudd_Not(bFunc), Cudd_Not(bFunc), &zCover ); + Cudd_Ref( bCover ); + Cudd_Ref( zCover ); + nClauses += Abc_CountZddCubes( dd, zCover ); + Cudd_RecursiveDeref( dd, bCover ); + Cudd_RecursiveDerefZdd( dd, zCover ); + } + return nClauses; +} + +/**Function************************************************************* + + Synopsis [Computes the area of the mapped circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + double TotalArea; + int i; + assert( Abc_NtkHasMapping(pNtk) ); + TotalArea = 0.0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { +// assert( pNode->pData ); + if ( pNode->pData == NULL ) + { + printf( "Node without mapping is encountered.\n" ); + continue; + } + TotalArea += Mio_GateReadArea( pNode->pData ); + } + return TotalArea; +} + +/**Function************************************************************* + + Synopsis [Counts the number of exors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += pNode->fExor; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of exors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_NodeIsMuxType(pNode); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if it is an AIG with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter; + if ( !Abc_NtkIsStrash(pNtk) ) + return 0; + Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_AigNodeIsChoice( pNode ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Reads the maximum number of fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nFaninsMax = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( nFaninsMax < Abc_ObjFaninNum(pNode) ) + nFaninsMax = Abc_ObjFaninNum(pNode); + } + return nFaninsMax; +} + +/**Function************************************************************* + + Synopsis [Reads the total number of all fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nFanins = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + nFanins += Abc_ObjFaninNum(pNode); + return nFanins; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pCopy = NULL; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanData( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanEquiv( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pEquiv = NULL; +} + +/**Function************************************************************* + + Synopsis [Counts the number of nodes having non-trivial copies.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountCopy( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i, Counter = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( Abc_ObjIsNode(pObj) ) + Counter += (pObj->pCopy != NULL); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Saves copy field of the objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vCopies; + Abc_Obj_t * pObj; + int i; + vCopies = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachObj( pNtk, pObj, i ) + Vec_PtrWriteEntry( vCopies, i, pObj->pCopy ); + return vCopies; +} + +/**Function************************************************************* + + Synopsis [Loads copy field of the objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pCopy = Vec_PtrEntry( vCopies, i ); +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanNext( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pNext = NULL; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the internal node has CO fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i; + Abc_ObjForEachFanout( pNode, pFanout, i ) + if ( Abc_ObjIsCo(pFanout) ) + return pFanout; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Checks if the internal node has CO fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i; + Abc_ObjForEachFanout( pNode, pFanout, i ) + if ( !Abc_ObjIsCo(pFanout) ) + return pFanout; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Checks if the internal node has CO drivers with the same name.] + + Description [Checks if the internal node can borrow its name from CO fanouts. + This is possible if all COs with non-complemented fanin edge pointing to this + node have the same name.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout, * pFanoutCo; + int i; + pFanoutCo = NULL; + Abc_ObjForEachFanout( pNode, pFanout, i ) + { + if ( !Abc_ObjIsCo(pFanout) ) + continue; + if ( Abc_ObjFaninC0(pFanout) ) + continue; + if ( pFanoutCo == NULL ) + { + assert( Abc_ObjFaninNum(pFanout) == 1 ); + assert( Abc_ObjFanin0(pFanout) == pNode ); + pFanoutCo = pFanout; + continue; + } + if ( strcmp( Abc_ObjName(pFanoutCo), Abc_ObjName(pFanout) ) ) // they have diff names + return NULL; + } + return pFanoutCo; +} + +/**Function************************************************************* + + Synopsis [Fixes the CO driver problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFixCoDriverProblem( Abc_Obj_t * pDriver, Abc_Obj_t * pNodeCo, int fDuplicate ) +{ + Abc_Ntk_t * pNtk = pDriver->pNtk; + Abc_Obj_t * pDriverNew, * pFanin; + int k; + if ( fDuplicate && !Abc_ObjIsCi(pDriver) ) + { + pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 ); + Abc_ObjForEachFanin( pDriver, pFanin, k ) + Abc_ObjAddFanin( pDriverNew, pFanin ); + if ( Abc_ObjFaninC0(pNodeCo) ) + { + // change polarity of the duplicated driver + Abc_NodeComplement( pDriverNew ); + Abc_ObjXorFaninC( pNodeCo, 0 ); + } + } + else + { + // add inverters and buffers when necessary + if ( Abc_ObjFaninC0(pNodeCo) ) + { + pDriverNew = Abc_NtkCreateNodeInv( pNtk, pDriver ); + Abc_ObjXorFaninC( pNodeCo, 0 ); + } + else + pDriverNew = Abc_NtkCreateNodeBuf( pNtk, pDriver ); + } + // update the fanin of the PO node + Abc_ObjPatchFanin( pNodeCo, pDriver, pDriverNew ); + assert( Abc_ObjFanoutNum(pDriverNew) == 1 ); + // remove the old driver if it dangles + // (this happens when the duplicated driver had only one complemented fanout) + if ( Abc_ObjFanoutNum(pDriver) == 0 ) + Abc_NtkDeleteObj( pDriver ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if COs of a logic network are simple.] + + Description [The COs of a logic network are simple under three conditions: + (1) The edge from CO to its driver is not complemented. + (2) If CI is a driver of a CO, they have the same name.] + (3) If two COs share the same driver, they have the same name.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pDriver; + int i; + assert( Abc_NtkIsLogic(pNtk) ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + // if the driver is complemented, this is an error + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_ObjFaninC0(pNode) ) + return 0; + // if the driver is a CI and has different name, this is an error + if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) ) + return 0; + // if the driver is visited for the first time, remember the CO name + if ( !Abc_NodeIsTravIdCurrent(pDriver) ) + { + pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode); + Abc_NodeSetTravIdCurrent(pDriver); + continue; + } + // the driver has second CO - if they have different name, this is an error + if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Transforms the network to have simple COs.] + + Description [The COs of a logic network are simple under three conditions: + (1) The edge from CO to its driver is not complemented. + (2) If CI is a driver of a CO, they have the same name.] + (3) If two COs share the same driver, they have the same name. + In some cases, such as FPGA mapping, we prevent the increase in delay + by duplicating the driver nodes, rather than adding invs/bufs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, bool fDuplicate ) +{ + Abc_Obj_t * pNode, * pDriver; + int i, nDupGates = 0; + assert( Abc_NtkIsLogic(pNtk) ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + // if the driver is complemented, this is an error + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_ObjFaninC0(pNode) ) + { + Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); + nDupGates++; + continue; + } + // if the driver is a CI and has different name, this is an error + if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) ) + { + Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); + nDupGates++; + continue; + } + // if the driver is visited for the first time, remember the CO name + if ( !Abc_NodeIsTravIdCurrent(pDriver) ) + { + pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode); + Abc_NodeSetTravIdCurrent(pDriver); + continue; + } + // the driver has second CO - if they have different name, this is an error + if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names + { + Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); + nDupGates++; + continue; + } + } + assert( Abc_NtkLogicHasSimpleCos(pNtk) ); + return nDupGates; +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode1, * pNode2; + int i; + if ( Vec_PtrPushUnique(p, pNode) ) + return; + // find the p of the node + for ( i = p->nSize-1; i > 0; i-- ) + { + pNode1 = p->pArray[i ]; + pNode2 = p->pArray[i-1]; + if ( Abc_ObjRegular(pNode1)->Level <= Abc_ObjRegular(pNode2)->Level ) + break; + p->pArray[i ] = pNode2; + p->pArray[i-1] = pNode1; + } +} + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsExorType( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Abc_ObjIsComplement(pNode) ); + // if the node is not AND, this is not EXOR + if ( !Abc_AigNodeIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not EXOR + if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + // if the children are not ANDs, this is not EXOR + if ( Abc_ObjFaninNum(pNode0) != 2 || Abc_ObjFaninNum(pNode1) != 2 ) + return 0; + // otherwise, the node is EXOR iff its grand-children are the same + return (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) || Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1)) && + (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) || Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1)); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsMuxType( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Abc_ObjIsComplement(pNode) ); + // if the node is not AND, this is not MUX + if ( !Abc_AigNodeIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not MUX + if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + // if the children are not ANDs, this is not MUX + if ( Abc_ObjFaninNum(pNode0) != 2 || Abc_ObjFaninNum(pNode1) != 2 ) + return 0; + // otherwise the node is MUX iff it has a pair of equal grandchildren + return (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC0(pNode1))) || + (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC1(pNode1))) || + (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC0(pNode1))) || + (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC1(pNode1))); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the control type of the MUX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsMuxControlType( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Abc_ObjIsComplement(pNode) ); + // skip the node that do not have two fanouts + if ( Abc_ObjFanoutNum(pNode) != 2 ) + return 0; + // get the fanouts + pNode0 = Abc_ObjFanout( pNode, 0 ); + pNode1 = Abc_ObjFanout( pNode, 1 ); + // if they have more than one fanout, we are not interested + if ( Abc_ObjFanoutNum(pNode0) != 1 || Abc_ObjFanoutNum(pNode1) != 1 ) + return 0; + // if the fanouts have the same fanout, this is MUX or EXOR (or a redundant gate (CA)(CB)) + return Abc_ObjFanout0(pNode0) == Abc_ObjFanout0(pNode1); +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE ) +{ + Abc_Obj_t * pNode0, * pNode1; + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_NodeIsMuxType(pNode) ); + // get children + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + // find the control variable +// if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) + if ( Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Abc_ObjFaninC0(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); + return Abc_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); + return Abc_ObjChild0(pNode0);//pNode1->p1; + } + } +// else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) + else if ( Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Abc_ObjFaninC0(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); + return Abc_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); + return Abc_ObjChild0(pNode0);//pNode1->p1; + } + } +// else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) + else if ( Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Abc_ObjFaninC1(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); + return Abc_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); + return Abc_ObjChild1(pNode0);//pNode1->p2; + } + } +// else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) + else if ( Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Abc_ObjFaninC1(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); + return Abc_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); + return Abc_ObjChild1(pNode0);//pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + +/**Function************************************************************* + + Synopsis [Prepares two network for a two-argument command similar to "verify".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, + Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2 ) +{ + int fCheck = 1; + FILE * pFile; + Abc_Ntk_t * pNtk1, * pNtk2; + int util_optind = 0; + + *pfDelete1 = 0; + *pfDelete2 = 0; + if ( argc == util_optind ) + { // use the spec + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty current network.\n" ); + return 0; + } + if ( pNtk->pSpec == NULL ) + { + fprintf( pErr, "The external spec is not given.\n" ); + return 0; + } + pFile = fopen( pNtk->pSpec, "r" ); + if ( pFile == NULL ) + { + fprintf( pErr, "Cannot open the external spec file \"%s\".\n", pNtk->pSpec ); + return 0; + } + else + fclose( pFile ); + pNtk1 = pNtk; + pNtk2 = Io_Read( pNtk->pSpec, Io_ReadFileType(pNtk->pSpec), fCheck ); + if ( pNtk2 == NULL ) + return 0; + *pfDelete2 = 1; + } + else if ( argc == util_optind + 1 ) + { + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty current network.\n" ); + return 0; + } + pNtk1 = pNtk; + pNtk2 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck ); + if ( pNtk2 == NULL ) + return 0; + *pfDelete2 = 1; + } + else if ( argc == util_optind + 2 ) + { + pNtk1 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck ); + if ( pNtk1 == NULL ) + return 0; + pNtk2 = Io_Read( argv[util_optind+1], Io_ReadFileType(argv[util_optind+1]), fCheck ); + if ( pNtk2 == NULL ) + { + Abc_NtkDelete( pNtk1 ); + return 0; + } + *pfDelete1 = 1; + *pfDelete2 = 1; + } + else + { + fprintf( pErr, "Wrong number of arguments.\n" ); + return 0; + } + *ppNtk1 = pNtk1; + *ppNtk2 = pNtk2; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if it is an AIG with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + Vec_PtrClear(vNodes); + Abc_ObjForEachFanin( pNode, pFanin, i ) + Vec_PtrPush( vNodes, pFanin ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if it is an AIG with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + int i; + Vec_PtrClear(vNodes); + Abc_ObjForEachFanout( pNode, pFanout, i ) + Vec_PtrPush( vNodes, pFanout ); +} + +/**Function************************************************************* + + Synopsis [Collects all latches in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkCollectLatches( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vLatches; + Abc_Obj_t * pObj; + int i; + vLatches = Vec_PtrAlloc( 10 ); + Abc_NtkForEachObj( pNtk, pObj, i ) + Vec_PtrPush( vLatches, pObj ); + return vLatches; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in increasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareLevelsIncrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) +{ + int Diff = Abc_ObjRegular(*pp1)->Level - Abc_ObjRegular(*pp2)->Level; + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareLevelsDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) +{ + int Diff = Abc_ObjRegular(*pp1)->Level - Abc_ObjRegular(*pp2)->Level; + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Creates the array of fanout counters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vFanNums; + Abc_Obj_t * pObj; + int i; + vFanNums = Vec_IntAlloc( 0 ); + Vec_IntFill( vFanNums, Abc_NtkObjNumMax(pNtk), -1 ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) ) + Vec_IntWriteEntry( vFanNums, i, Abc_ObjFanoutNum(pObj) ); + return vFanNums; +} + +/**Function************************************************************* + + Synopsis [Collects all objects into one array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachObj( pNtk, pNode, i ) + Vec_PtrPush( vNodes, pNode ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the array of CI IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkGetCiIds( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vCiIds; + Abc_Obj_t * pObj; + int i; + vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Vec_IntPush( vCiIds, pObj->Id ); + return vCiIds; +} + +/**Function************************************************************* + + Synopsis [Puts the nodes into the DFS order and reassign their IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkReassignIds( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Vec_Ptr_t * vObjsNew; + Abc_Obj_t * pNode, * pTemp, * pConst1; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); +//printf( "Total = %d. Current = %d.\n", Abc_NtkObjNumMax(pNtk), Abc_NtkObjNum(pNtk) ); + // start the array of objects with new IDs + vObjsNew = Vec_PtrAlloc( pNtk->nObjs ); + // put constant node first + pConst1 = Abc_AigConst1(pNtk); + assert( pConst1->Id == 0 ); + Vec_PtrPush( vObjsNew, pConst1 ); + // put PI nodes next + Abc_NtkForEachPi( pNtk, pNode, i ) + { + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + } + // put PO nodes next + Abc_NtkForEachPo( pNtk, pNode, i ) + { + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + } + // put assert nodes next + Abc_NtkForEachAssert( pNtk, pNode, i ) + { + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + } + // put latches and their inputs/outputs next + Abc_NtkForEachBox( pNtk, pNode, i ) + { + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + Abc_ObjForEachFanin( pNode, pTemp, k ) + { + pTemp->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pTemp ); + } + Abc_ObjForEachFanout( pNode, pTemp, k ) + { + pTemp->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pTemp ); + } + } + // finally, internal nodes in the DFS order + vNodes = Abc_AigDfs( pNtk, 1, 0 ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( pNode == pConst1 ) + continue; + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + } + Vec_PtrFree( vNodes ); + assert( Vec_PtrSize(vObjsNew) == pNtk->nObjs ); + + // update the fanin/fanout arrays + Abc_NtkForEachObj( pNtk, pNode, i ) + { + Abc_ObjForEachFanin( pNode, pTemp, k ) + pNode->vFanins.pArray[k] = pTemp->Id; + Abc_ObjForEachFanout( pNode, pTemp, k ) + pNode->vFanouts.pArray[k] = pTemp->Id; + } + + // replace the array of objs + Vec_PtrFree( pNtk->vObjs ); + pNtk->vObjs = vObjsNew; + + // rehash the AIG + Abc_AigRehash( pNtk->pManFunc ); + + // update the name manager!!! +} + +/**Function************************************************************* + + Synopsis [Detect cases when non-trivial FF matching is possible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDetectMatching( Abc_Ntk_t * pNtk ) +{ +/* + Abc_Obj_t * pLatch, * pFanin; + int i, nTFFs, nJKFFs; + nTFFs = nJKFFs = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + pFanin = Abc_ObjFanin0(pLatch); + if ( Abc_ObjFaninNum(pFanin) != 2 ) + continue; + if ( Abc_NodeIsExorType(pLatch) ) + { + if ( Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch || + Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch ) + nTFFs++; + } + if ( Abc_ObjFaninNum( Abc_ObjFanin0(pFanin) ) != 2 || + Abc_ObjFaninNum( Abc_ObjFanin1(pFanin) ) != 2 ) + continue; + + if ( (Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch || + Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch) && + (Abc_ObjFanin0(Abc_ObjFanin1(pFanin)) == pLatch || + Abc_ObjFanin1(Abc_ObjFanin1(pFanin)) == pLatch) ) + { + nJKFFs++; + } + } + printf( "D = %6d. T = %6d. JK = %6d. (%6.2f %%)\n", + Abc_NtkLatchNum(pNtk), nTFFs, nJKFFs, 100.0 * nJKFFs / Abc_NtkLatchNum(pNtk) ); +*/ +} + + +/**Function************************************************************* + + Synopsis [Compares the pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjPointerCompare( void ** pp1, void ** pp2 ) +{ + if ( *pp1 < *pp2 ) + return -1; + if ( *pp1 > *pp2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Adjusts the copy pointers.] + + Description [This procedure assumes that the network was transformed + into another network, which was in turn transformed into yet another + network. It makes the pCopy pointers of the original network point to + the objects of the yet another network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsNet(pObj) ) + pObj->pCopy = pObj->pCopy? Abc_ObjCopyCond(pObj->pCopy) : NULL; +} + + +/**Function************************************************************* + + Synopsis [Increaments the cut counter.] + + Description [Returns 1 if it becomes equal to the ref counter.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_ObjCrossCutInc( Abc_Obj_t * pObj ) +{ +// pObj->pCopy = (void *)(((int)pObj->pCopy)++); + int Value = (int)pObj->pCopy; + pObj->pCopy = (void *)(Value + 1); + return (int)pObj->pCopy == Abc_ObjFanoutNum(pObj); +} + +/**Function************************************************************* + + Synopsis [Computes cross-cut of the circuit.] + + Description [Returns 1 if it is the last visit to the node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCrossCut_rec( Abc_Obj_t * pObj, int * pnCutSize, int * pnCutSizeMax ) +{ + Abc_Obj_t * pFanin; + int i, nDecrem = 0; + int fReverse = 0; + if ( Abc_ObjIsCi(pObj) ) + return 0; + // if visited, increment visit counter + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return Abc_ObjCrossCutInc( pObj ); + Abc_NodeSetTravIdCurrent( pObj ); + // visit the fanins + if ( !Abc_ObjIsCi(pObj) ) + { + if ( fReverse ) + { + Abc_ObjForEachFanin( pObj, pFanin, i ) + { + pFanin = Abc_ObjFanin( pObj, Abc_ObjFaninNum(pObj) - 1 - i ); + nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax ); + } + } + else + { + Abc_ObjForEachFanin( pObj, pFanin, i ) + nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax ); + } + } + // count the node + (*pnCutSize)++; + if ( *pnCutSizeMax < *pnCutSize ) + *pnCutSizeMax = *pnCutSize; + (*pnCutSize) -= nDecrem; + return Abc_ObjCrossCutInc( pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes cross-cut of the circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCrossCut( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int nCutSize = 0, nCutSizeMax = 0; + int i; + Abc_NtkCleanCopy( pNtk ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_NtkCrossCut_rec( pObj, &nCutSize, &nCutSizeMax ); + nCutSize--; + } + assert( nCutSize == 0 ); + printf( "Max cross cut size = %6d. Ratio = %6.2f %%\n", nCutSizeMax, 100.0 * nCutSizeMax/Abc_NtkObjNum(pNtk) ); + return nCutSizeMax; +} + + +/**Function************************************************************* + + Synopsis [Prints all 3-var functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrint256() +{ + FILE * pFile; + unsigned i; + pFile = fopen( "4varfs.txt", "w" ); + for ( i = 1; i < (1<<16)-1; i++ ) + { + fprintf( pFile, "read_truth " ); + Extra_PrintBinary( pFile, &i, 16 ); + fprintf( pFile, "; clp; st; w 1.blif; map; cec 1.blif\n" ); + } + fclose( pFile ); +} + + +static int * pSupps; + +/**Function************************************************************* + + Synopsis [Compares the supergates by their level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCompareConesCompare( int * pNum1, int * pNum2 ) +{ + if ( pSupps[*pNum1] > pSupps[*pNum2] ) + return -1; + if ( pSupps[*pNum1] < pSupps[*pNum2] ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Analyze choice node support.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCompareCones( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSupp, * vNodes, * vReverse; + Abc_Obj_t * pObj, * pTemp; + int Iter, i, k, Counter, CounterCos, CounterCosNew; + int * pPerms; + + // sort COs by support size + pPerms = ALLOC( int, Abc_NtkCoNum(pNtk) ); + pSupps = ALLOC( int, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pPerms[i] = i; + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + pSupps[i] = Vec_PtrSize(vSupp); + Vec_PtrFree( vSupp ); + } + qsort( (void *)pPerms, Abc_NtkCoNum(pNtk), sizeof(int), (int (*)(const void *, const void *)) Abc_NtkCompareConesCompare ); + + // consider COs in this order + Iter = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pObj = Abc_NtkCo( pNtk, pPerms[i] ); + if ( pObj->fMarkA ) + continue; + Iter++; + + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); + vReverse = Abc_NtkDfsReverseNodesContained( pNtk, (Abc_Obj_t **)Vec_PtrArray(vSupp), Vec_PtrSize(vSupp) ); + // count the number of nodes in the reverse cone + Counter = 0; + for ( k = 1; k < Vec_PtrSize(vReverse) - 1; k++ ) + for ( pTemp = Vec_PtrEntry(vReverse, k); pTemp; pTemp = pTemp->pCopy ) + Counter++; + CounterCos = CounterCosNew = 0; + for ( pTemp = Vec_PtrEntryLast(vReverse); pTemp; pTemp = pTemp->pCopy ) + { + assert( Abc_ObjIsCo(pTemp) ); + CounterCos++; + if ( pTemp->fMarkA == 0 ) + CounterCosNew++; + pTemp->fMarkA = 1; + } + // print statistics + printf( "%4d CO %5d : Supp = %5d. Lev = %3d. Cone = %5d. Rev = %5d. COs = %3d (%3d).\n", + Iter, pPerms[i], Vec_PtrSize(vSupp), Abc_ObjLevel(Abc_ObjFanin0(pObj)), Vec_PtrSize(vNodes), Counter, CounterCos, CounterCosNew ); + + // free arrays + Vec_PtrFree( vSupp ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vReverse ); + + if ( Vec_PtrSize(vSupp) < 10 ) + break; + } + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->fMarkA = 0; + + free( pPerms ); + free( pSupps ); +} + +/**Function************************************************************* + + Synopsis [Analyze choice node support.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCompareSupports( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSupp; + Abc_Obj_t * pObj, * pTemp; + int i, nNodesOld; + assert( Abc_NtkIsStrash(pNtk) ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + if ( !Abc_AigNodeIsChoice(pObj) ) + continue; + + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + nNodesOld = Vec_PtrSize(vSupp); + Vec_PtrFree( vSupp ); + + for ( pTemp = pObj->pData; pTemp; pTemp = pTemp->pData ) + { + vSupp = Abc_NtkNodeSupport( pNtk, &pTemp, 1 ); + if ( nNodesOld != Vec_PtrSize(vSupp) ) + printf( "Choice orig = %3d Choice new = %3d\n", nNodesOld, Vec_PtrSize(vSupp) ); + Vec_PtrFree( vSupp ); + } + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abc_.c b/abc70930/src/base/abc/abc_.c new file mode 100644 index 00000000..50558bdb --- /dev/null +++ b/abc70930/src/base/abc/abc_.c @@ -0,0 +1,47 @@ +/**CFile**************************************************************** + + FileName [abc_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/module.make b/abc70930/src/base/abc/module.make new file mode 100644 index 00000000..7b34d8f6 --- /dev/null +++ b/abc70930/src/base/abc/module.make @@ -0,0 +1,18 @@ +SRC += src/base/abc/abcAig.c \ + src/base/abc/abcBlifMv.c \ + src/base/abc/abcCheck.c \ + src/base/abc/abcDfs.c \ + src/base/abc/abcFanio.c \ + src/base/abc/abcFunc.c \ + src/base/abc/abcHie.c \ + src/base/abc/abcLatch.c \ + src/base/abc/abcLib.c \ + src/base/abc/abcMinBase.c \ + src/base/abc/abcNames.c \ + src/base/abc/abcNetlist.c \ + src/base/abc/abcNtk.c \ + src/base/abc/abcObj.c \ + src/base/abc/abcRefs.c \ + src/base/abc/abcShow.c \ + src/base/abc/abcSop.c \ + src/base/abc/abcUtil.c diff --git a/abc70930/src/base/abci/abc.c b/abc70930/src/base/abci/abc.c new file mode 100644 index 00000000..a331e7fa --- /dev/null +++ b/abc70930/src/base/abci/abc.c @@ -0,0 +1,12765 @@ +/**CFile**************************************************************** + + FileName [abc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Command file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "mainInt.h" +#include "fraig.h" +#include "fxu.h" +#include "cut.h" +#include "fpga.h" +#include "if.h" +#include "res.h" +#include "lpk.h" +#include "aig.h" +#include "dar.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_CommandPrintStats ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintExdc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintIo ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintLatch ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintFanio ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintMffc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintFactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintLevel ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintSupport ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintSymms ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintUnate ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintAuto ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintKMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintGates ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintSharing ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintXCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintDsd ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandShow ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShowCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandCollapse ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandStrash ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBalance ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMulti ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRenode ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFastExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDisjoint ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandImfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLutpack ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRestructure ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandResubstitute ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDemiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandOrPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAndPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAppend ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFrames ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandReorder ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandOrder ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMuxes ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCone ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandNode ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTopmost ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTrim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExdcFree ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExdcGet ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExdcSet ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandEspresso ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//static int Abc_CommandXyz ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDouble ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandQuaVar ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandQuaRel ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandQuaReach ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandIStrash ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandICut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDCompress2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDrwsat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIRewriteSeq ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIResyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandISat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandHaig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMini ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandQbf ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigTrust ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigStore ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigRestore ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigClean ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigDress ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandHaigStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandHaigStop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandHaigUse ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandRecStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecStop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecAdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecUse ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandUnmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAttach ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSuperChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSuperChoiceLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFpgaFast ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIf ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandScut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandInit ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandZero ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandUndc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPipe ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeq ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandUnseq ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLcorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCycle ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandXsim ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDebug ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandTraceStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTraceCheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Init( Abc_Frame_t * pAbc ) +{ +// Abc_NtkBddImplicationTest(); + + Cmd_CommandAdd( pAbc, "Printing", "print_stats", Abc_CommandPrintStats, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_exdc", Abc_CommandPrintExdc, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_io", Abc_CommandPrintIo, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_latch", Abc_CommandPrintLatch, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_fanio", Abc_CommandPrintFanio, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_mffc", Abc_CommandPrintMffc, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_factor", Abc_CommandPrintFactor, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_level", Abc_CommandPrintLevel, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_supp", Abc_CommandPrintSupport, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_symm", Abc_CommandPrintSymms, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_unate", Abc_CommandPrintUnate, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_auto", Abc_CommandPrintAuto, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_kmap", Abc_CommandPrintKMap, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_gates", Abc_CommandPrintGates, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_sharing", Abc_CommandPrintSharing, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_xcut", Abc_CommandPrintXCut, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_dsd", Abc_CommandPrintDsd, 0 ); + + Cmd_CommandAdd( pAbc, "Printing", "show", Abc_CommandShow, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "show_bdd", Abc_CommandShowBdd, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "show_cut", Abc_CommandShowCut, 0 ); + + Cmd_CommandAdd( pAbc, "Synthesis", "collapse", Abc_CommandCollapse, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "strash", Abc_CommandStrash, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "balance", Abc_CommandBalance, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "multi", Abc_CommandMulti, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "renode", Abc_CommandRenode, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "cleanup", Abc_CommandCleanup, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "sweep", Abc_CommandSweep, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "fx", Abc_CommandFastExtract, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "dsd", Abc_CommandDisjoint, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "imfs", Abc_CommandImfs, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "lutpack", Abc_CommandLutpack, 1 ); + + Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 ); +// Cmd_CommandAdd( pAbc, "Synthesis", "restructure", Abc_CommandRestructure, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "resub", Abc_CommandResubstitute, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 ); + + Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 ); + Cmd_CommandAdd( pAbc, "Various", "comb", Abc_CommandComb, 1 ); + Cmd_CommandAdd( pAbc, "Various", "miter", Abc_CommandMiter, 1 ); + Cmd_CommandAdd( pAbc, "Various", "demiter", Abc_CommandDemiter, 1 ); + Cmd_CommandAdd( pAbc, "Various", "orpos", Abc_CommandOrPos, 1 ); + Cmd_CommandAdd( pAbc, "Various", "andpos", Abc_CommandAndPos, 1 ); + Cmd_CommandAdd( pAbc, "Various", "append", Abc_CommandAppend, 1 ); + Cmd_CommandAdd( pAbc, "Various", "frames", Abc_CommandFrames, 1 ); + Cmd_CommandAdd( pAbc, "Various", "sop", Abc_CommandSop, 0 ); + Cmd_CommandAdd( pAbc, "Various", "bdd", Abc_CommandBdd, 0 ); + Cmd_CommandAdd( pAbc, "Various", "aig", Abc_CommandAig, 0 ); + Cmd_CommandAdd( pAbc, "Various", "reorder", Abc_CommandReorder, 0 ); + Cmd_CommandAdd( pAbc, "Various", "order", Abc_CommandOrder, 0 ); + Cmd_CommandAdd( pAbc, "Various", "muxes", Abc_CommandMuxes, 1 ); + Cmd_CommandAdd( pAbc, "Various", "ext_seq_dcs", Abc_CommandExtSeqDcs, 0 ); + Cmd_CommandAdd( pAbc, "Various", "cone", Abc_CommandCone, 1 ); + Cmd_CommandAdd( pAbc, "Various", "node", Abc_CommandNode, 1 ); + Cmd_CommandAdd( pAbc, "Various", "topmost", Abc_CommandTopmost, 1 ); + Cmd_CommandAdd( pAbc, "Various", "trim", Abc_CommandTrim, 1 ); + Cmd_CommandAdd( pAbc, "Various", "short_names", Abc_CommandShortNames, 0 ); + Cmd_CommandAdd( pAbc, "Various", "exdc_free", Abc_CommandExdcFree, 1 ); + Cmd_CommandAdd( pAbc, "Various", "exdc_get", Abc_CommandExdcGet, 1 ); + Cmd_CommandAdd( pAbc, "Various", "exdc_set", Abc_CommandExdcSet, 1 ); + Cmd_CommandAdd( pAbc, "Various", "cut", Abc_CommandCut, 0 ); + Cmd_CommandAdd( pAbc, "Various", "espresso", Abc_CommandEspresso, 1 ); + Cmd_CommandAdd( pAbc, "Various", "gen", Abc_CommandGen, 0 ); +// Cmd_CommandAdd( pAbc, "Various", "xyz", Abc_CommandXyz, 1 ); + Cmd_CommandAdd( pAbc, "Various", "double", Abc_CommandDouble, 1 ); + Cmd_CommandAdd( pAbc, "Various", "test", Abc_CommandTest, 0 ); + + Cmd_CommandAdd( pAbc, "Various", "qvar", Abc_CommandQuaVar, 1 ); + Cmd_CommandAdd( pAbc, "Various", "qrel", Abc_CommandQuaRel, 1 ); + Cmd_CommandAdd( pAbc, "Various", "qreach", Abc_CommandQuaReach, 1 ); + + Cmd_CommandAdd( pAbc, "New AIG", "istrash", Abc_CommandIStrash, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "icut", Abc_CommandICut, 0 ); + Cmd_CommandAdd( pAbc, "New AIG", "irw", Abc_CommandIRewrite, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "drw", Abc_CommandDRewrite, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "drf", Abc_CommandDRefactor, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "dcompress2", Abc_CommandDCompress2, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "dchoice", Abc_CommandDChoice, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "drwsat", Abc_CommandDrwsat, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "irws", Abc_CommandIRewriteSeq, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "iresyn", Abc_CommandIResyn, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "isat", Abc_CommandISat, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "ifraig", Abc_CommandIFraig, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "dfraig", Abc_CommandDFraig, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "csweep", Abc_CommandCSweep, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "iprove", Abc_CommandIProve, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "haig", Abc_CommandHaig, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "mini", Abc_CommandMini, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "_bmc", Abc_CommandBmc, 0 ); + Cmd_CommandAdd( pAbc, "New AIG", "qbf", Abc_CommandQbf, 0 ); + + Cmd_CommandAdd( pAbc, "Fraiging", "fraig", Abc_CommandFraig, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_trust", Abc_CommandFraigTrust, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_store", Abc_CommandFraigStore, 0 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_restore", Abc_CommandFraigRestore, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_clean", Abc_CommandFraigClean, 0 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_sweep", Abc_CommandFraigSweep, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "dress", Abc_CommandFraigDress, 1 ); + + Cmd_CommandAdd( pAbc, "Choicing", "haig_start", Abc_CommandHaigStart, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "haig_stop", Abc_CommandHaigStop, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "haig_use", Abc_CommandHaigUse, 1 ); + + Cmd_CommandAdd( pAbc, "Choicing", "rec_start", Abc_CommandRecStart, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_stop", Abc_CommandRecStop, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_add", Abc_CommandRecAdd, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_ps", Abc_CommandRecPs, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_use", Abc_CommandRecUse, 1 ); + + Cmd_CommandAdd( pAbc, "SC mapping", "map", Abc_CommandMap, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "unmap", Abc_CommandUnmap, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "attach", Abc_CommandAttach, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "sc", Abc_CommandSuperChoice, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "scl", Abc_CommandSuperChoiceLut, 1 ); + + Cmd_CommandAdd( pAbc, "FPGA mapping", "fpga", Abc_CommandFpga, 1 ); + Cmd_CommandAdd( pAbc, "FPGA mapping", "ffpga", Abc_CommandFpgaFast, 1 ); + Cmd_CommandAdd( pAbc, "FPGA mapping", "if", Abc_CommandIf, 1 ); + +// Cmd_CommandAdd( pAbc, "Sequential", "scut", Abc_CommandScut, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "init", Abc_CommandInit, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "zero", Abc_CommandZero, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "undc", Abc_CommandUndc, 1 ); +// Cmd_CommandAdd( pAbc, "Sequential", "pipe", Abc_CommandPipe, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "retime", Abc_CommandRetime, 1 ); +// Cmd_CommandAdd( pAbc, "Sequential", "sfpga", Abc_CommandSeqFpga, 1 ); +// Cmd_CommandAdd( pAbc, "Sequential", "smap", Abc_CommandSeqMap, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "ssweep", Abc_CommandSeqSweep, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "lcorr", Abc_CommandLcorr, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "scleanup", Abc_CommandSeqCleanup, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "cycle", Abc_CommandCycle, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "xsim", Abc_CommandXsim, 0 ); + + Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "sec", Abc_CommandSec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "dsec", Abc_CommandDSec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "dprove", Abc_CommandDProve, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "sat", Abc_CommandSat, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "dsat", Abc_CommandDSat, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "prove", Abc_CommandProve, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "debug", Abc_CommandDebug, 0 ); + +// Cmd_CommandAdd( pAbc, "Verification", "trace_start", Abc_CommandTraceStart, 0 ); +// Cmd_CommandAdd( pAbc, "Verification", "trace_check", Abc_CommandTraceCheck, 0 ); + +// Rwt_Man4ExploreStart(); +// Map_Var3Print(); +// Map_Var4Test(); + +// Abc_NtkPrint256(); +// Kit_TruthCountMintermsPrecomp(); +// Kit_DsdPrecompute4Vars(); + + { + extern void Dar_LibStart(); + Dar_LibStart(); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_End() +{ +// Dar_LibDumpPriorities(); + + { + extern void Cnf_ClearMemory(); + Cnf_ClearMemory(); + } + { + extern void Dar_LibStop(); + Dar_LibStop(); + } + + Abc_NtkFraigStoreClean(); +// Rwt_Man4ExplorePrint(); + +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + bool fShort; + int c; + int fFactor; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set the defaults + fShort = 1; + fFactor = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sfh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fShort ^= 1; + break; + case 'f': + fFactor ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( Abc_FrameReadErr(pAbc), "Empty network.\n" ); + return 1; + } + Abc_NtkPrintStats( pOut, pNtk, fFactor ); + return 0; + +usage: + fprintf( pErr, "usage: print_stats [-fh]\n" ); + fprintf( pErr, "\t prints the network statistics\n" ); + fprintf( pErr, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkTemp; + double Percentage; + bool fShort; + int c; + int fPrintDc; + + extern double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set the defaults + fShort = 1; + fPrintDc = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sdh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fShort ^= 1; + break; + case 'd': + fPrintDc ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( Abc_FrameReadErr(pAbc), "Empty network.\n" ); + return 1; + } + if ( pNtk->pExdc == NULL ) + { + fprintf( Abc_FrameReadErr(pAbc), "Network has no EXDC.\n" ); + return 1; + } + + if ( fPrintDc ) + { + if ( !Abc_NtkIsStrash(pNtk->pExdc) ) + { + pNtkTemp = Abc_NtkStrash(pNtk->pExdc, 0, 0, 0); + Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtkTemp, 0) ) ); + Abc_NtkDelete( pNtkTemp ); + } + else + Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtk->pExdc, 0) ) ); + + printf( "EXDC network statistics: " ); + printf( "(" ); + if ( Percentage > 0.05 && Percentage < 99.95 ) + printf( "%.2f", Percentage ); + else if ( Percentage > 0.000005 && Percentage < 99.999995 ) + printf( "%.6f", Percentage ); + else + printf( "%f", Percentage ); + printf( " %% don't-cares)\n" ); + } + else + printf( "EXDC network statistics: \n" ); + Abc_NtkPrintStats( pOut, pNtk->pExdc, 0 ); + return 0; + +usage: + fprintf( pErr, "usage: print_exdc [-dh]\n" ); + fprintf( pErr, "\t prints the EXDC network statistics\n" ); + fprintf( pErr, "\t-d : toggles printing don't-care percentage [default = %s]\n", fPrintDc? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + if ( argc == globalUtilOptind + 1 ) + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Abc_NodePrintFanio( pOut, pNode ); + return 0; + } + // print the nodes + Abc_NtkPrintIo( pOut, pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: print_io [-h] <node>\n" ); + fprintf( pErr, "\t prints the PIs/POs or fanins/fanouts of a node\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tnode : the node to print fanins/fanouts\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintLatch( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + // print the nodes + Abc_NtkPrintLatch( pOut, pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: print_latch [-h]\n" ); + fprintf( pErr, "\t prints information about latches\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintFanio( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // print the nodes + Abc_NtkPrintFanio( pOut, pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: print_fanio [-h]\n" ); + fprintf( pErr, "\t prints the statistics about fanins/fanouts of all nodes\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintMffc( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + extern void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // print the nodes + Abc_NtkPrintMffc( pOut, pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: print_mffc [-h]\n" ); + fprintf( pErr, "\t prints the MFFC of each node in the network\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c; + int fUseRealNames; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseRealNames = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fUseRealNames ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + fprintf( pErr, "Printing factored forms can be done for SOP networks.\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + if ( argc == globalUtilOptind + 1 ) + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Abc_NodePrintFactor( pOut, pNode, fUseRealNames ); + return 0; + } + // print the nodes + Abc_NtkPrintFactor( pOut, pNtk, fUseRealNames ); + return 0; + +usage: + fprintf( pErr, "usage: print_factor [-nh] <node>\n" ); + fprintf( pErr, "\t prints the factored forms of nodes\n" ); + fprintf( pErr, "\t-n : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tnode : (optional) one node to consider\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c; + int fListNodes; + int fProfile; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fListNodes = 0; + fProfile = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nph" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fListNodes ^= 1; + break; + case 'p': + fProfile ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !fProfile && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + if ( argc == globalUtilOptind + 1 ) + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Abc_NodePrintLevel( pOut, pNode ); + return 0; + } + // process all COs + Abc_NtkPrintLevel( pOut, pNtk, fProfile, fListNodes ); + return 0; + +usage: + fprintf( pErr, "usage: print_level [-nph] <node>\n" ); + fprintf( pErr, "\t prints information about node level and cone size\n" ); + fprintf( pErr, "\t-n : toggles printing nodes by levels [default = %s]\n", fListNodes? "yes": "no" ); + fprintf( pErr, "\t-p : toggles printing level profile [default = %s]\n", fProfile? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tnode : (optional) one node to consider\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Vec_Ptr_t * vSuppFun; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fStruct; + int fVerbose; + extern Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose ); + extern void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fStruct = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fStruct ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // print support information + if ( fStruct ) + { + Abc_NtkPrintStrSupports( pNtk ); + return 0; + } + + if ( !Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "This command works only for combinational networks (run \"comb\").\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); + return 1; + } + vSuppFun = Sim_ComputeFunSupp( pNtk, fVerbose ); + free( vSuppFun->pArray[0] ); + Vec_PtrFree( vSuppFun ); + return 0; + +usage: + fprintf( pErr, "usage: print_supp [-svh]\n" ); + fprintf( pErr, "\t prints the supports of the CO nodes\n" ); + fprintf( pErr, "\t-s : toggle printing structural support only [default = %s].\n", fStruct? "yes": "no" ); + fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fUseBdds; + int fNaive; + int fReorder; + int fVerbose; + extern void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseBdds = 0; + fNaive = 0; + fReorder = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "bnrvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fUseBdds ^= 1; + break; + case 'n': + fNaive ^= 1; + break; + case 'r': + fReorder ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "This command works only for combinational networks (run \"comb\").\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose ); + Abc_NtkDelete( pNtk ); + } + return 0; + +usage: + fprintf( pErr, "usage: print_symm [-bnrvh]\n" ); + fprintf( pErr, "\t computes symmetries of the PO functions\n" ); + fprintf( pErr, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" ); + fprintf( pErr, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" ); + fprintf( pErr, "\t-r : enable dynamic BDD variable reordering [default = %s].\n", fReorder? "yes": "no" ); + fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintUnate( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fUseBdds; + int fUseNaive; + int fVerbose; + extern void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseBdds = 1; + fUseNaive = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "bnvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fUseBdds ^= 1; + break; + case 'n': + fUseNaive ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); + return 1; + } + Abc_NtkPrintUnate( pNtk, fUseBdds, fUseNaive, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: print_unate [-bnvh]\n" ); + fprintf( pErr, "\t computes unate variables of the PO functions\n" ); + fprintf( pErr, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" ); + fprintf( pErr, "\t-n : toggle naive BDD-based computation [default = %s].\n", fUseNaive? "yes": "no" ); + fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintAuto( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int Output; + int fNaive; + int fVerbose; + extern void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Output = -1; + fNaive = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Onvh" ) ) != EOF ) + { + switch ( c ) + { + case 'O': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + Output = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Output < 0 ) + goto usage; + break; + case 'n': + fNaive ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); + return 1; + } + + + Abc_NtkAutoPrint( pNtk, Output, fNaive, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: print_auto [-O num] [-nvh]\n" ); + fprintf( pErr, "\t computes autosymmetries of the PO functions\n" ); + fprintf( pErr, "\t-O num : (optional) the 0-based number of the output [default = all]\n"); + fprintf( pErr, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" ); + fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c; + int fUseRealNames; + + extern void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseRealNames = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fUseRealNames ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Visualization of Karnaugh maps works for logic networks.\n" ); + return 1; + } + if ( argc > globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + if ( argc == globalUtilOptind ) + { + pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); + if ( !Abc_ObjIsNode(pNode) ) + { + fprintf( pErr, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) ); + return 1; + } + } + else + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + } + Abc_NtkToBdd(pNtk); + Abc_NodePrintKMap( pNode, fUseRealNames ); + return 0; + +usage: + fprintf( pErr, "usage: print_kmap [-nh] <node>\n" ); + fprintf( pErr, " shows the truth table of the node\n" ); + fprintf( pErr, "\t-n : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tnode : the node to consider (default = the driver of the first PO)\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintGates( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fUseLibrary; + + extern void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseLibrary = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLibrary ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkHasAig(pNtk) ) + { + fprintf( pErr, "Printing gates does not work for AIGs and sequential AIGs.\n" ); + return 1; + } + + Abc_NtkPrintGates( pNtk, fUseLibrary ); + return 0; + +usage: + fprintf( pErr, "usage: print_gates [-lh]\n" ); + fprintf( pErr, "\t prints statistics about gates used in the network\n" ); + fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintSharing( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fUseLibrary; + + extern void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseLibrary = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLibrary ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + Abc_NtkPrintSharing( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: print_sharing [-h]\n" ); + fprintf( pErr, "\t prints the number of shared nodes in the TFI cones of the COs\n" ); +// fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintXCut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fUseLibrary; + + extern int Abc_NtkCrossCut( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseLibrary = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLibrary ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + Abc_NtkCrossCut( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: print_xcut [-h]\n" ); + fprintf( pErr, "\t prints the size of the cross cut of the current network\n" ); +// fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fCofactor; + int nCofLevel; + + extern void Kit_DsdTest( unsigned * pTruth, int nVars ); + extern void Kit_DsdPrintCofactors( unsigned * pTruth, int nVars, int nCofLevel, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nCofLevel = 1; + fCofactor = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nch" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nCofLevel = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCofLevel < 0 ) + goto usage; + break; + case 'c': + fCofactor ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + // get the truth table of the first output + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Currently works only for logic networks.\n" ); + return 1; + } + Abc_NtkToAig( pNtk ); + // convert it to truth table + { + Abc_Obj_t * pObj = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); + Vec_Int_t * vMemory = Vec_IntAlloc(0); + unsigned * pTruth; + if ( !Abc_ObjIsNode(pObj) ) + { + fprintf( pErr, "The fanin of the first PO node does not have a logic function.\n" ); + return 1; + } + if ( Abc_ObjFaninNum(pObj) > 16 ) + { + fprintf( pErr, "Currently works only for up to 16 inputs.\n" ); + return 1; + } + pTruth = Abc_ConvertAigToTruth( pNtk->pManFunc, Hop_Regular(pObj->pData), Abc_ObjFaninNum(pObj), vMemory, 0 ); + if ( Hop_IsComplement(pObj->pData) ) + Extra_TruthNot( pTruth, pTruth, Abc_ObjFaninNum(pObj) ); + Extra_PrintBinary( stdout, pTruth, 1 << Abc_ObjFaninNum(pObj) ); + printf( "\n" ); + if ( fCofactor ) + Kit_DsdPrintCofactors( pTruth, Abc_ObjFaninNum(pObj), nCofLevel, 1 ); + else + Kit_DsdTest( pTruth, Abc_ObjFaninNum(pObj) ); + Vec_IntFree( vMemory ); + } + return 0; + +usage: + fprintf( pErr, "usage: print_dsd [-ch] [-N num]\n" ); + fprintf( pErr, "\t print DSD formula for a single-output function with less than 16 variables\n" ); + fprintf( pErr, "\t-c : toggle recursive cofactoring [default = %s]\n", fCofactor? "yes": "no" ); + fprintf( pErr, "\t-N num : the number of levels to cofactor [default = %d]\n", nCofLevel ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fSeq; + int fGateNames; + int fUseReverse; + extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fSeq = 0; + fGateNames = 0; + fUseReverse = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "rsgh" ) ) != EOF ) + { + switch ( c ) + { + case 'r': + fUseReverse ^= 1; + break; + case 's': + fSeq ^= 1; + break; + case 'g': + fGateNames ^= 1; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse ); + return 0; + +usage: + fprintf( pErr, "usage: show [-srgh]\n" ); + fprintf( pErr, " visualizes the network structure using DOT and GSVIEW\n" ); +#ifdef WIN32 + fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); + fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); +#endif + fprintf( pErr, "\t-s : toggles visualization of sequential networks [default = %s].\n", fSeq? "yes": "no" ); + fprintf( pErr, "\t-r : toggles ordering nodes in reverse order [default = %s].\n", fUseReverse? "yes": "no" ); + fprintf( pErr, "\t-g : toggles printing gate names for mapped network [default = %s].\n", fGateNames? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c; + extern void Abc_NodeShowBdd( Abc_Obj_t * pNode ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsBddLogic(pNtk) ) + { + fprintf( pErr, "Visualizing BDDs can only be done for logic BDD networks (run \"bdd\").\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + if ( argc == globalUtilOptind ) + { + pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); + if ( !Abc_ObjIsNode(pNode) ) + { + fprintf( pErr, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) ); + return 1; + } + } + else + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + } + Abc_NodeShowBdd( pNode ); + return 0; + +usage: + fprintf( pErr, "usage: show_bdd [-h] <node>\n" ); + fprintf( pErr, " visualizes the BDD of a node using DOT and GSVIEW\n" ); +#ifdef WIN32 + fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); + fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); +#endif + fprintf( pErr, "\tnode : the node to consider [default = the driver of the first PO]\n"); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c; + int nNodeSizeMax; + int nConeSizeMax; + extern void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nNodeSizeMax = 10; + nConeSizeMax = ABC_INFINITY; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NCh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodeSizeMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConeSizeMax < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Visualizing cuts only works for AIGs (run \"strash\").\n" ); + return 1; + } + if ( argc != globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax ); + return 0; + +usage: + fprintf( pErr, "usage: show_cut [-N num] [-C num] [-h] <node>\n" ); + fprintf( pErr, " visualizes the cut of a node using DOT and GSVIEW\n" ); +#ifdef WIN32 + fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); + fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); +#endif + fprintf( pErr, "\t-N num : the max size of the cut to be computed [default = %d]\n", nNodeSizeMax ); + fprintf( pErr, "\t-C num : the max support of the containing cone [default = %d]\n", nConeSizeMax ); + fprintf( pErr, "\tnode : the node to consider\n"); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int fVerbose; + int fBddSizeMax; + int fDualRail; + int fReorder; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 1; + fReorder = 1; + fDualRail = 0; + fBddSizeMax = 50000000; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Brdvh" ) ) != EOF ) + { + switch ( c ) + { + case 'B': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + fBddSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( fBddSizeMax < 0 ) + goto usage; + break; + case 'd': + fDualRail ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'r': + fReorder ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Can only collapse a logic network or an AIG.\n" ); + return 1; + } + + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); + Abc_NtkDelete( pNtk ); + } + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Collapsing has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: collapse [-B num] [-rdvh]\n" ); + fprintf( pErr, "\t collapses the network by constructing global BDDs\n" ); + fprintf( pErr, "\t-B num : limit on live BDD nodes during collapsing [default = %d]\n", fBddSizeMax ); + fprintf( pErr, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); + fprintf( pErr, "\t-d : toggles dual-rail collapsing mode [default = %s]\n", fDualRail? "yes": "no" ); + fprintf( pErr, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fAllNodes; + int fRecord; + int fCleanup; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fAllNodes = 0; + fCleanup = 1; + fRecord = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "acrh" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fAllNodes ^= 1; + break; + case 'c': + fCleanup ^= 1; + break; + case 'r': + fRecord ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup, fRecord ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Strashing has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: strash [-acrh]\n" ); + fprintf( pErr, "\t transforms combinational logic into an AIG\n" ); + fprintf( pErr, "\t-a : toggles between using all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "DFS" ); + fprintf( pErr, "\t-c : toggles cleanup to remove the dagling AIG nodes [default = %s]\n", fCleanup? "all": "DFS" ); + fprintf( pErr, "\t-r : enables using the record of AIG subgraphs [default = %s]\n", fRecord? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp; + int c; + bool fDuplicate; + bool fSelective; + bool fUpdateLevel; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fDuplicate = 0; + fSelective = 0; + fUpdateLevel = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ldsh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'd': + fDuplicate ^= 1; + break; + case 's': + fSelective ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + { + pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective, fUpdateLevel ); + } + else + { + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtkTemp == NULL ) + { + fprintf( pErr, "Strashing before balancing has failed.\n" ); + return 1; + } + pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate, fSelective, fUpdateLevel ); + Abc_NtkDelete( pNtkTemp ); + } + + // check if balancing worked + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Balancing has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: balance [-ldsh]\n" ); + fprintf( pErr, "\t transforms the current network into a well-balanced AIG\n" ); + fprintf( pErr, "\t-l : toggle minimizing the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + fprintf( pErr, "\t-s : toggle duplication on the critical paths [default = %s]\n", fSelective? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMulti( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int nThresh, nFaninMax, c; + int fCnf; + int fMulti; + int fSimple; + int fFactor; + extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nThresh = 1; + nFaninMax = 20; + fCnf = 0; + fMulti = 1; + fSimple = 0; + fFactor = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "TFmcsfh" ) ) != EOF ) + { + switch ( c ) + { + case 'T': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + nThresh = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nThresh < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFaninMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFaninMax < 0 ) + goto usage; + break; + case 'c': + fCnf ^= 1; + break; + case 'm': + fMulti ^= 1; + break; + case 's': + fSimple ^= 1; + break; + case 'f': + fFactor ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Cannot renode a network that is not an AIG (run \"strash\").\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkMulti( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple, fFactor ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Renoding has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: multi [-T num] [-F num] [-msfch]\n" ); + fprintf( pErr, "\t transforms an AIG into a logic network by creating larger nodes\n" ); + fprintf( pErr, "\t-F num : the maximum fanin size after renoding [default = %d]\n", nFaninMax ); + fprintf( pErr, "\t-T num : the threshold for AIG node duplication [default = %d]\n", nThresh ); + fprintf( pErr, "\t (an AIG node is the root of a new node after renoding\n" ); + fprintf( pErr, "\t if this leads to duplication of no more than %d AIG nodes,\n", nThresh ); + fprintf( pErr, "\t that is, if [(numFanouts(Node)-1) * size(MFFC(Node))] <= %d)\n", nThresh ); + fprintf( pErr, "\t-m : creates multi-input AND graph [default = %s]\n", fMulti? "yes": "no" ); + fprintf( pErr, "\t-s : creates a simple AIG (no renoding) [default = %s]\n", fSimple? "yes": "no" ); + fprintf( pErr, "\t-f : creates a factor-cut network [default = %s]\n", fFactor? "yes": "no" ); + fprintf( pErr, "\t-c : performs renoding to derive the CNF [default = %s]\n", fCnf? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int nLutSize, nCutsMax, c; + int nFlowIters, nAreaIters; + int fArea; + int fUseBdds; + int fUseSops; + int fUseCnfs; + int fUseMv; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nLutSize, int nCutsMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nLutSize = 8; + nCutsMax = 4; + nFlowIters = 1; + nAreaIters = 1; + fArea = 0; + fUseBdds = 0; + fUseSops = 0; + fUseCnfs = 0; + fUseMv = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAabscivh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by a positive integer.\n" ); + goto usage; + } + nFlowIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFlowIters < 0 ) + goto usage; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-A\" should be followed by a positive integer.\n" ); + goto usage; + } + nAreaIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nAreaIters < 0 ) + goto usage; + break; + case 'a': + fArea ^= 1; + break; + case 'b': + fUseBdds ^= 1; + break; + case 's': + fUseSops ^= 1; + break; + case 'c': + fUseCnfs ^= 1; + break; + case 'i': + fUseMv ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( fUseBdds + fUseSops + fUseCnfs + fUseMv > 1 ) + { + fprintf( pErr, "Cannot optimize two parameters at the same time.\n" ); + return 1; + } + + if ( nLutSize < 3 || nLutSize > IF_MAX_FUNC_LUTSIZE ) + { + fprintf( pErr, "Incorrect LUT size (%d).\n", nLutSize ); + return 1; + } + + if ( nCutsMax < 1 || nCutsMax >= (1<<12) ) + { + fprintf( pErr, "Incorrect number of cuts.\n" ); + return 1; + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Cannot renode a network that is not an AIG (run \"strash\").\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkRenode( pNtk, nLutSize, nCutsMax, nFlowIters, nAreaIters, fArea, fUseBdds, fUseSops, fUseCnfs, fUseMv, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Renoding has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: renode [-K num] [-C num] [-F num] [-A num] [-sbciav]\n" ); + fprintf( pErr, "\t transforms the AIG into a logic network with larger nodes\n" ); + fprintf( pErr, "\t while minimizing the number of FF literals of the node SOPs\n" ); + fprintf( pErr, "\t-K num : the max cut size for renoding (2 < num < %d) [default = %d]\n", IF_MAX_FUNC_LUTSIZE+1, nLutSize ); + fprintf( pErr, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCutsMax ); + fprintf( pErr, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", nFlowIters ); + fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", nAreaIters ); + fprintf( pErr, "\t-s : toggles minimizing SOP cubes instead of FF lits [default = %s]\n", fUseSops? "yes": "no" ); + fprintf( pErr, "\t-b : toggles minimizing BDD nodes instead of FF lits [default = %s]\n", fUseBdds? "yes": "no" ); + fprintf( pErr, "\t-c : toggles minimizing CNF clauses instead of FF lits [default = %s]\n", fUseCnfs? "yes": "no" ); + fprintf( pErr, "\t-i : toggles minimizing MV-SOP instead of FF lits [default = %s]\n", fUseMv? "yes": "no" ); + fprintf( pErr, "\t-a : toggles area-oriented mapping [default = %s]\n", fArea? "yes": "no" ); + fprintf( pErr, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Cleanup cannot be performed on the AIG.\n" ); + return 1; + } + // modify the current network + Abc_NtkCleanup( pNtk, 1 ); + return 0; + +usage: + fprintf( pErr, "usage: cleanup [-h]\n" ); + fprintf( pErr, "\t removes dangling nodes\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "The classical (SIS-like) sweep can only be performed on a logic network.\n" ); + return 1; + } + // modify the current network + Abc_NtkSweep( pNtk, 0 ); + return 0; + +usage: + fprintf( pErr, "usage: sweep [-h]\n" ); + fprintf( pErr, "\t removes dangling nodes; propagates constant, buffers, inverters\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + FILE * pOut, * pErr; + Fxu_Data_t * p = NULL; + int c; + extern bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); + extern void Abc_NtkFxuFreeInfo( Fxu_Data_t * p ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // allocate the structure + p = ALLOC( Fxu_Data_t, 1 ); + memset( p, 0, sizeof(Fxu_Data_t) ); + // set the defaults + p->nSingleMax = 20000; + p->nPairsMax = 30000; + p->nNodesExt = 10000; + p->fOnlyS = 0; + p->fOnlyD = 0; + p->fUse0 = 0; + p->fUseCompl = 1; + p->fVerbose = 0; + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "SDNsdzcvh")) != EOF ) + { + switch (c) + { + case 'S': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + p->nSingleMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( p->nSingleMax < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + p->nPairsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( p->nPairsMax < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + p->nNodesExt = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( p->nNodesExt < 0 ) + goto usage; + break; + case 's': + p->fOnlyS ^= 1; + break; + case 'd': + p->fOnlyD ^= 1; + break; + case 'z': + p->fUse0 ^= 1; + break; + case 'c': + p->fUseCompl ^= 1; + break; + case 'v': + p->fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + Abc_NtkFxuFreeInfo( p ); + return 1; + } + + if ( Abc_NtkNodeNum(pNtk) == 0 ) + { + fprintf( pErr, "The network does not have internal nodes.\n" ); + Abc_NtkFxuFreeInfo( p ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Fast extract can only be applied to a logic network (run \"renode\").\n" ); + Abc_NtkFxuFreeInfo( p ); + return 1; + } + + + // the nodes to be merged are linked into the special linked list + Abc_NtkFastExtract( pNtk, p ); + Abc_NtkFxuFreeInfo( p ); + return 0; + +usage: + fprintf( pErr, "usage: fx [-S num] [-D num] [-N num] [-sdzcvh]\n"); + fprintf( pErr, "\t performs unate fast extract on the current network\n"); + fprintf( pErr, "\t-S num : max number of single-cube divisors to consider [default = %d]\n", p->nSingleMax ); + fprintf( pErr, "\t-D num : max number of double-cube divisors to consider [default = %d]\n", p->nPairsMax ); + fprintf( pErr, "\t-N num : the maximum number of divisors to extract [default = %d]\n", p->nNodesExt ); + fprintf( pErr, "\t-s : use only single-cube divisors [default = %s]\n", p->fOnlyS? "yes": "no" ); + fprintf( pErr, "\t-d : use only double-cube divisors [default = %s]\n", p->fOnlyD? "yes": "no" ); + fprintf( pErr, "\t-z : use zero-weight divisors [default = %s]\n", p->fUse0? "yes": "no" ); + fprintf( pErr, "\t-c : use complement in the binary case [default = %s]\n", p->fUseCompl? "yes": "no" ); + fprintf( pErr, "\t-v : print verbose information [default = %s]\n", p->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + Abc_NtkFxuFreeInfo( p ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkNew; + int fGlobal, fRecursive, fVerbose, fPrint, fShort, c; + + extern Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ); + extern int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fGlobal = 1; + fRecursive = 0; + fVerbose = 0; + fPrint = 0; + fShort = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "grvpsh" ) ) != EOF ) + { + switch ( c ) + { + case 'g': + fGlobal ^= 1; + break; + case 'r': + fRecursive ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'p': + fPrint ^= 1; + break; + case 's': + fShort ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( fGlobal ) + { +// fprintf( stdout, "Performing DSD of global functions of the network.\n" ); + // get the new network + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkDsdGlobal( pNtkNew, fVerbose, fPrint, fShort ); + Abc_NtkDelete( pNtkNew ); + } + else + { + pNtkRes = Abc_NtkDsdGlobal( pNtk, fVerbose, fPrint, fShort ); + } + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Global DSD has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } + else if ( fRecursive ) + { + if ( !Abc_NtkIsBddLogic( pNtk ) ) + { + fprintf( pErr, "This command is only applicable to logic BDD networks.\n" ); + return 1; + } + fprintf( stdout, "Performing recursive DSD and MUX decomposition of local functions.\n" ); + if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) ) + fprintf( pErr, "Recursive DSD has failed.\n" ); + } + else + { + if ( !Abc_NtkIsBddLogic( pNtk ) ) + { + fprintf( pErr, "This command is only applicable to logic BDD networks (run \"bdd\").\n" ); + return 1; + } + fprintf( stdout, "Performing simple non-recursive DSD of local functions.\n" ); + if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) ) + fprintf( pErr, "Simple DSD of local functions has failed.\n" ); + } + return 0; + +usage: + fprintf( pErr, "usage: dsd [-grvpsh]\n" ); + fprintf( pErr, "\t decomposes the network using disjoint-support decomposition\n" ); + fprintf( pErr, "\t-g : toggle DSD of global and local functions [default = %s]\n", fGlobal? "global": "local" ); + fprintf( pErr, "\t-r : toggle recursive DSD/MUX and simple DSD [default = %s]\n", fRecursive? "recursive DSD/MUX": "simple DSD" ); + fprintf( pErr, "\t-v : prints DSD statistics and runtime [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-p : prints DSD structure to the standard output [default = %s]\n", fPrint? "yes": "no" ); + fprintf( pErr, "\t-s : use short PI names when printing DSD structure [default = %s]\n", fShort? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandImfs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Res_Par_t Pars, * pPars = &Pars; + int c; + +// printf( "Implementation of this command is not finished.\n" ); +// return 1; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + pPars->nWindow = 62; + pPars->nGrowthLevel = 1; + pPars->nCands = 5; + pPars->nSimWords = 4; + pPars->fArea = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "WSCLavwh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nWindow = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nWindow < 1 || pPars->nWindow > 99 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nSimWords = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nSimWords < 1 || pPars->nSimWords > 256 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nCands = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCands < 0 || pPars->nCands > ABC_INFINITY ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY ) + goto usage; + break; + case 'a': + pPars->fArea ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "This command can only be applied to a logic network.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkResynthesize( pNtk, pPars ) ) + { + fprintf( pErr, "Resynthesis has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: imfs [-W <NM>] [-L <num>] [-C <num>] [-S <num>] [-avwh]\n" ); + fprintf( pErr, "\t performs resubstitution-based resynthesis with interpolation\n" ); + fprintf( pErr, "\t-W <NM> : fanin/fanout levels (NxM) of the window (00 <= NM <= 99) [default = %d%d]\n", pPars->nWindow/10, pPars->nWindow%10 ); + fprintf( pErr, "\t-L <num> : the largest increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); + fprintf( pErr, "\t-C <num> : the max number of resub candidates (1 <= n) [default = %d]\n", pPars->nCands ); + fprintf( pErr, "\t-S <num> : the number of simulation words (1 <= n <= 256) [default = %d]\n", pPars->nSimWords ); + fprintf( pErr, "\t-a : toggle optimization for area only [default = %s]\n", pPars->fArea? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle printout subgraph statistics [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLutpack( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Lpk_Par_t Pars, * pPars = &Pars; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + memset( pPars, 0, sizeof(Lpk_Par_t) ); + pPars->nLutsMax = 4; // (N) the maximum number of LUTs in the structure + pPars->nLutsOver = 3; // (Q) the maximum number of LUTs not in the MFFC + pPars->nVarsShared = 0; // (S) the maximum number of shared variables (crossbars) + pPars->nGrowthLevel = 0; // (L) the maximum number of increased levels + pPars->fSatur = 1; + pPars->fZeroCost = 0; + pPars->fFirst = 0; + pPars->fOldAlgo = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NQSLszfovwh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLutsMax < 2 || pPars->nLutsMax > 8 ) + goto usage; + break; + case 'Q': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-Q\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLutsOver = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLutsOver < 0 || pPars->nLutsOver > 8 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nVarsShared = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 4 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY ) + goto usage; + break; + case 's': + pPars->fSatur ^= 1; + break; + case 'z': + pPars->fZeroCost ^= 1; + break; + case 'f': + pPars->fFirst ^= 1; + break; + case 'o': + pPars->fOldAlgo ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "This command can only be applied to a logic network.\n" ); + return 1; + } + if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 3 ) + { + fprintf( pErr, "The number of shared variables (%d) is not in the range 0 <= S <= 3.\n", pPars->nVarsShared ); + return 1; + } + + // modify the current network + if ( !Lpk_Resynthesize( pNtk, pPars ) ) + { + fprintf( pErr, "Resynthesis has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: lutpack [-N <num>] [-Q <num>] [-S <num>] [-L <num>] [-szfovwh]\n" ); + fprintf( pErr, "\t performs \"rewriting\" for LUT networks\n" ); + fprintf( pErr, "\t-N <num> : the max number of LUTs in the structure (2 <= num) [default = %d]\n", pPars->nLutsMax ); + fprintf( pErr, "\t-Q <num> : the max number of LUTs not in MFFC (0 <= num) [default = %d]\n", pPars->nLutsOver ); + fprintf( pErr, "\t-S <num> : the max number of LUT inputs shared (0 <= num <= 3) [default = %d]\n", pPars->nVarsShared ); + fprintf( pErr, "\t-L <num> : max level increase after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); + fprintf( pErr, "\t-s : toggle iteration till saturation [default = %s]\n", pPars->fSatur? "yes": "no" ); + fprintf( pErr, "\t-z : toggle zero-cost replacements [default = %s]\n", pPars->fZeroCost? "yes": "no" ); + fprintf( pErr, "\t-f : toggle using only first node and first cut [default = %s]\n", pPars->fFirst? "yes": "no" ); + fprintf( pErr, "\t-o : toggle using old implementation [default = %s]\n", pPars->fOldAlgo? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle detailed printout of decomposed functions [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + bool fUpdateLevel; + bool fPrecompute; + bool fUseZeros; + bool fVerbose; + bool fVeryVerbose; + bool fPlaceEnable; + // external functions + extern void Rwr_Precompute(); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUpdateLevel = 1; + fPrecompute = 0; + fUseZeros = 0; + fVerbose = 0; + fVeryVerbose = 0; + fPlaceEnable = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'x': + fPrecompute ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'p': + fPlaceEnable ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( fPrecompute ) + { + Rwr_Precompute(); + return 0; + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkRewrite( pNtk, fUpdateLevel, fUseZeros, fVerbose, fVeryVerbose, fPlaceEnable ) ) + { + fprintf( pErr, "Rewriting has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: rewrite [-lzvwh]\n" ); + fprintf( pErr, "\t performs technology-independent rewriting of the AIG\n" ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle printout subgraph statistics [default = %s]\n", fVeryVerbose? "yes": "no" ); +// fprintf( pErr, "\t-p : toggle placement-aware rewriting [default = %s]\n", fPlaceEnable? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nNodeSizeMax; + int nConeSizeMax; + bool fUpdateLevel; + bool fUseZeros; + bool fUseDcs; + bool fVerbose; + extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nNodeSizeMax = 10; + nConeSizeMax = 16; + fUpdateLevel = 1; + fUseZeros = 0; + fUseDcs = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NClzdvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodeSizeMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConeSizeMax < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'd': + fUseDcs ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + if ( fUseDcs && nNodeSizeMax >= nConeSizeMax ) + { + fprintf( pErr, "For don't-care to work, containing cone should be larger than collapsed node.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ) ) + { + fprintf( pErr, "Refactoring has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: refactor [-N num] [-C num] [-lzdvh]\n" ); + fprintf( pErr, "\t performs technology-independent refactoring of the AIG\n" ); + fprintf( pErr, "\t-N num : the max support of the collapsed node [default = %d]\n", nNodeSizeMax ); + fprintf( pErr, "\t-C num : the max support of the containing cone [default = %d]\n", nConeSizeMax ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); + fprintf( pErr, "\t-d : toggle using don't-cares [default = %s]\n", fUseDcs? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRestructure( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nCutsMax; + bool fUpdateLevel; + bool fUseZeros; + bool fVerbose; + extern int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutsMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nCutsMax = 5; + fUpdateLevel = 0; + fUseZeros = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Klzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( nCutsMax < 4 || nCutsMax > CUT_SIZE_MAX ) + { + fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", 4, CUT_SIZE_MAX ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkRestructure( pNtk, nCutsMax, fUpdateLevel, fUseZeros, fVerbose ) ) + { + fprintf( pErr, "Refactoring has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: restructure [-K num] [-lzvh]\n" ); + fprintf( pErr, "\t performs technology-independent restructuring of the AIG\n" ); + fprintf( pErr, "\t-K num : the max cut size (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, nCutsMax ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int RS_CUT_MIN = 4; + int RS_CUT_MAX = 16; + int c; + int nCutsMax; + int nNodesMax; + int nLevelsOdc; + bool fUpdateLevel; + bool fUseZeros; + bool fVerbose; + bool fVeryVerbose; + extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nLevelsOdc, bool fUpdateLevel, bool fVerbose, bool fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nCutsMax = 8; + nNodesMax = 1; + nLevelsOdc = 0; + fUpdateLevel = 1; + fUseZeros = 0; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KNFlzvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodesMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodesMax < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nLevelsOdc = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevelsOdc < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( nCutsMax < RS_CUT_MIN || nCutsMax > RS_CUT_MAX ) + { + fprintf( pErr, "Can only compute cuts for %d <= K <= %d.\n", RS_CUT_MIN, RS_CUT_MAX ); + return 1; + } + if ( nNodesMax < 0 || nNodesMax > 3 ) + { + fprintf( pErr, "Can only resubstitute at most 3 nodes.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) ) + { + fprintf( pErr, "Refactoring has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: resub [-K num] [-N num] [-F num] [-lzvwh]\n" ); + fprintf( pErr, "\t performs technology-independent restructuring of the AIG\n" ); + fprintf( pErr, "\t-K num : the max cut size (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax ); + fprintf( pErr, "\t-N num : the max number of nodes to add (0 <= num <= 3) [default = %d]\n", nNodesMax ); + fprintf( pErr, "\t-F num : the number of fanout levels for ODC computation [default = %d]\n", nLevelsOdc ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle verbose printout of ODC computation [default = %s]\n", fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRr( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c, Window; + int nFaninLevels; + int nFanoutLevels; + int fUseFanouts; + int fVerbose; + extern int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFaninLevels = 3; + nFanoutLevels = 3; + fUseFanouts = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Wfvh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + Window = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Window < 0 ) + goto usage; + nFaninLevels = Window / 10; + nFanoutLevels = Window % 10; + break; + case 'f': + fUseFanouts ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkRR( pNtk, nFaninLevels, nFanoutLevels, fUseFanouts, fVerbose ) ) + { + fprintf( pErr, "Redundancy removal has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: rr [-W NM] [-fvh]\n" ); + fprintf( pErr, "\t removes combinational redundancies in the current network\n" ); + fprintf( pErr, "\t-W NM : window size: TFI (N) and TFO (M) logic levels [default = %d%d]\n", nFaninLevels, nFanoutLevels ); + fprintf( pErr, "\t-f : toggle RR w.r.t. fanouts [default = %s]\n", fUseFanouts? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nLutSize; + int fCheck; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nLutSize = 12; + fCheck = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kcvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'c': + fCheck ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Can only collapse a logic network or an AIG.\n" ); + return 1; + } + + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose ); + Abc_NtkDelete( pNtk ); + } + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Cascade synthesis has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: cascade [-K <num>] [-cvh]\n" ); + fprintf( pErr, "\t performs LUT cascade synthesis for the current network\n" ); + fprintf( pErr, "\t-K num : the number of LUT inputs [default = %d]\n", nLutSize ); + fprintf( pErr, "\t-c : check equivalence after synthesis [default = %s]\n", fCheck? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t \n"); + fprintf( pErr, " A lookup-table cascade is a programmable architecture developed by\n"); + fprintf( pErr, " Professor Tsutomu Sasao (sasao@cse.kyutech.ac.jp) at Kyushu Institute\n"); + fprintf( pErr, " of Technology. This work received Takeda Techno-Entrepreneurship Award:\n"); + fprintf( pErr, " http://www.lsi-cad.com/sasao/photo/takeda.html\n"); + fprintf( pErr, "\t \n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash( pNtk ) ) + { + fprintf( pErr, "This command is only applicable to strashed networks.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkToLogic( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Converting to a logic network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: logic [-h]\n" ); + fprintf( pErr, "\t transforms an AIG into a logic network with SOPs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandComb( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The network is already combinational.\n" ); + return 0; + } + + // get the new network + pNtkRes = Abc_NtkDup( pNtk ); + Abc_NtkMakeComb( pNtkRes ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: comb [-h]\n" ); + fprintf( pErr, "\t makes the current network combinational by replacing latches by PI/PO pairs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[32]; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; + int c; + int fCheck; + int fComb; + int nPartSize; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fComb = 1; + fCheck = 1; + nPartSize = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Pch" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nPartSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPartSize < 0 ) + goto usage; + break; + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + + // compute the miter + pNtkRes = Abc_NtkMiter( pNtk1, pNtk2, fComb, nPartSize ); + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + + // get the new network + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Miter computation has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + if ( nPartSize == 0 ) + strcpy( Buffer, "unused" ); + else + sprintf( Buffer, "%d", nPartSize ); + fprintf( pErr, "usage: miter [-P num] [-ch] <file1> <file2>\n" ); + fprintf( pErr, "\t computes the miter of the two circuits\n" ); + fprintf( pErr, "\t-P num : output partition size [default = %s]\n", Buffer ); + fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); + fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); + fprintf( pErr, "\t if no files are given, uses the current network and its spec\n"); + fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk;//, * pNtkRes; + int fComb; + int c; + extern int Abc_NtkDemiter( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "The network is not strashed.\n" ); + return 1; + } + + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + fprintf( pErr, "The network is not a miter.\n" ); + return 1; + } + + if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) ) + { + fprintf( pErr, "The miter's PO is not an EXOR.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkDemiter( pNtk ) ) + { + fprintf( pErr, "Demitering has failed.\n" ); + return 1; + } + // replace the current network +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: demiter [-h]\n" ); + fprintf( pErr, "\t removes topmost EXOR from the miter to create two POs\n" ); +// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandOrPos( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk;//, * pNtkRes; + int fComb; + int c; + extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "The network is not strashed.\n" ); + return 1; + } +/* + if ( Abc_NtkPoNum(pNtk) == 1 ) + { + fprintf( pErr, "The network already has one PO.\n" ); + return 1; + } +*/ +/* + if ( Abc_NtkLatchNum(pNtk) ) + { + fprintf( pErr, "The miter has latches. ORing is not performed.\n" ); + return 1; + } +*/ + // get the new network + if ( !Abc_NtkCombinePos( pNtk, 0 ) ) + { + fprintf( pErr, "ORing the POs has failed.\n" ); + return 1; + } + // replace the current network +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: orpos [-h]\n" ); + fprintf( pErr, "\t creates single-output miter by ORing the POs of the current network\n" ); +// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAndPos( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk;//, * pNtkRes; + int fComb; + int c; + extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "The network is not strashed.\n" ); + return 1; + } + + if ( Abc_NtkPoNum(pNtk) == 1 ) + { + fprintf( pErr, "The network already has one PO.\n" ); + return 1; + } + + if ( Abc_NtkLatchNum(pNtk) ) + { + fprintf( pErr, "The miter has latches. ORing is not performed.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkCombinePos( pNtk, 1 ) ) + { + fprintf( pErr, "ANDing the POs has failed.\n" ); + return 1; + } + // replace the current network +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: andpos [-h]\n" ); + fprintf( pErr, "\t creates single-output miter by ANDing the POs of the current network\n" ); +// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAppend( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk2; + char * FileName; + int fComb; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + // get the second network + if ( argc != globalUtilOptind + 1 ) + { + fprintf( pErr, "The network to append is not given.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "The base network should be strashed for the appending to work.\n" ); + return 1; + } + + // read the second network + FileName = argv[globalUtilOptind]; + pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1 ); + if ( pNtk2 == NULL ) + return 1; + + // check if the second network is combinational + if ( Abc_NtkLatchNum(pNtk2) ) + { + fprintf( pErr, "The second network has latches. Appending does not work for such networks.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkAppend( pNtk, pNtk2, 1 ) ) + { + Abc_NtkDelete( pNtk2 ); + fprintf( pErr, "Appending the networks failed.\n" ); + return 1; + } + Abc_NtkDelete( pNtk2 ); + // sweep dangling logic + Abc_AigCleanup( pNtk->pManFunc ); + // replace the current network +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: append [-h] <file>\n" ); + fprintf( pErr, "\t appends a combinational network on top of the current network\n" ); +// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t<file> : file name with the second network\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkTemp, * pNtkRes; + int fInitial; + int nFrames; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fInitial = 0; + nFrames = 5; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Fih" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames <= 0 ) + goto usage; + break; + case 'i': + fInitial ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkFrames( pNtkTemp, nFrames, fInitial ); + Abc_NtkDelete( pNtkTemp ); + } + else + pNtkRes = Abc_NtkFrames( pNtk, nFrames, fInitial ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Unrolling the network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: frames [-F num] [-ih]\n" ); + fprintf( pErr, "\t unrolls the network for a number of time frames\n" ); + fprintf( pErr, "\t-F num : the number of frames to unroll [default = %d]\n", nFrames ); + fprintf( pErr, "\t-i : toggles initializing the first frame [default = %s]\n", fInitial? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int fDirect; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fDirect = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDirect ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Converting to SOP is possible only for logic networks.\n" ); + return 1; + } + if ( !Abc_NtkToSop(pNtk, fDirect) ) + { + fprintf( pErr, "Converting to SOP has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: sop [-dh]\n" ); + fprintf( pErr, "\t converts node functions to SOP\n" ); + fprintf( pErr, "\t-d : toggles using both phases or only positive [default = %s]\n", fDirect? "direct": "both" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Converting to BDD is possible only for logic networks.\n" ); + return 1; + } + if ( Abc_NtkIsBddLogic(pNtk) ) + { + fprintf( pOut, "The logic network is already in the BDD form.\n" ); + return 0; + } + if ( !Abc_NtkToBdd(pNtk) ) + { + fprintf( pErr, "Converting to BDD has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: bdd [-h]\n" ); + fprintf( pErr, "\t converts node functions to BDD\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Converting to AIG is possible only for logic networks.\n" ); + return 1; + } + if ( Abc_NtkIsAigLogic(pNtk) ) + { + fprintf( pOut, "The logic network is already in the AIG form.\n" ); + return 0; + } + if ( !Abc_NtkToAig(pNtk) ) + { + fprintf( pErr, "Converting to AIG has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: aig [-h]\n" ); + fprintf( pErr, "\t converts node functions to AIG\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandReorder( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fVerbose; + extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkIsBddLogic(pNtk) ) + { + fprintf( pErr, "Variable reordering is possible when node functions are BDDs (run \"bdd\").\n" ); + return 1; + } + Abc_NtkBddReorder( pNtk, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: reorder [-vh]\n" ); + fprintf( pErr, "\t reorders local functions of the nodes using sifting\n" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandOrder( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr, * pFile; + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + int fReverse; + int fVerbose; + extern void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose ); + extern void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fReverse = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) + { + switch ( c ) + { + case 'r': + fReverse ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } +// if ( Abc_NtkLatchNum(pNtk) > 0 ) +// { +// printf( "Currently this procedure does not work for sequential networks.\n" ); +// return 1; +// } + + // if the var order file is given, implement this order + pFileName = NULL; + if ( argc == globalUtilOptind + 1 ) + { + pFileName = argv[globalUtilOptind]; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + fprintf( pErr, "Cannot open file \"%s\" with the BDD variable order.\n", pFileName ); + return 1; + } + fclose( pFile ); + } + if ( pFileName ) + Abc_NtkImplementCiOrder( pNtk, pFileName, fReverse, fVerbose ); + else + Abc_NtkFindCiOrder( pNtk, fReverse, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: order [-rvh] <file>\n" ); + fprintf( pErr, "\t computes a good static CI variable order\n" ); + fprintf( pErr, "\t-r : toggle reverse ordering [default = %s]\n", fReverse? "yes": "no" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t<file> : (optional) file with the given variable order\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsBddLogic(pNtk) ) + { + fprintf( pErr, "Only a BDD logic network can be converted to MUXes.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkBddToMuxes( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Converting to MUXes has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: muxes [-h]\n" ); + fprintf( pErr, "\t converts the current network by a network derived by\n" ); + fprintf( pErr, "\t replacing all nodes by DAGs isomorphic to the local BDDs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fVerbose; + extern int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNet, bool fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + fprintf( stdout, "The current network has no latches.\n" ); + return 0; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Extracting sequential don't-cares works only for AIGs (run \"strash\").\n" ); + return 0; + } + if ( !Abc_NtkExtractSequentialDcs( pNtk, fVerbose ) ) + { + fprintf( stdout, "Extracting sequential don't-cares has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: ext_seq_dcs [-vh]\n" ); + fprintf( pErr, "\t create EXDC network using unreachable states\n" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCone( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + Abc_Obj_t * pNode, * pNodeCo; + int c; + int fUseAllCis; + int fUseMffc; + int Output; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseAllCis = 0; + fUseMffc = 0; + Output = -1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Omah" ) ) != EOF ) + { + switch ( c ) + { + case 'O': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + Output = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Output < 0 ) + goto usage; + break; + case 'm': + fUseMffc ^= 1; + case 'a': + fUseAllCis ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Currently can only be applied to the logic network or an AIG.\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + pNodeCo = NULL; + if ( argc == globalUtilOptind + 1 ) + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + if ( fUseMffc ) + pNtkRes = Abc_NtkCreateMffc( pNtk, pNode, argv[globalUtilOptind] ); + else + pNtkRes = Abc_NtkCreateCone( pNtk, pNode, argv[globalUtilOptind], fUseAllCis ); + } + else + { + if ( Output == -1 ) + { + fprintf( pErr, "The node is not specified.\n" ); + return 1; + } + if ( Output >= Abc_NtkCoNum(pNtk) ) + { + fprintf( pErr, "The 0-based output number (%d) is larger than the number of outputs (%d).\n", Output, Abc_NtkCoNum(pNtk) ); + return 1; + } + pNodeCo = Abc_NtkCo( pNtk, Output ); + if ( fUseMffc ) + pNtkRes = Abc_NtkCreateMffc( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo) ); + else + pNtkRes = Abc_NtkCreateCone( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo), fUseAllCis ); + } + if ( pNodeCo && Abc_ObjFaninC0(pNodeCo) ) + printf( "The extracted cone represents the complement function of the CO.\n" ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Writing the logic cone of one node has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: cone [-O num] [-amh] <name>\n" ); + fprintf( pErr, "\t replaces the current network by one logic cone\n" ); + fprintf( pErr, "\t-a : toggle writing all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" ); + fprintf( pErr, "\t-m : toggle writing only MFFC or complete TFI cone [default = %s]\n", fUseMffc? "MFFC": "TFI cone" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t-O num : (optional) the 0-based number of the CO to extract\n"); + fprintf( pErr, "\tname : (optional) the name of the node to extract\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandNode( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + Abc_Obj_t * pNode; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Currently can only be applied to a logic network.\n" ); + return 1; + } + + if ( argc != globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + + pNtkRes = Abc_NtkCreateFromNode( pNtk, pNode ); +// pNtkRes = Abc_NtkDeriveFromBdd( pNtk->pManFunc, pNode->pData, NULL, NULL ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Splitting one node has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: node [-h] <name>\n" ); + fprintf( pErr, "\t replaces the current network by the network composed of one node\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tname : the node name\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTopmost( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nLevels; + extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nLevels = 10; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Currently only works for structurally hashed circuits.\n" ); + return 0; + } + + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( stdout, "Currently can only works for combinational circuits.\n" ); + return 0; + } + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + fprintf( stdout, "Currently expects a single-output miter.\n" ); + return 0; + } + + pNtkRes = Abc_NtkTopmost( pNtk, nLevels ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: topmost [-N num] [-h]\n" ); + fprintf( pErr, "\t replaces the current network by several of its topmost levels\n" ); + fprintf( pErr, "\t-N num : max number of levels [default = %d]\n", nLevels ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tname : the node name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTrim( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nLevels; + extern Abc_Ntk_t * Abc_NtkTrim( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nLevels = 10; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) + { + switch ( c ) + { +/* + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels < 0 ) + goto usage; + break; +*/ + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Currently only works for logic circuits.\n" ); + return 0; + } + + pNtkRes = Abc_NtkTrim( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: trim [-h]\n" ); + fprintf( pErr, "\t removes POs fed by PIs and constants, and PIs w/o fanout\n" ); +// fprintf( pErr, "\t-N num : max number of levels [default = %d]\n", nLevels ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + Abc_NtkShortNames( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: short_names [-h]\n" ); + fprintf( pErr, "\t replaces PI/PO/latch names by short char strings\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExdcFree( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( pNtk->pExdc == NULL ) + { + fprintf( pErr, "The network has no EXDC.\n" ); + return 1; + } + + Abc_NtkDelete( pNtk->pExdc ); + pNtk->pExdc = NULL; + + // replace the current network + pNtkRes = Abc_NtkDup( pNtk ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: exdc_free [-h]\n" ); + fprintf( pErr, "\t frees the EXDC network of the current network\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExdcGet( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( pNtk->pExdc == NULL ) + { + fprintf( pErr, "The network has no EXDC.\n" ); + return 1; + } + + // replace the current network + pNtkRes = Abc_NtkDup( pNtk->pExdc ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: exdc_get [-h]\n" ); + fprintf( pErr, "\t replaces the current network by the EXDC of the current network\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExdcSet( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr, * pFile; + Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; + char * FileName; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[globalUtilOptind]; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); + if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) ) + fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName ); + fprintf( pAbc->Err, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pNtkNew = Io_Read( FileName, Io_ReadFileType(FileName), 1 ); + if ( pNtkNew == NULL ) + { + fprintf( pAbc->Err, "Reading network from file has failed.\n" ); + return 1; + } + + // replace the EXDC + if ( pNtk->pExdc ) + { + Abc_NtkDelete( pNtk->pExdc ); + pNtk->pExdc = NULL; + } + pNtkRes = Abc_NtkDup( pNtk ); + pNtkRes->pExdc = pNtkNew; + + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: exdc_set [-h] <file>\n" ); + fprintf( pErr, "\t sets the network from file as EXDC for the current network\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t<file> : file with the new EXDC network\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Cut_Params_t Params, * pParams = &Params; + Cut_Man_t * pCutMan; + Cut_Oracle_t * pCutOracle; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fOracle; + extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); + extern void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * pCutOracle ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fOracle = 0; + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts) + pParams->nKeepMax = 1000; // the max number of cuts kept at a node + pParams->fTruth = 0; // compute truth tables + pParams->fFilter = 1; // filter dominated cuts + pParams->fDrop = 0; // drop cuts on the fly + pParams->fDag = 0; // compute DAG cuts + pParams->fTree = 0; // compute tree cuts + pParams->fGlobal = 0; // compute global cuts + pParams->fLocal = 0; // compute local cuts + pParams->fFancy = 0; // compute something fancy + pParams->fMap = 0; // compute mapping delay + pParams->fVerbose = 0; // the verbosiness flag + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyglzmvoh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nVarsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nVarsMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nKeepMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nKeepMax < 0 ) + goto usage; + break; + case 't': + pParams->fTruth ^= 1; + break; + case 'f': + pParams->fFilter ^= 1; + break; + case 'd': + pParams->fDrop ^= 1; + break; + case 'x': + pParams->fDag ^= 1; + break; + case 'y': + pParams->fTree ^= 1; + break; + case 'g': + pParams->fGlobal ^= 1; + break; + case 'l': + pParams->fLocal ^= 1; + break; + case 'z': + pParams->fFancy ^= 1; + break; + case 'm': + pParams->fMap ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 'o': + fOracle ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Cut computation is available only for AIGs (run \"strash\").\n" ); + return 1; + } + if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX ) + { + fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX ); + return 1; + } + if ( pParams->fDag && pParams->fTree ) + { + fprintf( pErr, "Cannot compute both DAG cuts and tree cuts at the same time.\n" ); + return 1; + } + + if ( fOracle ) + pParams->fRecord = 1; + pCutMan = Abc_NtkCuts( pNtk, pParams ); + if ( fOracle ) + pCutOracle = Cut_OracleStart( pCutMan ); + Cut_ManStop( pCutMan ); + if ( fOracle ) + { + Abc_NtkCutsOracle( pNtk, pCutOracle ); + Cut_OracleStop( pCutOracle ); + } + return 0; + +usage: + fprintf( pErr, "usage: cut [-K num] [-M num] [-tfdxyzmvh]\n" ); + fprintf( pErr, "\t computes k-feasible cuts for the AIG\n" ); + fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); + fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); + fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); + fprintf( pErr, "\t-f : toggle filtering of duplicated/dominated [default = %s]\n", pParams->fFilter? "yes": "no" ); + fprintf( pErr, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" ); + fprintf( pErr, "\t-x : toggle computing only DAG cuts [default = %s]\n", pParams->fDag? "yes": "no" ); + fprintf( pErr, "\t-y : toggle computing only tree cuts [default = %s]\n", pParams->fTree? "yes": "no" ); + fprintf( pErr, "\t-g : toggle computing only global cuts [default = %s]\n", pParams->fGlobal? "yes": "no" ); + fprintf( pErr, "\t-l : toggle computing only local cuts [default = %s]\n", pParams->fLocal? "yes": "no" ); + fprintf( pErr, "\t-z : toggle fancy computations [default = %s]\n", pParams->fFancy? "yes": "no" ); + fprintf( pErr, "\t-m : toggle delay-oriented FPGA mapping [default = %s]\n", pParams->fMap? "yes": "no" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandScut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Cut_Params_t Params, * pParams = &Params; + Cut_Man_t * pCutMan; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts) + pParams->nKeepMax = 1000; // the max number of cuts kept at a node + pParams->fTruth = 0; // compute truth tables + pParams->fFilter = 1; // filter dominated cuts + pParams->fSeq = 1; // compute sequential cuts + pParams->fVerbose = 0; // the verbosiness flag + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KMtvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nVarsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nVarsMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nKeepMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nKeepMax < 0 ) + goto usage; + break; + case 't': + pParams->fTruth ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } +/* + if ( !Abc_NtkIsSeq(pNtk) ) + { + fprintf( pErr, "Sequential cuts can be computed for sequential AIGs (run \"seq\").\n" ); + return 1; + } +*/ + if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX ) + { + fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX ); + return 1; + } + + pCutMan = Abc_NtkSeqCuts( pNtk, pParams ); + Cut_ManStop( pCutMan ); + return 0; + +usage: + fprintf( pErr, "usage: scut [-K num] [-M num] [-tvh]\n" ); + fprintf( pErr, "\t computes k-feasible cuts for the sequential AIG\n" ); + fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); + fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); + fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandEspresso( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fVerbose; + extern void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "SOP minimization is possible for logic networks (run \"renode\").\n" ); + return 1; + } + Abc_NtkEspresso( pNtk, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: espresso [-vh]\n" ); + fprintf( pErr, "\t minimizes SOPs of the local functions using Espresso\n" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nVars; + int fAdder; + int fSorter; + int fMesh; + int fFpga; + int fVerbose; + char * FileName; + extern void Abc_GenAdder( char * pFileName, int nVars ); + extern void Abc_GenSorter( char * pFileName, int nVars ); + extern void Abc_GenMesh( char * pFileName, int nVars ); + extern void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars ); + + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nVars = 8; + fAdder = 0; + fSorter = 0; + fMesh = 0; + fFpga = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nasmfvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; + case 'a': + fAdder ^= 1; + break; + case 's': + fSorter ^= 1; + break; + case 'm': + fMesh ^= 1; + break; + case 'f': + fFpga ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[globalUtilOptind]; + if ( fAdder ) + Abc_GenAdder( FileName, nVars ); + else if ( fSorter ) + Abc_GenSorter( FileName, nVars ); + else if ( fMesh ) + Abc_GenMesh( FileName, nVars ); + else if ( fFpga ) + Abc_GenFpga( FileName, 4, 3, 10 ); +// Abc_GenFpga( FileName, 2, 2, 3 ); +// Abc_GenFpga( FileName, 3, 2, 5 ); + else + printf( "Type of circuit is not specified.\n" ); + return 0; + +usage: + fprintf( pErr, "usage: gen [-N] [-asmfvh] <file>\n" ); + fprintf( pErr, "\t generates simple circuits\n" ); + fprintf( pErr, "\t-N num : the number of variables [default = %d]\n", nVars ); + fprintf( pErr, "\t-a : generate ripple-carry adder [default = %s]\n", fAdder? "yes": "no" ); + fprintf( pErr, "\t-s : generate a sorter [default = %s]\n", fSorter? "yes": "no" ); + fprintf( pErr, "\t-m : generate a mesh [default = %s]\n", fMesh? "yes": "no" ); + fprintf( pErr, "\t-f : generate a LUT FPGA structure [default = %s]\n", fFpga? "yes": "no" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t<file> : output file name\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandXyz( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes;//, * pNtkTemp; + int c; + int nLutMax; + int nPlaMax; + int RankCost; + int fFastMode; + int fRewriting; + int fSynthesis; + int fVerbose; +// extern Abc_Ntk_t * Abc_NtkXyz( Abc_Ntk_t * pNtk, int nPlaMax, bool fEsop, bool fSop, bool fInvs, bool fVerbose ); + extern void * Abc_NtkPlayer( void * pNtk, int nLutMax, int nPlaMax, int RankCost, int fFastMode, int fRewriting, int fSynthesis, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nLutMax = 8; + nPlaMax = 128; + RankCost = 96000; + fFastMode = 1; + fRewriting = 0; + fSynthesis = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "LPRfrsvh" ) ) != EOF ) + { + switch ( c ) + { + case 'L': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + nLutMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutMax < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nPlaMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPlaMax < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + RankCost = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( RankCost < 0 ) + goto usage; + break; + case 'f': + fFastMode ^= 1; + break; + case 'r': + fRewriting ^= 1; + break; + case 's': + fSynthesis ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Only works for strashed networks.\n" ); + return 1; + } +/* + if ( nLutMax < 2 || nLutMax > 12 || nPlaMax < 8 || nPlaMax > 128 ) + { + fprintf( pErr, "Incorrect LUT/PLA parameters.\n" ); + return 1; + } +*/ + // run the command +// pNtkRes = Abc_NtkXyz( pNtk, nPlaMax, 1, 0, fInvs, fVerbose ); +/* + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtkTemp = Abc_NtkStrash( pNtk, 0, 1, 0 ); + pNtkRes = Abc_NtkPlayer( pNtkTemp, nLutMax, nPlaMax, RankCost, fFastMode, fRewriting, fSynthesis, fVerbose ); + Abc_NtkDelete( pNtkTemp ); + } + else + pNtkRes = Abc_NtkPlayer( pNtk, nLutMax, nPlaMax, RankCost, fFastMode, fRewriting, fSynthesis, fVerbose ); +*/ + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: xyz [-L num] [-P num] [-R num] [-frsvh]\n" ); + fprintf( pErr, "\t specilized LUT/PLA decomposition\n" ); + fprintf( pErr, "\t-L num : maximum number of LUT inputs (2<=num<=8) [default = %d]\n", nLutMax ); + fprintf( pErr, "\t-P num : maximum number of PLA inputs/cubes (8<=num<=128) [default = %d]\n", nPlaMax ); + fprintf( pErr, "\t-R num : maximum are of one decomposition rank [default = %d]\n", RankCost ); + fprintf( pErr, "\t-f : toggle using fast LUT mapping mode [default = %s]\n", fFastMode? "yes": "no" ); + fprintf( pErr, "\t-r : toggle using one pass of AIG rewriting [default = %s]\n", fRewriting? "yes": "no" ); + fprintf( pErr, "\t-s : toggle using synthesis by AIG rewriting [default = %s]\n", fSynthesis? "yes": "no" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDouble( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int nFrames; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFrames = 50; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + fprintf( pErr, "Only works for logic SOP networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkDouble( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: double [-vh]\n" ); + fprintf( pErr, "\t puts together two parallel copies of the current network\n" ); +// fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int nLevels; + int fVerbose; +// extern Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk ); +// extern Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk ); +// extern void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ); +// extern int Pr_ManProofTest( char * pFileName ); + extern void Abc_NtkCompareSupports( Abc_Ntk_t * pNtk ); + extern void Abc_NtkCompareCones( Abc_Ntk_t * pNtk ); + extern Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk ); + extern Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName ); + extern Abc_Ntk_t * Abc_NtkFilter( Abc_Ntk_t * pNtk ); + extern Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkPcmTest( Abc_Ntk_t * pNtk, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + nLevels = 1000; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } +/* + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsSeq(pNtk) ) + { + fprintf( pErr, "Only works for non-sequential networks.\n" ); + return 1; + } +*/ + +// Abc_NtkTestEsop( pNtk ); +// Abc_NtkTestSop( pNtk ); +// printf( "This command is currently not used.\n" ); + // run the command +// pNtkRes = Abc_NtkMiterForCofactors( pNtk, 0, 0, -1 ); +// pNtkRes = Abc_NtkNewAig( pNtk ); + +/* + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); +*/ + +// if ( Cut_CellIsRunning() ) +// Cut_CellDumpToFile(); +// else +// Cut_CellPrecompute(); +// Cut_CellLoad(); +/* + { + Abc_Ntk_t * pNtkRes; + extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); + pNtkRes = Abc_NtkTopmost( pNtk, nLevels ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } +*/ +// Abc_NtkSimulteBuggyMiter( pNtk ); + +// Rwr_Temp(); +// Abc_MvExperiment(); +// Ivy_TruthTest(); + + +// Ivy_TruthEstimateNodesTest(); +/* + pNtkRes = Abc_NtkIvy( pNtk ); +// pNtkRes = Abc_NtkPlayer( pNtk, nLevels, 0 ); +// pNtkRes = NULL; + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); +*/ +// Abc_NtkMaxFlowTest( pNtk ); +// Pr_ManProofTest( "trace.cnf" ); + +// Abc_NtkCompareSupports( pNtk ); +// Abc_NtkCompareCones( pNtk ); +/* + { + extern Vec_Vec_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int fVerbose ); + Vec_Vec_t * vParts; + vParts = Abc_NtkPartitionSmart( pNtk, 1 ); + Vec_VecFree( vParts ); + } +*/ +// Abc_Ntk4VarTable( pNtk ); +// Dar_NtkGenerateArrays( pNtk ); +// Dar_ManDeriveCnfTest2(); +/* + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Network should be strashed. Command has failed.\n" ); + return 1; + } +*/ +/* + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Currently only works for structurally hashed circuits.\n" ); + return 0; + } +*/ + if ( Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Currently only works for logic circuits.\n" ); + return 0; + } + +// pNtkRes = Abc_NtkDar( pNtk ); +// pNtkRes = Abc_NtkDarRetime( pNtk, nLevels, 1 ); +// pNtkRes = Abc_NtkPcmTest( pNtk, fVerbose ); + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; +usage: + fprintf( pErr, "usage: test [-h]\n" ); + fprintf( pErr, "\t testbench for new procedures\n" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandQuaVar( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, iVar, fUniv, fVerbose, RetValue; + extern int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + iVar = 0; + fUniv = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Iuvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + iVar = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iVar < 0 ) + goto usage; + break; + case 'u': + fUniv ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" ); + return 1; + } + + // get the strashed network + pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + RetValue = Abc_NtkQuantify( pNtkRes, fUniv, iVar, fVerbose ); + // clean temporary storage for the cofactors + Abc_NtkCleanData( pNtkRes ); + Abc_AigCleanup( pNtkRes->pManFunc ); + // check the result + if ( !RetValue ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: qvar [-I num] [-uvh]\n" ); + fprintf( pErr, "\t quantifies one variable using the AIG\n" ); + fprintf( pErr, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar ); + fprintf( pErr, "\t-u : toggle universal quantification [default = %s]\n", fUniv? "yes": "no" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandQuaRel( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, iVar, fInputs, fVerbose; + extern Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + iVar = 0; + fInputs = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Iqvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + iVar = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iVar < 0 ) + goto usage; + break; + case 'q': + fInputs ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" ); + return 1; + } + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "This command works only for sequential circuits.\n" ); + return 1; + } + + // get the strashed network + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); + pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose ); + Abc_NtkDelete( pNtk ); + } + else + pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose ); + // check if the result is available + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: qrel [-qvh]\n" ); + fprintf( pErr, "\t computes transition relation of the sequential network\n" ); +// fprintf( pErr, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar ); + fprintf( pErr, "\t-q : perform quantification of inputs [default = %s]\n", fInputs? "yes": "no" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandQuaReach( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nIters, fVerbose; + extern Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtk, int nIters, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nIters = 256; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" ); + return 1; + } + if ( !Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "This command works only for combinational transition relations.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + if ( Abc_NtkPoNum(pNtk) > 1 ) + { + fprintf( pErr, "The transition relation should have one output.\n" ); + return 1; + } + if ( Abc_NtkPiNum(pNtk) % 2 != 0 ) + { + fprintf( pErr, "The transition relation should have an even number of inputs.\n" ); + return 1; + } + + pNtkRes = Abc_NtkReachability( pNtk, nIters, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: qreach [-I num] [-vh]\n" ); + fprintf( pErr, "\t computes unreachable states using AIG-based quantification\n" ); + fprintf( pErr, "\t assumes that the current network is a transition relation\n" ); + fprintf( pErr, "\t assumes that the initial state is composed of all zeros\n" ); + fprintf( pErr, "\t-I num : the number of image computations to perform [default = %d]\n", nIters ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp; + int c; + extern Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtkTemp = Abc_NtkStrash( pNtk, 0, 1, 0 ); + pNtkRes = Abc_NtkIvyStrash( pNtkTemp ); + Abc_NtkDelete( pNtkTemp ); + } + else + pNtkRes = Abc_NtkIvyStrash( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: istrash [-h]\n" ); + fprintf( pErr, "\t perform sequential structural hashing\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandICut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c, nInputs; + extern void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nInputs = 5; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nInputs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInputs < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + Abc_NtkIvyCuts( pNtk, nInputs ); + return 0; + +usage: + fprintf( pErr, "usage: icut [-K num] [-h]\n" ); + fprintf( pErr, "\t computes sequential cuts of the given size\n" ); + fprintf( pErr, "\t-K num : the number of cut inputs (2 <= num <= 6) [default = %d]\n", nInputs ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUpdateLevel, fUseZeroCost, fVerbose; + extern Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUpdateLevel = 1; + fUseZeroCost = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeroCost ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyRewrite( pNtk, fUpdateLevel, fUseZeroCost, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: irw [-lzvh]\n" ); + fprintf( pErr, "\t perform combinational AIG rewriting\n" ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + Dar_RwrPar_t Pars, * pPars = &Pars; + int c; + + extern Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Dar_ManDefaultRwrParams( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CNflzvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCutsMax < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nSubgMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nSubgMax < 0 ) + goto usage; + break; + case 'f': + pPars->fFanout ^= 1; + break; + case 'l': + pPars->fUpdateLevel ^= 1; + break; + case 'z': + pPars->fUseZeros ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDRewrite( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: drw [-C num] [-N num] [-flzvwh]\n" ); + fprintf( pErr, "\t performs combinational AIG rewriting\n" ); + fprintf( pErr, "\t-C num : the max number of cuts at a node [default = %d]\n", pPars->nCutsMax ); + fprintf( pErr, "\t-N num : the max number of subgraphs tried [default = %d]\n", pPars->nSubgMax ); + fprintf( pErr, "\t-f : toggle representing fanouts [default = %s]\n", pPars->fFanout? "yes": "no" ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + Dar_RefPar_t Pars, * pPars = &Pars; + int c; + + extern Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Dar_ManDefaultRefParams( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "MKCelzvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'M': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMffcMin = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMffcMin < 0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLeafMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLeafMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCutsMax < 0 ) + goto usage; + break; + case 'e': + pPars->fExtend ^= 1; + break; + case 'l': + pPars->fUpdateLevel ^= 1; + break; + case 'z': + pPars->fUseZeros ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + if ( pPars->nLeafMax < 4 || pPars->nLeafMax > 15 ) + { + fprintf( pErr, "This command only works for cut sizes 4 <= K <= 15.\n" ); + return 1; + } + pNtkRes = Abc_NtkDRefactor( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: drf [-M num] [-K num] [-C num] [-elzvwh]\n" ); + fprintf( pErr, "\t performs combinational AIG refactoring\n" ); + fprintf( pErr, "\t-M num : the min MFFC size to attempt refactoring [default = %d]\n", pPars->nMffcMin ); + fprintf( pErr, "\t-K num : the max number of cuts leaves [default = %d]\n", pPars->nLeafMax ); + fprintf( pErr, "\t-C num : the max number of cuts to try at a node [default = %d]\n", pPars->nCutsMax ); + fprintf( pErr, "\t-e : toggle extending tbe cut below MFFC [default = %s]\n", pPars->fExtend? "yes": "no" ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int fBalance, fVerbose, fUpdateLevel, c; + + extern Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fBalance = 0; + fVerbose = 0; + fUpdateLevel = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "blvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fBalance ^= 1; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDCompress2( pNtk, fBalance, fUpdateLevel, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: dcompress2 [-blvh]\n" ); + fprintf( pErr, "\t performs combinational AIG optimization\n" ); + fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); + fprintf( pErr, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDChoice( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int fBalance, fVerbose, fUpdateLevel, c; + + extern Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fBalance = 1; + fUpdateLevel = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "blvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fBalance ^= 1; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDChoice( pNtk, fBalance, fUpdateLevel, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: dchoice [-blvh]\n" ); + fprintf( pErr, "\t performs partitioned choicing using a new AIG package\n" ); + fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); + fprintf( pErr, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDrwsat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int fBalance, fVerbose, c; + + extern Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fBalance = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "bvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fBalance ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDrwsat( pNtk, fBalance, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: drwsat [-bvh]\n" ); + fprintf( pErr, "\t performs combinational AIG optimization for SAT\n" ); + fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIRewriteSeq( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUpdateLevel, fUseZeroCost, fVerbose; + extern Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUpdateLevel = 0; + fUseZeroCost = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeroCost ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyRewriteSeq( pNtk, fUseZeroCost, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: irws [-zvh]\n" ); + fprintf( pErr, "\t perform sequential AIG rewriting\n" ); +// fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIResyn( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUpdateLevel, fVerbose; + extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUpdateLevel = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyResyn( pNtk, fUpdateLevel, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: iresyn [-lvh]\n" ); + fprintf( pErr, "\t performs combinational resynthesis\n" ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandISat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUpdateLevel, fVerbose; + int nConfLimit; + + extern Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nConfLimit = 100000; + fUpdateLevel = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Clzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvySat( pNtk, nConfLimit, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: isat [-C num] [-vh]\n" ); + fprintf( pErr, "\t tries to prove the miter constant 0\n" ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); +// fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fProve, fVerbose, fDoSparse; + int nConfLimit; + + extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nConfLimit = 100; + fDoSparse = 0; + fProve = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Cspvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 's': + fDoSparse ^= 1; + break; + case 'p': + fProve ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: ifraig [-C num] [-spvh]\n" ); + fprintf( pErr, "\t performs fraiging using a new method\n" ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" ); + fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nConfLimit, fDoSparse, fProve, fSpeculate, fChoicing, fVerbose; + + extern Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nConfLimit = 100; + fDoSparse = 1; + fProve = 0; + fSpeculate = 0; + fChoicing = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Csprcvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 's': + fDoSparse ^= 1; + break; + case 'p': + fProve ^= 1; + break; + case 'r': + fSpeculate ^= 1; + break; + case 'c': + fChoicing ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkDarFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fSpeculate, fChoicing, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: dfraig [-C num] [-sprcvh]\n" ); + fprintf( pErr, "\t performs fraiging using a new method\n" ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" ); + fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" ); + fprintf( pErr, "\t-r : toggle speculative reduction [default = %s]\n", fSpeculate? "yes": "no" ); + fprintf( pErr, "\t-c : toggle accumulation of choices [default = %s]\n", fChoicing? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nCutsMax, nLeafMax, fVerbose; + + extern Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nCutsMax = 8; + nLeafMax = 6; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CKvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLeafMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLeafMax < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( nCutsMax < 2 ) + { + fprintf( pErr, "The number of cuts cannot be less than 2.\n" ); + return 1; + } + + if ( nLeafMax < 3 || nLeafMax > 16 ) + { + fprintf( pErr, "The number of leaves is infeasible.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkCSweep( pNtk, nCutsMax, nLeafMax, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: csweep [-C num] [-K num] [-vh]\n" ); + fprintf( pErr, "\t performs cut sweeping using a new method\n" ); + fprintf( pErr, "\t-C num : limit on the number of cuts (C >= 2) [default = %d]\n", nCutsMax ); + fprintf( pErr, "\t-K num : limit on the cut size (3 <= K <= 16) [default = %d]\n", nLeafMax ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Prove_Params_t Params, * pParams = &Params; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkTemp; + int c, clk, RetValue; + + extern int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Prove_ParamsSetDefault( pParams ); + pParams->fUseRewriting = 1; + pParams->fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) + { + switch ( c ) + { + case 'r': + pParams->fUseRewriting ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + clk = clock(); + + if ( Abc_NtkIsStrash(pNtk) ) + pNtkTemp = Abc_NtkDup( pNtk ); + else + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + + RetValue = Abc_NtkIvyProve( &pNtkTemp, pParams ); + + // verify that the pattern is correct + if ( RetValue == 0 ) + { + int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); + free( pSimInfo ); + } + + if ( RetValue == -1 ) + printf( "UNDECIDED " ); + else if ( RetValue == 0 ) + printf( "SATISFIABLE " ); + else + printf( "UNSATISFIABLE " ); + //printf( "\n" ); + + PRT( "Time", clock() - clk ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp ); + return 0; + +usage: + fprintf( pErr, "usage: iprove [-rvh]\n" ); + fprintf( pErr, "\t performs CEC using a new method\n" ); + fprintf( pErr, "\t-r : toggle AIG rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pParams->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandHaig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUseZeroCost, fVerbose, nIters; + extern Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int nIters, int fUseZeroCost, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nIters = 2; + fUseZeroCost = 0; + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Izvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'z': + fUseZeroCost ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyHaig( pNtk, nIters, fUseZeroCost, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: haig [-Izvh]\n" ); + fprintf( pErr, "\t prints HAIG stats after sequential rewriting\n" ); + fprintf( pErr, "\t-I num : the number of rewriting iterations [default = %d]\n", nIters ); + fprintf( pErr, "\t-z : toggle zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMini( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + extern Abc_Ntk_t * Abc_NtkMiniBalance( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Only works for combinatinally strashed AIG networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkMiniBalance( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: mini [-h]\n" ); + fprintf( pErr, "\t perform balancing using new package\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBmc( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nFrames; + int fInit; + int fVerbose; + + extern void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFrames = 5; + fInit = 0; + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kivh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'i': + fInit ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + Abc_NtkBmc( pNtk, nFrames, fInit, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Abc_NtkBmc( pNtk, nFrames, fInit, fVerbose ); + Abc_NtkDelete( pNtk ); + } + return 0; + +usage: + fprintf( pErr, "usage: _bmc [-K num] [-ivh]\n" ); + fprintf( pErr, "\t perform bounded model checking\n" ); + fprintf( pErr, "\t-K num : number of time frames [default = %d]\n", nFrames ); + fprintf( pErr, "\t-i : toggle initialization of the first frame [default = %s]\n", fInit? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandQbf( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nPars; + int fVerbose; + + extern void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nPars = -1; + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Pvh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nPars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPars < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "Works only for combinational networks.\n" ); + return 1; + } + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + fprintf( pErr, "The miter should have one primary output.\n" ); + return 1; + } + if ( !(nPars > 0 && nPars < Abc_NtkPiNum(pNtk)) ) + { + fprintf( pErr, "The number of paramter variables is invalid (should be > 0 and < PI num).\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + Abc_NtkQbf( pNtk, nPars, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Abc_NtkQbf( pNtk, nPars, fVerbose ); + Abc_NtkDelete( pNtk ); + } + return 0; + +usage: + fprintf( pErr, "usage: qbf [-P num] [-vh]\n" ); + fprintf( pErr, "\t solves a quantified boolean formula problem EpVxM(p,x)\n" ); + fprintf( pErr, "\t-P num : number of paramters (should be the first PIs) [default = %d]\n", nPars ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[100]; + Fraig_Params_t Params, * pParams = &Params; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int fAllNodes; + int fExdc; + int c; + int fPartition = 0; + extern void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fExdc = 0; + fAllNodes = 0; + memset( pParams, 0, sizeof(Fraig_Params_t) ); + pParams->nPatsRand = 2048; // the number of words of random simulation info + pParams->nPatsDyna = 2048; // the number of words of dynamic simulation info + pParams->nBTLimit = 100; // the max number of backtracks to perform + pParams->fFuncRed = 1; // performs only one level hashing + pParams->fFeedBack = 1; // enables solver feedback + pParams->fDist1Pats = 1; // enables distance-1 patterns + pParams->fDoSparse = 1; // performs equiv tests for sparse functions + pParams->fChoicing = 0; // enables recording structural choices + pParams->fTryProve = 0; // tries to solve the final miter + pParams->fVerbose = 0; // the verbosiness flag + pParams->fVerboseP = 0; // the verbosiness flag + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "RDCrscptvaeh" ) ) != EOF ) + { + switch ( c ) + { + case 'R': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nPatsRand = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nPatsRand < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nPatsDyna = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nPatsDyna < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nBTLimit < 0 ) + goto usage; + break; + + case 'r': + pParams->fFuncRed ^= 1; + break; + case 's': + pParams->fDoSparse ^= 1; + break; + case 'c': + pParams->fChoicing ^= 1; + break; + case 'p': + pParams->fTryProve ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 't': + fPartition ^= 1; + break; + case 'a': + fAllNodes ^= 1; + break; + case 'e': + fExdc ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Can only fraig a logic network or an AIG.\n" ); + return 1; + } + + // report the proof + pParams->fVerboseP = pParams->fTryProve; + + // get the new network + if ( fPartition ) + { + pNtkRes = Abc_NtkDup( pNtk ); + if ( Abc_NtkIsStrash(pNtk) ) + Abc_NtkFraigPartitionedTime( pNtk, &Params ); + else + { + pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 ); + Abc_NtkFraigPartitionedTime( pNtk, &Params ); + Abc_NtkDelete( pNtk ); + } + } + else + { + if ( Abc_NtkIsStrash(pNtk) ) + pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc ); + else + { + pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 ); + pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc ); + Abc_NtkDelete( pNtk ); + } + } + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Fraiging has failed.\n" ); + return 1; + } + + if ( pParams->fTryProve ) // report the result + Abc_NtkMiterReport( pNtkRes ); + + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + sprintf( Buffer, "%d", pParams->nBTLimit ); + fprintf( pErr, "usage: fraig [-R num] [-D num] [-C num] [-rscpvtah]\n" ); + fprintf( pErr, "\t transforms a logic network into a functionally reduced AIG\n" ); + fprintf( pErr, "\t-R num : number of random patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsRand ); + fprintf( pErr, "\t-D num : number of systematic patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsDyna ); + fprintf( pErr, "\t-C num : number of backtracks for one SAT problem [default = %s]\n", pParams->nBTLimit==-1? "infinity" : Buffer ); + fprintf( pErr, "\t-r : toggle functional reduction [default = %s]\n", pParams->fFuncRed? "yes": "no" ); + fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", pParams->fDoSparse? "yes": "no" ); + fprintf( pErr, "\t-c : toggle accumulation of choices [default = %s]\n", pParams->fChoicing? "yes": "no" ); + fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", pParams->fTryProve? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", pParams->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" ); + fprintf( pErr, "\t-a : toggle between all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "dfs" ); + fprintf( pErr, "\t-t : toggle using partitioned representation [default = %s]\n", fPartition? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigTrust( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fDuplicate; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fDuplicate = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDuplicate ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkFraigTrust( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Fraiging in the trust mode has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: fraig_trust [-h]\n" ); + fprintf( pErr, "\t transforms the current network into an AIG assuming it is FRAIG with choices\n" ); +// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigStore( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fDuplicate; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fDuplicate = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDuplicate ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkFraigStore( pNtk ) ) + { + fprintf( pErr, "Fraig storing has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: fraig_store [-h]\n" ); + fprintf( pErr, "\t saves the current network in the AIG database\n" ); +// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigRestore( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fDuplicate; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fDuplicate = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDuplicate ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkFraigRestore(); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Fraig restoring has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: fraig_restore [-h]\n" ); + fprintf( pErr, "\t makes the current network by fraiging the AIG database\n" ); +// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigClean( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fDuplicate; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fDuplicate = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDuplicate ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + Abc_NtkFraigStoreClean(); + return 0; + +usage: + fprintf( pErr, "usage: fraig_clean [-h]\n" ); + fprintf( pErr, "\t cleans the internal FRAIG storage\n" ); +// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fUseInv; + int fExdc; + int fVerbose; + int fVeryVerbose; + extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseInv = 1; + fExdc = 0; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ievwh" ) ) != EOF ) + { + switch ( c ) + { + case 'i': + fUseInv ^= 1; + break; + case 'e': + fExdc ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Cannot sweep AIGs (use \"fraig\").\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Transform the current network into a logic network.\n" ); + return 1; + } + // modify the current network + if ( !Abc_NtkFraigSweep( pNtk, fUseInv, fExdc, fVerbose, fVeryVerbose ) ) + { + fprintf( pErr, "Sweeping has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: fraig_sweep [-evwh]\n" ); + fprintf( pErr, "\t performs technology-dependent sweep\n" ); + fprintf( pErr, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : prints equivalence class information [default = %s]\n", fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigDress( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + int fVerbose; + extern void Abc_NtkDress( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for logic networks.\n" ); + return 1; + } + if ( argc != globalUtilOptind && argc != globalUtilOptind + 1 ) + goto usage; + if ( argc == globalUtilOptind && Abc_NtkSpec(pNtk) == NULL ) + { + fprintf( pErr, "The current network has no spec.\n" ); + return 1; + } + // get the input file name + pFileName = (argc == globalUtilOptind + 1) ? argv[globalUtilOptind] : Abc_NtkSpec(pNtk); + // modify the current network + Abc_NtkDress( pNtk, pFileName, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: dress [-vh] <file>\n" ); + fprintf( pErr, "\t transfers internal node names from file to the current network\n" ); + fprintf( pErr, "\t<file> : network with names (if not given, the current network spec is used)\n" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandHaigStart( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" ); + return 0; + } + Abc_NtkHaigStart( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: haig_start [-h]\n" ); + fprintf( pErr, "\t starts constructive accumulation of combinational choices\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandHaigStop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" ); + return 0; + } + Abc_NtkHaigStop( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: haig_stop [-h]\n" ); + fprintf( pErr, "\t cleans the internal storage for combinational choices\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandHaigUse( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" ); + return 0; + } + // get the new network + pNtkRes = Abc_NtkHaigUse( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Transforming internal storage into AIG with choices has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: haig_use [-h]\n" ); + fprintf( pErr, "\t transforms internal storage into an AIG with choices\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecStart( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nVars; + int nCuts; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nVars = 4; + nCuts = 8; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KCh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 1 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCuts < 1 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !(nVars >= 3 && nVars <= 16) ) + { + fprintf( pErr, "The range of allowed values is 3 <= K <= 16.\n" ); + return 0; + } + if ( Abc_NtkRecIsRunning() ) + { + fprintf( pErr, "The AIG subgraph recording is already started.\n" ); + return 0; + } + if ( pNtk && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" ); + return 0; + } + Abc_NtkRecStart( pNtk, nVars, nCuts ); + return 0; + +usage: + fprintf( pErr, "usage: rec_start [-K num] [-C num] [-h]\n" ); + fprintf( pErr, "\t starts recording AIG subgraphs (should be called for\n" ); + fprintf( pErr, "\t an empty network or after reading in a previous record)\n" ); + fprintf( pErr, "\t-K num : the largest number of inputs [default = %d]\n", nVars ); + fprintf( pErr, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCuts ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecStop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning() ) + { + fprintf( pErr, "This command works only after calling \"rec_start\".\n" ); + return 0; + } + Abc_NtkRecStop(); + return 0; + +usage: + fprintf( pErr, "usage: rec_stop [-h]\n" ); + fprintf( pErr, "\t cleans the internal storage for AIG subgraphs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecAdd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works for AIGs.\n" ); + return 0; + } + if ( !Abc_NtkRecIsRunning() ) + { + fprintf( pErr, "This command works for AIGs after calling \"rec_start\".\n" ); + return 0; + } + Abc_NtkRecAdd( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: rec_add [-h]\n" ); + fprintf( pErr, "\t adds subgraphs from the current network to the set\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecPs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning() ) + { + fprintf( pErr, "This command works for AIGs only after calling \"rec_start\".\n" ); + return 0; + } + Abc_NtkRecPs(); + return 0; + +usage: + fprintf( pErr, "usage: rec_ps [-h]\n" ); + fprintf( pErr, "\t prints statistics about the recorded AIG subgraphs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecUse( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning() ) + { + fprintf( pErr, "This command works for AIGs only after calling \"rec_start\".\n" ); + return 0; + } + // get the new network + pNtkRes = Abc_NtkRecUse(); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Transforming internal AIG subgraphs into an AIG with choices has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: rec_use [-h]\n" ); + fprintf( pErr, "\t transforms internal storage into an AIG with choices\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + char Buffer[100]; + double DelayTarget; + int fRecovery; + int fSweep; + int fSwitching; + int fVerbose; + int c; + extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, int fSwitching, int fVerbose ); + extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + DelayTarget =-1; + fRecovery = 1; + fSweep = 1; + fSwitching = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Daspvh" ) ) != EOF ) + { + switch ( c ) + { + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); + goto usage; + } + DelayTarget = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( DelayTarget <= 0.0 ) + goto usage; + break; + case 'a': + fRecovery ^= 1; + break; + case 's': + fSweep ^= 1; + break; + case 'p': + fSwitching ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Strashing before mapping has failed.\n" ); + return 1; + } + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Balancing before mapping has failed.\n" ); + return 1; + } + fprintf( pOut, "The network was strashed and balanced before mapping.\n" ); + // get the new network + pNtkRes = Abc_NtkMap( pNtk, DelayTarget, fRecovery, fSwitching, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_NtkDelete( pNtk ); + fprintf( pErr, "Mapping has failed.\n" ); + return 1; + } + Abc_NtkDelete( pNtk ); + } + else + { + // get the new network + pNtkRes = Abc_NtkMap( pNtk, DelayTarget, fRecovery, fSwitching, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Mapping has failed.\n" ); + return 1; + } + } + + if ( fSweep ) + Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 ); + + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + if ( DelayTarget == -1 ) + sprintf( Buffer, "not used" ); + else + sprintf( Buffer, "%.3f", DelayTarget ); + fprintf( pErr, "usage: map [-D float] [-aspvh]\n" ); + fprintf( pErr, "\t performs standard cell mapping of the current network\n" ); + fprintf( pErr, "\t-D float : sets the global required times [default = %s]\n", Buffer ); + fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); + fprintf( pErr, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" ); + fprintf( pErr, "\t-p : optimizes power by minimizing switching [default = %s]\n", fSwitching? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkHasMapping(pNtk) ) + { + fprintf( pErr, "Cannot unmap the network that is not mapped.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkMapToSop( pNtk ) ) + { + fprintf( pErr, "Unmapping has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: unmap [-h]\n" ); + fprintf( pErr, "\t replaces the library gates by the logic nodes represented using SOPs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAttach( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + fprintf( pErr, "Can only attach gates if the nodes have SOP representations.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkAttach( pNtk ) ) + { + fprintf( pErr, "Attaching gates has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: attach [-h]\n" ); + fprintf( pErr, "\t replaces the SOP functions by the gates from the library\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Superchoicing works only for the AIG representation (run \"strash\").\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkSuperChoice( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Superchoicing has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: sc [-h]\n" ); + fprintf( pErr, "\t performs superchoicing\n" ); + fprintf( pErr, "\t (accumulate: \"r file.blif; rsup; b; sc; f -ac; wb file_sc.blif\")\n" ); + fprintf( pErr, "\t (map without supergate library: \"r file_sc.blif; ft; map\")\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSuperChoiceLut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int nLutSize; + int nCutSizeMax; + int fVerbose; + extern int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 1; + nLutSize = 4; + nCutSizeMax = 10; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KNh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by a positive integer.\n" ); + goto usage; + } + nCutSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutSizeMax < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Superchoicing works only for the AIG representation (run \"strash\").\n" ); + return 1; + } + + // convert the network into the SOP network + pNtkRes = Abc_NtkToLogic( pNtk ); + + // get the new network + if ( !Abc_NtkSuperChoiceLut( pNtkRes, nLutSize, nCutSizeMax, fVerbose ) ) + { + Abc_NtkDelete( pNtkRes ); + fprintf( pErr, "Superchoicing has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: scl [-K num] [-N num] [-vh]\n" ); + fprintf( pErr, "\t performs superchoicing for K-LUTs\n" ); + fprintf( pErr, "\t (accumulate: \"r file.blif; b; scl; f -ac; wb file_sc.blif\")\n" ); + fprintf( pErr, "\t (FPGA map: \"r file_sc.blif; ft; read_lut lutlibK; fpga\")\n" ); + fprintf( pErr, "\t-K num : the number of LUT inputs [default = %d]\n", nLutSize ); + fprintf( pErr, "\t-N num : the max size of the cut [default = %d]\n", nCutSizeMax ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[100]; + char LutSize[100]; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fRecovery; + int fSwitching; + int fLatchPaths; + int fVerbose; + int nLutSize; + float DelayTarget; + + extern Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fRecovery = 1; + fSwitching = 0; + fLatchPaths = 0; + fVerbose = 0; + DelayTarget =-1; + nLutSize =-1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "aplvhDK" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fRecovery ^= 1; + break; + case 'p': + fSwitching ^= 1; + break; + case 'l': + fLatchPaths ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); + goto usage; + } + DelayTarget = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( DelayTarget <= 0.0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // create the new LUT library + if ( nLutSize >= 3 && nLutSize <= 10 ) + Fpga_SetSimpleLutLib( nLutSize ); +/* + else + { + fprintf( pErr, "Cannot perform FPGA mapping with LUT size %d.\n", nLutSize ); + return 1; + } +*/ + if ( !Abc_NtkIsStrash(pNtk) ) + { + // strash and balance the network + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Strashing before FPGA mapping has failed.\n" ); + return 1; + } + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Balancing before FPGA mapping has failed.\n" ); + return 1; + } + fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" ); + // get the new network + pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_NtkDelete( pNtk ); + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 1; + } + Abc_NtkDelete( pNtk ); + } + else + { + // get the new network + pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 1; + } + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + if ( DelayTarget == -1 ) + sprintf( Buffer, "best possible" ); + else + sprintf( Buffer, "%.2f", DelayTarget ); + if ( nLutSize == -1 ) + sprintf( LutSize, "library" ); + else + sprintf( LutSize, "%d", nLutSize ); + fprintf( pErr, "usage: fpga [-D float] [-K num] [-aplvh]\n" ); + fprintf( pErr, "\t performs FPGA mapping of the current network\n" ); + fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); + fprintf( pErr, "\t-p : optimizes power by minimizing switching activity [default = %s]\n", fSwitching? "yes": "no" ); + fprintf( pErr, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", fLatchPaths? "yes": "no" ); + fprintf( pErr, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer ); + fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < 11) [default = %s]%s\n", LutSize, (nLutSize == -1 ? " (type \"print_lut\")" : "") ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : prints the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFpgaFast( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[100]; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fRecovery; + int fVerbose; + int nLutSize; + float DelayTarget; + + extern Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fRecovery = 1; + fVerbose = 0; + DelayTarget =-1; + nLutSize = 5; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "avhDK" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fRecovery ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); + goto usage; + } + DelayTarget = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( DelayTarget <= 0.0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + // strash and balance the network + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Strashing before FPGA mapping has failed.\n" ); + return 1; + } + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Balancing before FPGA mapping has failed.\n" ); + return 1; + } + fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" ); + // get the new network + pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_NtkDelete( pNtk ); + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 1; + } + Abc_NtkDelete( pNtk ); + } + else + { + // get the new network + pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 1; + } + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + if ( DelayTarget == -1 ) + sprintf( Buffer, "not used" ); + else + sprintf( Buffer, "%.2f", DelayTarget ); + fprintf( pErr, "usage: ffpga [-K num] [-avh]\n" ); + fprintf( pErr, "\t performs fast FPGA mapping of the current network\n" ); + fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); +// fprintf( pErr, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer ); + fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < 32) [default = %d]\n", nLutSize ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : prints the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[100]; + char LutSize[100]; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + If_Par_t Pars, * pPars = &Pars; + int c; + extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + memset( pPars, 0, sizeof(If_Par_t) ); + // user-controlable paramters + pPars->nLutSize = -1; + pPars->nCutsMax = 8; + pPars->nFlowIters = 1; + pPars->nAreaIters = 2; + pPars->DelayTarget = -1; + pPars->fPreprocess = 1;// + pPars->fArea = 0; + pPars->fFancy = 0; + pPars->fExpRed = 1;// + pPars->fLatchPaths = 0; + pPars->fSeqMap = 0; + pPars->fVerbose = 0;// + // internal parameters + pPars->fTruth = 0; + pPars->nLatches = pNtk? Abc_NtkLatchNum(pNtk) : 0; + pPars->fLiftLeaves = 0; + pPars->pLutLib = Abc_FrameReadLibLut(); + pPars->pTimesArr = NULL; + pPars->pTimesArr = NULL; + pPars->pFuncCost = NULL; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADpaflrstvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLutSize < 0 ) + goto usage; + // if the LUT size is specified, disable library + pPars->pLutLib = NULL; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCutsMax < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->nFlowIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nFlowIters < 0 ) + goto usage; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-A\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->nAreaIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nAreaIters < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); + goto usage; + } + pPars->DelayTarget = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->DelayTarget <= 0.0 ) + goto usage; + break; + case 'p': + pPars->fPreprocess ^= 1; + break; + case 'a': + pPars->fArea ^= 1; + break; + case 'f': + pPars->fFancy ^= 1; + break; + case 'l': + pPars->fLatchPaths ^= 1; + break; + case 'r': + pPars->fExpRed ^= 1; + break; + case 's': + pPars->fSeqMap ^= 1; + break; + case 't': + pPars->fLiftLeaves ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( pPars->fSeqMap && pPars->nLatches == 0 ) + { + fprintf( pErr, "The network has no latches. Use combinational mapping instead of sequential.\n" ); + return 1; + } + + if ( pPars->nLutSize == -1 ) + { + if ( pPars->pLutLib == NULL ) + { + fprintf( pErr, "The LUT library is not given.\n" ); + return 1; + } + // get LUT size from the library + pPars->nLutSize = pPars->pLutLib->LutMax; + } + + if ( pPars->nLutSize < 3 || pPars->nLutSize > IF_MAX_LUTSIZE ) + { + fprintf( pErr, "Incorrect LUT size (%d).\n", pPars->nLutSize ); + return 1; + } + + if ( pPars->nCutsMax < 1 || pPars->nCutsMax >= (1<<12) ) + { + fprintf( pErr, "Incorrect number of cuts.\n" ); + return 1; + } + + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + printf( "Performing FPGA mapping with choices.\n" ); +// printf( "Currently mapping with choices is not enabled.\n" ); + pPars->fTruth = 1; +// return 1; + } + + if ( pPars->fTruth && pPars->nLutSize > IF_MAX_FUNC_LUTSIZE ) + { + fprintf( pErr, "Mapping with choices requires computing truth tables. In this case, the LUT size cannot be more than %d.\n", IF_MAX_FUNC_LUTSIZE ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + // strash and balance the network + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Strashing before FPGA mapping has failed.\n" ); + return 1; + } + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Balancing before FPGA mapping has failed.\n" ); + return 1; + } + fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" ); + // get the new network + pNtkRes = Abc_NtkIf( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + Abc_NtkDelete( pNtk ); + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 0; + } + Abc_NtkDelete( pNtk ); + } + else + { + // get the new network + pNtkRes = Abc_NtkIf( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 0; + } + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + if ( pPars->DelayTarget == -1 ) + sprintf( Buffer, "best possible" ); + else + sprintf( Buffer, "%.2f", pPars->DelayTarget ); + if ( pPars->nLutSize == -1 ) + sprintf( LutSize, "library" ); + else + sprintf( LutSize, "%d", pPars->nLutSize ); + fprintf( pErr, "usage: if [-K num] [-C num] [-F num] [-A num] [-D float] [-pafrsvh]\n" ); + fprintf( pErr, "\t performs FPGA technology mapping of the network\n" ); + fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); + fprintf( pErr, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); + fprintf( pErr, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters ); + fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters ); + fprintf( pErr, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); + fprintf( pErr, "\t-p : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); + fprintf( pErr, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" ); +// fprintf( pErr, "\t-f : toggles one fancy feature [default = %s]\n", pPars->fFancy? "yes": "no" ); + fprintf( pErr, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" ); + fprintf( pErr, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" ); + fprintf( pErr, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeqMap? "yes": "no" ); +// fprintf( pErr, "\t-t : toggles the use of true sequential cuts [default = %s]\n", pPars->fLiftLeaves? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : prints the command usage\n"); + return 1; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandInit( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj; + int c, i; + int fZeros; + int fOnes; + int fRandom; + int fDontCare; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fZeros = 0; + fOnes = 0; + fRandom = 0; + fDontCare = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "zordh" ) ) != EOF ) + { + switch ( c ) + { + case 'z': + fZeros ^= 1; + break; + case 'o': + fOnes ^= 1; + break; + case 'r': + fRandom ^= 1; + break; + case 'd': + fDontCare ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The current network is combinational.\n" ); + return 0; + } + + if ( fZeros ) + { + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_LatchSetInit0( pObj ); + } + else if ( fOnes ) + { + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_LatchSetInit1( pObj ); + } + else if ( fRandom ) + { + Abc_NtkForEachLatch( pNtk, pObj, i ) + if ( rand() & 1 ) + Abc_LatchSetInit1( pObj ); + else + Abc_LatchSetInit0( pObj ); + } + else if ( fDontCare ) + { + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_LatchSetInitDc( pObj ); + } + else + printf( "The initial states remain unchanged.\n" ); + return 0; + +usage: + fprintf( pErr, "usage: init [-zordh]\n" ); + fprintf( pErr, "\t resets initial states of all latches\n" ); + fprintf( pErr, "\t-z : set zeros initial states [default = %s]\n", fZeros? "yes": "no" ); + fprintf( pErr, "\t-o : set ones initial states [default = %s]\n", fOnes? "yes": "no" ); + fprintf( pErr, "\t-d : set don't-care initial states [default = %s]\n", fDontCare? "yes": "no" ); + fprintf( pErr, "\t-r : set random initial states [default = %s]\n", fRandom? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandZero( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + extern Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, bool fCleanup ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The current network is combinational.\n" ); + return 0; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs.\n" ); + return 0; + } + + // get the new network + pNtkRes = Abc_NtkRestrashZero( pNtk, 0 ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Converting to sequential AIG has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: zero [-h]\n" ); + fprintf( pErr, "\t converts latches to have const-0 initial value\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandUndc( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The current network is combinational.\n" ); + return 0; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "This command works only for logic networks.\n" ); + return 0; + } + + // get the new network + Abc_NtkConvertDcLatches( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: undc [-h]\n" ); + fprintf( pErr, "\t converts latches with DC init values into free PIs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPipe( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nLatches; + extern void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nLatches = 5; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Lh" ) ) != EOF ) + { + switch ( c ) + { + case 'L': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-L\" should be followed by a positive integer.\n" ); + goto usage; + } + nLatches = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLatches < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The current network is combinational.\n" ); + return 1; + } + + // update the network + Abc_NtkLatchPipe( pNtk, nLatches ); + return 0; + +usage: + fprintf( pErr, "usage: pipe [-L num] [-h]\n" ); + fprintf( pErr, "\t inserts the given number of latches at each PI for pipelining\n" ); + fprintf( pErr, "\t-L num : the number of latches to insert [default = %d]\n", nLatches ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + fprintf( pErr, "The network has no latches.\n" ); + return 0; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Conversion to sequential AIG works only for combinational AIGs (run \"strash\").\n" ); + return 1; + } + + // get the new network +// pNtkRes = Abc_NtkAigToSeq( pNtk ); + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Converting to sequential AIG has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: seq [-h]\n" ); + fprintf( pErr, "\t converts AIG into sequential AIG\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandUnseq( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fShare; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fShare = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fShare ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } +/* + if ( !Abc_NtkIsSeq(pNtk) ) + { + fprintf( pErr, "Conversion to combinational AIG works only for sequential AIG (run \"seq\").\n" ); + return 1; + } +*/ + // share the latches on the fanout edges +// if ( fShare ) +// Seq_NtkShareFanouts(pNtk); + + // get the new network +// pNtkRes = Abc_NtkSeqToLogicSop( pNtk ); + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Converting sequential AIG into an SOP logic network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: unseq [-sh]\n" ); + fprintf( pErr, "\t converts sequential AIG into an SOP logic network\n" ); + fprintf( pErr, "\t-s : toggle sharing latches [default = %s]\n", fShare? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nMaxIters; + int fForward; + int fBackward; + int fOneStep; + int fVerbose; + int Mode; + extern int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Mode = 5; + fForward = 0; + fBackward = 0; + fOneStep = 0; + fVerbose = 0; + nMaxIters = 15; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Mfbsvh" ) ) != EOF ) + { + switch ( c ) + { + case 'M': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-M\" should be followed by a positive integer.\n" ); + goto usage; + } + Mode = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Mode < 0 ) + goto usage; + break; + case 'f': + fForward ^= 1; + break; + case 'b': + fBackward ^= 1; + break; + case 's': + fOneStep ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( fForward && fBackward ) + { + fprintf( pErr, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" ); + return 1; + } + + if ( !Abc_NtkLatchNum(pNtk) ) + { + fprintf( pErr, "The network has no latches. Retiming is not performed.\n" ); + return 0; + } + + if ( Mode < 0 || Mode > 6 ) + { + fprintf( pErr, "The mode (%d) is incorrect. Retiming is not performed.\n", Mode ); + return 0; + } + + if ( Abc_NtkIsStrash(pNtk) ) + { + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "Retiming with choice nodes is not implemented.\n" ); + return 0; + } + // convert the network into an SOP network + pNtkRes = Abc_NtkToLogic( pNtk ); + // perform the retiming + Abc_NtkRetime( pNtkRes, Mode, fForward, fBackward, fOneStep, fVerbose ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + } + + // get the network in the SOP form + if ( !Abc_NtkToSop(pNtk, 0) ) + { + printf( "Converting to SOPs has failed.\n" ); + return 0; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "The network is not a logic network. Retiming is not performed.\n" ); + return 0; + } + + // perform the retiming + Abc_NtkRetime( pNtk, Mode, fForward, fBackward, fOneStep, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: retime [-M num] [-fbvh]\n" ); + fprintf( pErr, "\t retimes the current network using one of the algorithms:\n" ); + fprintf( pErr, "\t 1: most forward retiming\n" ); + fprintf( pErr, "\t 2: most backward retiming\n" ); + fprintf( pErr, "\t 3: forward and backward min-area retiming\n" ); + fprintf( pErr, "\t 4: forward and backward min-delay retiming\n" ); + fprintf( pErr, "\t 5: mode 3 followed by mode 4\n" ); + fprintf( pErr, "\t 6: Pan's optimum-delay retiming using binary search\n" ); + fprintf( pErr, "\t-M num : the retiming algorithm to use [default = %d]\n", Mode ); + fprintf( pErr, "\t-f : enables forward-only retiming in modes 3,4,5 [default = %s]\n", fForward? "yes": "no" ); + fprintf( pErr, "\t-b : enables backward-only retiming in modes 3,4,5 [default = %s]\n", fBackward? "yes": "no" ); + fprintf( pErr, "\t-s : enables retiming one step only in mode 4 [default = %s]\n", fOneStep? "yes": "no" ); + fprintf( pErr, "\t-v : enables verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +// fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters ); +// fprintf( pErr, "\t-f : toggle forward retiming (for AIGs) [default = %s]\n", fForward? "yes": "no" ); +// fprintf( pErr, "\t-b : toggle backward retiming (for AIGs) [default = %s]\n", fBackward? "yes": "no" ); +// fprintf( pErr, "\t-i : toggle computation of initial state [default = %s]\n", fInitial? "yes": "no" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; + int c, nMaxIters; + int fVerbose; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nMaxIters = 15; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nMaxIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxIters < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkHasAig(pNtk) ) + { +/* + // quit if there are choice nodes + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "Currently cannot map/retime networks with choice nodes.\n" ); + return 0; + } +*/ +// if ( Abc_NtkIsStrash(pNtk) ) +// pNtkNew = Abc_NtkAigToSeq(pNtk); +// else +// pNtkNew = Abc_NtkDup(pNtk); + pNtkNew = NULL; + } + else + { + // strash and balance the network + pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtkNew == NULL ) + { + fprintf( pErr, "Strashing before FPGA mapping/retiming has failed.\n" ); + return 1; + } + + pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtkNew == NULL ) + { + fprintf( pErr, "Balancing before FPGA mapping has failed.\n" ); + return 1; + } + + // convert into a sequential AIG +// pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew ); + pNtkNew = NULL; + Abc_NtkDelete( pNtkRes ); + if ( pNtkNew == NULL ) + { + fprintf( pErr, "Converting into a seq AIG before FPGA mapping/retiming has failed.\n" ); + return 1; + } + + fprintf( pOut, "The network was strashed and balanced before FPGA mapping/retiming.\n" ); + } + + // get the new network +// pNtkRes = Seq_NtkFpgaMapRetime( pNtkNew, nMaxIters, fVerbose ); + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { +// fprintf( pErr, "Sequential FPGA mapping has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return 0; + } + Abc_NtkDelete( pNtkNew ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: sfpga [-I num] [-vh]\n" ); + fprintf( pErr, "\t performs integrated sequential FPGA mapping/retiming\n" ); + fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; + int c, nMaxIters; + int fVerbose; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nMaxIters = 15; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nMaxIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxIters < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkHasAig(pNtk) ) + { +/* + // quit if there are choice nodes + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "Currently cannot map/retime networks with choice nodes.\n" ); + return 0; + } +*/ +// if ( Abc_NtkIsStrash(pNtk) ) +// pNtkNew = Abc_NtkAigToSeq(pNtk); +// else +// pNtkNew = Abc_NtkDup(pNtk); + pNtkNew = NULL; + } + else + { + // strash and balance the network + pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtkNew == NULL ) + { + fprintf( pErr, "Strashing before SC mapping/retiming has failed.\n" ); + return 1; + } + + pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtkNew == NULL ) + { + fprintf( pErr, "Balancing before SC mapping/retiming has failed.\n" ); + return 1; + } + + // convert into a sequential AIG +// pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew ); + pNtkNew = NULL; + Abc_NtkDelete( pNtkRes ); + if ( pNtkNew == NULL ) + { + fprintf( pErr, "Converting into a seq AIG before SC mapping/retiming has failed.\n" ); + return 1; + } + + fprintf( pOut, "The network was strashed and balanced before SC mapping/retiming.\n" ); + } + + // get the new network +// pNtkRes = Seq_MapRetime( pNtkNew, nMaxIters, fVerbose ); + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { +// fprintf( pErr, "Sequential FPGA mapping has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return 0; + } + Abc_NtkDelete( pNtkNew ); + + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: smap [-I num] [-vh]\n" ); + fprintf( pErr, "\t performs integrated sequential standard-cell mapping/retiming\n" ); + fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int nFramesP; + int nFramesK; + int nMaxImps; + int fUseImps; + int fRewrite; + int fLatchCorr; + int fWriteImps; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFrames, int nMaxImps, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFramesP = 0; + nFramesK = 1; + nMaxImps = 5000; + fUseImps = 0; + fRewrite = 0; + fLatchCorr = 0; + fWriteImps = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "PFIirlevh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nFramesP = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFramesP < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFramesK = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFramesK <= 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nMaxImps = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxImps <= 0 ) + goto usage; + break; + case 'i': + fUseImps ^= 1; + break; + case 'r': + fRewrite ^= 1; + break; + case 'l': + fLatchCorr ^= 1; + break; + case 'e': + fWriteImps ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); + return 0; + } + + // get the new network + pNtkRes = Abc_NtkDarSeqSweep( pNtk, nFramesP, nFramesK, nMaxImps, fRewrite, fUseImps, fLatchCorr, fWriteImps, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Sequential sweeping has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: ssweep [-P num] [-F num] [-I num] [-ilrevh]\n" ); + fprintf( pErr, "\t performs sequential sweep using K-step induction\n" ); + fprintf( pErr, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP ); + fprintf( pErr, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", nFramesK ); + fprintf( pErr, "\t-I num : max number of implications to consider [default = %d]\n", nMaxImps ); + fprintf( pErr, "\t-i : toggle using implications [default = %s]\n", fUseImps? "yes": "no" ); + fprintf( pErr, "\t-l : toggle latch correspondence only [default = %s]\n", fLatchCorr? "yes": "no" ); + fprintf( pErr, "\t-r : toggle AIG rewriting [default = %s]\n", fRewrite? "yes": "no" ); + fprintf( pErr, "\t-e : toggle writing implications as assertions [default = %s]\n", fWriteImps? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int nFramesP; + int nConfMax; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFramesP = 0; + nConfMax = 10000; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "PCvh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nFramesP = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFramesP < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfMax < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); + return 0; + } + + // get the new network + pNtkRes = Abc_NtkDarLcorr( pNtk, nFramesP, nConfMax, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Sequential sweeping has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: lcorr [-P num] [-C num] [-vh]\n" ); + fprintf( pErr, "\t computes latch correspondence using 1-step induction\n" ); + fprintf( pErr, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP ); + fprintf( pErr, "\t-C num : max conflict number when proving latch equivalence [default = %d]\n", nConfMax ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fLatchSweep; + int fAutoSweep; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fLatchSweep = 0; + fAutoSweep = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lavh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fLatchSweep ^= 1; + break; + case 'a': + fAutoSweep ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Only works for structrally hashed networks.\n" ); + return 1; + } + if ( !Abc_NtkLatchNum(pNtk) ) + { + fprintf( pErr, "Only works for sequential networks.\n" ); + return 1; + } + // modify the current network + pNtkRes = Abc_NtkDarLatchSweep( pNtk, fLatchSweep, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Sequential cleanup has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: scleanup [-lvh]\n" ); + fprintf( pErr, "\t performs sequential cleanup\n" ); + fprintf( pErr, "\t - removes nodes/latches that do not feed into POs\n" ); + fprintf( pErr, "\t - removes stuck-at and identical latches (latch sweep)\n" ); +// fprintf( pErr, "\t - replaces autonomous logic by free PI variables\n" ); + fprintf( pErr, "\t (the latter may change sequential behaviour)\n" ); + fprintf( pErr, "\t-l : toggle sweeping latches [default = %s]\n", fLatchSweep? "yes": "no" ); +// fprintf( pErr, "\t-a : toggle removing autonomous logic [default = %s]\n", fAutoSweep? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCycle( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nFrames; + int fVerbose; + extern void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); + extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFrames = 100; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSopLogic(pNtk) ) + { + fprintf( pErr, "Only works for strashed networks or logic SOP networks.\n" ); + return 1; + } + if ( !Abc_NtkLatchNum(pNtk) ) + { + fprintf( pErr, "Only works for sequential networks.\n" ); + return 1; + } + + if ( Abc_NtkIsStrash(pNtk) ) + Abc_NtkCycleInitState( pNtk, nFrames, fVerbose ); + else + Abc_NtkCycleInitStateSop( pNtk, nFrames, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: cycle [-F num] [-vh]\n" ); + fprintf( pErr, "\t cycles sequiential circuit for the given number of timeframes\n" ); + fprintf( pErr, "\t to derive a new initial state (which may be on the envelope)\n" ); + fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandXsim( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nFrames; + int fXInputs; + int fXState; + int fVerbose; + extern void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFrames = 10; + fXInputs = 0; + fXState = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Fisvh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'i': + fXInputs ^= 1; + break; + case 's': + fXState ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Only works for strashed networks.\n" ); + return 1; + } + if ( !Abc_NtkLatchNum(pNtk) ) + { + fprintf( pErr, "Only works for sequential networks.\n" ); + return 1; + } + Abc_NtkXValueSimulate( pNtk, nFrames, fXInputs, fXState, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: xsim [-F num] [-isvh]\n" ); + fprintf( pErr, "\t performs X-valued simulation of the AIG\n" ); + fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); + fprintf( pErr, "\t-i : toggle X-valued representation of inputs [default = %s]\n", fXInputs? "yes": "no" ); + fprintf( pErr, "\t-s : toggle X-valued representation of state [default = %s]\n", fXState? "yes": "no" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[16]; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; + int c; + int fSat; + int fVerbose; + int nSeconds; + int nPartSize; + int nConfLimit; + int nInsLimit; + int fPartition; + + extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ); + extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); + extern void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose ); + extern void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fSat = 0; + fVerbose = 0; + nSeconds = 20; + nPartSize = 0; + nConfLimit = 10000; + nInsLimit = 0; + fPartition = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "TCIPpsvh" ) ) != EOF ) + { + switch ( c ) + { + case 'T': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + nSeconds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSeconds < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nInsLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInsLimit < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nPartSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPartSize < 0 ) + goto usage; + break; + case 'p': + fPartition ^= 1; + break; + case 's': + fSat ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + + // perform equivalence checking + if ( fPartition ) + Abc_NtkCecFraigPartAuto( pNtk1, pNtk2, nSeconds, fVerbose ); + else if ( nPartSize ) + Abc_NtkCecFraigPart( pNtk1, pNtk2, nSeconds, nPartSize, fVerbose ); + else if ( fSat ) + Abc_NtkCecSat( pNtk1, pNtk2, nConfLimit, nInsLimit ); + else + Abc_NtkCecFraig( pNtk1, pNtk2, nSeconds, fVerbose ); + + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + return 0; + +usage: + if ( nPartSize == 0 ) + strcpy( Buffer, "unused" ); + else + sprintf( Buffer, "%d", nPartSize ); + fprintf( pErr, "usage: cec [-T num] [-C num] [-I num] [-P num] [-psvh] <file1> <file2>\n" ); + fprintf( pErr, "\t performs combinational equivalence checking\n" ); + fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-I num : limit on the number of clause inspections [default = %d]\n", nInsLimit ); + fprintf( pErr, "\t-P num : partition size for multi-output networks [default = %s]\n", Buffer ); + fprintf( pErr, "\t-p : toggle automatic partitioning [default = %s]\n", fPartition? "yes": "no" ); + fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); + fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); + fprintf( pErr, "\t if no files are given, uses the current network and its spec\n"); + fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; + int c; + int fRetime; + int fSat; + int fVerbose; + int nFrames; + int nSeconds; + int nConfLimit; + int nInsLimit; + + extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames ); + extern int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ); + extern void Abc_NtkSecRetime( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ); + + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fRetime = 0; // verification after retiming + fSat = 0; + fVerbose = 0; + nFrames = 5; + nSeconds = 20; + nConfLimit = 10000; + nInsLimit = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "FTCIsrvh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames <= 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + nSeconds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSeconds < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nInsLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInsLimit < 0 ) + goto usage; + break; + case 'r': + fRetime ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 's': + fSat ^= 1; + break; + default: + goto usage; + } + } + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + + if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) + { + printf( "The network has no latches. Used combinational command \"cec\".\n" ); + return 0; + } + + // perform equivalence checking + if ( fRetime ) + Abc_NtkSecRetime( pNtk1, pNtk2 ); + else if ( fSat ) + Abc_NtkSecSat( pNtk1, pNtk2, nConfLimit, nInsLimit, nFrames ); + else + Abc_NtkSecFraig( pNtk1, pNtk2, nSeconds, nFrames, fVerbose ); + + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + return 0; + +usage: + fprintf( pErr, "usage: sec [-F num] [-T num] [-C num] [-I num] [-srvh] <file1> <file2>\n" ); + fprintf( pErr, "\t performs bounded sequential equivalence checking\n" ); + fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" ); + fprintf( pErr, "\t-r : toggles retiming verification [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t-F num : the number of time frames to use [default = %d]\n", nFrames ); + fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit ); + fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); + fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); + fprintf( pErr, "\t if no files are given, uses the current network and its spec\n"); + fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; + int c; + int fRetimeFirst; + int fVerbose; + int fVeryVerbose; + int nFrames; + + extern int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFrames =16; + fRetimeFirst = 1; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Krwvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'r': + fRetimeFirst ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + + if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) + { + printf( "The network has no latches. Used combinational command \"cec\".\n" ); + return 0; + } + + // perform verification + Abc_NtkDarSec( pNtk1, pNtk2, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); + + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + return 0; + +usage: + fprintf( pErr, "usage: dsec [-K num] [-rwvh] <file1> <file2>\n" ); + fprintf( pErr, "\t performs inductive sequential equivalence checking\n" ); + fprintf( pErr, "\t-K num : the limit on the depth of induction [default = %d]\n", nFrames ); + fprintf( pErr, "\t-r : toggles forward retiming at the beginning [default = %s]\n", fRetimeFirst? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggles additional verbose output [default = %s]\n", fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); + fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); + fprintf( pErr, "\t if no files are given, uses the current network and its spec\n"); + fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fRetimeFirst; + int fVerbose; + int fVeryVerbose; + int nFrames; + + extern int Abc_NtkDarProve( Abc_Ntk_t * pNtk, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFrames = 16; + fRetimeFirst = 1; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Krwvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'r': + fRetimeFirst ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + printf( "The network has no latches. Used combinational command \"iprove\".\n" ); + return 0; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); + return 0; + } + + // perform verification + Abc_NtkDarProve( pNtk, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: dprove [-K num] [-rwvh]\n" ); + fprintf( pErr, "\t performs SEC on the sequential miter\n" ); + fprintf( pErr, "\t-K num : the limit on the depth of induction [default = %d]\n", nFrames ); + fprintf( pErr, "\t-r : toggles forward retiming at the beginning [default = %s]\n", fRetimeFirst? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggles additional verbose output [default = %s]\n", fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int RetValue; + int fVerbose; + int nConfLimit; + int nInsLimit; + int clk; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + nConfLimit = 100000; + nInsLimit = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nInsLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInsLimit < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" ); + return 0; + } + + clk = clock(); + if ( Abc_NtkIsStrash(pNtk) ) + { + RetValue = Abc_NtkMiterSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose, NULL, NULL ); + } + else + { + assert( Abc_NtkIsLogic(pNtk) ); + Abc_NtkToBdd( pNtk ); + RetValue = Abc_NtkMiterSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose, NULL, NULL ); + } + + // verify that the pattern is correct + if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 ) + { + //int i; + //Abc_Obj_t * pObj; + int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" ); + free( pSimInfo ); + /* + // print model + Abc_NtkForEachPi( pNtk, pObj, i ) + { + printf( "%d", (int)(pNtk->pModel[i] > 0) ); + if ( i == 70 ) + break; + } + printf( "\n" ); + */ + } + + if ( RetValue == -1 ) + printf( "UNDECIDED " ); + else if ( RetValue == 0 ) + printf( "SATISFIABLE " ); + else + printf( "UNSATISFIABLE " ); + //printf( "\n" ); + PRT( "Time", clock() - clk ); + return 0; + +usage: + fprintf( pErr, "usage: sat [-C num] [-I num] [-vh]\n" ); + fprintf( pErr, "\t solves the combinational miter using SAT solver MiniSat-1.14\n" ); + fprintf( pErr, "\t derives CNF from the current network and leave it unchanged\n" ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDSat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int RetValue; + int fVerbose; + int nConfLimit; + int nInsLimit; + int clk; + + extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose ); + + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + nConfLimit = 100000; + nInsLimit = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nInsLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInsLimit < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" ); + return 0; + } + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + fprintf( stdout, "Currently expects a single-output miter.\n" ); + return 0; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Currently only works for structurally hashed circuits.\n" ); + return 0; + } + + clk = clock(); + RetValue = Abc_NtkDSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose ); + // verify that the pattern is correct + if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 ) + { + //int i; + //Abc_Obj_t * pObj; + int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" ); + free( pSimInfo ); + /* + // print model + Abc_NtkForEachPi( pNtk, pObj, i ) + { + printf( "%d", (int)(pNtk->pModel[i] > 0) ); + if ( i == 70 ) + break; + } + printf( "\n" ); + */ + } + + if ( RetValue == -1 ) + printf( "UNDECIDED " ); + else if ( RetValue == 0 ) + printf( "SATISFIABLE " ); + else + printf( "UNSATISFIABLE " ); + //printf( "\n" ); + PRT( "Time", clock() - clk ); + return 0; + +usage: + fprintf( pErr, "usage: dsat [-C num] [-I num] [-vh]\n" ); + fprintf( pErr, "\t solves the combinational miter using SAT solver MiniSat-1.14\n" ); + fprintf( pErr, "\t derives CNF from the current network and leave it unchanged\n" ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkTemp; + Prove_Params_t Params, * pParams = &Params; + int c, clk, RetValue; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Prove_ParamsSetDefault( pParams ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NCFLIrfbvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nItersMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nItersMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nMiteringLimitStart = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nMiteringLimitStart < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nFraigingLimitStart = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nFraigingLimitStart < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nMiteringLimitLast = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nMiteringLimitLast < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nTotalInspectLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nTotalInspectLimit < 0 ) + goto usage; + break; + case 'r': + pParams->fUseRewriting ^= 1; + break; + case 'f': + pParams->fUseFraiging ^= 1; + break; + case 'b': + pParams->fUseBdds ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" ); + return 0; + } + if ( Abc_NtkCoNum(pNtk) != 1 ) + { + fprintf( stdout, "Currently can only solve the miter with one output.\n" ); + return 0; + } + clk = clock(); + + if ( Abc_NtkIsStrash(pNtk) ) + pNtkTemp = Abc_NtkDup( pNtk ); + else + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + + RetValue = Abc_NtkMiterProve( &pNtkTemp, pParams ); + + // verify that the pattern is correct + if ( RetValue == 0 ) + { + int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); + free( pSimInfo ); + } + + if ( RetValue == -1 ) + printf( "UNDECIDED " ); + else if ( RetValue == 0 ) + printf( "SATISFIABLE " ); + else + printf( "UNSATISFIABLE " ); + //printf( "\n" ); + + PRT( "Time", clock() - clk ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp ); + return 0; + +usage: + fprintf( pErr, "usage: prove [-N num] [-C num] [-F num] [-L num] [-I num] [-rfbvh]\n" ); + fprintf( pErr, "\t solves combinational miter by rewriting, FRAIGing, and SAT\n" ); + fprintf( pErr, "\t replaces the current network by the cone modified by rewriting\n" ); + fprintf( pErr, "\t-N num : max number of iterations [default = %d]\n", pParams->nItersMax ); + fprintf( pErr, "\t-C num : max starting number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitStart ); + fprintf( pErr, "\t-F num : max starting number of conflicts in fraiging [default = %d]\n", pParams->nFraigingLimitStart ); + fprintf( pErr, "\t-L num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast ); + fprintf( pErr, "\t-I num : max number of clause inspections in all SAT calls [default = %d]\n", (int)pParams->nTotalInspectLimit ); + fprintf( pErr, "\t-r : toggle the use of rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" ); + fprintf( pErr, "\t-f : toggle the use of FRAIGing [default = %s]\n", pParams->fUseFraiging? "yes": "no" ); + fprintf( pErr, "\t-b : toggle the use of BDDs [default = %s]\n", pParams->fUseBdds? "yes": "no" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDebug( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + extern void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) ); + extern int Abc_NtkRetimeDebug( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "This command is applicable to logic networks.\n" ); + return 1; + } + + Abc_NtkAutoDebug( pNtk, Abc_NtkRetimeDebug ); + return 0; + +usage: + fprintf( pErr, "usage: debug [-h]\n" ); + fprintf( pErr, "\t performs automated debugging of the given procedure\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTraceStart( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command is applicable to AIGs.\n" ); + return 1; + } +/* + Abc_HManStart(); + if ( !Abc_HManPopulate( pNtk ) ) + { + fprintf( pErr, "Failed to start the tracing database.\n" ); + return 1; + } +*/ + return 0; + +usage: + fprintf( pErr, "usage: trace_start [-h]\n" ); + fprintf( pErr, "\t starts verification tracing\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTraceCheck( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command is applicable to AIGs.\n" ); + return 1; + } +/* + if ( !Abc_HManIsRunning(pNtk) ) + { + fprintf( pErr, "The tracing database is not available.\n" ); + return 1; + } + + if ( !Abc_HManVerify( 1, pNtk->Id ) ) + fprintf( pErr, "Verification failed.\n" ); + Abc_HManStop(); +*/ + return 0; + +usage: + fprintf( pErr, "usage: trace_check [-h]\n" ); + fprintf( pErr, "\t checks the current network using verification trace\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcAttach.c b/abc70930/src/base/abci/abcAttach.c new file mode 100644 index 00000000..d5d2aa16 --- /dev/null +++ b/abc70930/src/base/abci/abcAttach.c @@ -0,0 +1,404 @@ +/**CFile**************************************************************** + + FileName [abcAttach.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Attaches the library gates to the current network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcAttach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ATTACH_FULL (~((unsigned)0)) +#define ATTACH_MASK(n) ((~((unsigned)0)) >> (32-(n))) + +static void Abc_AttachSetupTruthTables( unsigned uTruths[][2] ); +static void Abc_AttachComputeTruth( char * pSop, unsigned uTruthsIn[][2], unsigned * uTruthNode ); +static Mio_Gate_t * Abc_AttachFind( Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned * uTruthNode, int * Perm ); +static int Abc_AttachCompare( unsigned ** puTruthGates, int nGates, unsigned * uTruthNode ); +static int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned uTruths[][2] ); +static void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned * uTruthPerm ); + +static char ** s_pPerms = NULL; +static int s_nPerms; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Attaches gates from the current library to the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkAttach( Abc_Ntk_t * pNtk ) +{ + Mio_Library_t * pGenlib; + unsigned ** puTruthGates; + unsigned uTruths[6][2]; + Abc_Obj_t * pNode; + Mio_Gate_t ** ppGates; + int nGates, nFanins, i; + + assert( Abc_NtkIsSopLogic(pNtk) ); + + // check that the library is available + pGenlib = Abc_FrameReadLibGen(); + if ( pGenlib == NULL ) + { + printf( "The current library is not available.\n" ); + return 0; + } + + // start the truth tables + Abc_AttachSetupTruthTables( uTruths ); + + // collect all the gates + ppGates = Mio_CollectRoots( pGenlib, 6, (float)1.0e+20, 1, &nGates ); + + // derive the gate truth tables + puTruthGates = ALLOC( unsigned *, nGates ); + puTruthGates[0] = ALLOC( unsigned, 2 * nGates ); + for ( i = 1; i < nGates; i++ ) + puTruthGates[i] = puTruthGates[i-1] + 2; + for ( i = 0; i < nGates; i++ ) + Mio_DeriveTruthTable( ppGates[i], uTruths, Mio_GateReadInputs(ppGates[i]), 6, puTruthGates[i] ); + + // assign the gates to pNode->pCopy + Abc_NtkCleanCopy( pNtk ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + nFanins = Abc_ObjFaninNum(pNode); + if ( nFanins == 0 ) + { + if ( Abc_SopIsConst1(pNode->pData) ) + pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadConst1(pGenlib); + else + pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadConst0(pGenlib); + } + else if ( nFanins == 1 ) + { + if ( Abc_SopIsBuf(pNode->pData) ) + pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadBuf(pGenlib); + else + pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadInv(pGenlib); + } + else if ( nFanins > 6 ) + { + printf( "Cannot attach gate with more than 6 inputs to node %s.\n", Abc_ObjName(pNode) ); + free( puTruthGates[0] ); + free( puTruthGates ); + free( ppGates ); + return 0; + } + else if ( !Abc_NodeAttach( pNode, ppGates, puTruthGates, nGates, uTruths ) ) + { + printf( "Could not attach the library gate to node %s.\n", Abc_ObjName(pNode) ); + free( puTruthGates[0] ); + free( puTruthGates ); + free( ppGates ); + return 0; + } + } + free( puTruthGates[0] ); + free( puTruthGates ); + free( ppGates ); + FREE( s_pPerms ); + + // perform the final transformation + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( pNode->pCopy == NULL ) + { + printf( "Some elementary gates (constant, buffer, or inverter) are missing in the library.\n" ); + return 0; + } + } + + // replace SOP representation by the gate representation + Abc_NtkForEachNode( pNtk, pNode, i ) + pNode->pData = pNode->pCopy, pNode->pCopy = NULL; + pNtk->ntkFunc = ABC_FUNC_MAP; + Extra_MmFlexStop( pNtk->pManFunc ); + pNtk->pManFunc = pGenlib; + + printf( "Library gates are successfully attached to the nodes.\n" ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkAttach: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned uTruths[][2] ) +{ + int Perm[10]; + int pTempInts[10]; + unsigned uTruthNode[2]; + Abc_Obj_t * pFanin; + Mio_Gate_t * pGate; + int nFanins, i; + + // compute the node's truth table + Abc_AttachComputeTruth( pNode->pData, uTruths, uTruthNode ); + // find the matching gate and permutation + pGate = Abc_AttachFind( ppGates, puTruthGates, nGates, uTruthNode, Perm ); + if ( pGate == NULL ) + return 0; + // permute the fanins + nFanins = Abc_ObjFaninNum(pNode); + Abc_ObjForEachFanin( pNode, pFanin, i ) + pTempInts[i] = pFanin->Id; + for ( i = 0; i < nFanins; i++ ) + pNode->vFanins.pArray[Perm[i]] = pTempInts[i]; + // set the gate + pNode->pCopy = (Abc_Obj_t *)pGate; + return 1; +} + +/**Function************************************************************* + + Synopsis [Sets up the truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AttachSetupTruthTables( unsigned uTruths[][2] ) +{ + int m, v; + for ( v = 0; v < 5; v++ ) + uTruths[v][0] = 0; + // set up the truth tables + for ( m = 0; m < 32; m++ ) + for ( v = 0; v < 5; v++ ) + if ( m & (1 << v) ) + uTruths[v][0] |= (1 << m); + // make adjustments for the case of 6 variables + for ( v = 0; v < 5; v++ ) + uTruths[v][1] = uTruths[v][0]; + uTruths[5][0] = 0; + uTruths[5][1] = ATTACH_FULL; +} + +/**Function************************************************************* + + Synopsis [Compute the truth table of the node's cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AttachComputeTruth( char * pSop, unsigned uTruthsIn[][2], unsigned * uTruthRes ) +{ +// Mvc_Cube_t * pCube; + unsigned uSignCube[2]; + int Value; +// int nInputs = pCover->nBits/2; + int nInputs = 6; + int nFanins = Abc_SopGetVarNum(pSop); + char * pCube; + int k; + + // make sure that the number of input truth tables in equal to the number of gate inputs + assert( nInputs < 7 ); + + // clean the resulting truth table + uTruthRes[0] = 0; + uTruthRes[1] = 0; + if ( nInputs < 6 ) + { + // consider the case when only one unsigned can be used +// Mvc_CoverForEachCube( pCover, pCube ) + Abc_SopForEachCube( pSop, nFanins, pCube ) + { + uSignCube[0] = ATTACH_FULL; +// Mvc_CubeForEachVarValue( pCover, pCube, Var, Value ) + Abc_CubeForEachVar( pCube, Value, k ) + { + if ( Value == '0' ) + uSignCube[0] &= ~uTruthsIn[k][0]; + else if ( Value == '1' ) + uSignCube[0] &= uTruthsIn[k][0]; + } + uTruthRes[0] |= uSignCube[0]; + } + if ( Abc_SopGetPhase(pSop) == 0 ) + uTruthRes[0] = ~uTruthRes[0]; + if ( nInputs < 5 ) + uTruthRes[0] &= ATTACH_MASK(1<<nInputs); + } + else + { + // consider the case when two unsigneds should be used +// Mvc_CoverForEachCube( pCover, pCube ) + Abc_SopForEachCube( pSop, nFanins, pCube ) + { + uSignCube[0] = ATTACH_FULL; + uSignCube[1] = ATTACH_FULL; +// Mvc_CubeForEachVarValue( pCover, pCube, Var, Value ) + Abc_CubeForEachVar( pCube, Value, k ) + { + if ( Value == '0' ) + { + uSignCube[0] &= ~uTruthsIn[k][0]; + uSignCube[1] &= ~uTruthsIn[k][1]; + } + else if ( Value == '1' ) + { + uSignCube[0] &= uTruthsIn[k][0]; + uSignCube[1] &= uTruthsIn[k][1]; + } + } + uTruthRes[0] |= uSignCube[0]; + uTruthRes[1] |= uSignCube[1]; + } + + // complement if the SOP is complemented + if ( Abc_SopGetPhase(pSop) == 0 ) + { + uTruthRes[0] = ~uTruthRes[0]; + uTruthRes[1] = ~uTruthRes[1]; + } + } +} + +/**Function************************************************************* + + Synopsis [Find the gate by truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mio_Gate_t * Abc_AttachFind( Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned * uTruthNode, int * Perm ) +{ + unsigned uTruthPerm[2]; + int i, v, iNum; + + // try the gates without permutation + if ( (iNum = Abc_AttachCompare( puTruthGates, nGates, uTruthNode )) >= 0 ) + { + for ( v = 0; v < 6; v++ ) + Perm[v] = v; + return ppGates[iNum]; + } + // get permutations + if ( s_pPerms == NULL ) + { + s_pPerms = Extra_Permutations( 6 ); + s_nPerms = Extra_Factorial( 6 ); + } + // try permutations + for ( i = 0; i < s_nPerms; i++ ) + { + Abc_TruthPermute( s_pPerms[i], 6, uTruthNode, uTruthPerm ); + if ( (iNum = Abc_AttachCompare( puTruthGates, nGates, uTruthPerm )) >= 0 ) + { + for ( v = 0; v < 6; v++ ) + Perm[v] = (int)s_pPerms[i][v]; + return ppGates[iNum]; + } + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Find the gate by truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AttachCompare( unsigned ** puTruthGates, int nGates, unsigned * uTruthNode ) +{ + int i; + for ( i = 0; i < nGates; i++ ) + if ( puTruthGates[i][0] == uTruthNode[0] && puTruthGates[i][1] == uTruthNode[1] ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Permutes the 6-input truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned * uTruthPerm ) +{ + int nMints, iMintPerm, iMint, v; + uTruthPerm[0] = uTruthPerm[1] = 0; + nMints = (1 << nVars); + for ( iMint = 0; iMint < nMints; iMint++ ) + { + if ( (uTruthNode[iMint>>5] & (1 << (iMint&31))) == 0 ) + continue; + iMintPerm = 0; + for ( v = 0; v < nVars; v++ ) + if ( iMint & (1 << v) ) + iMintPerm |= (1 << pPerm[v]); + uTruthPerm[iMintPerm>>5] |= (1 << (iMintPerm&31)); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcAuto.c b/abc70930/src/base/abci/abcAuto.c new file mode 100644 index 00000000..40212c17 --- /dev/null +++ b/abc70930/src/base/abci/abcAuto.c @@ -0,0 +1,239 @@ +/**CFile**************************************************************** + + FileName [abcAuto.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Computation of autosymmetries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcAuto.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive ); +static void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ) +{ + DdManager * dd; // the BDD manager used to hold shared BDDs + DdNode ** pbGlobal; // temporary storage for global BDDs + char ** pInputNames; // pointers to the CI names + char ** pOutputNames; // pointers to the CO names + int nOutputs, nInputs, i; + Vec_Ptr_t * vFuncsGlob; + Abc_Obj_t * pObj; + + // compute the global BDDs + if ( Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose) == NULL ) + return; + + // get information about the network + nInputs = Abc_NtkCiNum(pNtk); + nOutputs = Abc_NtkCoNum(pNtk); +// dd = pNtk->pManGlob; + dd = Abc_NtkGlobalBddMan( pNtk ); + + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); + pbGlobal = (DdNode **)Vec_PtrArray( vFuncsGlob ); + + // get the network names + pInputNames = Abc_NtkCollectCioNames( pNtk, 0 ); + pOutputNames = Abc_NtkCollectCioNames( pNtk, 1 ); + + // print the size of the BDDs + if ( fVerbose ) + printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // allocate additional variables + for ( i = 0; i < nInputs; i++ ) + Cudd_bddNewVar( dd ); + assert( Cudd_ReadSize(dd) == 2 * nInputs ); + + // create ZDD variables in the manager + Cudd_zddVarsFromBddVars( dd, 2 ); + + // perform the analysis of the primary output functions for auto-symmetry + if ( Output == -1 ) + Abc_NtkAutoPrintAll( dd, nInputs, pbGlobal, nOutputs, pInputNames, pOutputNames, fNaive ); + else + Abc_NtkAutoPrintOne( dd, nInputs, pbGlobal, Output, pInputNames, pOutputNames, fNaive ); + + // deref the PO functions +// Abc_NtkFreeGlobalBdds( pNtk ); + // stop the global BDD manager +// Extra_StopManager( pNtk->pManGlob ); +// pNtk->pManGlob = NULL; + Abc_NtkFreeGlobalBdds( pNtk, 1 ); + free( pInputNames ); + free( pOutputNames ); + Vec_PtrFree( vFuncsGlob ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive ) +{ + DdNode * bSpace1, * bSpace2, * bCanVars, * bReduced, * zEquations; + double nMints; + int nSupp, SigCounter, o; + + int nAutos; + int nAutoSyms; + int nAutoSymsMax; + int nAutoSymsMaxSupp; + int nAutoSymOuts; + int nSuppSizeMax; + int clk; + + nAutoSymOuts = 0; + nAutoSyms = 0; + nAutoSymsMax = 0; + nAutoSymsMaxSupp = 0; + nSuppSizeMax = 0; + clk = clock(); + + SigCounter = 0; + for ( o = 0; o < nOutputs; o++ ) + { +// bSpace1 = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[o] ); Cudd_Ref( bSpace1 ); + bSpace1 = Extra_bddSpaceFromFunction( dd, pbOutputs[o], pbOutputs[o] ); Cudd_Ref( bSpace1 ); + bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 ); Cudd_Ref( bCanVars ); + bReduced = Extra_bddSpaceReduce( dd, pbOutputs[o], bCanVars ); Cudd_Ref( bReduced ); + zEquations = Extra_bddSpaceEquations( dd, bSpace1 ); Cudd_Ref( zEquations ); + + nSupp = Cudd_SupportSize( dd, bSpace1 ); + nMints = Cudd_CountMinterm( dd, bSpace1, nSupp ); + nAutos = Extra_Base2LogDouble(nMints); + printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", o, nSupp, nAutos ); + + if ( nAutos > 0 ) + { + nAutoSymOuts++; + nAutoSyms += nAutos; + if ( nAutoSymsMax < nAutos ) + { + nAutoSymsMax = nAutos; + nAutoSymsMaxSupp = nSupp; + } + } + if ( nSuppSizeMax < nSupp ) + nSuppSizeMax = nSupp; + + +//PRB( dd, bCanVars ); +//PRB( dd, bReduced ); +//Cudd_PrintMinterm( dd, bReduced ); +//printf( "The equations are:\n" ); +//Cudd_zddPrintCover( dd, zEquations ); +//printf( "\n" ); +//fflush( stdout ); + + bSpace2 = Extra_bddSpaceFromMatrixPos( dd, zEquations ); Cudd_Ref( bSpace2 ); +//PRB( dd, bSpace1 ); +//PRB( dd, bSpace2 ); + if ( bSpace1 != bSpace2 ) + printf( "Spaces are NOT EQUAL!\n" ); +// else +// printf( "Spaces are equal.\n" ); + + Cudd_RecursiveDeref( dd, bSpace1 ); + Cudd_RecursiveDeref( dd, bSpace2 ); + Cudd_RecursiveDeref( dd, bCanVars ); + Cudd_RecursiveDeref( dd, bReduced ); + Cudd_RecursiveDerefZdd( dd, zEquations ); + } + + printf( "The cumulative statistics for all outputs:\n" ); + printf( "Ins=%3d ", nInputs ); + printf( "InMax=%3d ", nSuppSizeMax ); + printf( "Outs=%3d ", nOutputs ); + printf( "Auto=%3d ", nAutoSymOuts ); + printf( "SumK=%3d ", nAutoSyms ); + printf( "KMax=%2d ", nAutoSymsMax ); + printf( "Supp=%3d ", nAutoSymsMaxSupp ); + printf( "Time=%4.2f ", (float)(clock() - clk)/(float)(CLOCKS_PER_SEC) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive ) +{ + DdNode * bSpace1, * bCanVars, * bReduced, * zEquations; + double nMints; + int nSupp, SigCounter; + int nAutos; + + SigCounter = 0; + bSpace1 = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[Output] ); Cudd_Ref( bSpace1 ); +// bSpace1 = Extra_bddSpaceFromFunction( dd, pbOutputs[Output], pbOutputs[Output] ); Cudd_Ref( bSpace1 ); + bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 ); Cudd_Ref( bCanVars ); + bReduced = Extra_bddSpaceReduce( dd, pbOutputs[Output], bCanVars ); Cudd_Ref( bReduced ); + zEquations = Extra_bddSpaceEquations( dd, bSpace1 ); Cudd_Ref( zEquations ); + + nSupp = Cudd_SupportSize( dd, bSpace1 ); + nMints = Cudd_CountMinterm( dd, bSpace1, nSupp ); + nAutos = Extra_Base2LogDouble(nMints); + printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", Output, nSupp, nAutos ); + + Cudd_RecursiveDeref( dd, bSpace1 ); + Cudd_RecursiveDeref( dd, bCanVars ); + Cudd_RecursiveDeref( dd, bReduced ); + Cudd_RecursiveDerefZdd( dd, zEquations ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcBalance.c b/abc70930/src/base/abci/abcBalance.c new file mode 100644 index 00000000..f9b3384e --- /dev/null +++ b/abc70930/src/base/abci/abcBalance.c @@ -0,0 +1,613 @@ +/**CFile**************************************************************** + + FileName [abcBalance.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Performs global balancing of the AIG by the number of levels.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcBalance.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel ); +static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel ); +static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vSuper, int Level, int fDuplicate, bool fSelective ); +static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective ); +static void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk ); +static Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Balances the AIG network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel ) +{ + extern void Abc_NtkHaigTranfer( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ); + Abc_Ntk_t * pNtkAig; + assert( Abc_NtkIsStrash(pNtk) ); + // compute the required times + if ( fSelective ) + { + Abc_NtkStartReverseLevels( pNtk, 0 ); + Abc_NtkMarkCriticalNodes( pNtk ); + } + // perform balancing + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer HAIG + Abc_NtkHaigTranfer( pNtk, pNtkAig ); + // perform balancing + Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate, fSelective, fUpdateLevel ); + Abc_NtkFinalize( pNtk, pNtkAig ); + // undo the required times + if ( fSelective ) + { + Abc_NtkStopReverseLevels( pNtk ); + Abc_NtkCleanMarkA( pNtk ); + } + if ( pNtk->pExdc ) + pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkBalance: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Balances the AIG network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel ) +{ + int fCheck = 1; + ProgressBar * pProgress; + Vec_Vec_t * vStorage; + Abc_Obj_t * pNode, * pDriver; + int i; + + // set the level of PIs of AIG according to the arrival times of the old network + Abc_NtkSetNodeLevelsArrival( pNtk ); + // allocate temporary storage for supergates + vStorage = Vec_VecStart( 10 ); + // perform balancing of POs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // strash the driver node + pDriver = Abc_ObjFanin0(pNode); + Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, 0, fDuplicate, fSelective, fUpdateLevel ); + } + Extra_ProgressBarStop( pProgress ); + Vec_VecFree( vStorage ); +} + +/**Function************************************************************* + + Synopsis [Finds the left bound on the next candidate to be paired.] + + Description [The nodes in the array are in the decreasing order of levels. + The last node in the array has the smallest level. By default it would be paired + with the next node on the left. However, it may be possible to pair it with some + other node on the left, in such a way that the new node is shared. This procedure + finds the index of the left-most node, which can be paired with the last node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) +{ + Abc_Obj_t * pNodeRight, * pNodeLeft; + int Current; + // if two or less nodes, pair with the first + if ( Vec_PtrSize(vSuper) < 3 ) + return 0; + // set the pointer to the one before the last + Current = Vec_PtrSize(vSuper) - 2; + pNodeRight = Vec_PtrEntry( vSuper, Current ); + // go through the nodes to the left of this one + for ( Current--; Current >= 0; Current-- ) + { + // get the next node on the left + pNodeLeft = Vec_PtrEntry( vSuper, Current ); + // if the level of this node is different, quit the loop + if ( Abc_ObjRegular(pNodeLeft)->Level != Abc_ObjRegular(pNodeRight)->Level ) + break; + } + Current++; + // get the node, for which the equality holds + pNodeLeft = Vec_PtrEntry( vSuper, Current ); + assert( Abc_ObjRegular(pNodeLeft)->Level == Abc_ObjRegular(pNodeRight)->Level ); + return Current; +} + +/**Function************************************************************* + + Synopsis [Moves closer to the end the node that is best for sharing.] + + Description [If there is no node with sharing, randomly chooses one of + the legal nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeBalancePermute( Abc_Ntk_t * pNtkNew, Vec_Ptr_t * vSuper, int LeftBound ) +{ + Abc_Obj_t * pNode1, * pNode2, * pNode3; + int RightBound, i; + // get the right bound + RightBound = Vec_PtrSize(vSuper) - 2; + assert( LeftBound <= RightBound ); + if ( LeftBound == RightBound ) + return; + // get the two last nodes + pNode1 = Vec_PtrEntry( vSuper, RightBound + 1 ); + pNode2 = Vec_PtrEntry( vSuper, RightBound ); + // find the first node that can be shared + for ( i = RightBound; i >= LeftBound; i-- ) + { + pNode3 = Vec_PtrEntry( vSuper, i ); + if ( Abc_AigAndLookup( pNtkNew->pManFunc, pNode1, pNode3 ) ) + { + if ( pNode3 == pNode2 ) + return; + Vec_PtrWriteEntry( vSuper, i, pNode2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pNode3 ); + return; + } + } +/* + // we did not find the node to share, randomize choice + { + int Choice = rand() % (RightBound - LeftBound + 1); + pNode3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); + if ( pNode3 == pNode2 ) + return; + Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pNode2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pNode3 ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Rebalances the multi-input node rooted at pNodeOld.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel ) +{ + Abc_Aig_t * pMan = pNtkNew->pManFunc; + Abc_Obj_t * pNodeNew, * pNode1, * pNode2; + Vec_Ptr_t * vSuper; + int i, LeftBound; + assert( !Abc_ObjIsComplement(pNodeOld) ); + // return if the result if known + if ( pNodeOld->pCopy ) + return pNodeOld->pCopy; + assert( Abc_ObjIsNode(pNodeOld) ); + // get the implication supergate +// Abc_NodeBalanceConeExor( pNodeOld ); + vSuper = Abc_NodeBalanceCone( pNodeOld, vStorage, Level, fDuplicate, fSelective ); + if ( vSuper->nSize == 0 ) + { // it means that the supergate contains two nodes in the opposite polarity + pNodeOld->pCopy = Abc_ObjNot(Abc_AigConst1(pNtkNew)); + return pNodeOld->pCopy; + } + // for each old node, derive the new well-balanced node + for ( i = 0; i < vSuper->nSize; i++ ) + { + pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular(vSuper->pArray[i]), vStorage, Level + 1, fDuplicate, fSelective, fUpdateLevel ); + vSuper->pArray[i] = Abc_ObjNotCond( pNodeNew, Abc_ObjIsComplement(vSuper->pArray[i]) ); + } + if ( vSuper->nSize < 2 ) + printf( "BUG!\n" ); + // sort the new nodes by level in the decreasing order + Vec_PtrSort( vSuper, Abc_NodeCompareLevelsDecrease ); + // balance the nodes + assert( vSuper->nSize > 1 ); + while ( vSuper->nSize > 1 ) + { + // find the left bound on the node to be paired + LeftBound = (!fUpdateLevel)? 0 : Abc_NodeBalanceFindLeft( vSuper ); + // find the node that can be shared (if no such node, randomize choice) + Abc_NodeBalancePermute( pNtkNew, vSuper, LeftBound ); + // pull out the last two nodes + pNode1 = Vec_PtrPop(vSuper); + pNode2 = Vec_PtrPop(vSuper); + Abc_VecObjPushUniqueOrderByLevel( vSuper, Abc_AigAnd(pMan, pNode1, pNode2) ); + } + // make sure the balanced node is not assigned + assert( pNodeOld->pCopy == NULL ); + // mark the old node with the new node + pNodeOld->pCopy = vSuper->pArray[0]; + vSuper->nSize = 0; +// if ( Abc_ObjRegular(pNodeOld->pCopy) == Abc_AigConst1(pNtkNew) ) +// printf( "Constant node\n" ); +// assert( pNodeOld->Level >= Abc_ObjRegular(pNodeOld->pCopy)->Level ); + // update HAIG + if ( Abc_ObjRegular(pNodeOld->pCopy)->pNtk->pHaig ) + Hop_ObjCreateChoice( pNodeOld->pEquiv, Abc_ObjRegular(pNodeOld->pCopy)->pEquiv ); + return pNodeOld->pCopy; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes in the cone delimited by fMarkA==1.] + + Description [Returns -1 if the AND-cone has the same node in both polarities. + Returns 1 if the AND-cone has the same node in the same polarity. Returns 0 + if the AND-cone has no repeated nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, int fDuplicate, bool fSelective ) +{ + Vec_Ptr_t * vNodes; + int RetValue, i; + assert( !Abc_ObjIsComplement(pNode) ); + // extend the storage + if ( Vec_VecSize( vStorage ) <= Level ) + Vec_VecPush( vStorage, Level, 0 ); + // get the temporary array of nodes + vNodes = Vec_VecEntry( vStorage, Level ); + Vec_PtrClear( vNodes ); + // collect the nodes in the implication supergate + RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, fDuplicate, fSelective ); + assert( vNodes->nSize > 1 ); + // unmark the visited nodes + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vNodes->nSize = 0; + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Collects the nodes in the cone delimited by fMarkA==1.] + + Description [Returns -1 if the AND-cone has the same node in both polarities. + Returns 1 if the AND-cone has the same node in the same polarity. Returns 0 + if the AND-cone has no repeated nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective ) +{ + int RetValue1, RetValue2, i; + // check if the node is visited + if ( Abc_ObjRegular(pNode)->fMarkB ) + { + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pNode ) + return 1; + // check if the node is present in the opposite polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == Abc_ObjNot(pNode) ) + return -1; + assert( 0 ); + return 0; + } + // if the new node is complemented or a PI, another gate begins + if ( !fFirst && (Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || !fDuplicate && !fSelective && (Abc_ObjFanoutNum(pNode) > 1)) ) + { + Vec_PtrPush( vSuper, pNode ); + Abc_ObjRegular(pNode)->fMarkB = 1; + return 0; + } + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + // go through the branches + RetValue1 = Abc_NodeBalanceCone_rec( Abc_ObjChild0(pNode), vSuper, 0, fDuplicate, fSelective ); + RetValue2 = Abc_NodeBalanceCone_rec( Abc_ObjChild1(pNode), vSuper, 0, fDuplicate, fSelective ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeBalanceConeExor_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst ) +{ + int RetValue1, RetValue2, i; + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pNode ) + return 1; + // if the new node is complemented or a PI, another gate begins + if ( !fFirst && (!pNode->fExor || !Abc_ObjIsNode(pNode)) ) + { + Vec_PtrPush( vSuper, pNode ); + return 0; + } + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + assert( pNode->fExor ); + // go through the branches + RetValue1 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin0(Abc_ObjFanin0(pNode)), vSuper, 0 ); + RetValue2 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin1(Abc_ObjFanin0(pNode)), vSuper, 0 ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vSuper; + if ( !pNode->fExor ) + return NULL; + vSuper = Vec_PtrAlloc( 10 ); + Abc_NodeBalanceConeExor_rec( pNode, vSuper, 1 ); + printf( "%d ", Vec_PtrSize(vSuper) ); + Vec_PtrFree( vSuper ); + return NULL; +} + + + +/**Function************************************************************* + + Synopsis [Collects the nodes in the implication supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeFindCone_rec( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNodeC, * pNodeT, * pNodeE; + int RetValue, i; + assert( !Abc_ObjIsComplement(pNode) ); + if ( Abc_ObjIsCi(pNode) ) + return NULL; + // start the new array + vNodes = Vec_PtrAlloc( 4 ); + // if the node is the MUX collect its fanins + if ( Abc_NodeIsMuxType(pNode) ) + { + pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE ); + Vec_PtrPush( vNodes, Abc_ObjRegular(pNodeC) ); + Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeT) ); + Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeE) ); + } + else + { + // collect the nodes in the implication supergate + RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, 1, 0 ); + assert( vNodes->nSize > 1 ); + // unmark the visited nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + Abc_ObjRegular(pNode)->fMarkB = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vNodes->nSize = 0; + } + // call for the fanin + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + pNode = Abc_ObjRegular(pNode); + if ( pNode->pCopy ) + continue; + pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Attaches the implication supergates to internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + Abc_NtkCleanCopy( pNtk ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pNode = Abc_ObjFanin0(pNode); + if ( pNode->pCopy ) + continue; + pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode ); + } +} + +/**Function************************************************************* + + Synopsis [Attaches the implication supergates to internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( pNode->pCopy ) + { + Vec_PtrFree( (Vec_Ptr_t *)pNode->pCopy ); + pNode->pCopy = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Compute levels of implication supergates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkBalanceLevel_rec( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vSuper; + Abc_Obj_t * pFanin; + int i, LevelMax; + assert( !Abc_ObjIsComplement(pNode) ); + if ( pNode->Level > 0 ) + return pNode->Level; + if ( Abc_ObjIsCi(pNode) ) + return 0; + vSuper = (Vec_Ptr_t *)pNode->pCopy; + assert( vSuper != NULL ); + LevelMax = 0; + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + pFanin = Abc_ObjRegular(pFanin); + Abc_NtkBalanceLevel_rec(pFanin); + if ( LevelMax < (int)pFanin->Level ) + LevelMax = pFanin->Level; + } + pNode->Level = LevelMax + 1; + return pNode->Level; +} + + +/**Function************************************************************* + + Synopsis [Compute levels of implication supergates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBalanceLevel( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + Abc_NtkForEachObj( pNtk, pNode, i ) + pNode->Level = 0; + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_NtkBalanceLevel_rec( Abc_ObjFanin0(pNode) ); +} + + +/**Function************************************************************* + + Synopsis [Marks the nodes on the critical and near critical paths.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( Abc_ObjRequiredLevel(pNode) - pNode->Level <= 1 ) + pNode->fMarkA = 1, Counter++; + printf( "The number of nodes on the critical paths = %6d (%5.2f %%)\n", Counter, 100.0 * Counter / Abc_NtkNodeNum(pNtk) ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcBmc.c b/abc70930/src/base/abci/abcBmc.c new file mode 100644 index 00000000..af6d237b --- /dev/null +++ b/abc70930/src/base/abci/abcBmc.c @@ -0,0 +1,115 @@ +/**CFile**************************************************************** + + FileName [abcBmc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Performs bounded model check.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcBmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ); + +static void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose ) +{ + Ivy_FraigParams_t Params, * pParams = &Params; + Ivy_Man_t * pMan, * pFrames, * pFraig; + Vec_Ptr_t * vMapping; + // convert to IVY manager + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + // generate timeframes + pFrames = Ivy_ManFrames( pMan, Abc_NtkLatchNum(pNtk), nFrames, fInit, &vMapping ); + // fraig the timeframes + Ivy_FraigParamsDefault( pParams ); + pParams->nBTLimitNode = ABC_INFINITY; + pParams->fVerbose = 0; + pParams->fProve = 0; + pFraig = Ivy_FraigPerform( pFrames, pParams ); +printf( "Frames have %6d nodes. ", Ivy_ManNodeNum(pFrames) ); +printf( "Fraig has %6d nodes.\n", Ivy_ManNodeNum(pFraig) ); + // report the classes +// if ( fVerbose ) +// Abc_NtkBmcReport( pMan, pFrames, pFraig, vMapping, nFrames ); + // free stuff + Vec_PtrFree( vMapping ); + Ivy_ManStop( pFraig ); + Ivy_ManStop( pFrames ); + Ivy_ManStop( pMan ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames ) +{ + Ivy_Obj_t * pFirst1, * pFirst2, * pFirst3; + int i, f, nIdMax, Prev2, Prev3; + nIdMax = Ivy_ManObjIdMax(pMan); + // check what is the number of nodes in each frame + Prev2 = Prev3 = 0; + for ( f = 0; f < nFrames; f++ ) + { + Ivy_ManForEachNode( pMan, pFirst1, i ) + { + pFirst2 = Ivy_Regular( Vec_PtrEntry(vMapping, f * nIdMax + pFirst1->Id) ); + if ( Ivy_ObjIsConst1(pFirst2) || pFirst2->Type == 0 ) + continue; + pFirst3 = Ivy_Regular( pFirst2->pEquiv ); + if ( Ivy_ObjIsConst1(pFirst3) || pFirst3->Type == 0 ) + continue; + break; + } + if ( f ) + printf( "Frame %3d : Strash = %5d Fraig = %5d\n", f, pFirst2->Id - Prev2, pFirst3->Id - Prev3 ); + Prev2 = pFirst2->Id; + Prev3 = pFirst3->Id; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcCas.c b/abc70930/src/base/abci/abcCas.c new file mode 100644 index 00000000..4ed7a774 --- /dev/null +++ b/abc70930/src/base/abci/abcCas.c @@ -0,0 +1,111 @@ +/**CFile**************************************************************** + + FileName [abcCas.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Decomposition of shared BDDs into LUT cascade.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcCas.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +/* + This LUT cascade synthesis algorithm is described in the paper: + A. Mishchenko and T. Sasao, "Encoding of Boolean functions and its + application to LUT cascade synthesis", Proc. IWLS '02, pp. 115-120. + http://www.eecs.berkeley.edu/~alanmi/publications/2002/iwls02_enc.pdf +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutputs, int nInputs, int nOutputs, int nLutSize, int fCheck, int fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ) +{ + DdManager * dd; + DdNode ** ppOutputs; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode; + char * pFileGeneric; + int fBddSizeMax = 500000; + int fReorder = 1; + int i, clk = clock(); + + assert( Abc_NtkIsStrash(pNtk) ); + // compute the global BDDs + if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL ) + return NULL; + + if ( fVerbose ) + { + DdManager * dd = Abc_NtkGlobalBddMan( pNtk ); + printf( "Shared BDD size = %6d nodes. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + PRT( "BDD construction time", clock() - clk ); + } + + // collect global BDDs + dd = Abc_NtkGlobalBddMan( pNtk ); + ppOutputs = ALLOC( DdNode *, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + ppOutputs[i] = Abc_ObjGlobalBdd(pNode); + + // call the decomposition + pFileGeneric = Extra_FileNameGeneric( pNtk->pSpec ); + if ( !Abc_CascadeExperiment( pFileGeneric, dd, ppOutputs, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), nLutSize, fCheck, fVerbose ) ) + { + // the LUT size is too small + } + + // for now, duplicate the network + pNtkNew = Abc_NtkDup( pNtk ); + + // cleanup + Abc_NtkFreeGlobalBdds( pNtk, 1 ); + free( ppOutputs ); + free( pFileGeneric ); + +// if ( pNtk->pExdc ) +// pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkCollapse: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcClpBdd.c b/abc70930/src/base/abci/abcClpBdd.c new file mode 100644 index 00000000..341ff5b0 --- /dev/null +++ b/abc70930/src/base/abci/abcClpBdd.c @@ -0,0 +1,162 @@ +/**CFile**************************************************************** + + FileName [abcCollapse.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Collapsing the network into two-levels.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ); +static Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collapses the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew; + int clk = clock(); + + assert( Abc_NtkIsStrash(pNtk) ); + // compute the global BDDs + if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL ) + return NULL; + if ( fVerbose ) + { + DdManager * dd = Abc_NtkGlobalBddMan( pNtk ); + printf( "Shared BDD size = %6d nodes. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + PRT( "BDD construction time", clock() - clk ); + } + + // create the new network + pNtkNew = Abc_NtkFromGlobalBdds( pNtk ); +// Abc_NtkFreeGlobalBdds( pNtk ); + Abc_NtkFreeGlobalBdds( pNtk, 1 ); + if ( pNtkNew == NULL ) + { +// Cudd_Quit( pNtk->pManGlob ); +// pNtk->pManGlob = NULL; + return NULL; + } +// Extra_StopManager( pNtk->pManGlob ); +// pNtk->pManGlob = NULL; + + // make the network minimum base + Abc_NtkMinimumBase( pNtkNew ); + + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkCollapse: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Derives the network with the given global BDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pDriver, * pNodeNew; +// DdManager * dd = pNtk->pManGlob; + DdManager * dd = Abc_NtkGlobalBddMan( pNtk ); + int i; + // start the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); + // make sure the new manager has the same number of inputs + Cudd_bddIthVar( pNtkNew->pManFunc, dd->size-1 ); + // process the POs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_ObjIsCi(pDriver) && !strcmp(Abc_ObjName(pNode), Abc_ObjName(pDriver)) ) + { + Abc_ObjAddFanin( pNode->pCopy, pDriver->pCopy ); + continue; + } +// pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Vec_PtrEntry(pNtk->vFuncsGlob, i) ); + pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Abc_ObjGlobalBdd(pNode) ); + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + } + Extra_ProgressBarStop( pProgress ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Derives the network with the given global BDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc ) +{ + Abc_Obj_t * pNodeNew, * pTemp; + int i; + // create a new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + // add the fanins in the order, in which they appear in the reordered manager + Abc_NtkForEachCi( pNtkNew, pTemp, i ) + Abc_ObjAddFanin( pNodeNew, Abc_NtkCi(pNtkNew, dd->invperm[i]) ); + // transfer the function + pNodeNew->pData = Extra_TransferLevelByLevel( dd, pNtkNew->pManFunc, bFunc ); Cudd_Ref( pNodeNew->pData ); + return pNodeNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcClpSop.c b/abc70930/src/base/abci/abcClpSop.c new file mode 100644 index 00000000..de92243f --- /dev/null +++ b/abc70930/src/base/abci/abcClpSop.c @@ -0,0 +1,53 @@ +/**CFile**************************************************************** + + FileName [abcCollapse.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Collapsing the network into two-levels.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collapses the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCollapseSop( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew; + pNtkNew = NULL; + return pNtkNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcCut.c b/abc70930/src/base/abci/abcCut.c new file mode 100644 index 00000000..d399ce5f --- /dev/null +++ b/abc70930/src/base/abci/abcCut.c @@ -0,0 +1,620 @@ +/**CFile**************************************************************** + + FileName [abcCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface to cut computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "cut.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ); +static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ); + +extern int nTotal, nGood, nEqual; + +static Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ); +static int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) +{ + ProgressBar * pProgress; + Cut_Man_t * p; + Abc_Obj_t * pObj, * pNode; + Vec_Ptr_t * vNodes; + Vec_Int_t * vChoices; + int i; + int clk = clock(); + + extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ); + extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ); + + nTotal = nGood = nEqual = 0; + + assert( Abc_NtkIsStrash(pNtk) ); + // start the manager + pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); + p = Cut_ManStart( pParams ); + // compute node attributes if local or global cuts are requested + if ( pParams->fGlobal || pParams->fLocal ) + { + extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ); + Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) ); + } + // prepare for cut dropping + if ( pParams->fDrop ) + Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); + // set cuts for PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_NodeSetTriv( p, pObj->Id ); + // compute cuts for internal nodes + vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs + vChoices = Vec_IntAlloc( 100 ); + pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // when we reached a CO, it is time to deallocate the cuts + if ( Abc_ObjIsCo(pObj) ) + { + if ( pParams->fDrop ) + Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + continue; + } + // skip constant node, it has no cuts +// if ( Abc_NodeIsConst(pObj) ) +// continue; + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // compute the cuts to the internal node + Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree ); + // consider dropping the fanins cuts + if ( pParams->fDrop ) + { + Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); + } + // add cuts due to choices + if ( Abc_AigNodeIsChoice(pObj) ) + { + Vec_IntClear( vChoices ); + for ( pNode = pObj; pNode; pNode = pNode->pData ) + Vec_IntPush( vChoices, pNode->Id ); + Cut_NodeUnionCuts( p, vChoices ); + } + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + Vec_IntFree( vChoices ); + Cut_ManPrintStats( p ); +PRT( "TOTAL ", clock() - clk ); + printf( "Area = %d.\n", Abc_NtkComputeArea( pNtk, p ) ); +//Abc_NtkPrintCuts( p, pNtk, 0 ); +// Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk ); + + // temporary printout of stats + if ( nTotal ) + printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal ); + return p; +} + +/**Function************************************************************* + + Synopsis [Cut computation using the oracle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p ) +{ + Abc_Obj_t * pObj; + Vec_Ptr_t * vNodes; + int i, clk = clock(); + int fDrop = Cut_OracleReadDrop(p); + + assert( Abc_NtkIsStrash(pNtk) ); + + // prepare cut droppping + if ( fDrop ) + Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); + + // set cuts for PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_OracleNodeSetTriv( p, pObj->Id ); + + // compute cuts for internal nodes + vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // when we reached a CO, it is time to deallocate the cuts + if ( Abc_ObjIsCo(pObj) ) + { + if ( fDrop ) + Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + continue; + } + // skip constant node, it has no cuts +// if ( Abc_NodeIsConst(pObj) ) +// continue; + // compute the cuts to the internal node + Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), + Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); + // consider dropping the fanins cuts + if ( fDrop ) + { + Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); + } + } + Vec_PtrFree( vNodes ); +//PRT( "Total", clock() - clk ); +//Abc_NtkPrintCuts_( p, pNtk, 0 ); +} + + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) +{ +/* + Cut_Man_t * p; + Abc_Obj_t * pObj, * pNode; + int i, nIters, fStatus; + Vec_Int_t * vChoices; + int clk = clock(); + + assert( Abc_NtkIsSeq(pNtk) ); + assert( pParams->fSeq ); +// assert( Abc_NtkIsDfsOrdered(pNtk) ); + + // start the manager + pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); + pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk ); + p = Cut_ManStart( pParams ); + + // set cuts for the constant node and the PIs + pObj = Abc_AigConst1(pNtk); + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_NodeSetTriv( p, pObj->Id ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { +//printf( "Setting trivial cut %d.\n", pObj->Id ); + Cut_NodeSetTriv( p, pObj->Id ); + } + // label the cutset nodes and set their number in the array + // assign the elementary cuts to the cutset nodes + Abc_SeqForEachCutsetNode( pNtk, pObj, i ) + { + assert( pObj->fMarkC == 0 ); + pObj->fMarkC = 1; + pObj->pCopy = (Abc_Obj_t *)i; + Cut_NodeSetTriv( p, pObj->Id ); +//printf( "Setting trivial cut %d.\n", pObj->Id ); + } + + // process the nodes + vChoices = Vec_IntAlloc( 100 ); + for ( nIters = 0; nIters < 10; nIters++ ) + { +//printf( "ITERATION %d:\n", nIters ); + // compute the cuts for the internal nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + { + Abc_NodeGetCutsSeq( p, pObj, nIters==0 ); + // add cuts due to choices + if ( Abc_AigNodeIsChoice(pObj) ) + { + Vec_IntClear( vChoices ); + for ( pNode = pObj; pNode; pNode = pNode->pData ) + Vec_IntPush( vChoices, pNode->Id ); + Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 ); + } + } + // merge the new cuts with the old cuts + Abc_NtkForEachPi( pNtk, pObj, i ) + Cut_NodeNewMergeWithOld( p, pObj->Id ); + Abc_AigForEachAnd( pNtk, pObj, i ) + Cut_NodeNewMergeWithOld( p, pObj->Id ); + // for the cutset, transfer temp cuts to new cuts + fStatus = 0; + Abc_SeqForEachCutsetNode( pNtk, pObj, i ) + fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i ); + if ( fStatus == 0 ) + break; + } + Vec_IntFree( vChoices ); + + // if the status is not finished, transfer new to old for the cutset + Abc_SeqForEachCutsetNode( pNtk, pObj, i ) + Cut_NodeNewMergeWithOld( p, pObj->Id ); + + // transfer the old cuts to the new positions + Abc_NtkForEachObj( pNtk, pObj, i ) + Cut_NodeOldTransferToNew( p, pObj->Id ); + + // unlabel the cutset nodes + Abc_SeqForEachCutsetNode( pNtk, pObj, i ) + pObj->fMarkC = 0; +if ( pParams->fVerbose ) +{ + Cut_ManPrintStats( p ); +PRT( "TOTAL ", clock() - clk ); +printf( "Converged after %d iterations.\n", nIters ); +} +//Abc_NtkPrintCuts( p, pNtk, 1 ); + return p; +*/ + return NULL; +} + +/**Function************************************************************* + + Synopsis [Computes area.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p ) +{ + Abc_Obj_t * pObj; + int Counter, i; + Counter = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + Counter += Cut_ManMappingArea_rec( p, Abc_ObjFaninId0(pObj) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) +{ + void * pList; + if ( pList = Abc_NodeReadCuts( p, pObj ) ) + return pList; + Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree ); + Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree ); + return Abc_NodeGetCuts( p, pObj, fDag, fTree ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) +{ + Abc_Obj_t * pFanin; + int fDagNode, fTriv, TreeCode = 0; +// assert( Abc_NtkIsStrash(pObj->pNtk) ); + assert( Abc_ObjFaninNum(pObj) == 2 ); + + + // check if the node is a DAG node + fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)); + // increment the counter of DAG nodes + if ( fDagNode ) Cut_ManIncrementDagNodes( p ); + // add the trivial cut if the node is a DAG node, or if we compute all cuts + fTriv = fDagNode || !fDag; + // check if fanins are DAG nodes + if ( fTree ) + { + pFanin = Abc_ObjFanin0(pObj); + TreeCode |= (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)); + pFanin = Abc_ObjFanin1(pObj); + TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1); + } + + + // changes due to the global/local cut computation + { + Cut_Params_t * pParams = Cut_ManReadParams(p); + if ( pParams->fLocal ) + { + Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs(p); + fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id ); + if ( fDagNode ) Cut_ManIncrementDagNodes( p ); +// fTriv = fDagNode || !pParams->fGlobal; + fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id ); + TreeCode = 0; + pFanin = Abc_ObjFanin0(pObj); + TreeCode |= Vec_IntEntry( vNodeAttrs, pFanin->Id ); + pFanin = Abc_ObjFanin1(pObj); + TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1); + } + } + return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), + Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv ) +{ +/* + int CutSetNum; + assert( Abc_NtkIsSeq(pObj->pNtk) ); + assert( Abc_ObjFaninNum(pObj) == 2 ); + fTriv = pObj->fMarkC ? 0 : fTriv; + CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1; + Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), + Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum ); +*/ +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ) +{ + return Cut_NodeReadCutsNew( p, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ) +{ + Cut_NodeFreeCuts( p, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ) +{ + Cut_Man_t * pMan = p; + Cut_Cut_t * pList; + Abc_Obj_t * pObj; + int i; + printf( "Cuts of the network:\n" ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + pList = Abc_NodeReadCuts( p, pObj ); + printf( "Node %s:\n", Abc_ObjName(pObj) ); + Cut_CutPrintList( pList, fSeq ); + } +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ) +{ + Cut_Man_t * pMan = p; + Cut_Cut_t * pList; + Abc_Obj_t * pObj; + pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 ); + pList = Abc_NodeReadCuts( p, pObj ); + printf( "Node %s:\n", Abc_ObjName(pObj) ); + Cut_CutPrintList( pList, fSeq ); +} + + + + +/**Function************************************************************* + + Synopsis [Assigns global attributes randomly.] + + Description [Old code.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vAttrs; +// Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj;//, * pTemp; + int i;//, k; + int nNodesTotal = 0, nMffcsTotal = 0; + extern Vec_Ptr_t * Abc_NodeMffsInsideCollect( Abc_Obj_t * pNode ); + + vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); +// Abc_NtkForEachCi( pNtk, pObj, i ) +// Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); + + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( Abc_ObjIsNode(pObj) ) + nNodesTotal++; + if ( Abc_ObjIsCo(pObj) && Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) + nMffcsTotal += Abc_NodeMffcSize( Abc_ObjFanin0(pObj) ); +// if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) ) +// if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) ) + if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) ) + { + int nMffc = Abc_NodeMffcSize(pObj); + nMffcsTotal += Abc_NodeMffcSize(pObj); +// printf( "%d ", nMffc ); + + if ( nMffc > 2 || Abc_ObjFanoutNum(pObj) > 8 ) + Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); + } + } +/* + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( Vec_IntEntry( vAttrs, pObj->Id ) ) + { + vNodes = Abc_NodeMffsInsideCollect( pObj ); + Vec_PtrForEachEntry( vNodes, pTemp, k ) + if ( pTemp != pObj ) + Vec_IntWriteEntry( vAttrs, pTemp->Id, 0 ); + Vec_PtrFree( vNodes ); + } + } +*/ + printf( "Total nodes = %d. Total MFFC nodes = %d.\n", nNodesTotal, nMffcsTotal ); + return vAttrs; +} + +/**Function************************************************************* + + Synopsis [Assigns global attributes randomly.] + + Description [Old code.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSubDagSize_rec( Abc_Obj_t * pObj, Vec_Int_t * vAttrs ) +{ + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 0; + Abc_NodeSetTravIdCurrent(pObj); + if ( Vec_IntEntry( vAttrs, pObj->Id ) ) + return 0; + if ( Abc_ObjIsCi(pObj) ) + return 1; + assert( Abc_ObjFaninNum(pObj) == 2 ); + return 1 + Abc_NtkSubDagSize_rec(Abc_ObjFanin0(pObj), vAttrs) + + Abc_NtkSubDagSize_rec(Abc_ObjFanin1(pObj), vAttrs); +} + +/**Function************************************************************* + + Synopsis [Assigns global attributes randomly.] + + Description [Old code.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkGetNodeAttributes2( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vAttrs; + Abc_Obj_t * pObj; + int i, nSize; + assert( Abc_NtkIsDfsOrdered(pNtk) ); + vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + // skip no-nodes and nodes without fanouts + if ( pObj->Id == 0 || !(Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) ) + continue; + // the node has more than one fanout - count its sub-DAG size + Abc_NtkIncrementTravId( pNtk ); + nSize = Abc_NtkSubDagSize_rec( pObj, vAttrs ); + if ( nSize > 15 ) + Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); + } + return vAttrs; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcDar.c b/abc70930/src/base/abci/abcDar.c new file mode 100644 index 00000000..90fe35e9 --- /dev/null +++ b/abc70930/src/base/abci/abcDar.c @@ -0,0 +1,1212 @@ +/**CFile**************************************************************** + + FileName [abcDar.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [DAG-aware rewriting.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDar.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "aig.h" +#include "dar.h" +#include "cnf.h" +#include "fra.h" +#include "fraig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [Assumes that registers are ordered after PIs/POs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters ) +{ + Aig_Man_t * pMan; + Aig_Obj_t * pObjNew; + Abc_Obj_t * pObj; + int i, nNodes, nDontCares; + // make sure the latches follow PIs/POs + if ( fRegisters ) + { + assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( i < Abc_NtkPiNum(pNtk) ) + assert( Abc_ObjIsPi(pObj) ); + else + assert( Abc_ObjIsBo(pObj) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + if ( i < Abc_NtkPoNum(pNtk) ) + assert( Abc_ObjIsPo(pObj) ); + else + assert( Abc_ObjIsBi(pObj) ); + // print warning about initial values + nDontCares = 0; + Abc_NtkForEachLatch( pNtk, pObj, i ) + if ( Abc_LatchIsInitDc(pObj) ) + { + Abc_LatchSetInit0(pObj); + nDontCares++; + } + if ( nDontCares ) + { + printf( "Warning: %d registers in this network have don't-care init values.\n", nDontCares ); + printf( "The don't-care are assumed to be 0. The result may not verify.\n" ); + printf( "Use command \"print_latch\" to see the init values of registers.\n" ); + printf( "Use command \"init\" to change the values.\n" ); + } + } + // create the manager + pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 ); + pMan->pName = Extra_UtilStrsav( pNtk->pName ); + // save the number of registers + if ( fRegisters ) + { + pMan->nRegs = Abc_NtkLatchNum(pNtk); + pMan->vFlopNums = Vec_IntStartNatural( pMan->nRegs ); + } + // transfer the pointers to the basic nodes + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreatePi(pMan); + // complement the 1-values registers + if ( fRegisters ) + Abc_NtkForEachLatch( pNtk, pObj, i ) + if ( Abc_LatchIsInit1(pObj) ) + Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy); + // perform the conversion of the internal nodes (assumes DFS ordering) +// pMan->fAddStrash = 1; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + pObj->pCopy = (Abc_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj), (Aig_Obj_t *)Abc_ObjChild1Copy(pObj) ); +// printf( "%d->%d ", pObj->Id, ((Aig_Obj_t *)pObj->pCopy)->Id ); + } + pMan->fAddStrash = 0; + // create the POs + Abc_NtkForEachCo( pNtk, pObj, i ) + Aig_ObjCreatePo( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj) ); + // complement the 1-valued registers + if ( fRegisters ) + Aig_ManForEachLiSeq( pMan, pObjNew, i ) + if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) ) + pObjNew->pFanin0 = Aig_Not(pObjNew->pFanin0); + // remove dangling nodes + if ( nNodes = Aig_ManCleanup( pMan ) ) + printf( "Abc_NtkToDar(): Unexpected %d dangling nodes when converting to AIG!\n", nNodes ); +//Aig_ManDumpVerilog( pMan, "test.v" ); + if ( !Aig_ManCheck( pMan ) ) + { + printf( "Abc_NtkToDar: AIG check has failed.\n" ); + Aig_ManStop( pMan ); + return NULL; + } + return pMan; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjNew; + Aig_Obj_t * pObj; + int i; +// assert( Aig_ManRegNum(pMan) == Abc_NtkLatchNum(pNtkOld) ); + // perform strashing + pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); + Aig_ManForEachPi( pMan, pObj, i ) + pObj->pData = Abc_NtkCi(pNtkNew, i); + // rebuild the AIG + vNodes = Aig_ManDfs( pMan ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( Aig_ObjIsBuf(pObj) ) + pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); + else + pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); + Vec_PtrFree( vNodes ); + // connect the PO nodes + Aig_ManForEachPo( pMan, pObj, i ) + { + if ( pMan->nAsserts && i == Aig_ManPoNum(pMan) - pMan->nAsserts ) + break; + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); + } + // if there are assertions, add them + if ( pMan->nAsserts > 0 ) + Aig_ManForEachAssert( pMan, pObj, i ) + { + pObjNew = Abc_NtkCreateAssert(pNtkNew); + Abc_ObjAssignName( pObjNew, "assert_", Abc_ObjName(pObjNew) ); + Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); + } + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [This procedure should be called after seq sweeping, + which changes the number of registers.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjNew, * pLatch; + Aig_Obj_t * pObj, * pObjLo, * pObjLi; + int i; +// assert( Aig_ManRegNum(pMan) != Abc_NtkLatchNum(pNtkOld) ); + // perform strashing + pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); + Aig_ManForEachPiSeq( pMan, pObj, i ) + pObj->pData = Abc_NtkCi(pNtkNew, i); + // create as many latches as there are registers in the manager + Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i ) + { + pObjNew = Abc_NtkCreateLatch( pNtkNew ); + pObjLi->pData = Abc_NtkCreateBi( pNtkNew ); + pObjLo->pData = Abc_NtkCreateBo( pNtkNew ); + Abc_ObjAddFanin( pObjNew, pObjLi->pData ); + Abc_ObjAddFanin( pObjLo->pData, pObjNew ); + Abc_LatchSetInit0( pObjNew ); + } + if ( pMan->vFlopNums == NULL ) + Abc_NtkAddDummyBoxNames( pNtkNew ); + else + { + assert( Abc_NtkBoxNum(pNtkOld) == Abc_NtkLatchNum(pNtkOld) ); + Abc_NtkForEachLatch( pNtkNew, pObjNew, i ) + { + pLatch = Abc_NtkBox( pNtkOld, Vec_IntEntry( pMan->vFlopNums, i ) ); + Abc_ObjAssignName( pObjNew, Abc_ObjName(pLatch), NULL ); + Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pLatch)), NULL ); + Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pLatch)), NULL ); + } + } + // rebuild the AIG + vNodes = Aig_ManDfs( pMan ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( Aig_ObjIsBuf(pObj) ) + pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); + else + pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); + Vec_PtrFree( vNodes ); + // connect the PO nodes + Aig_ManForEachPo( pMan, pObj, i ) + { + if ( pMan->nAsserts && i == Aig_ManPoNum(pMan) - pMan->nAsserts ) + break; + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); + } + // if there are assertions, add them + if ( pMan->nAsserts > 0 ) + Aig_ManForEachAssert( pMan, pObj, i ) + { + pObjNew = Abc_NtkCreateAssert(pNtkNew); + Abc_ObjAssignName( pObjNew, "assert_", Abc_ObjName(pObjNew) ); + Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); + } + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Aig_Obj_t * pObj, * pTemp; + int i; + assert( pMan->pEquivs != NULL ); + assert( Aig_ManBufNum(pMan) == 0 ); + // perform strashing + pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); + Aig_ManForEachPi( pMan, pObj, i ) + pObj->pData = Abc_NtkCi(pNtkNew, i); + + // rebuild the AIG + vNodes = Aig_ManDfsChoices( pMan ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); + if ( pTemp = pMan->pEquivs[pObj->Id] ) + { + Abc_Obj_t * pAbcRepr, * pAbcObj; + assert( pTemp->pData != NULL ); + pAbcRepr = pObj->pData; + pAbcObj = pTemp->pData; + pAbcObj->pData = pAbcRepr->pData; + pAbcRepr->pData = pAbcObj; + } + } +//printf( "Total = %d. Collected = %d.\n", Aig_ManNodeNum(pMan), Vec_PtrSize(vNodes) ); + Vec_PtrFree( vNodes ); + // connect the PO nodes + Aig_ManForEachPo( pMan, pObj, i ) + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromDarSeq( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1; + Aig_Obj_t * pObj; + int i; +// assert( Aig_ManLatchNum(pMan) > 0 ); + // perform strashing + pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); + Aig_ManForEachPi( pMan, pObj, i ) + pObj->pData = Abc_NtkPi(pNtkNew, i); + // create latches of the new network + Aig_ManForEachObj( pMan, pObj, i ) + { + if ( !Aig_ObjIsLatch(pObj) ) + continue; + pObjNew = Abc_NtkCreateLatch( pNtkNew ); + pFaninNew0 = Abc_NtkCreateBi( pNtkNew ); + pFaninNew1 = Abc_NtkCreateBo( pNtkNew ); + Abc_ObjAddFanin( pObjNew, pFaninNew0 ); + Abc_ObjAddFanin( pFaninNew1, pObjNew ); + Abc_LatchSetInit0( pObjNew ); + pObj->pData = Abc_ObjFanout0( pObjNew ); + } + Abc_NtkAddDummyBoxNames( pNtkNew ); + // rebuild the AIG + vNodes = Aig_ManDfs( pMan ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // add the first fanin + pObj->pData = pFaninNew0 = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); + if ( Aig_ObjIsBuf(pObj) ) + continue; + // add the second fanin + pFaninNew1 = (Abc_Obj_t *)Aig_ObjChild1Copy(pObj); + // create the new node + if ( Aig_ObjIsExor(pObj) ) + pObj->pData = pObjNew = Abc_AigXor( pNtkNew->pManFunc, pFaninNew0, pFaninNew1 ); + else + pObj->pData = pObjNew = Abc_AigAnd( pNtkNew->pManFunc, pFaninNew0, pFaninNew1 ); + } + Vec_PtrFree( vNodes ); + // connect the PO nodes + Aig_ManForEachPo( pMan, pObj, i ) + { + pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkNew, i), pFaninNew ); + } + // connect the latches + Aig_ManForEachObj( pMan, pObj, i ) + { + if ( !Aig_ObjIsLatch(pObj) ) + continue; + pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj ); + Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pObj->pData)), pFaninNew ); + } + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkFromIvySeq(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Collect latch values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkGetLatchValues( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vInits; + Abc_Obj_t * pLatch; + int i; + vInits = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + assert( Abc_LatchIsInit1(pLatch) == 0 ); + Vec_IntPush( vInits, Abc_LatchIsInit1(pLatch) ); + } + return vInits; +} + +/**Function************************************************************* + + Synopsis [Performs verification after retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSecRetime( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ) +{ + int fRemove1, fRemove2; + Aig_Man_t * pMan1, * pMan2; + int * pArray; + + fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0, 0)); + fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0, 0)); + + + pMan1 = Abc_NtkToDar( pNtk1, 0 ); + pMan2 = Abc_NtkToDar( pNtk2, 0 ); + + Aig_ManPrintStats( pMan1 ); + Aig_ManPrintStats( pMan2 ); + +// pArray = Abc_NtkGetLatchValues(pNtk1); + pArray = NULL; + Aig_ManSeqStrash( pMan1, Abc_NtkLatchNum(pNtk1), pArray ); + free( pArray ); + +// pArray = Abc_NtkGetLatchValues(pNtk2); + pArray = NULL; + Aig_ManSeqStrash( pMan2, Abc_NtkLatchNum(pNtk2), pArray ); + free( pArray ); + + Aig_ManPrintStats( pMan1 ); + Aig_ManPrintStats( pMan2 ); + + Aig_ManStop( pMan1 ); + Aig_ManStop( pMan2 ); + + + if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); + if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkAig = NULL; + Aig_Man_t * pMan; + extern void Fra_ManPartitionTest( Aig_Man_t * p, int nComLim ); + + assert( Abc_NtkIsStrash(pNtk) ); + // convert to the AIG manager + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; + + // perform computation +// Fra_ManPartitionTest( pMan, 4 ); + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + + // make sure everything is okay + if ( pNtkAig && !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkDar: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; +} + + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose ) +{ + Fra_Par_t Pars, * pPars = &Pars; + Abc_Ntk_t * pNtkAig; + Aig_Man_t * pMan, * pTemp; + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; + Fra_ParamsDefault( pPars ); + pPars->nBTLimitNode = nConfLimit; + pPars->fChoicing = fChoicing; + pPars->fDoSparse = fDoSparse; + pPars->fSpeculate = fSpeculate; + pPars->fProve = fProve; + pPars->fVerbose = fVerbose; + pMan = Fra_FraigPerform( pTemp = pMan, pPars ); + if ( fChoicing ) + pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan ); + else + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pTemp ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose ) +{ + extern Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose ); + Abc_Ntk_t * pNtkAig; + Aig_Man_t * pMan, * pTemp; + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; + pMan = Csw_Sweep( pTemp = pMan, nCutsMax, nLeafMax, fVerbose ); + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pTemp ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars ) +{ + Aig_Man_t * pMan, * pTemp; + Abc_Ntk_t * pNtkAig; + int clk; + assert( Abc_NtkIsStrash(pNtk) ); + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; +// Aig_ManPrintStats( pMan ); +/* +// Aig_ManSupports( pMan ); + { + Vec_Vec_t * vParts; + vParts = Aig_ManPartitionSmart( pMan, 50, 1, NULL ); + Vec_VecFree( vParts ); + } +*/ + Dar_ManRewrite( pMan, pPars ); +// pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel ); +// Aig_ManStop( pTemp ); + +clk = clock(); + pMan = Aig_ManDup( pTemp = pMan, 0 ); + Aig_ManStop( pTemp ); +//PRT( "time", clock() - clk ); + +// Aig_ManPrintStats( pMan ); + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars ) +{ + Aig_Man_t * pMan, * pTemp; + Abc_Ntk_t * pNtkAig; + int clk; + assert( Abc_NtkIsStrash(pNtk) ); + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; +// Aig_ManPrintStats( pMan ); + + Dar_ManRefactor( pMan, pPars ); +// pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel ); +// Aig_ManStop( pTemp ); + +clk = clock(); + pMan = Aig_ManDup( pTemp = pMan, 0 ); + Aig_ManStop( pTemp ); +//PRT( "time", clock() - clk ); + +// Aig_ManPrintStats( pMan ); + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose ) +{ + Aig_Man_t * pMan, * pTemp; + Abc_Ntk_t * pNtkAig; + int clk; + assert( Abc_NtkIsStrash(pNtk) ); + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; +// Aig_ManPrintStats( pMan ); + +clk = clock(); + pMan = Dar_ManCompress2( pTemp = pMan, fBalance, fUpdateLevel, fVerbose ); + Aig_ManStop( pTemp ); +//PRT( "time", clock() - clk ); + +// Aig_ManPrintStats( pMan ); + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose ) +{ + Aig_Man_t * pMan, * pTemp; + Abc_Ntk_t * pNtkAig; + assert( Abc_NtkIsStrash(pNtk) ); + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; + pMan = Dar_ManChoice( pTemp = pMan, fBalance, fUpdateLevel, fVerbose ); + Aig_ManStop( pTemp ); + pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose ) +{ + Aig_Man_t * pMan, * pTemp; + Abc_Ntk_t * pNtkAig; + int clk; + assert( Abc_NtkIsStrash(pNtk) ); + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; +// Aig_ManPrintStats( pMan ); + +clk = clock(); + pMan = Dar_ManRwsat( pTemp = pMan, fBalance, fVerbose ); + Aig_ManStop( pTemp ); +//PRT( "time", clock() - clk ); + +// Aig_ManPrintStats( pMan ); + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkConstructFromCnf( Abc_Ntk_t * pNtk, Cnf_Man_t * p, Vec_Ptr_t * vMapped ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pNodeNew; + Aig_Obj_t * pObj, * pLeaf; + Cnf_Cut_t * pCut; + Vec_Int_t * vCover; + unsigned uTruth; + int i, k, nDupGates; + // create the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + // make the mapper point to the new network + Aig_ManConst1(p->pManAig)->pData = Abc_NtkCreateNodeConst1(pNtkNew); + Abc_NtkForEachCi( pNtk, pNode, i ) + Aig_ManPi(p->pManAig, i)->pData = pNode->pCopy; + // process the nodes in topological order + vCover = Vec_IntAlloc( 1 << 16 ); + Vec_PtrForEachEntry( vMapped, pObj, i ) + { + // create new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + // add fanins according to the cut + pCut = pObj->pData; + Cnf_CutForEachLeaf( p->pManAig, pCut, pLeaf, k ) + Abc_ObjAddFanin( pNodeNew, pLeaf->pData ); + // add logic function + if ( pCut->nFanins < 5 ) + { + uTruth = 0xFFFF & *Cnf_CutTruth(pCut); + Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vCover ); + pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, pCut->nFanins, vCover ); + } + else + pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, pCut->nFanins, pCut->vIsop[1] ); + // save the node + pObj->pData = pNodeNew; + } + Vec_IntFree( vCover ); + // add the CO drivers + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pObj = Aig_ManPo(p->pManAig, i); + pNodeNew = Abc_ObjNotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + } + + // remove the constant node if not used + pNodeNew = (Abc_Obj_t *)Aig_ManConst1(p->pManAig)->pData; + if ( Abc_ObjFanoutNum(pNodeNew) == 0 ) + Abc_NtkDeleteObj( pNodeNew ); + // minimize the node +// Abc_NtkSweep( pNtkNew, 0 ); + // decouple the PO driver nodes to reduce the number of levels + nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); +// if ( nDupGates && If_ManReadVerbose(pIfMan) ) +// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkConstructFromCnf(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Vec_Ptr_t * vMapped; + Aig_Man_t * pMan; + Cnf_Man_t * pManCnf; + Cnf_Dat_t * pCnf; + Abc_Ntk_t * pNtkNew = NULL; + assert( Abc_NtkIsStrash(pNtk) ); + + // convert to the AIG manager + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; + if ( !Aig_ManCheck( pMan ) ) + { + printf( "Abc_NtkDarToCnf: AIG check has failed.\n" ); + Aig_ManStop( pMan ); + return NULL; + } + // perform balance + Aig_ManPrintStats( pMan ); + + // derive CNF + pCnf = Cnf_Derive( pMan, 0 ); + pManCnf = Cnf_ManRead(); + + // write the network for verification + vMapped = Cnf_ManScanMapping( pManCnf, 1, 0 ); + pNtkNew = Abc_NtkConstructFromCnf( pNtk, pManCnf, vMapped ); + Vec_PtrFree( vMapped ); + + // write CNF into a file + Cnf_DataWriteIntoFile( pCnf, pFileName, 0 ); + Cnf_DataFree( pCnf ); + Cnf_ClearMemory(); + + Aig_ManStop( pMan ); + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Solves combinational miter using a SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose ) +{ + sat_solver * pSat; + Aig_Man_t * pMan; + Cnf_Dat_t * pCnf; + int status, RetValue, clk = clock(); + Vec_Int_t * vCiIds; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkLatchNum(pNtk) == 0 ); + assert( Abc_NtkPoNum(pNtk) == 1 ); + + // conver to the manager + pMan = Abc_NtkToDar( pNtk, 0 ); + // derive CNF + pCnf = Cnf_Derive( pMan, 0 ); +// pCnf = Cnf_DeriveSimple( pMan, 0 ); + // convert into the SAT solver + pSat = Cnf_DataWriteIntoSolver( pCnf ); + vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan ); + Aig_ManStop( pMan ); + Cnf_DataFree( pCnf ); + // solve SAT + if ( pSat == NULL ) + { + Vec_IntFree( vCiIds ); +// printf( "Trivially unsat\n" ); + return 1; + } + + +// printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); +// PRT( "Time", clock() - clk ); + + // simplify the problem + clk = clock(); + status = sat_solver_simplify(pSat); +// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); +// PRT( "Time", clock() - clk ); + if ( status == 0 ) + { + Vec_IntFree( vCiIds ); + sat_solver_delete( pSat ); +// printf( "The problem is UNSATISFIABLE after simplification.\n" ); + return 1; + } + + // solve the miter + clk = clock(); + if ( fVerbose ) + pSat->verbosity = 1; + status = sat_solver_solve( pSat, NULL, NULL, (sint64)nConfLimit, (sint64)nInsLimit, (sint64)0, (sint64)0 ); + if ( status == l_Undef ) + { +// printf( "The problem timed out.\n" ); + RetValue = -1; + } + else if ( status == l_True ) + { +// printf( "The problem is SATISFIABLE.\n" ); + RetValue = 0; + } + else if ( status == l_False ) + { +// printf( "The problem is UNSATISFIABLE.\n" ); + RetValue = 1; + } + else + assert( 0 ); +// PRT( "SAT sat_solver time", clock() - clk ); +// printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts ); + + // if the problem is SAT, get the counterexample + if ( status == l_True ) + { + pNtk->pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); + } + // free the sat_solver + if ( fVerbose ) + Sat_SolverPrintStats( stdout, pSat ); +//sat_solver_store_write( pSat, "trace.cnf" ); +//sat_solver_store_free( pSat ); + sat_solver_delete( pSat ); + Vec_IntFree( vCiIds ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFramesK, int nMaxImps, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose ) +{ + Fraig_Params_t Params; + Abc_Ntk_t * pNtkAig, * pNtkFraig; + Aig_Man_t * pMan, * pTemp; + int clk = clock(); + + // preprocess the miter by fraiging it + // (note that for each functional class, fraiging leaves one representative; + // so fraiging does not reduce the number of functions represented by nodes + Fraig_ParamsSetDefault( &Params ); + Params.nBTLimit = 100000; +// pNtkFraig = Abc_NtkFraig( pNtk, &Params, 0, 0 ); + pNtkFraig = Abc_NtkDup( pNtk ); +if ( fVerbose ) +{ +PRT( "Initial fraiging time", clock() - clk ); +} + + pMan = Abc_NtkToDar( pNtkFraig, 1 ); + Abc_NtkDelete( pNtkFraig ); + if ( pMan == NULL ) + return NULL; + + pMan = Fra_FraigInduction( pTemp = pMan, nFramesP, nFramesK, nMaxImps, fRewrite, fUseImps, fLatchCorr, fWriteImps, fVerbose, NULL ); + Aig_ManStop( pTemp ); + + if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) ) + pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); + else + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Computes latch correspondence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose ) +{ + Aig_Man_t * pMan, * pTemp; + Abc_Ntk_t * pNtkAig; + pMan = Abc_NtkToDar( pNtk, 1 ); + if ( pMan == NULL ) + return NULL; + pMan = Fra_FraigLatchCorrespondence( pTemp = pMan, nFramesP, nConfMax, 0, fVerbose, NULL ); + Aig_ManStop( pTemp ); + if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) ) + pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); + else + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDarProve( Abc_Ntk_t * pNtk, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ) +{ + Aig_Man_t * pMan; + int RetValue; + // derive the AIG manager + pMan = Abc_NtkToDar( pNtk, 1 ); + if ( pMan == NULL ) + { + printf( "Converting miter into AIG has failed.\n" ); + return -1; + } + assert( pMan->nRegs > 0 ); + // perform verification + RetValue = Fra_FraigSec( pMan, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); + Aig_ManStop( pMan ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ) +{ +// Fraig_Params_t Params; + Aig_Man_t * pMan; + Abc_Ntk_t * pMiter;//, * pTemp; + int RetValue; + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return 0; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ); + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames ); + Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return 0; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pMiter ); + printf( "Networks are equivalent after structural hashing.\n" ); + return 1; + } + + // commented out because something became non-inductive +/* + // preprocess the miter by fraiging it + // (note that for each functional class, fraiging leaves one representative; + // so fraiging does not reduce the number of functions represented by nodes + Fraig_ParamsSetDefault( &Params ); + Params.nBTLimit = 100000; + pMiter = Abc_NtkFraig( pTemp = pMiter, &Params, 0, 0 ); + Abc_NtkDelete( pTemp ); + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ); + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames ); + Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return 0; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pMiter ); + printf( "Networks are equivalent after structural hashing.\n" ); + return 1; + } +*/ + // derive the AIG manager + pMan = Abc_NtkToDar( pMiter, 1 ); + Abc_NtkDelete( pMiter ); + if ( pMan == NULL ) + { + printf( "Converting miter into AIG has failed.\n" ); + return -1; + } + assert( pMan->nRegs > 0 ); + + // perform verification + RetValue = Fra_FraigSec( pMan, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); + Aig_ManStop( pMan ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Aig_Man_t * pMan; + pMan = Abc_NtkToDar( pNtk, 1 ); + if ( pMan == NULL ) + return NULL; + Aig_ManSeqCleanup( pMan ); + if ( fLatchSweep ) + { + if ( pMan->nRegs ) + pMan = Aig_ManReduceLaches( pMan, fVerbose ); + if ( pMan->nRegs ) + pMan = Aig_ManConstReduce( pMan, fVerbose ); + } + pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Aig_Man_t * pMan, * pTemp; + pMan = Abc_NtkToDar( pNtk, 1 ); + if ( pMan == NULL ) + return NULL; +// Aig_ManReduceLachesCount( pMan ); + + pMan = Rtm_ManRetime( pTemp = pMan, 1, nStepsMax, 0 ); + Aig_ManStop( pTemp ); + +// pMan = Aig_ManReduceLaches( pMan, 1 ); +// pMan = Aig_ManConstReduce( pMan, 1 ); + + pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcDebug.c b/abc70930/src/base/abci/abcDebug.c new file mode 100644 index 00000000..95b95d89 --- /dev/null +++ b/abc70930/src/base/abci/abcDebug.c @@ -0,0 +1,208 @@ +/**CFile**************************************************************** + + FileName [abcDebug.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Automated debugging procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDebug.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtk, int ObjNum, int fConst1 ); + +extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Takes a network and a procedure to test.] + + Description [The network demonstrates the bug in the procedure. + Procedure should return 1 if the bug is demonstrated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) ) +{ + Abc_Ntk_t * pNtkMod; + char * pFileName = "bug_found.blif"; + int i, nSteps, nIter, ModNum, RandNum = 1, clk, clkTotal = clock(); + assert( Abc_NtkIsLogic(pNtk) ); + srand( 0x123123 ); + // create internal copy of the network + pNtk = Abc_NtkDup(pNtk); + if ( !(*pFuncError)( pNtk ) ) + { + printf( "The original network does not cause the bug. Quitting.\n" ); + Abc_NtkDelete( pNtk ); + return; + } + // perform incremental modifications + for ( nIter = 0; ; nIter++ ) + { + clk = clock(); + // count how many ways of modifying the network exists + nSteps = 2 * Abc_NtkCountFaninsTotal(pNtk); + // try modifying the network as many times + RandNum ^= rand(); + for ( i = 0; i < nSteps; i++ ) + { + // get the shifted number of bug + ModNum = (i + RandNum) % nSteps; + // get the modified network + pNtkMod = Abc_NtkAutoDebugModify( pNtk, ModNum/2, ModNum%2 ); + // write the network + Io_WriteBlifLogic( pNtk, "bug_temp.blif", 1 ); + // check if the bug is still there + if ( (*pFuncError)( pNtkMod ) ) // bug is still there + { + Abc_NtkDelete( pNtk ); + pNtk = pNtkMod; + break; + } + else // no bug + Abc_NtkDelete( pNtkMod ); + } + printf( "Iter %6d : Latches = %6d. Nodes = %6d. Steps = %6d. Error step = %3d. ", + nIter, Abc_NtkLatchNum(pNtk), Abc_NtkNodeNum(pNtk), nSteps, i ); + PRT( "Time", clock() - clk ); + if ( i == nSteps ) // could not modify it while preserving the bug + break; + } + // write out the final network + Io_WriteBlifLogic( pNtk, pFileName, 1 ); + printf( "Final network written into file \"%s\". ", pFileName ); + PRT( "Total time", clock() - clkTotal ); + Abc_NtkDelete( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Counts the total number of fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pFanin; + int i, k, Counter = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) ) + continue; + if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 ) + continue; + if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) ) + continue; + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the node and fanin to be modified.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkFindGivenFanin( Abc_Ntk_t * pNtk, int Step, Abc_Obj_t ** ppObj, Abc_Obj_t ** ppFanin ) +{ + Abc_Obj_t * pObj, * pFanin; + int i, k, Counter = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) ) + continue; + if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 ) + continue; + if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) ) + continue; + if ( Counter++ == Step ) + { + *ppObj = pObj; + *ppFanin = pFanin; + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Perform modification with the given number.] + + Description [Modification consists of replacing the node by a constant.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtkInit, int Step, int fConst1 ) +{ + extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj, * pFanin, * pConst; + // copy the network + pNtk = Abc_NtkDup( pNtkInit ); + assert( Abc_NtkNodeNum(pNtk) == Abc_NtkNodeNum(pNtkInit) ); + // find the object number + Abc_NtkFindGivenFanin( pNtk, Step, &pObj, &pFanin ); + // consider special case + if ( Abc_ObjIsPo(pObj) && Abc_NodeIsConst(pFanin) ) + { + Abc_NtkDeleteAll_rec( pObj ); + return pNtk; + } + // plug in a constant node + pConst = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); + Abc_ObjTransferFanout( pFanin, pConst ); + Abc_NtkDeleteAll_rec( pFanin ); + + Abc_NtkSweep( pNtk, 0 ); + Abc_NtkCleanupSeq( pNtk, 0, 0, 0 ); + Abc_NtkToSop( pNtk, 0 ); + Abc_NtkCycleInitStateSop( pNtk, 50, 0 ); + return pNtk; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcDress.c b/abc70930/src/base/abci/abcDress.c new file mode 100644 index 00000000..f8182532 --- /dev/null +++ b/abc70930/src/base/abci/abcDress.c @@ -0,0 +1,209 @@ +/**CFile**************************************************************** + + FileName [abcDress.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Transfers names from one netlist to the other.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDress.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk ); +static void Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose ); + +extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transfers names from one netlist to the other.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDress( Abc_Ntk_t * pNtkLogic, char * pFileName, int fVerbose ) +{ + Abc_Ntk_t * pNtkOrig, * pNtkLogicOrig; + Abc_Ntk_t * pMiter, * pMiterFraig; + stmm_table * tMapping; + + assert( Abc_NtkIsLogic(pNtkLogic) ); + + // get the original netlist + pNtkOrig = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 1 ); + if ( pNtkOrig == NULL ) + return; + assert( Abc_NtkIsNetlist(pNtkOrig) ); + + Abc_NtkCleanCopy(pNtkLogic); + Abc_NtkCleanCopy(pNtkOrig); + + // convert it into the logic network + pNtkLogicOrig = Abc_NtkToLogic( pNtkOrig ); + // check that the networks have the same PIs/POs/latches + if ( !Abc_NtkCompareSignals( pNtkLogic, pNtkLogicOrig, 1, 1 ) ) + { + Abc_NtkDelete( pNtkOrig ); + Abc_NtkDelete( pNtkLogicOrig ); + return; + } + + // convert the current logic network into an AIG + pMiter = Abc_NtkStrash( pNtkLogic, 1, 0, 0 ); + + // convert it into the AIG and make the netlist point to the AIG + Abc_NtkAppend( pMiter, pNtkLogicOrig, 1 ); + Abc_NtkTransferCopy( pNtkOrig ); + Abc_NtkDelete( pNtkLogicOrig ); + +if ( fVerbose ) +{ +printf( "After mitering:\n" ); +printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) ); +printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) ); +} + + // fraig the miter (miter nodes point to the fraiged miter) + pMiterFraig = Abc_NtkIvyFraig( pMiter, 100, 1, 0, 1, 0 ); + // make netlists point to the fraiged miter + Abc_NtkTransferCopy( pNtkLogic ); + Abc_NtkTransferCopy( pNtkOrig ); + Abc_NtkDelete( pMiter ); + +if ( fVerbose ) +{ +printf( "After fraiging:\n" ); +printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) ); +printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) ); +} + + // derive mapping from the fraiged nodes into their prototype nodes in the original netlist + tMapping = Abc_NtkDressDeriveMapping( pNtkOrig ); + + // transfer the names to the new netlist + Abc_NtkDressTransferNames( pNtkLogic, tMapping, fVerbose ); + + // clean up + stmm_free_table( tMapping ); + Abc_NtkDelete( pMiterFraig ); + Abc_NtkDelete( pNtkOrig ); +} + +/**Function************************************************************* + + Synopsis [Returns the mapping from the fraig nodes point into the nodes of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk ) +{ + stmm_table * tResult; + Abc_Obj_t * pNode, * pNodeMap, * pNodeFraig; + int i; + assert( Abc_NtkIsNetlist(pNtk) ); + tResult = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // get the fraiged node + pNodeFraig = Abc_ObjRegular(pNode->pCopy); + // if this node is already mapped, skip + if ( stmm_is_member( tResult, (char *)pNodeFraig ) ) + continue; + // get the mapping of this node + pNodeMap = Abc_ObjNotCond( pNode, Abc_ObjIsComplement(pNode->pCopy) ); + // add the mapping + stmm_insert( tResult, (char *)pNodeFraig, (char *)pNodeMap ); + } + return tResult; +} + +/**Function************************************************************* + + Synopsis [Attaches the names of to the new netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose ) +{ + Abc_Obj_t * pNet, * pNode, * pNodeMap, * pNodeFraig; + char * pName; + int i, Counter = 0, CounterInv = 0, CounterInit = stmm_count(tMapping); + assert( Abc_NtkIsLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // if the node already has a name, quit + pName = Nm_ManFindNameById( pNtk->pManName, pNode->Id ); + if ( pName != NULL ) + continue; + // get the fraiged node + pNodeFraig = Abc_ObjRegular(pNode->pCopy); + // find the matching node of the original netlist + if ( !stmm_lookup( tMapping, (char *)pNodeFraig, (char **)&pNodeMap ) ) + continue; + // find the true match + pNodeMap = Abc_ObjNotCond( pNodeMap, Abc_ObjIsComplement(pNode->pCopy) ); + // get the name + pNet = Abc_ObjFanout0(Abc_ObjRegular(pNodeMap)); + pName = Nm_ManFindNameById( pNet->pNtk->pManName, pNet->Id ); + assert( pName != NULL ); + // set the name + if ( Abc_ObjIsComplement(pNodeMap) ) + { + Abc_ObjAssignName( pNode, pName, "_inv" ); + CounterInv++; + } + else + { + Abc_ObjAssignName( pNode, pName, NULL ); + Counter++; + } + // remove the name + stmm_delete( tMapping, (char **)&pNodeFraig, (char **)&pNodeMap ); + } + if ( fVerbose ) + { + printf( "Total number of names collected = %5d.\n", CounterInit ); + printf( "Total number of names assigned = %5d. (Dir = %5d. Compl = %5d.)\n", + Counter + CounterInv, Counter, CounterInv ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcDsd.c b/abc70930/src/base/abci/abcDsd.c new file mode 100644 index 00000000..c00a7d7c --- /dev/null +++ b/abc70930/src/base/abci/abcDsd.c @@ -0,0 +1,551 @@ +/**CFile**************************************************************** + + FileName [abcDsd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Decomposes the network using disjoint-support decomposition.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dsd.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ); +static void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +static Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters ); + +static Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk ); +static void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive, int * pCounters ); +static bool Abc_NodeIsForDsd( Abc_Obj_t * pNode ); +static int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the DSD network.] + + Description [Takes the strashed network (pNtk), derives global BDDs for + the combinational outputs of this network, and decomposes these BDDs using + disjoint support decomposition. Finally, constructs and return a new + network, which is topologically equivalent to the decomposition tree. + Allocates and frees a new BDD manager and a new DSD manager.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ) +{ + DdManager * dd; + Abc_Ntk_t * pNtkNew; + assert( Abc_NtkIsStrash(pNtk) ); + dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); + if ( dd == NULL ) + return NULL; + if ( fVerbose ) + printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + // transform the result of mapping into a BDD network + pNtkNew = Abc_NtkDsdInternal( pNtk, fVerbose, fPrint, fShort ); + Extra_StopManager( dd ); + if ( pNtkNew == NULL ) + return NULL; + // copy EXDC network + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkDsdGlobal: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Constructs the decomposed network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ) +{ + char ** ppNamesCi, ** ppNamesCo; + Vec_Ptr_t * vFuncsGlob; + Dsd_Manager_t * pManDsd; + Abc_Ntk_t * pNtkNew; + DdManager * dd; + Abc_Obj_t * pObj; + int i; + + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vFuncsGlob, Cudd_NotCond(Abc_ObjGlobalBdd(pObj), Abc_ObjFaninC0(pObj)) ); + + // perform the decomposition + dd = Abc_NtkGlobalBddMan(pNtk); + pManDsd = Dsd_ManagerStart( dd, Abc_NtkCiNum(pNtk), fVerbose ); + Dsd_Decompose( pManDsd, (DdNode **)vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) ); + Vec_PtrFree( vFuncsGlob ); + Abc_NtkFreeGlobalBdds( pNtk, 0 ); + if ( pManDsd == NULL ) + { + Cudd_Quit( dd ); + return NULL; + } + + // start the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); + // make sure the new manager has enough inputs + Cudd_bddIthVar( pNtkNew->pManFunc, dd->size-1 ); + // put the results into the new network (save new CO drivers in old CO drivers) + Abc_NtkDsdConstruct( pManDsd, pNtk, pNtkNew ); + // finalize the new network + Abc_NtkFinalize( pNtk, pNtkNew ); + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + if ( fPrint ) + { + ppNamesCi = Abc_NtkCollectCioNames( pNtk, 0 ); + ppNamesCo = Abc_NtkCollectCioNames( pNtk, 1 ); + Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, fShort, -1 ); + free( ppNamesCi ); + free( ppNamesCo ); + } + + // stop the DSD manager + Dsd_ManagerStop( pManDsd ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Constructs the decomposed network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + Dsd_Node_t ** ppNodesDsd; + Dsd_Node_t * pNodeDsd; + Abc_Obj_t * pNode, * pNodeNew, * pDriver; + int i, nNodesDsd; + + // save the CI nodes in the DSD nodes + Dsd_NodeSetMark( Dsd_ManagerReadConst1(pManDsd), (int)Abc_NtkCreateNodeConst1(pNtkNew) ); + Abc_NtkForEachCi( pNtk, pNode, i ) + { + pNodeDsd = Dsd_ManagerReadInput( pManDsd, i ); + Dsd_NodeSetMark( pNodeDsd, (int)pNode->pCopy ); + } + + // collect DSD nodes in DFS order (leaves and const1 are not collected) + ppNodesDsd = Dsd_TreeCollectNodesDfs( pManDsd, &nNodesDsd ); + for ( i = 0; i < nNodesDsd; i++ ) + Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNtkNew, NULL ); + free( ppNodesDsd ); + + // set the pointers to the CO drivers + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pDriver = Abc_ObjFanin0( pNode ); + if ( !Abc_ObjIsNode(pDriver) ) + continue; + if ( !Abc_AigNodeIsAnd(pDriver) ) + continue; + pNodeDsd = Dsd_ManagerReadRoot( pManDsd, i ); + pNodeNew = (Abc_Obj_t *)Dsd_NodeReadMark( Dsd_Regular(pNodeDsd) ); + assert( !Abc_ObjIsComplement(pNodeNew) ); + pDriver->pCopy = Abc_ObjNotCond( pNodeNew, Dsd_IsComplement(pNodeDsd) ); + } +} + +/**Function************************************************************* + + Synopsis [Performs DSD using the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters ) +{ + DdManager * ddDsd = Dsd_ManagerReadDd( pManDsd ); + DdManager * ddNew = pNtkNew->pManFunc; + Dsd_Node_t * pFaninDsd; + Abc_Obj_t * pNodeNew, * pFanin; + DdNode * bLocal, * bTemp, * bVar; + Dsd_Type_t Type; + int i, nDecs; + + // create the new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + // add the fanins + Type = Dsd_NodeReadType( pNodeDsd ); + nDecs = Dsd_NodeReadDecsNum( pNodeDsd ); + assert( nDecs > 1 ); + for ( i = 0; i < nDecs; i++ ) + { + pFaninDsd = Dsd_NodeReadDec( pNodeDsd, i ); + pFanin = (Abc_Obj_t *)Dsd_NodeReadMark(Dsd_Regular(pFaninDsd)); + Abc_ObjAddFanin( pNodeNew, pFanin ); + assert( Type == DSD_NODE_OR || !Dsd_IsComplement(pFaninDsd) ); + } + + // create the local function depending on the type of the node + ddNew = pNtkNew->pManFunc; + switch ( Type ) + { + case DSD_NODE_CONST1: + { + bLocal = ddNew->one; Cudd_Ref( bLocal ); + break; + } + case DSD_NODE_OR: + { + bLocal = Cudd_Not(ddNew->one); Cudd_Ref( bLocal ); + for ( i = 0; i < nDecs; i++ ) + { + pFaninDsd = Dsd_NodeReadDec( pNodeDsd, i ); + bVar = Cudd_NotCond( ddNew->vars[i], Dsd_IsComplement(pFaninDsd) ); + bLocal = Cudd_bddOr( ddNew, bTemp = bLocal, bVar ); Cudd_Ref( bLocal ); + Cudd_RecursiveDeref( ddNew, bTemp ); + } + break; + } + case DSD_NODE_EXOR: + { + bLocal = Cudd_Not(ddNew->one); Cudd_Ref( bLocal ); + for ( i = 0; i < nDecs; i++ ) + { + bLocal = Cudd_bddXor( ddNew, bTemp = bLocal, ddNew->vars[i] ); Cudd_Ref( bLocal ); + Cudd_RecursiveDeref( ddNew, bTemp ); + } + break; + } + case DSD_NODE_PRIME: + { + if ( pCounters ) + { + if ( nDecs < 10 ) + pCounters[nDecs]++; + else + pCounters[10]++; + } + bLocal = Dsd_TreeGetPrimeFunction( ddDsd, pNodeDsd ); Cudd_Ref( bLocal ); + bLocal = Extra_TransferLevelByLevel( ddDsd, ddNew, bTemp = bLocal ); Cudd_Ref( bLocal ); +/* +if ( nDecs == 3 ) +{ +Extra_bddPrint( ddDsd, bTemp ); +printf( "\n" ); +} +*/ + Cudd_RecursiveDeref( ddDsd, bTemp ); + // bLocal is now in the new BDD manager + break; + } + default: + { + assert( 0 ); + break; + } + } + pNodeNew->pData = bLocal; + Dsd_NodeSetMark( pNodeDsd, (int)pNodeNew ); + return pNodeNew; +} + + + + + + +/**Function************************************************************* + + Synopsis [Recursively decomposes internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive ) +{ + Dsd_Manager_t * pManDsd; + DdManager * dd = pNtk->pManFunc; + Vec_Ptr_t * vNodes; + int i; + int pCounters[11] = {0}; + + assert( Abc_NtkIsBddLogic(pNtk) ); + + // make the network minimum base + Abc_NtkMinimumBase( pNtk ); + + // start the DSD manager + pManDsd = Dsd_ManagerStart( dd, dd->size, 0 ); + + // collect nodes for decomposition + vNodes = Abc_NtkCollectNodesForDsd( pNtk ); + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_NodeDecompDsdAndMux( vNodes->pArray[i], vNodes, pManDsd, fRecursive, pCounters ); + Vec_PtrFree( vNodes ); + + printf( "Number of non-decomposable functions:\n" ); + for ( i = 3; i < 10; i++ ) + printf( "Inputs = %d. Functions = %6d.\n", i, pCounters[i] ); + printf( "Inputs > %d. Functions = %6d.\n", 9, pCounters[10] ); + + // stop the DSD manager + Dsd_ManagerStop( pManDsd ); + + // make sure everything is okay + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkDsdRecursive: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes that may need decomposition.] + + Description [The nodes that do not need decomposition are those + whose BDD has more internal nodes than the support size.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsForDsd(pNode) ) + Vec_PtrPush( vNodes, pNode ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive, int * pCounters ) +{ + DdManager * dd = pNode->pNtk->pManFunc; + Abc_Obj_t * pRoot, * pFanin, * pNode1, * pNode2, * pNodeC; + Dsd_Node_t ** ppNodesDsd, * pNodeDsd, * pFaninDsd; + int i, nNodesDsd, iVar, fCompl; + + // try disjoint support decomposition + pNodeDsd = Dsd_DecomposeOne( pManDsd, pNode->pData ); + fCompl = Dsd_IsComplement( pNodeDsd ); + pNodeDsd = Dsd_Regular( pNodeDsd ); + + // determine what decomposition to use + if ( !fRecursive || Dsd_NodeReadDecsNum(pNodeDsd) != Abc_ObjFaninNum(pNode) ) + { // perform DSD + + // set the inputs + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + pFaninDsd = Dsd_ManagerReadInput( pManDsd, i ); + Dsd_NodeSetMark( pFaninDsd, (int)pFanin ); + } + + // construct the intermediate nodes + ppNodesDsd = Dsd_TreeCollectNodesDfsOne( pManDsd, pNodeDsd, &nNodesDsd ); + for ( i = 0; i < nNodesDsd; i++ ) + { + pRoot = Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNode->pNtk, pCounters ); + if ( Abc_NodeIsForDsd(pRoot) && fRecursive ) + Vec_PtrPush( vNodes, pRoot ); + } + free( ppNodesDsd ); + + // remove the current fanins + Abc_ObjRemoveFanins( pNode ); + // add fanin to the root + Abc_ObjAddFanin( pNode, pRoot ); + // update the function to be that of buffer + Cudd_RecursiveDeref( dd, pNode->pData ); + pNode->pData = Cudd_NotCond( dd->vars[0], fCompl ); Cudd_Ref( pNode->pData ); + } + else // perform MUX-decomposition + { + // get the cofactoring variable + iVar = Abc_NodeFindMuxVar( dd, pNode->pData, Abc_ObjFaninNum(pNode) ); + pNodeC = Abc_ObjFanin( pNode, iVar ); + + // get the negative cofactor + pNode1 = Abc_NtkCloneObj( pNode ); + pNode1->pData = Cudd_Cofactor( dd, pNode->pData, Cudd_Not(dd->vars[iVar]) ); Cudd_Ref( pNode1->pData ); + Abc_NodeMinimumBase( pNode1 ); + if ( Abc_NodeIsForDsd(pNode1) ) + Vec_PtrPush( vNodes, pNode1 ); + + // get the positive cofactor + pNode2 = Abc_NtkCloneObj( pNode ); + pNode2->pData = Cudd_Cofactor( dd, pNode->pData, dd->vars[iVar] ); Cudd_Ref( pNode2->pData ); + Abc_NodeMinimumBase( pNode2 ); + if ( Abc_NodeIsForDsd(pNode2) ) + Vec_PtrPush( vNodes, pNode2 ); + + // remove the current fanins + Abc_ObjRemoveFanins( pNode ); + // add new fanins + Abc_ObjAddFanin( pNode, pNodeC ); + Abc_ObjAddFanin( pNode, pNode2 ); + Abc_ObjAddFanin( pNode, pNode1 ); + // update the function to be that of MUX + Cudd_RecursiveDeref( dd, pNode->pData ); + pNode->pData = Cudd_bddIte( dd, dd->vars[0], dd->vars[1], dd->vars[2] ); Cudd_Ref( pNode->pData ); + } +} + +/**Function************************************************************* + + Synopsis [Checks if the node should be decomposed by DSD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsForDsd( Abc_Obj_t * pNode ) +{ + DdManager * dd = pNode->pNtk->pManFunc; +// DdNode * bFunc, * bFunc0, * bFunc1; + assert( Abc_ObjIsNode(pNode) ); +// if ( Cudd_DagSize(pNode->pData)-1 > Abc_ObjFaninNum(pNode) ) +// return 1; +// return 0; + +/* + // this does not catch things like a(b+c), which should be decomposed + for ( bFunc = Cudd_Regular(pNode->pData); !cuddIsConstant(bFunc); ) + { + bFunc0 = Cudd_Regular( cuddE(bFunc) ); + bFunc1 = cuddT(bFunc); + if ( bFunc0 == b1 ) + bFunc = bFunc1; + else if ( bFunc1 == b1 || bFunc0 == bFunc1 ) + bFunc = bFunc0; + else + return 1; + } +*/ + if ( Abc_ObjFaninNum(pNode) > 2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Determines a cofactoring variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars ) +{ + DdNode * bVar, * bCof0, * bCof1; + int SuppSumMin = 1000000; + int i, nSSD, nSSQ, iVar; + +// printf( "\n\nCofactors:\n\n" ); + iVar = -1; + for ( i = 0; i < nVars; i++ ) + { + bVar = dd->vars[i]; + + bCof0 = Cudd_Cofactor( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof0 ); + bCof1 = Cudd_Cofactor( dd, bFunc, bVar ); Cudd_Ref( bCof1 ); + +// nodD = Cudd_DagSize(bCof0); +// nodQ = Cudd_DagSize(bCof1); +// printf( "+%02d: D=%2d. Q=%2d. ", i, nodD, nodQ ); +// printf( "S=%2d. D=%2d. ", nodD + nodQ, abs(nodD-nodQ) ); + + nSSD = Cudd_SupportSize( dd, bCof0 ); + nSSQ = Cudd_SupportSize( dd, bCof1 ); + +// printf( "SD=%2d. SQ=%2d. ", nSSD, nSSQ ); +// printf( "S=%2d. D=%2d. ", nSSD + nSSQ, abs(nSSD - nSSQ) ); +// printf( "Cost=%3d. ", Cost(nodD,nodQ,nSSD,nSSQ) ); +// printf( "\n" ); + + Cudd_RecursiveDeref( dd, bCof0 ); + Cudd_RecursiveDeref( dd, bCof1 ); + + if ( SuppSumMin > nSSD + nSSQ ) + { + SuppSumMin = nSSD + nSSQ; + iVar = i; + } + } + return iVar; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcEspresso.c b/abc70930/src/base/abci/abcEspresso.c new file mode 100644 index 00000000..8f9c7277 --- /dev/null +++ b/abc70930/src/base/abci/abcEspresso.c @@ -0,0 +1,250 @@ +/**CFile**************************************************************** + + FileName [abcEspresso.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to minimize SOPs using Espresso.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcEspresso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "espresso.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NodeEspresso( Abc_Obj_t * pNode ); +static pset_family Abc_SopToEspresso( char * pSop ); +static char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover ); +static pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Minimizes SOP representations using Espresso.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsLogic(pNtk) ); + // convert the network to have SOPs + if ( Abc_NtkHasMapping(pNtk) ) + Abc_NtkMapToSop(pNtk); + else if ( Abc_NtkHasBdd(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Abc_NtkEspresso(): Converting to SOPs has failed.\n" ); + return; + } + } + // minimize SOPs of all nodes + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( i ) Abc_NodeEspresso( pNode ); +} + +/**Function************************************************************* + + Synopsis [Minimizes SOP representation of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeEspresso( Abc_Obj_t * pNode ) +{ + extern void define_cube_size( int n ); + pset_family Cover; + int fCompl; + + assert( Abc_ObjIsNode(pNode) ); + // define the cube for this node + define_cube_size( Abc_ObjFaninNum(pNode) ); + // create the Espresso cover + fCompl = Abc_SopIsComplement( pNode->pData ); + Cover = Abc_SopToEspresso( pNode->pData ); + // perform minimization + Cover = Abc_EspressoMinimize( Cover, NULL ); // deletes also cover + // convert back onto the node's SOP representation + pNode->pData = Abc_SopFromEspresso( pNode->pNtk->pManFunc, Cover ); + if ( fCompl ) Abc_SopComplement( pNode->pData ); + sf_free(Cover); +} + +/**Function************************************************************* + + Synopsis [Converts SOP in ABC into SOP representation in Espresso.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +pset_family Abc_SopToEspresso( char * pSop ) +{ + char * pCube; + pset_family Cover; + pset set; + int nCubes, nVars, Value, v; + + if ( pSop == NULL ) + return NULL; + + nVars = Abc_SopGetVarNum(pSop); + nCubes = Abc_SopGetCubeNum(pSop); + assert( cube.size == 2 * nVars ); + + if ( Abc_SopIsConst0(pSop) ) + { + Cover = sf_new(0, cube.size); + return Cover; + } + if ( Abc_SopIsConst1(pSop) ) + { + Cover = sf_new(1, cube.size); + set = GETSET(Cover, Cover->count++); + set_copy( set, cube.fullset ); + return Cover; + } + + // create the cover + Cover = sf_new(nCubes, cube.size); + // fill in the cubes + Abc_SopForEachCube( pSop, nVars, pCube ) + { + set = GETSET(Cover, Cover->count++); + set_copy( set, cube.fullset ); + Abc_CubeForEachVar( pCube, Value, v ) + { + if ( Value == '0' ) + set_remove(set, 2*v+1); + else if ( Value == '1' ) + set_remove(set, 2*v); + } + } + return Cover; +} + +/**Function************************************************************* + + Synopsis [Converts SOP representation in Espresso into SOP in ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover ) +{ + pset set; + char * pSop, * pCube; + int Lit, nVars, nCubes, i, k; + + nVars = Cover->sf_size/2; + nCubes = Cover->count; + + pSop = Abc_SopStart( pMan, nCubes, nVars ); + + // go through the cubes + i = 0; + Abc_SopForEachCube( pSop, nVars, pCube ) + { + set = GETSET(Cover, i++); + for ( k = 0; k < nVars; k++ ) + { + Lit = GETINPUT(set, k); + if ( Lit == ZERO ) + pCube[k] = '0'; + else if ( Lit == ONE ) + pCube[k] = '1'; + } + } + return pSop; +} + + +/**Function************************************************************* + + Synopsis [Minimizes the cover using Espresso.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset ) +{ + pset_family pOffset; + int fNewDcset, i; + int fSimple = 0; + int fSparse = 0; + + if ( fSimple ) + { + for ( i = 0; i < cube.num_vars; i++ ) + pOnset = d1merge( pOnset, i ); + pOnset = sf_contain( pOnset ); + return pOnset; + } + + // create the dcset + fNewDcset = (pDcset == NULL); + if ( pDcset == NULL ) + pDcset = sf_new( 1, cube.size ); + pDcset->wsize = pOnset->wsize; + pDcset->sf_size = pOnset->sf_size; + + // derive the offset + if ( pDcset->sf_size == 0 || pDcset->count == 0 ) + pOffset = complement(cube1list(pOnset)); + else + pOffset = complement(cube2list(pOnset, pDcset)); + + // perform minimization + skip_make_sparse = !fSparse; + pOnset = espresso( pOnset, pDcset, pOffset ); + + // free covers + sf_free( pOffset ); + if ( fNewDcset ) + sf_free( pDcset ); + return pOnset; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcExtract.c b/abc70930/src/base/abci/abcExtract.c new file mode 100644 index 00000000..52ea03a3 --- /dev/null +++ b/abc70930/src/base/abci/abcExtract.c @@ -0,0 +1,51 @@ +/**CFile**************************************************************** + + FileName [abcMvCost.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Calculating the cost of one MV block.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMvCost.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MvCostTest( Abc_Ntk_t * pNtk ) +{ + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcFpga.c b/abc70930/src/base/abci/abcFpga.c new file mode 100644 index 00000000..3bc9fbed --- /dev/null +++ b/abc70930/src/base/abci/abcFpga.c @@ -0,0 +1,278 @@ +/**CFile**************************************************************** + + FileName [abcFpga.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFpga.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fpgaInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose ); +static Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk ); +static Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Interface with the FPGA mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose ) +{ + int fShowSwitching = 1; + Abc_Ntk_t * pNtkNew; + Fpga_Man_t * pMan; + Vec_Int_t * vSwitching; + float * pSwitching = NULL; + + assert( Abc_NtkIsStrash(pNtk) ); + + // print a warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Performing FPGA mapping with choices.\n" ); + + // compute switching activity + fShowSwitching |= fSwitching; + if ( fShowSwitching ) + { + extern Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ); + vSwitching = Sim_NtkComputeSwitching( pNtk, 4096 ); + pSwitching = (float *)vSwitching->pArray; + } + + // perform FPGA mapping + pMan = Abc_NtkToFpga( pNtk, fRecovery, pSwitching, fLatchPaths, fVerbose ); + if ( pSwitching ) Vec_IntFree( vSwitching ); + if ( pMan == NULL ) + return NULL; + Fpga_ManSetSwitching( pMan, fSwitching ); + Fpga_ManSetLatchPaths( pMan, fLatchPaths ); + Fpga_ManSetLatchNum( pMan, Abc_NtkLatchNum(pNtk) ); + Fpga_ManSetDelayTarget( pMan, DelayTarget ); + if ( !Fpga_Mapping( pMan ) ) + { + Fpga_ManFree( pMan ); + return NULL; + } + + // transform the result of mapping into a BDD network + pNtkNew = Abc_NtkFromFpga( pMan, pNtk ); + if ( pNtkNew == NULL ) + return NULL; + Fpga_ManFree( pMan ); + + // make the network minimum base + Abc_NtkMinimumBase( pNtkNew ); + + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkFpga: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Load the network into FPGA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose ) +{ + Fpga_Man_t * pMan; + ProgressBar * pProgress; + Fpga_Node_t * pNodeFpga; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pFanin, * pPrev; + float * pfArrivals; + int i; + + assert( Abc_NtkIsStrash(pNtk) ); + + // start the mapping manager and set its parameters + pMan = Fpga_ManCreate( Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), fVerbose ); + if ( pMan == NULL ) + return NULL; + Fpga_ManSetAreaRecovery( pMan, fRecovery ); + Fpga_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) ); + pfArrivals = Abc_NtkGetCiArrivalFloats(pNtk); + if ( fLatchPaths ) + { + for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) + pfArrivals[i] = -FPGA_FLOAT_LARGE; + } + Fpga_ManSetInputArrivals( pMan, pfArrivals ); + + // create PIs and remember them in the old nodes + Abc_NtkCleanCopy( pNtk ); + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fpga_ManReadConst1(pMan); + Abc_NtkForEachCi( pNtk, pNode, i ) + { + pNodeFpga = Fpga_ManReadInputs(pMan)[i]; + pNode->pCopy = (Abc_Obj_t *)pNodeFpga; + if ( pSwitching ) + Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] ); + } + + // load the AIG into the mapper + vNodes = Abc_AigDfs( pNtk, 0, 0 ); + pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // add the node to the mapper + pNodeFpga = Fpga_NodeAnd( pMan, + Fpga_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), + Fpga_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); + assert( pNode->pCopy == NULL ); + // remember the node + pNode->pCopy = (Abc_Obj_t *)pNodeFpga; + if ( pSwitching ) + Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] ); + // set up the choice node + if ( Abc_AigNodeIsChoice( pNode ) ) + for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) + { + Fpga_NodeSetNextE( (Fpga_Node_t *)pPrev->pCopy, (Fpga_Node_t *)pFanin->pCopy ); + Fpga_NodeSetRepr( (Fpga_Node_t *)pFanin->pCopy, (Fpga_Node_t *)pNode->pCopy ); + } + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + + // set the primary outputs without copying the phase + Abc_NtkForEachCo( pNtk, pNode, i ) + Fpga_ManReadOutputs(pMan)[i] = (Fpga_Node_t *)Abc_ObjFanin0(pNode)->pCopy; + return pMan; +} + +/**Function************************************************************* + + Synopsis [Creates the mapped network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pNodeNew; + int i, nDupGates; + // create the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); + // make the mapper point to the new network + Fpga_CutsCleanSign( pMan ); + Fpga_ManCleanData0( pMan ); + Abc_NtkForEachCi( pNtk, pNode, i ) + Fpga_NodeSetData0( Fpga_ManReadInputs(pMan)[i], (char *)pNode->pCopy ); + // set the constant node +// if ( Fpga_NodeReadRefs(Fpga_ManReadConst1(pMan)) > 0 ) + Fpga_NodeSetData0( Fpga_ManReadConst1(pMan), (char *)Abc_NtkCreateNodeConst1(pNtkNew) ); + // process the nodes in topological order + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNodeNew = Abc_NodeFromFpga_rec( pNtkNew, Fpga_ManReadOutputs(pMan)[i] ); + assert( !Abc_ObjIsComplement(pNodeNew) ); + Abc_ObjFanin0(pNode)->pCopy = pNodeNew; + } + Extra_ProgressBarStop( pProgress ); + // finalize the new network + Abc_NtkFinalize( pNtk, pNtkNew ); + // remove the constant node if not used + pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0(Fpga_ManReadConst1(pMan)); + if ( Abc_ObjFanoutNum(pNodeNew) == 0 ) + Abc_NtkDeleteObj( pNodeNew ); + // decouple the PO driver nodes to reduce the number of levels + nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); +// if ( nDupGates && Fpga_ManReadVerbose(pMan) ) +// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Derive one node after FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga ) +{ + Fpga_Cut_t * pCutBest; + Fpga_Node_t ** ppLeaves; + Abc_Obj_t * pNodeNew; + int i, nLeaves; + assert( !Fpga_IsComplement(pNodeFpga) ); + // return if the result if known + pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0( pNodeFpga ); + if ( pNodeNew ) + return pNodeNew; + assert( Fpga_NodeIsAnd(pNodeFpga) ); + // get the parameters of the best cut + pCutBest = Fpga_NodeReadCutBest( pNodeFpga ); + ppLeaves = Fpga_CutReadLeaves( pCutBest ); + nLeaves = Fpga_CutReadLeavesNum( pCutBest ); + // create a new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + for ( i = 0; i < nLeaves; i++ ) + Abc_ObjAddFanin( pNodeNew, Abc_NodeFromFpga_rec(pNtkNew, ppLeaves[i]) ); + // derive the function of this node + pNodeNew->pData = Fpga_TruthsCutBdd( pNtkNew->pManFunc, pCutBest ); Cudd_Ref( pNodeNew->pData ); + Fpga_NodeSetData0( pNodeFpga, (char *)pNodeNew ); + return pNodeNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcFpgaFast.c b/abc70930/src/base/abci/abcFpgaFast.c new file mode 100644 index 00000000..356b855e --- /dev/null +++ b/abc70930/src/base/abci/abcFpgaFast.c @@ -0,0 +1,190 @@ +/**CFile**************************************************************** + + FileName [abcFpgaFast.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Fast FPGA mapper.] + + Author [Sungmin Cho] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFpgaFast.c,v 1.00 2006/09/02 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ); + +static Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ); +static Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes ); + +static inline void Abc_ObjSetIvy2Abc( Ivy_Man_t * p, int IvyId, Abc_Obj_t * pObjAbc ) { assert(Vec_PtrEntry(p->pCopy, IvyId) == NULL); assert(!Abc_ObjIsComplement(pObjAbc)); Vec_PtrWriteEntry( p->pCopy, IvyId, pObjAbc ); } +static inline Abc_Obj_t * Abc_ObjGetIvy2Abc( Ivy_Man_t * p, int IvyId ) { return Vec_PtrEntry( p->pCopy, IvyId ); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs fast FPGA mapping of the network.] + + Description [Takes the AIG to be mapped, the LUT size, and verbosity + flag. Produces the new network by fast FPGA mapping of the current + network. If the current network in ABC in not an AIG, the user should + run command "strash" to make sure that the current network into an AIG + before calling this procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose ) +{ + Ivy_Man_t * pMan; + Abc_Ntk_t * pNtkNew; + // make sure the network is an AIG + assert( Abc_NtkIsStrash(pNtk) ); + // convert the network into the AIG + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + // perform fast FPGA mapping + Ivy_FastMapPerform( pMan, nLutSize, fRecovery, fVerbose ); + // convert back into the ABC network + pNtkNew = Ivy_ManFpgaToAbc( pNtk, pMan ); + Ivy_FastMapStop( pMan ); + Ivy_ManStop( pMan ); + // make sure that the final network passes the test + if ( pNtkNew != NULL && !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkFastMap: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Constructs the ABC network after mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjAbc, * pObj; + Ivy_Obj_t * pObjIvy; + Vec_Int_t * vNodes; + int i; + // start mapping from Ivy into Abc + pMan->pCopy = Vec_PtrStart( Ivy_ManObjIdMax(pMan) + 1 ); + // start the new ABC network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Abc_ObjSetIvy2Abc( pMan, Ivy_ManConst1(pMan)->Id, Abc_NtkCreateNodeConst1(pNtkNew) ); + Abc_NtkForEachCi( pNtkNew, pObjAbc, i ) + Abc_ObjSetIvy2Abc( pMan, Ivy_ManPi(pMan, i)->Id, pObjAbc ); + // recursively construct the network + vNodes = Vec_IntAlloc( 100 ); + Ivy_ManForEachPo( pMan, pObjIvy, i ) + { + // get the new ABC node corresponding to the old fanin of the PO in IVY + pObjAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ObjFanin0(pObjIvy), vNodes ); + // consider the case of complemented fanin of the PO + if ( Ivy_ObjFaninC0(pObjIvy) ) // complement + { + if ( Abc_ObjIsCi(pObjAbc) ) + pObjAbc = Abc_NtkCreateNodeInv( pNtkNew, pObjAbc ); + else + { + // clone the node + pObj = Abc_NtkCloneObj( pObjAbc ); + // set complemented functions + pObj->pData = Hop_Not( pObjAbc->pData ); + // return the new node + pObjAbc = pObj; + } + } + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjAbc ); + } + Vec_IntFree( vNodes ); + Vec_PtrFree( pMan->pCopy ); + pMan->pCopy = NULL; + // remove dangling nodes + Abc_NtkCleanup( pNtkNew, 0 ); + // fix CIs feeding directly into COs + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Recursively construct the new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes ) +{ + Vec_Int_t Supp, * vSupp = &Supp; + Abc_Obj_t * pObjAbc, * pFaninAbc; + Ivy_Obj_t * pNodeIvy; + int i, Entry; + // skip the node if it is a constant or already processed + pObjAbc = Abc_ObjGetIvy2Abc( pMan, pObjIvy->Id ); + if ( pObjAbc ) + return pObjAbc; + assert( Ivy_ObjIsAnd(pObjIvy) || Ivy_ObjIsExor(pObjIvy) ); + // get the support of K-LUT + Ivy_FastMapReadSupp( pMan, pObjIvy, vSupp ); + // create new ABC node and its fanins + pObjAbc = Abc_NtkCreateNode( pNtkNew ); + Vec_IntForEachEntry( vSupp, Entry, i ) + { + pFaninAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ManObj(pMan, Entry), vNodes ); + Abc_ObjAddFanin( pObjAbc, pFaninAbc ); + } + // collect the nodes used in the cut + Ivy_ManCollectCut( pMan, pObjIvy, vSupp, vNodes ); + // create the local function + Ivy_ManForEachNodeVec( pMan, vNodes, pNodeIvy, i ) + { + if ( i < Vec_IntSize(vSupp) ) + pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_IthVar( pNtkNew->pManFunc, i ); + else + pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_And( pNtkNew->pManFunc, (Hop_Obj_t *)Ivy_ObjChild0Equiv(pNodeIvy), (Hop_Obj_t *)Ivy_ObjChild1Equiv(pNodeIvy) ); + } + // set the local function + pObjAbc->pData = (Abc_Obj_t *)pObjIvy->pEquiv; + // set the node + Abc_ObjSetIvy2Abc( pMan, pObjIvy->Id, pObjAbc ); + return pObjAbc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcFraig.c b/abc70930/src/base/abci/abcFraig.c new file mode 100644 index 00000000..be8a25f1 --- /dev/null +++ b/abc70930/src/base/abci/abcFraig.c @@ -0,0 +1,803 @@ +/**CFile**************************************************************** + + FileName [abcFraig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures interfacing with the FRAIG package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFraig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fraig.h" +#include "main.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); +static Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig ); +static void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs ); +extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc ); +static void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); + +static int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk ); +static void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +static Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Interfaces the network with the FRAIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ) +{ + Fraig_Params_t * pPars = pParams; + Abc_Ntk_t * pNtkNew; + Fraig_Man_t * pMan; + // check if EXDC is present + if ( fExdc && pNtk->pExdc == NULL ) + fExdc = 0, printf( "Warning: Networks has no EXDC.\n" ); + // perform fraiging + pMan = Abc_NtkToFraig( pNtk, pParams, fAllNodes, fExdc ); + // add algebraic choices +// if ( pPars->fChoicing ) +// Fraig_ManAddChoices( pMan, 0, 6 ); + // prove the miter if asked to + if ( pPars->fTryProve ) + Fraig_ManProveMiter( pMan ); + // reconstruct FRAIG in the new network + if ( fExdc ) + pNtkNew = Abc_NtkFromFraig2( pMan, pNtk ); + else + pNtkNew = Abc_NtkFromFraig( pMan, pNtk ); + Fraig_ManFree( pMan ); + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkFraig: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transforms the strashed network into FRAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ) +{ + int fInternal = ((Fraig_Params_t *)pParams)->fInternal; + Fraig_Man_t * pMan; + ProgressBar * pProgress; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + + assert( Abc_NtkIsStrash(pNtk) ); + + // create the FRAIG manager + pMan = Fraig_ManCreate( pParams ); + + // map the constant node + Abc_NtkCleanCopy( pNtk ); + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan); + // create PIs and remember them in the old nodes + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, i); + + // perform strashing + vNodes = Abc_AigDfs( pNtk, fAllNodes, 0 ); + if ( !fInternal ) + pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjFaninNum(pNode) == 0 ) + continue; + if ( !fInternal ) + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNode->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan, + Fraig_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), + Fraig_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); + } + if ( !fInternal ) + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + + // use EXDC to change the mapping of nodes into FRAIG nodes + if ( fExdc ) + Abc_NtkFraigRemapUsingExdc( pMan, pNtk ); + + // set the primary outputs + Abc_NtkForEachCo( pNtk, pNode, i ) + Fraig_ManSetPo( pMan, (Fraig_Node_t *)Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Derives EXDC node for the given network.] + + Description [Assumes that EXDCs of all POs are the same. + Returns the EXDC of the first PO.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc ) +{ + Abc_Ntk_t * pNtkStrash; + Abc_Obj_t * pObj; + Fraig_Node_t * gResult; + char ** ppNames; + int i, k; + // strash the EXDC network + pNtkStrash = Abc_NtkStrash( pNtkExdc, 0, 0, 0 ); + Abc_NtkCleanCopy( pNtkStrash ); + Abc_AigConst1(pNtkStrash)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan); + // set the mapping of the PI nodes + ppNames = Abc_NtkCollectCioNames( pNtkMain, 0 ); + Abc_NtkForEachCi( pNtkStrash, pObj, i ) + { + for ( k = 0; k < Abc_NtkCiNum(pNtkMain); k++ ) + if ( strcmp( Abc_ObjName(pObj), ppNames[k] ) == 0 ) + { + pObj->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, k); + break; + } + assert( pObj->pCopy != NULL ); + } + free( ppNames ); + // build FRAIG for each node + Abc_AigForEachAnd( pNtkStrash, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan, + Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ), + Fraig_NotCond( Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC1(pObj) ) ); + // get the EXDC to be returned + pObj = Abc_NtkPo( pNtkStrash, 0 ); + gResult = Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); + Abc_NtkDelete( pNtkStrash ); + return gResult; +} + + +/**Function************************************************************* + + Synopsis [Changes mapping of the old nodes into FRAIG nodes using EXDC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + Fraig_Node_t * gNodeNew, * gNodeExdc; + stmm_table * tTable; + stmm_generator * gen; + Abc_Obj_t * pNode, * pNodeBest; + Abc_Obj_t * pClass, ** ppSlot; + Vec_Ptr_t * vNexts; + int i; + + // get the global don't-cares + assert( pNtk->pExdc ); + gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc ); + + // save the next pointers + vNexts = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + Vec_PtrWriteEntry( vNexts, pNode->Id, pNode->pNext ); + + // find the classes of AIG nodes which have FRAIG nodes assigned + Abc_NtkCleanNext( pNtk ); + tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( pNode->pCopy ) + { + gNodeNew = Fraig_NodeAnd( pMan, (Fraig_Node_t *)pNode->pCopy, Fraig_Not(gNodeExdc) ); + if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(gNodeNew), (char ***)&ppSlot ) ) + *ppSlot = NULL; + pNode->pNext = *ppSlot; + *ppSlot = pNode; + } + + // for reach non-trival class, find the node with minimum level, and replace other nodes by it + Abc_AigSetNodePhases( pNtk ); + stmm_foreach_item( tTable, gen, (char **)&gNodeNew, (char **)&pClass ) + { + if ( pClass->pNext == NULL ) + continue; + // find the node with minimum level + pNodeBest = pClass; + for ( pNode = pClass->pNext; pNode; pNode = pNode->pNext ) + if ( pNodeBest->Level > pNode->Level ) + pNodeBest = pNode; + // remap the class nodes + for ( pNode = pClass; pNode; pNode = pNode->pNext ) + pNode->pCopy = Abc_ObjNotCond( pNodeBest->pCopy, pNode->fPhase ^ pNodeBest->fPhase ); + } + stmm_free_table( tTable ); + + // restore the next pointers + Abc_NtkCleanNext( pNtk ); + Abc_NtkForEachNode( pNtk, pNode, i ) + pNode->pNext = Vec_PtrEntry( vNexts, pNode->Id ); + Vec_PtrFree( vNexts ); +} + +/**Function************************************************************* + + Synopsis [Transforms FRAIG into strashed network with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pNodeNew; + int i; + // create the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // make the mapper point to the new network + Abc_NtkForEachCi( pNtk, pNode, i ) + Fraig_NodeSetData1( Fraig_ManReadIthVar(pMan, i), (Fraig_Node_t *)pNode->pCopy ); + // set the constant node + Fraig_NodeSetData1( Fraig_ManReadConst1(pMan), (Fraig_Node_t *)Abc_AigConst1(pNtkNew) ); + // process the nodes in topological order + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNodeNew = Abc_NodeFromFraig_rec( pNtkNew, Fraig_ManReadOutputs(pMan)[i] ); + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + } + Extra_ProgressBarStop( pProgress ); + Abc_NtkReassignIds( pNtkNew ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transforms into AIG one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig ) +{ + Abc_Obj_t * pRes, * pRes0, * pRes1, * pResMin, * pResCur; + Fraig_Node_t * pNodeTemp, * pNodeFraigR = Fraig_Regular(pNodeFraig); + void ** ppTail; + // check if the node was already considered + if ( pRes = (Abc_Obj_t *)Fraig_NodeReadData1(pNodeFraigR) ) + return Abc_ObjNotCond( pRes, Fraig_IsComplement(pNodeFraig) ); + // solve the children + pRes0 = Abc_NodeFromFraig_rec( pNtkNew, Fraig_NodeReadOne(pNodeFraigR) ); + pRes1 = Abc_NodeFromFraig_rec( pNtkNew, Fraig_NodeReadTwo(pNodeFraigR) ); + // derive the new node + pRes = Abc_AigAnd( pNtkNew->pManFunc, pRes0, pRes1 ); + pRes->fPhase = Fraig_NodeReadSimInv( pNodeFraigR ); + // if the node has an equivalence class, find its representative + if ( Fraig_NodeReadRepr(pNodeFraigR) == NULL && Fraig_NodeReadNextE(pNodeFraigR) != NULL ) + { + // go through the FRAIG nodes belonging to this equivalence class + // and find the representative node (the node with the smallest level) + pResMin = pRes; + for ( pNodeTemp = Fraig_NodeReadNextE(pNodeFraigR); pNodeTemp; pNodeTemp = Fraig_NodeReadNextE(pNodeTemp) ) + { + assert( Fraig_NodeReadData1(pNodeTemp) == NULL ); + pResCur = Abc_NodeFromFraig_rec( pNtkNew, pNodeTemp ); + if ( pResMin->Level > pResCur->Level ) + pResMin = pResCur; + } + // link the nodes in such a way that representative goes first + ppTail = &pResMin->pData; + if ( pRes != pResMin ) + { + *ppTail = pRes; + ppTail = &pRes->pData; + } + for ( pNodeTemp = Fraig_NodeReadNextE(pNodeFraigR); pNodeTemp; pNodeTemp = Fraig_NodeReadNextE(pNodeTemp) ) + { + pResCur = (Abc_Obj_t *)Fraig_NodeReadData1(pNodeTemp); + assert( pResCur ); + if ( pResMin == pResCur ) + continue; + *ppTail = pResCur; + ppTail = &pResCur->pData; + } + assert( *ppTail == NULL ); + + // update the phase of the node + pRes = Abc_ObjNotCond( pResMin, (pRes->fPhase ^ pResMin->fPhase) ); + } + Fraig_NodeSetData1( pNodeFraigR, (Fraig_Node_t *)pRes ); + return Abc_ObjNotCond( pRes, Fraig_IsComplement(pNodeFraig) ); +} + +/**Function************************************************************* + + Synopsis [Transforms FRAIG into strashed network without choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + stmm_table * tTable; + Vec_Ptr_t * vNodeReprs; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pRepr, ** ppSlot; + int i; + + // map the nodes into their lowest level representives + tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); + pNode = Abc_AigConst1(pNtk); + if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) ) + *ppSlot = pNode; + Abc_NtkForEachCi( pNtk, pNode, i ) + if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) ) + *ppSlot = pNode; + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( pNode->pCopy ) + { + if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) ) + *ppSlot = pNode; + else if ( (*ppSlot)->Level > pNode->Level ) + *ppSlot = pNode; + } + // save representatives for each node + vNodeReprs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( pNode->pCopy ) + { + if ( !stmm_lookup( tTable, (char *)Fraig_Regular(pNode->pCopy), (char **)&pRepr ) ) + assert( 0 ); + if ( pNode != pRepr ) + Vec_PtrWriteEntry( vNodeReprs, pNode->Id, pRepr ); + } + stmm_free_table( tTable ); + + // create the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + + // perform strashing + Abc_AigSetNodePhases( pNtk ); + Abc_NtkIncrementTravId( pNtk ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs ); + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodeReprs ); + + // finalize the network + Abc_NtkFinalize( pNtk, pNtkNew ); + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Transforms into AIG one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs ) +{ + Abc_Obj_t * pRepr; + // skip the PIs and constants + if ( Abc_ObjFaninNum(pNode) < 2 ) + return; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + assert( Abc_ObjIsNode( pNode ) ); + // get the node's representative + if ( pRepr = Vec_PtrEntry(vNodeReprs, pNode->Id) ) + { + Abc_NtkFromFraig2_rec( pNtkNew, pRepr, vNodeReprs ); + pNode->pCopy = Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pNode->fPhase ); + return; + } + Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs ); + Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin1(pNode), vNodeReprs ); + pNode->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); +} + + + +/**Function************************************************************* + + Synopsis [Interfaces the network with the FRAIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + printf( "Abc_NtkFraigTrust: Trust mode works for netlists and logic SOP networks.\n" ); + return NULL; + } + + if ( !Abc_NtkFraigTrustCheck(pNtk) ) + { + printf( "Abc_NtkFraigTrust: The network does not look like an AIG with choice nodes.\n" ); + return NULL; + } + + // perform strashing + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + Abc_NtkFraigTrustOne( pNtk, pNtkNew ); + Abc_NtkFinalize( pNtk, pNtkNew ); + Abc_NtkReassignIds( pNtkNew ); + + // print a warning about choice nodes + printf( "Warning: The resulting AIG contains %d choice nodes.\n", Abc_NtkGetChoiceNum( pNtkNew ) ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkFraigTrust: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Checks whether the node can be processed in the trust mode.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nFanins; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + nFanins = Abc_ObjFaninNum(pNode); + if ( nFanins < 2 ) + continue; + if ( nFanins == 2 && Abc_SopIsAndType(pNode->pData) ) + continue; + if ( !Abc_SopIsOrType(pNode->pData) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Interfaces the network with the FRAIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pNodeNew, * pObj; + int i; + + // perform strashing + vNodes = Abc_NtkDfs( pNtk, 0 ); + pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // get the node + assert( Abc_ObjIsNode(pNode) ); + // strash the node + pNodeNew = Abc_NodeFraigTrust( pNtkNew, pNode ); + // get the old object + if ( Abc_NtkIsNetlist(pNtk) ) + pObj = Abc_ObjFanout0( pNode ); // the fanout net + else + pObj = pNode; // the node itself + // make sure the node is not yet strashed + assert( pObj->pCopy == NULL ); + // mark the old object with the new AIG node + pObj->pCopy = pNodeNew; + } + Vec_PtrFree( vNodes ); + Extra_ProgressBarStop( pProgress ); +} + +/**Function************************************************************* + + Synopsis [Transforms one node into a FRAIG in the trust mode.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pSum, * pFanin; + void ** ppTail; + int i, nFanins, fCompl; + + assert( Abc_ObjIsNode(pNode) ); + // get the number of node's fanins + nFanins = Abc_ObjFaninNum( pNode ); + assert( nFanins == Abc_SopGetVarNum(pNode->pData) ); + // check if it is a constant + if ( nFanins == 0 ) + return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Abc_SopIsConst0(pNode->pData) ); + if ( nFanins == 1 ) + return Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_SopIsInv(pNode->pData) ); + if ( nFanins == 2 && Abc_SopIsAndType(pNode->pData) ) + return Abc_AigAnd( pNtkNew->pManFunc, + Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, !Abc_SopGetIthCareLit(pNode->pData,0) ), + Abc_ObjNotCond( Abc_ObjFanin1(pNode)->pCopy, !Abc_SopGetIthCareLit(pNode->pData,1) ) ); + assert( Abc_SopIsOrType(pNode->pData) ); + fCompl = Abc_SopGetIthCareLit(pNode->pData,0); + // get the root of the choice node (the first fanin) + pSum = Abc_ObjFanin0(pNode)->pCopy; + // connect other fanins + ppTail = &pSum->pData; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( i == 0 ) + continue; + *ppTail = pFanin->pCopy; + ppTail = &pFanin->pCopy->pData; + // set the complemented bit of this cut + if ( fCompl ^ Abc_SopGetIthCareLit(pNode->pData, i) ) + pFanin->pCopy->fPhase = 1; + } + assert( *ppTail == NULL ); + return pSum; +} + + + + +/**Function************************************************************* + + Synopsis [Interfaces the network with the FRAIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkFraigStore( Abc_Ntk_t * pNtkAdd ) +{ + Vec_Ptr_t * vStore; + Abc_Ntk_t * pNtk; + // create the network to be stored + pNtk = Abc_NtkStrash( pNtkAdd, 0, 0, 0 ); + if ( pNtk == NULL ) + { + printf( "Abc_NtkFraigStore: Initial strashing has failed.\n" ); + return 0; + } + // get the network currently stored + vStore = Abc_FrameReadStore(); + if ( Vec_PtrSize(vStore) > 0 ) + { + // check that the networks have the same PIs + // reorder PIs of pNtk2 according to pNtk1 + if ( !Abc_NtkCompareSignals( pNtk, Vec_PtrEntry(vStore, 0), 1, 1 ) ) + { + printf( "Trying to store the network with different primary inputs.\n" ); + printf( "The previously stored networks are deleted and this one is added.\n" ); + Abc_NtkFraigStoreClean(); + } + } + Vec_PtrPush( vStore, pNtk ); +// printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pNtk) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Interfaces the network with the FRAIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFraigRestore() +{ + extern Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams ); + Fraig_Params_t Params; + Vec_Ptr_t * vStore; + Abc_Ntk_t * pNtk, * pFraig; + int nWords1, nWords2, nWordsMin; + int clk = clock(); + + // get the stored network + vStore = Abc_FrameReadStore(); + if ( Vec_PtrSize(vStore) == 0 ) + { + printf( "There are no network currently in storage.\n" ); + return NULL; + } +// printf( "Currently stored %d networks will be fraiged.\n", Vec_PtrSize(vStore) ); + pNtk = Vec_PtrEntry( vStore, 0 ); + + // swap the first and last network + // this should lead to the primary choice being "better" because of synthesis + pNtk = Vec_PtrPop( vStore ); + Vec_PtrPush( vStore, Vec_PtrEntry(vStore,0) ); + Vec_PtrWriteEntry( vStore, 0, pNtk ); + + // to determine the number of simulation patterns + // use the following strategy + // at least 64 words (32 words random and 32 words dynamic) + // no more than 256M for one circuit (128M + 128M) + nWords1 = 32; + nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk)); + nWordsMin = ABC_MIN( nWords1, nWords2 ); + + // set parameters for fraiging + Fraig_ParamsSetDefault( &Params ); + Params.nPatsRand = nWordsMin * 32; // the number of words of random simulation info + Params.nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info + Params.nBTLimit = 1000; // the max number of backtracks to perform + Params.fFuncRed = 1; // performs only one level hashing + Params.fFeedBack = 1; // enables solver feedback + Params.fDist1Pats = 1; // enables distance-1 patterns + Params.fDoSparse = 1; // performs equiv tests for sparse functions + Params.fChoicing = 1; // enables recording structural choices + Params.fTryProve = 0; // tries to solve the final miter + Params.fVerbose = 0; // the verbosiness flag + + // perform partitioned computation of structural choices + pFraig = Abc_NtkFraigPartitioned( vStore, &Params ); + Abc_NtkFraigStoreClean(); +//PRT( "Total choicing time", clock() - clk ); + return pFraig; +} + +/**Function************************************************************* + + Synopsis [Interfaces the network with the FRAIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigStoreClean() +{ + Vec_Ptr_t * vStore; + Abc_Ntk_t * pNtk; + int i; + vStore = Abc_FrameReadStore(); + Vec_PtrForEachEntry( vStore, pNtk, i ) + Abc_NtkDelete( pNtk ); + Vec_PtrClear( vStore ); +} + +/**Function************************************************************* + + Synopsis [Checks the correctness of stored networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigStoreCheck( Abc_Ntk_t * pFraig ) +{ + Abc_Obj_t * pNode0, * pNode1; + int nPoOrig, nPoFinal, nStored; + int i, k; + // check that the PO functions are correct + nPoFinal = Abc_NtkPoNum(pFraig); + nStored = Abc_FrameReadStoreSize(); + assert( nPoFinal % nStored == 0 ); + nPoOrig = nPoFinal / nStored; + for ( i = 0; i < nPoOrig; i++ ) + { + pNode0 = Abc_ObjFanin0( Abc_NtkPo(pFraig, i) ); + for ( k = 1; k < nStored; k++ ) + { + pNode1 = Abc_ObjFanin0( Abc_NtkPo(pFraig, k*nPoOrig+i) ); + if ( pNode0 != pNode1 ) + printf( "Verification for PO #%d of network #%d has failed. The PO function is not used.\n", i+1, k+1 ); + } + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcFxu.c b/abc70930/src/base/abci/abcFxu.c new file mode 100644 index 00000000..45515dd1 --- /dev/null +++ b/abc70930/src/base/abci/abcFxu.c @@ -0,0 +1,260 @@ +/**CFile**************************************************************** + + FileName [abcFxu.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface with the fast extract package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFxu.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fxu.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static bool Abc_NtkFxuCheck( Abc_Ntk_t * pNtk ); +static void Abc_NtkFxuCollectInfo( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); +static void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Performs fast_extract on the current network.] + + Description [Takes the network and the maximum number of nodes to extract. + Uses the concurrent double-cube and single cube divisor extraction procedure. + Modifies the network in the end, after extracting all nodes. Note that + Ntk_NetworkSweep() may increase the performance of this procedure because + the single-literal nodes will not be created in the sparse matrix. Returns 1 + if the network has been changed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) +{ + assert( Abc_NtkIsLogic(pNtk) ); + // if the network is already in the SOP form, it may come from BLIF file + // and it may not be SCC-free, in which case FXU will not work correctly + if ( Abc_NtkIsSopLogic(pNtk) ) + { // to make sure the SOPs are SCC-free +// Abc_NtkSopToBdd(pNtk); +// Abc_NtkBddToSop(pNtk); + } + // get the network in the SOP form + if ( !Abc_NtkToSop(pNtk, 0) ) + { + printf( "Abc_NtkFastExtract(): Converting to SOPs has failed.\n" ); + return 0; + } + // check if the network meets the requirements + if ( !Abc_NtkFxuCheck(pNtk) ) + { + printf( "Abc_NtkFastExtract: Nodes have duplicated or complemented fanins. FXU is not performed.\n" ); + return 0; + } + // sweep removes useless nodes + Abc_NtkCleanup( pNtk, 0 ); + // collect information about the covers + Abc_NtkFxuCollectInfo( pNtk, p ); + // call the fast extract procedure + if ( Fxu_FastExtract(p) > 0 ) + { + // update the network + Abc_NtkFxuReconstruct( pNtk, p ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtk ) ) + printf( "Abc_NtkFastExtract: The network check has failed.\n" ); + return 1; + } + else + printf( "Warning: The network has not been changed by \"fx\".\n" ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Makes sure the nodes do not have complemented and duplicated fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkFxuCheck( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pFanin1, * pFanin2; + int n, i, k; + Abc_NtkForEachNode( pNtk, pNode, n ) + { + Abc_ObjForEachFanin( pNode, pFanin1, i ) + { + if ( i < 2 && Abc_ObjFaninC(pNode, i) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin2, k ) + { + if ( i == k ) + continue; + if ( pFanin1 == pFanin2 ) + return 0; + } + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Collect information about the network for fast_extract.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFxuCollectInfo( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) +{ + Abc_Obj_t * pNode; + int i; + // add information to the manager + p->pManSop = pNtk->pManFunc; + p->vSops = Vec_PtrAlloc(0); + p->vFanins = Vec_PtrAlloc(0); + p->vSopsNew = Vec_PtrAlloc(0); + p->vFaninsNew = Vec_PtrAlloc(0); + Vec_PtrFill( p->vSops, Abc_NtkObjNumMax(pNtk), NULL ); + Vec_PtrFill( p->vFanins, Abc_NtkObjNumMax(pNtk), NULL ); + Vec_PtrFill( p->vSopsNew, Abc_NtkObjNumMax(pNtk) + p->nNodesExt, NULL ); + Vec_PtrFill( p->vFaninsNew, Abc_NtkObjNumMax(pNtk) + p->nNodesExt, NULL ); + // add SOPs and fanin array + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_SopGetVarNum(pNode->pData) < 2 ) + continue; + if ( Abc_SopGetCubeNum(pNode->pData) < 1 ) + continue; + p->vSops->pArray[i] = pNode->pData; + p->vFanins->pArray[i] = &pNode->vFanins; + } + p->nNodesOld = Abc_NtkObjNumMax(pNtk); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFxuFreeInfo( Fxu_Data_t * p ) +{ + int i; + // free the arrays of new fanins + if ( p->vFaninsNew ) + for ( i = 0; i < p->vFaninsNew->nSize; i++ ) + if ( p->vFaninsNew->pArray[i] ) + Vec_IntFree( p->vFaninsNew->pArray[i] ); + // free the arrays + if ( p->vSops ) Vec_PtrFree( p->vSops ); + if ( p->vSopsNew ) Vec_PtrFree( p->vSopsNew ); + if ( p->vFanins ) Vec_PtrFree( p->vFanins ); + if ( p->vFaninsNew ) Vec_PtrFree( p->vFaninsNew ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Recostructs the network after FX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) +{ + Vec_Int_t * vFanins; + Abc_Obj_t * pNode, * pFanin; + int i, k; + + assert( p->vFanins->nSize < p->vFaninsNew->nSize ); + // create the new nodes + for ( i = p->vFanins->nSize; i < p->vFanins->nSize + p->nNodesNew; i++ ) + { + // start the node + pNode = Abc_NtkCreateNode( pNtk ); + assert( i == (int)pNode->Id ); + } + // update the old nodes + for ( i = 0; i < p->vFanins->nSize; i++ ) + { + // the new array of fanins + vFanins = p->vFaninsNew->pArray[i]; + if ( vFanins == NULL ) + continue; + // remove old fanins + pNode = Abc_NtkObj( pNtk, i ); + Abc_ObjRemoveFanins( pNode ); + // add new fanins + vFanins = p->vFaninsNew->pArray[i]; + for ( k = 0; k < vFanins->nSize; k++ ) + { + pFanin = Abc_NtkObj( pNtk, vFanins->pArray[k] ); + Abc_ObjAddFanin( pNode, pFanin ); + } + pNode->pData = p->vSopsNew->pArray[i]; + assert( pNode->pData != NULL ); + } + // set up the new nodes + for ( i = p->vFanins->nSize; i < p->vFanins->nSize + p->nNodesNew; i++ ) + { + // get the new node + pNode = Abc_NtkObj( pNtk, i ); + // add the fanins + vFanins = p->vFaninsNew->pArray[i]; + for ( k = 0; k < vFanins->nSize; k++ ) + { + pFanin = Abc_NtkObj( pNtk, vFanins->pArray[k] ); + Abc_ObjAddFanin( pNode, pFanin ); + } + pNode->pData = p->vSopsNew->pArray[i]; + assert( pNode->pData != NULL ); + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcGen.c b/abc70930/src/base/abci/abcGen.c new file mode 100644 index 00000000..bfb41374 --- /dev/null +++ b/abc70930/src/base/abci/abcGen.c @@ -0,0 +1,511 @@ +/**CFile**************************************************************** + + FileName [abc_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 ); +void Abc_WriteComp( FILE * pFile ); +void Abc_WriteFullAdder( FILE * pFile ); + +void Abc_GenAdder( char * pFileName, int nVars ); +void Abc_GenSorter( char * pFileName, int nVars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_GenAdder( char * pFileName, int nVars ) +{ + FILE * pFile; + int i; + + assert( nVars > 0 ); + + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# %d-bit ripple-carry adder generated by ABC on %s\n", nVars, Extra_TimeStamp() ); + fprintf( pFile, ".model Adder%02d\n", nVars ); + + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " a%02d", i ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " b%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".outputs" ); + for ( i = 0; i <= nVars; i++ ) + fprintf( pFile, " y%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".names c\n" ); + if ( nVars == 1 ) + fprintf( pFile, ".subckt FA a=a00 b=b00 cin=c s=y00 cout=y01\n" ); + else + { + fprintf( pFile, ".subckt FA a=a00 b=b00 cin=c s=y00 cout=%02d\n", 0 ); + for ( i = 1; i < nVars-1; i++ ) + fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=%02d s=y%02d cout=%02d\n", i, i, i-1, i, i ); + fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=%02d s=y%02d cout=y%02d\n", i, i, i-1, i, i+1 ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); + + Abc_WriteFullAdder( pFile ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_GenSorter( char * pFileName, int nVars ) +{ + FILE * pFile; + int i, k, Counter, nDigits; + + assert( nVars > 1 ); + + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# %d-bit sorter generated by ABC on %s\n", nVars, Extra_TimeStamp() ); + fprintf( pFile, ".model Sorter%02d\n", nVars ); + + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " x%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".outputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " y%02d", i ); + fprintf( pFile, "\n" ); + + Counter = 0; + nDigits = Extra_Base10Log( (nVars-2)*nVars ); + if ( nVars == 2 ) + fprintf( pFile, ".subckt Comp a=x00 b=x01 x=y00 y=y01\n" ); + else + { + fprintf( pFile, ".subckt Layer0" ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " x%02d=x%02d", k, k ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ ); + fprintf( pFile, "\n" ); + Counter -= nVars; + for ( i = 1; i < nVars-2; i++ ) + { + fprintf( pFile, ".subckt Layer%d", (i&1) ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ ); + fprintf( pFile, "\n" ); + Counter -= nVars; + } + fprintf( pFile, ".subckt Layer%d", (i&1) ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " y%02d=y%02d", k, k ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); + + Abc_WriteLayer( pFile, nVars, 0 ); + Abc_WriteLayer( pFile, nVars, 1 ); + Abc_WriteComp( pFile ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 ) +{ + int i; + fprintf( pFile, ".model Layer%d\n", fSkip1 ); + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " x%02d", i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".outputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " y%02d", i ); + fprintf( pFile, "\n" ); + if ( fSkip1 ) + { + fprintf( pFile, ".names x00 y00\n" ); + fprintf( pFile, "1 1\n" ); + i = 1; + } + else + i = 0; + for ( ; i + 1 < nVars; i += 2 ) + fprintf( pFile, ".subckt Comp a=x%02d b=x%02d x=y%02d y=y%02d\n", i, i+1, i, i+1 ); + if ( i < nVars ) + { + fprintf( pFile, ".names x%02d y%02d\n", i, i ); + fprintf( pFile, "1 1\n" ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_WriteComp( FILE * pFile ) +{ + fprintf( pFile, ".model Comp\n" ); + fprintf( pFile, ".inputs a b\n" ); + fprintf( pFile, ".outputs x y\n" ); + fprintf( pFile, ".names a b x\n" ); + fprintf( pFile, "11 1\n" ); + fprintf( pFile, ".names a b y\n" ); + fprintf( pFile, "1- 1\n" ); + fprintf( pFile, "-1 1\n" ); + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_WriteFullAdder( FILE * pFile ) +{ + fprintf( pFile, ".model FA\n" ); + fprintf( pFile, ".inputs a b cin\n" ); + fprintf( pFile, ".outputs s cout\n" ); + fprintf( pFile, ".names a b k\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names k cin s\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names a b cin cout\n" ); + fprintf( pFile, "11- 1\n" ); + fprintf( pFile, "1-1 1\n" ); + fprintf( pFile, "-11 1\n" ); + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_WriteCell( FILE * pFile ) +{ + fprintf( pFile, ".model cell\n" ); + fprintf( pFile, ".inputs px1 px2 py1 py2 x y\n" ); + fprintf( pFile, ".outputs fx fy\n" ); + fprintf( pFile, ".names x y a\n" ); + fprintf( pFile, "11 1\n" ); + fprintf( pFile, ".names px1 a x nx\n" ); + fprintf( pFile, "11- 1\n" ); + fprintf( pFile, "0-1 1\n" ); + fprintf( pFile, ".names py1 a y ny\n" ); + fprintf( pFile, "11- 1\n" ); + fprintf( pFile, "0-1 1\n" ); + fprintf( pFile, ".names px2 nx fx\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names py2 ny fy\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_GenMesh( char * pFileName, int nVars ) +{ + FILE * pFile; + int i, k; + + assert( nVars > 0 ); + + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# %dx%d mesh generated by ABC on %s\n", nVars, nVars, Extra_TimeStamp() ); + fprintf( pFile, ".model mesh%d\n", nVars ); + + for ( i = 0; i < nVars; i++ ) + for ( k = 0; k < nVars; k++ ) + { + fprintf( pFile, ".inputs" ); + fprintf( pFile, " p%d%dx1", i, k ); + fprintf( pFile, " p%d%dx2", i, k ); + fprintf( pFile, " p%d%dy1", i, k ); + fprintf( pFile, " p%d%dy2", i, k ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " v%02d v%02d", 2*i, 2*i+1 ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".outputs" ); + fprintf( pFile, " fx00" ); + fprintf( pFile, "\n" ); + + for ( i = 0; i < nVars; i++ ) // horizontal + for ( k = 0; k < nVars; k++ ) // vertical + { + fprintf( pFile, ".subckt cell" ); + fprintf( pFile, " px1=p%d%dx1", i, k ); + fprintf( pFile, " px2=p%d%dx2", i, k ); + fprintf( pFile, " py1=p%d%dy1", i, k ); + fprintf( pFile, " py2=p%d%dy2", i, k ); + if ( k == nVars - 1 ) + fprintf( pFile, " x=v%02d", i ); + else + fprintf( pFile, " x=fx%d%d", i, k+1 ); + if ( i == nVars - 1 ) + fprintf( pFile, " y=v%02d", nVars+k ); + else + fprintf( pFile, " y=fy%d%d", i+1, k ); + // outputs + fprintf( pFile, " fx=fx%d%d", i, k ); + fprintf( pFile, " fy=fy%d%d", i, k ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + Abc_WriteCell( pFile ); + fclose( pFile ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_WriteKLut( FILE * pFile, int nLutSize ) +{ + int i, iVar, iNext, nPars = (1 << nLutSize); + fprintf( pFile, "\n" ); + fprintf( pFile, ".model lut%d\n", nLutSize ); + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nPars; i++ ) + fprintf( pFile, " p%02d", i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nLutSize; i++ ) + fprintf( pFile, " i%d", i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".outputs o\n" ); + fprintf( pFile, ".names n01 o\n" ); + fprintf( pFile, "1 1\n" ); + // write internal MUXes + iVar = 0; + iNext = 2; + for ( i = 1; i < nPars; i++ ) + { + if ( i == iNext ) + { + iNext *= 2; + iVar++; + } + if ( iVar == nLutSize - 1 ) + fprintf( pFile, ".names i%d p%02d p%02d n%02d\n", iVar, 2*(i-nPars/2), 2*(i-nPars/2)+1, i ); + else + fprintf( pFile, ".names i%d n%02d n%02d n%02d\n", iVar, 2*i, 2*i+1, i ); + fprintf( pFile, "01- 1\n" ); + fprintf( pFile, "1-1 1\n" ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Generates structure of L K-LUTs implementing an N-var function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars ) +{ + FILE * pFile; + int nVarsLut = (1 << nLutSize); // the number of LUT variables + int nVarsLog = Extra_Base2Log( nVars + nLuts - 1 ); // the number of encoding vars + int nVarsDeg = (1 << nVarsLog); // the number of LUT variables (total) + int nParsLut = nLuts * (1 << nLutSize); // the number of LUT params + int nParsVar = nLuts * nLutSize * nVarsLog; // the number of var params + int i, j, k; + + assert( nVars > 0 ); + + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# Structure with %d %d-LUTs for %d-var function generated by ABC on %s\n", nLuts, nLutSize, nVars, Extra_TimeStamp() ); + fprintf( pFile, ".model struct%dx%d_%d\n", nLuts, nLutSize, nVars ); + + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nParsLut; i++ ) + fprintf( pFile, " pl%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nParsVar; i++ ) + fprintf( pFile, " pv%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " v%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".outputs" ); + fprintf( pFile, " v%02d", nVars + nLuts - 1 ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".names Gnd\n" ); + fprintf( pFile, " 0\n" ); + + // generate LUTs + for ( i = 0; i < nLuts; i++ ) + { + fprintf( pFile, ".subckt lut%d", nLutSize ); + // generate config parameters + for ( k = 0; k < nVarsLut; k++ ) + fprintf( pFile, " p%02d=pl%02d", k, i * nVarsLut + k ); + // generate the inputs + for ( k = 0; k < nLutSize; k++ ) + fprintf( pFile, " i%d=s%02d", k, i * nLutSize + k ); + // generate the output + fprintf( pFile, " o=v%02d", nVars + i ); + fprintf( pFile, "\n" ); + } + + // generate LUT inputs + for ( i = 0; i < nLuts; i++ ) + { + for ( j = 0; j < nLutSize; j++ ) + { + fprintf( pFile, ".subckt lut%d", nVarsLog ); + // generate config parameters + for ( k = 0; k < nVarsDeg; k++ ) + { + if ( k < nVars + nLuts - 1 && k < nVars + i ) + fprintf( pFile, " p%02d=v%02d", k, k ); + else + fprintf( pFile, " p%02d=Gnd", k ); + } + // generate the inputs + for ( k = 0; k < nVarsLog; k++ ) + fprintf( pFile, " i%d=pv%02d", k, (i * nLutSize + j) * nVarsLog + k ); + // generate the output + fprintf( pFile, " o=s%02d", i * nLutSize + j ); + fprintf( pFile, "\n" ); + } + } + + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); + + // generate LUTs + Abc_WriteKLut( pFile, nLutSize ); + if ( nVarsLog != nLutSize ) + Abc_WriteKLut( pFile, nVarsLog ); + fclose( pFile ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcHaig.c b/abc70930/src/base/abci/abcHaig.c new file mode 100644 index 00000000..d3513bbe --- /dev/null +++ b/abc70930/src/base/abci/abcHaig.c @@ -0,0 +1,726 @@ +/**CFile**************************************************************** + + FileName [abcHaig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Implements history AIG for combinational rewriting.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcHaig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start history AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkHaigStart( Abc_Ntk_t * pNtk ) +{ + Hop_Man_t * p; + Abc_Obj_t * pObj, * pTemp; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + // check if the package is already started + if ( pNtk->pHaig ) + { + Abc_NtkHaigStop( pNtk ); + assert( pNtk->pHaig == NULL ); + printf( "Warning: Previous history AIG was removed.\n" ); + } + // make sure the data is clean + Abc_NtkForEachObj( pNtk, pObj, i ) + assert( pObj->pEquiv == NULL ); + // start the HOP package + p = Hop_ManStart(); + p->vObjs = Vec_PtrAlloc( 4096 ); + Vec_PtrPush( p->vObjs, Hop_ManConst1(p) ); + // map the constant node + Abc_AigConst1(pNtk)->pEquiv = Hop_ManConst1(p); + // map the CIs + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pEquiv = Hop_ObjCreatePi(p); + // map the internal nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pEquiv = Hop_And( p, Abc_ObjChild0Equiv(pObj), Abc_ObjChild1Equiv(pObj) ); + // map the choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + // print warning about choice nodes + printf( "Warning: The choice nodes in the original AIG are converted into HAIG.\n" ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( !Abc_AigNodeIsChoice( pObj ) ) + continue; + for ( pTemp = pObj->pData; pTemp; pTemp = pTemp->pData ) + Hop_ObjCreateChoice( pObj->pEquiv, pTemp->pEquiv ); + } + } + // make sure everything is okay + if ( !Hop_ManCheck(p) ) + { + printf( "Abc_NtkHaigStart: Check for History AIG has failed.\n" ); + Hop_ManStop(p); + return 0; + } + pNtk->pHaig = p; + return 1; +} + +/**Function************************************************************* + + Synopsis [Stops history AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkHaigStop( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + if ( pNtk->pHaig == NULL ) + { + printf( "Warning: History AIG is not allocated.\n" ); + return 1; + } + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pEquiv = NULL; + Hop_ManStop( pNtk->pHaig ); + pNtk->pHaig = NULL; + return 1; +} + +/**Function************************************************************* + + Synopsis [Transfers the HAIG to the new network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkHaigTranfer( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj; + int i; + if ( pNtkOld->pHaig == NULL ) + return; + // transfer the package + assert( pNtkNew->pHaig == NULL ); + pNtkNew->pHaig = pNtkOld->pHaig; + pNtkOld->pHaig = NULL; + // transfer constant pointer + Abc_AigConst1(pNtkOld)->pCopy->pEquiv = Abc_AigConst1(pNtkOld)->pEquiv; + // transfer the CI pointers + Abc_NtkForEachCi( pNtkOld, pObj, i ) + pObj->pCopy->pEquiv = pObj->pEquiv; +} + + + +/**Function************************************************************* + + Synopsis [Collects the nodes in the classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkHaigCollectMembers( Hop_Man_t * p ) +{ + Vec_Ptr_t * vObjs; + Hop_Obj_t * pObj; + int i; + vObjs = Vec_PtrAlloc( 4098 ); + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( pObj->pData == NULL ) + continue; + pObj->pData = Hop_ObjRepr( pObj ); + Vec_PtrPush( vObjs, pObj ); + } + return vObjs; +} + +/**Function************************************************************* + + Synopsis [Creates classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkHaigCreateClasses( Vec_Ptr_t * vMembers ) +{ + Vec_Ptr_t * vClasses; + Hop_Obj_t * pObj, * pRepr; + int i; + + // count classes + vClasses = Vec_PtrAlloc( 4098 ); + Vec_PtrForEachEntry( vMembers, pObj, i ) + { + pRepr = pObj->pData; + assert( pRepr->pData == NULL ); + if ( pRepr->fMarkA == 0 ) // new + { + pRepr->fMarkA = 1; + Vec_PtrPush( vClasses, pRepr ); + } + } + + // set representatives as representatives + Vec_PtrForEachEntry( vClasses, pObj, i ) + { + pObj->fMarkA = 0; + pObj->pData = pObj; + } + + // go through the members and update + Vec_PtrForEachEntry( vMembers, pObj, i ) + { + pRepr = pObj->pData; + if ( ((Hop_Obj_t *)pRepr->pData)->Id > pObj->Id ) + pRepr->pData = pObj; + } + + // change representatives of the class + Vec_PtrForEachEntry( vMembers, pObj, i ) + { + pRepr = pObj->pData; + pObj->pData = pRepr->pData; + assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id ); + } + + // update classes + Vec_PtrForEachEntry( vClasses, pObj, i ) + { + pRepr = pObj->pData; + assert( pRepr->pData == pRepr ); +// pRepr->pData = NULL; + Vec_PtrWriteEntry( vClasses, i, pRepr ); + Vec_PtrPush( vMembers, pObj ); + } + + Vec_PtrForEachEntry( vMembers, pObj, i ) + if ( pObj->pData == pObj ) + pObj->pData = NULL; + +/* + Vec_PtrForEachEntry( vMembers, pObj, i ) + { + printf( "ObjId = %4d : ", pObj->Id ); + if ( pObj->pData == NULL ) + { + printf( "NULL" ); + } + else + { + printf( "%4d", ((Hop_Obj_t *)pObj->pData)->Id ); + assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id ); + } + printf( "\n" ); + } +*/ + return vClasses; +} + +/**Function************************************************************* + + Synopsis [Counts how many data members have non-trivial fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkHaigCountFans( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( pObj->pData == NULL ) + continue; + if ( Hop_ObjRefs(pObj) > 0 ) + Counter++; + } + printf( "The number of class members with fanouts = %5d.\n", Counter ); + return Counter; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Hop_Obj_t * Hop_ObjReprHop( Hop_Obj_t * pObj ) +{ + Hop_Obj_t * pRepr; + assert( pObj->pNext != NULL ); + if ( pObj->pData == NULL ) + return pObj->pNext; + pRepr = pObj->pData; + assert( pRepr->pData == pRepr ); + return Hop_NotCond( pRepr->pNext, pObj->fPhase ^ pRepr->fPhase ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Hop_Obj_t * Hop_ObjChild0Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin0(pObj)), Hop_ObjFaninC0(pObj) ); } +static inline Hop_Obj_t * Hop_ObjChild1Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin1(pObj)), Hop_ObjFaninC1(pObj) ); } + +/**Function************************************************************* + + Synopsis [Stops history AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Man_t * Abc_NtkHaigReconstruct( Hop_Man_t * p ) +{ + Hop_Man_t * pNew; + Hop_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + pObj->pNext = NULL; + // start the HOP package + pNew = Hop_ManStart(); + pNew->vObjs = Vec_PtrAlloc( p->nCreated ); + Vec_PtrPush( pNew->vObjs, Hop_ManConst1(pNew) ); + // map the constant node + Hop_ManConst1(p)->pNext = Hop_ManConst1(pNew); + // map the CIs + Hop_ManForEachPi( p, pObj, i ) + pObj->pNext = Hop_ObjCreatePi(pNew); + // map the internal nodes + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( !Hop_ObjIsNode(pObj) ) + continue; + pObj->pNext = Hop_And( pNew, Hop_ObjChild0Hop(pObj), Hop_ObjChild1Hop(pObj) ); +// assert( !Hop_IsComplement(pObj->pNext) ); + if ( Hop_ManConst1(pNew) == Hop_Regular(pObj->pNext) ) + Counter++; + if ( pObj->pData ) // member of the class + Hop_Regular(pObj->pNext)->pData = Hop_Regular(((Hop_Obj_t *)pObj->pData)->pNext); + } +// printf( " Counter = %d.\n", Counter ); + // transfer the POs + Hop_ManForEachPo( p, pObj, i ) + Hop_ObjCreatePo( pNew, Hop_ObjChild0Hop(pObj) ); + // check the new manager + if ( !Hop_ManCheck(pNew) ) + { + printf( "Abc_NtkHaigReconstruct: Check for History AIG has failed.\n" ); + Hop_ManStop(pNew); + return NULL; + } + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkHaigCheckTfi_rec( Abc_Obj_t * pNode, Abc_Obj_t * pOld ) +{ + if ( pNode == NULL ) + return 0; + if ( pNode == pOld ) + return 1; + // check the trivial cases + if ( Abc_ObjIsCi(pNode) ) + return 0; + assert( Abc_ObjIsNode(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return 0; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // check the children + if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin0(pNode), pOld ) ) + return 1; + if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin1(pNode), pOld ) ) + return 1; + // check equivalent nodes + return Abc_NtkHaigCheckTfi_rec( pNode->pData, pOld ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkHaigCheckTfi( Abc_Ntk_t * pNtk, Abc_Obj_t * pOld, Abc_Obj_t * pNew ) +{ + assert( !Abc_ObjIsComplement(pOld) ); + assert( !Abc_ObjIsComplement(pNew) ); + Abc_NtkIncrementTravId(pNtk); + return Abc_NtkHaigCheckTfi_rec( pNew, pOld ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Abc_Obj_t * Hop_ObjChild0Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin0(pObj)->pNext, Hop_ObjFaninC0(pObj) ); } +static inline Abc_Obj_t * Hop_ObjChild1Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin1(pObj)->pNext, Hop_ObjFaninC1(pObj) ); } + +/**Function************************************************************* + + Synopsis [Stops history AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkHaigRecreateAig( Abc_Ntk_t * pNtk, Hop_Man_t * p ) +{ + Abc_Ntk_t * pNtkAig; + Abc_Obj_t * pObjOld, * pObjAbcThis, * pObjAbcRepr; + Hop_Obj_t * pObj; + int i; + assert( p->nCreated == Vec_PtrSize(p->vObjs) ); + + // start the new network + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + + // transfer new nodes to the PIs of HOP + Hop_ManConst1(p)->pNext = (Hop_Obj_t *)Abc_AigConst1( pNtkAig ); + Hop_ManForEachPi( p, pObj, i ) + pObj->pNext = (Hop_Obj_t *)Abc_NtkCi( pNtkAig, i ); + + // construct new nodes + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( !Hop_ObjIsNode(pObj) ) + continue; + pObj->pNext = (Hop_Obj_t *)Abc_AigAnd( pNtkAig->pManFunc, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) ); + assert( !Hop_IsComplement(pObj->pNext) ); + } + + // set the COs + Abc_NtkForEachCo( pNtk, pObjOld, i ) + Abc_ObjAddFanin( pObjOld->pCopy, Hop_ObjChild0Next(Hop_ManPo(p,i)) ); + + // construct choice nodes + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + // skip the node without choices + if ( pObj->pData == NULL ) + continue; + // skip the representative of the class + if ( pObj->pData == pObj ) + continue; + // do not create choices for constant 1 and PIs + if ( !Hop_ObjIsNode(pObj->pData) ) + continue; + // get the corresponding new nodes + pObjAbcThis = (Abc_Obj_t *)pObj->pNext; + pObjAbcRepr = (Abc_Obj_t *)((Hop_Obj_t *)pObj->pData)->pNext; + // the new node cannot be already in the class + assert( pObjAbcThis->pData == NULL ); + // the new node cannot have fanouts + assert( Abc_ObjFanoutNum(pObjAbcThis) == 0 ); + // these should be different nodes + assert( pObjAbcRepr != pObjAbcThis ); + // do not create choices if there is a path from pObjAbcThis to pObjAbcRepr + if ( !Abc_NtkHaigCheckTfi( pNtkAig, pObjAbcRepr, pObjAbcThis ) ) + { + // find the last node in the class + while ( pObjAbcRepr->pData ) + pObjAbcRepr = pObjAbcRepr->pData; + // add the new node at the end of the list + pObjAbcRepr->pData = pObjAbcThis; + } + } + + // finish the new network +// Abc_NtkFinalize( pNtk, pNtkAig ); +// Abc_AigCleanup( pNtkAig->pManFunc ); + // check correctness of the network + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkHaigUse: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Resets representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkHaigResetReprsOld( Hop_Man_t * pMan ) +{ + Vec_Ptr_t * vMembers, * vClasses; + + // collect members of the classes and make them point to reprs + vMembers = Abc_NtkHaigCollectMembers( pMan ); + printf( "Collected %6d class members.\n", Vec_PtrSize(vMembers) ); + + // create classes + vClasses = Abc_NtkHaigCreateClasses( vMembers ); + printf( "Collected %6d classes. (Ave = %5.2f)\n", Vec_PtrSize(vClasses), + (float)(Vec_PtrSize(vMembers))/Vec_PtrSize(vClasses) ); + + Vec_PtrFree( vMembers ); + Vec_PtrFree( vClasses ); +} + +/**Function************************************************************* + + Synopsis [Resets representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkHaigResetReprs( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj, * pRepr; + int i, nClasses, nMembers, nFanouts, nNormals; + // clear self-classes + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + // fix the strange situation of double-loop + pRepr = pObj->pData; + if ( pRepr && pRepr->pData == pObj ) + pRepr->pData = pRepr; + // remove self-loops + if ( pObj->pData == pObj ) + pObj->pData = NULL; + } + // set representatives + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( pObj->pData == NULL ) + continue; + // get representative of the node + pRepr = Hop_ObjRepr( pObj ); + pRepr->pData = pRepr; + // set the representative + pObj->pData = pRepr; + } + // make each class point to the smallest topological order + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( pObj->pData == NULL ) + continue; + pRepr = Hop_ObjRepr( pObj ); + if ( pRepr->Id > pObj->Id ) + { + pRepr->pData = pObj; + pObj->pData = pObj; + } + else + pObj->pData = pRepr; + } + // count classes, members, and fanouts - and verify + nMembers = nClasses = nFanouts = nNormals = 0; + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( pObj->pData == NULL ) + continue; + // count members + nMembers++; + // count the classes and fanouts + if ( pObj->pData == pObj ) + nClasses++; + else if ( Hop_ObjRefs(pObj) > 0 ) + nFanouts++; + else + nNormals++; + // compare representatives + pRepr = Hop_ObjRepr( pObj ); + assert( pObj->pData == pRepr ); + assert( pRepr->Id <= pObj->Id ); + } +// printf( "Nodes = %7d. Member = %7d. Classes = %6d. Fanouts = %6d. Normals = %6d.\n", +// Hop_ManNodeNum(p), nMembers, nClasses, nFanouts, nNormals ); + return nFanouts; +} + +/**Function************************************************************* + + Synopsis [Stops history AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkHaigUse( Abc_Ntk_t * pNtk ) +{ + Hop_Man_t * pMan, * pManTemp; + Abc_Ntk_t * pNtkAig; + Abc_Obj_t * pObj; + int i; + + // check if HAIG is available + assert( Abc_NtkIsStrash(pNtk) ); + if ( pNtk->pHaig == NULL ) + { + printf( "Warning: History AIG is not available.\n" ); + return NULL; + } + // convert HOP package into AIG with choices + // print HAIG stats +// Hop_ManPrintStats( pMan ); // USES DATA!!! + + // add the POs + Abc_NtkForEachCo( pNtk, pObj, i ) + Hop_ObjCreatePo( pNtk->pHaig, Abc_ObjChild0Equiv(pObj) ); + + // clean the old network + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pEquiv = NULL; + pMan = pNtk->pHaig; + pNtk->pHaig = 0; + + // iteratively reconstruct the HOP manager to create choice nodes + while ( Abc_NtkHaigResetReprs( pMan ) ) + { + pMan = Abc_NtkHaigReconstruct( pManTemp = pMan ); + Hop_ManStop( pManTemp ); + } + + // traverse in the topological order and create new AIG + pNtkAig = Abc_NtkHaigRecreateAig( pNtk, pMan ); + Hop_ManStop( pMan ); + + // free HAIG + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Transform HOP manager into the one without loops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ) +{ + Abc_Ntk_t * pNtkAig; + Hop_Man_t * pManTemp; + + // iteratively reconstruct the HOP manager to create choice nodes + while ( Abc_NtkHaigResetReprs( pMan ) ) + { + pMan = Abc_NtkHaigReconstruct( pManTemp = pMan ); + Hop_ManStop( pManTemp ); + } + + // traverse in the topological order and create new AIG + pNtkAig = Abc_NtkHaigRecreateAig( pNtk, pMan ); + Hop_ManStop( pMan ); + return pNtkAig; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcIf.c b/abc70930/src/base/abci/abcIf.c new file mode 100644 index 00000000..bb56c22c --- /dev/null +++ b/abc70930/src/base/abci/abcIf.c @@ -0,0 +1,497 @@ +/**CFile**************************************************************** + + FileName [abcIf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: abcIf.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "if.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); +static Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover ); +static Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj ); +static Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk ); + +extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Interface with the FPGA mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) +{ + Abc_Ntk_t * pNtkNew; + If_Man_t * pIfMan; + + assert( Abc_NtkIsStrash(pNtk) ); + + // get timing information + pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk); + pPars->pTimesReq = NULL; + + // set the latch paths + if ( pPars->fLatchPaths && pPars->pTimesArr ) + { + int c; + for ( c = 0; c < Abc_NtkPiNum(pNtk); c++ ) + pPars->pTimesArr[c] = -ABC_INFINITY; + } + + // perform FPGA mapping + pIfMan = Abc_NtkToIf( pNtk, pPars ); + if ( pIfMan == NULL ) + return NULL; + if ( !If_ManPerformMapping( pIfMan ) ) + { + If_ManStop( pIfMan ); + return NULL; + } + + // transform the result of mapping into the new network + pNtkNew = Abc_NtkFromIf( pIfMan, pNtk ); + if ( pNtkNew == NULL ) + return NULL; + If_ManStop( pIfMan ); + + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkIf: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Load the network into FPGA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) +{ + ProgressBar * pProgress; + If_Man_t * pIfMan; + Abc_Obj_t * pNode, * pFanin, * pPrev; + Vec_Ptr_t * vNodes; + int i; + + assert( Abc_NtkIsStrash(pNtk) ); +// vNodes = Abc_NtkFindGoodOrder( pNtk ); + vNodes = Abc_AigDfs( pNtk, 0, 0 ); + + // start the mapping manager and set its parameters + pIfMan = If_ManStart( pPars ); + + // print warning about excessive memory usage + if ( 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30) > 1.0 ) + printf( "Warning: The mapper will allocate %.1f Gb for to represent the subject graph with %d AIG nodes.\n", + 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30), Abc_NtkObjNum(pNtk) ); + + // create PIs and remember them in the old nodes + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan ); + Abc_NtkForEachCi( pNtk, pNode, i ) + { + pNode->pCopy = (Abc_Obj_t *)If_ManCreateCi( pIfMan ); +//printf( "AIG CI %2d -> IF CI %2d\n", pNode->Id, ((If_Obj_t *)pNode->pCopy)->Id ); + } + + // load the AIG into the mapper + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); +// Abc_AigForEachAnd( pNtk, pNode, i ) + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, "Initial" ); + // add the node to the mapper + pNode->pCopy = (Abc_Obj_t *)If_ManCreateAnd( pIfMan, + If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), + If_NotCond( (If_Obj_t *)Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); + // set up the choice node + if ( Abc_AigNodeIsChoice( pNode ) ) + { + pIfMan->nChoices++; + for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) + If_ObjSetChoice( (If_Obj_t *)pPrev->pCopy, (If_Obj_t *)pFanin->pCopy ); + If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pCopy ); + } +//printf( "AIG node %2d -> IF node %2d\n", pNode->Id, ((If_Obj_t *)pNode->pCopy)->Id ); + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + + // set the primary outputs without copying the phase + Abc_NtkForEachCo( pNtk, pNode, i ) + If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) ); + return pIfMan; +} + +/**Function************************************************************* + + Synopsis [Creates the mapped network.] + + Description [Assuming the copy field of the mapped nodes are NULL.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pNodeNew; + Vec_Int_t * vCover; + int i, nDupGates; + // create the new network + if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); + else if ( pIfMan->pPars->fUseSops ) + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + else + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG ); + // prepare the mapping manager + If_ManCleanNodeCopy( pIfMan ); + If_ManCleanCutData( pIfMan ); + // make the mapper point to the new network + If_ObjSetCopy( If_ManConst1(pIfMan), Abc_NtkCreateNodeConst1(pNtkNew) ); + Abc_NtkForEachCi( pNtk, pNode, i ) + If_ObjSetCopy( If_ManCi(pIfMan, i), pNode->pCopy ); + // process the nodes in topological order + vCover = Vec_IntAlloc( 1 << 16 ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, "Final" ); + pNodeNew = Abc_NodeFromIf_rec( pNtkNew, pIfMan, If_ObjFanin0(If_ManCo(pIfMan, i)), vCover ); + pNodeNew = Abc_ObjNotCond( pNodeNew, If_ObjFaninC0(If_ManCo(pIfMan, i)) ); + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + } + Extra_ProgressBarStop( pProgress ); + Vec_IntFree( vCover ); + // remove the constant node if not used + pNodeNew = (Abc_Obj_t *)If_ObjCopy( If_ManConst1(pIfMan) ); + if ( Abc_ObjFanoutNum(pNodeNew) == 0 ) + Abc_NtkDeleteObj( pNodeNew ); + // minimize the node + if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) + Abc_NtkSweep( pNtkNew, 0 ); + if ( pIfMan->pPars->fUseBdds ) + Abc_NtkBddReorder( pNtkNew, 0 ); + // decouple the PO driver nodes to reduce the number of levels + nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); +// if ( nDupGates && If_ManReadVerbose(pIfMan) ) +// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Derive one node after FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover ) +{ + Abc_Obj_t * pNodeNew; + If_Cut_t * pCutBest; + If_Obj_t * pIfLeaf; + int i; + // return if the result if known + pNodeNew = (Abc_Obj_t *)If_ObjCopy( pIfObj ); + if ( pNodeNew ) + return pNodeNew; + assert( pIfObj->Type == IF_AND ); + // get the parameters of the best cut + // create a new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pCutBest = If_ObjCutBest( pIfObj ); + if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) + { + If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i ) + Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); + } + else + { + If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) + Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); + } + // set the level of the new node + pNodeNew->Level = Abc_ObjLevelNew( pNodeNew ); + // derive the function of this node + if ( pIfMan->pPars->fTruth ) + { + if ( pIfMan->pPars->fUseBdds ) + { + // transform truth table into the BDD + pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 0 ); Cudd_Ref(pNodeNew->pData); + } + else if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) + { + // transform truth table into the BDD + pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 1 ); Cudd_Ref(pNodeNew->pData); + } + else if ( pIfMan->pPars->fUseSops ) + { + // transform truth table into the SOP + int RetValue = Kit_TruthIsop( If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), vCover, 1 ); + assert( RetValue == 0 || RetValue == 1 ); + // check the case of constant cover + if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) ) + { + assert( RetValue == 0 ); + pNodeNew->pData = Abc_SopCreateAnd( pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), NULL ); + pNodeNew = (Vec_IntSize(vCover) == 0) ? Abc_NtkCreateNodeConst0(pNtkNew) : Abc_NtkCreateNodeConst1(pNtkNew); + } + else + { + // derive the AIG for that tree + pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), vCover ); + if ( RetValue ) + Abc_SopComplement( pNodeNew->pData ); + } + } + else + { + extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); + pNodeNew->pData = Kit_TruthToHop( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), vCover ); + } + // complement the node if the cut was complemented + if ( pCutBest->fCompl ) + Abc_NodeComplement( pNodeNew ); + } + else + pNodeNew->pData = Abc_NodeIfToHop( pNtkNew->pManFunc, pIfMan, pIfObj ); + If_ObjSetCopy( pIfObj, pNodeNew ); + return pNodeNew; +} + +/**Function************************************************************* + + Synopsis [Recursively derives the truth table for the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_NodeIfToHop_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited ) +{ + If_Cut_t * pCut; + Hop_Obj_t * gFunc, * gFunc0, * gFunc1; + // get the best cut + pCut = If_ObjCutBest(pIfObj); + // if the cut is visited, return the result + if ( If_CutData(pCut) ) + return If_CutData(pCut); + // compute the functions of the children + gFunc0 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin0, vVisited ); + gFunc1 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin1, vVisited ); + // get the function of the cut + gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pIfObj->fCompl0), Hop_NotCond(gFunc1, pIfObj->fCompl1) ); + assert( If_CutData(pCut) == NULL ); + If_CutSetData( pCut, gFunc ); + // add this cut to the visited list + Vec_PtrPush( vVisited, pCut ); + return gFunc; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table for one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj ) +{ + If_Cut_t * pCut; + Hop_Obj_t * gFunc; + If_Obj_t * pLeaf; + int i; + // get the best cut + pCut = If_ObjCutBest(pIfObj); + assert( pCut->nLeaves > 1 ); + // set the leaf variables + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + If_CutSetData( If_ObjCutBest(pLeaf), Hop_IthVar(pHopMan, i) ); + // recursively compute the function while collecting visited cuts + Vec_PtrClear( pIfMan->vTemp ); + gFunc = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp ); +// printf( "%d ", Vec_PtrSize(p->vTemp) ); + // clean the cuts + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + If_CutSetData( If_ObjCutBest(pLeaf), NULL ); + Vec_PtrForEachEntry( pIfMan->vTemp, pCut, i ) + If_CutSetData( pCut, NULL ); + return gFunc; +} + + +/**Function************************************************************* + + Synopsis [Comparison for two nodes with the flow.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjCompareFlow( Abc_Obj_t ** ppNode0, Abc_Obj_t ** ppNode1 ) +{ + float Flow0 = Abc_Int2Float((int)(*ppNode0)->pCopy); + float Flow1 = Abc_Int2Float((int)(*ppNode1)->pCopy); + if ( Flow0 > Flow1 ) + return -1; + if ( Flow0 < Flow1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Orders AIG nodes so that nodes from larger cones go first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFindGoodOrder_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + if ( !Abc_ObjIsNode(pNode) ) + return; + assert( Abc_ObjIsNode( pNode ) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin of the node + Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes ); + Abc_NtkFindGoodOrder_rec( Abc_ObjFanin1(pNode), vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Orders AIG nodes so that nodes from larger cones go first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes, * vCos; + Abc_Obj_t * pNode, * pFanin0, * pFanin1; + float Flow0, Flow1; + int i; + + // initialize the flow + Abc_AigConst1(pNtk)->pCopy = NULL; + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = NULL; + // compute the flow + Abc_AigForEachAnd( pNtk, pNode, i ) + { + pFanin0 = Abc_ObjFanin0(pNode); + pFanin1 = Abc_ObjFanin1(pNode); + Flow0 = Abc_Int2Float((int)pFanin0->pCopy)/Abc_ObjFanoutNum(pFanin0); + Flow1 = Abc_Int2Float((int)pFanin1->pCopy)/Abc_ObjFanoutNum(pFanin1); + pNode->pCopy = (Abc_Obj_t *)Abc_Float2Int(Flow0 + Flow1+(float)1.0); + } + // find the flow of the COs + vCos = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pNode->pCopy = Abc_ObjFanin0(pNode)->pCopy; +// pNode->pCopy = (Abc_Obj_t *)Abc_Float2Int((float)Abc_ObjFanin0(pNode)->Level); + Vec_PtrPush( vCos, pNode ); + } + + // sort nodes in the increasing order of the flow + qsort( (Abc_Obj_t **)Vec_PtrArray(vCos), Abc_NtkCoNum(pNtk), + sizeof(Abc_Obj_t *), (int (*)(const void *, const void *))Abc_ObjCompareFlow ); + // verify sorting + pFanin0 = Vec_PtrEntry(vCos, 0); + pFanin1 = Vec_PtrEntryLast(vCos); + assert( Abc_Int2Float((int)pFanin0->pCopy) >= Abc_Int2Float((int)pFanin1->pCopy) ); + + // collect the nodes in the topological order from the new array + Abc_NtkIncrementTravId( pNtk ); + vNodes = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( vCos, pNode, i ) + { + Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes ); +// printf( "%.2f ", Abc_Int2Float((int)pNode->pCopy) ); + } + Vec_PtrFree( vCos ); + return vNodes; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcIvy.c b/abc70930/src/base/abci/abcIvy.c new file mode 100644 index 00000000..b878091b --- /dev/null +++ b/abc70930/src/base/abci/abcIvy.c @@ -0,0 +1,1101 @@ +/**CFile**************************************************************** + + FileName [abcIvy.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Strashing of the current network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcIvy.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dec.h" +#include "ivy.h" +#include "fraig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan ); +static Abc_Ntk_t * Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig ); +static Ivy_Man_t * Abc_NtkToIvy( Abc_Ntk_t * pNtkOld ); + +static void Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ); +static Ivy_Obj_t * Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode ); +static Ivy_Obj_t * Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ); +static Ivy_Obj_t * Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ); +static Ivy_Obj_t * Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ); +extern char * Mio_GateReadSop( void * pGate ); + +typedef int Abc_Edge_t; +static inline Abc_Edge_t Abc_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } +static inline int Abc_EdgeId( Abc_Edge_t Edge ) { return Edge >> 1; } +static inline int Abc_EdgeIsComplement( Abc_Edge_t Edge ) { return Edge & 1; } +static inline Abc_Edge_t Abc_EdgeRegular( Abc_Edge_t Edge ) { return (Edge >> 1) << 1; } +static inline Abc_Edge_t Abc_EdgeNot( Abc_Edge_t Edge ) { return Edge ^ 1; } +static inline Abc_Edge_t Abc_EdgeNotCond( Abc_Edge_t Edge, int fCond ) { return Edge ^ fCond; } +static inline Abc_Edge_t Abc_EdgeFromNode( Abc_Obj_t * pNode ) { return Abc_EdgeCreate( Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ); } +static inline Abc_Obj_t * Abc_EdgeToNode( Abc_Ntk_t * p, Abc_Edge_t Edge ) { return Abc_ObjNotCond( Abc_NtkObj(p, Abc_EdgeId(Edge)), Abc_EdgeIsComplement(Edge) ); } + +static inline Abc_Obj_t * Abc_ObjFanin0Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ); } +static inline Abc_Obj_t * Abc_ObjFanin1Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ); } + +static Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs ); + +extern int timeRetime; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Prepares the IVY package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ) +{ + Ivy_Man_t * pMan; + int fCleanup = 1; +//timeRetime = clock(); + assert( !Abc_NtkIsNetlist(pNtk) ); + if ( Abc_NtkIsBddLogic(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Abc_NtkIvyBefore(): Converting to SOPs has failed.\n" ); + return NULL; + } + } + if ( fSeq && Abc_NtkCountSelfFeedLatches(pNtk) ) + { + printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtk) ); +// return NULL; + } + // print warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" ); + // convert to the AIG manager + pMan = Abc_NtkToIvy( pNtk ); + if ( !Ivy_ManCheck( pMan ) ) + { + printf( "AIG check has failed.\n" ); + Ivy_ManStop( pMan ); + return NULL; + } +// Ivy_ManPrintStats( pMan ); + if ( fSeq ) + { + int nLatches = Abc_NtkLatchNum(pNtk); + Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, fUseDc ); + Ivy_ManMakeSeq( pMan, nLatches, vInit->pArray ); + Vec_IntFree( vInit ); +// Ivy_ManPrintStats( pMan ); + } +//timeRetime = clock() - timeRetime; + return pMan; +} + +/**Function************************************************************* + + Synopsis [Prepares the IVY package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyAfter( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan, int fSeq, int fHaig ) +{ + Abc_Ntk_t * pNtkAig; + int nNodes, fCleanup = 1; + // convert from the AIG manager + if ( fSeq ) + pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan, fHaig ); + else + pNtkAig = Abc_NtkFromIvy( pNtk, pMan ); + // report the cleanup results + if ( !fHaig && fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) + printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkStrash: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan; + pMan = Abc_NtkIvyBefore( pNtk, 1, 0 ); + if ( pMan == NULL ) + return NULL; + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int nIters, int fUseZeroCost, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan; + int clk; +// int i; +/* +extern int nMoves; +extern int nMovesS; +extern int nClauses; +extern int timeInv; + +nMoves = 0; +nMovesS = 0; +nClauses = 0; +timeInv = 0; +*/ + pMan = Abc_NtkIvyBefore( pNtk, 1, 1 ); + if ( pMan == NULL ) + return NULL; +//timeRetime = clock(); + +clk = clock(); + Ivy_ManHaigStart( pMan, fVerbose ); +// Ivy_ManRewriteSeq( pMan, 0, 0 ); +// for ( i = 0; i < nIters; i++ ) +// Ivy_ManRewriteSeq( pMan, fUseZeroCost, 0 ); + +//printf( "%d ", Ivy_ManNodeNum(pMan) ); + Ivy_ManRewriteSeq( pMan, 0, 0 ); + Ivy_ManRewriteSeq( pMan, 0, 0 ); + Ivy_ManRewriteSeq( pMan, 1, 0 ); +//printf( "%d ", Ivy_ManNodeNum(pMan) ); +//printf( "%d ", Ivy_ManNodeNum(pMan->pHaig) ); +//PRT( " ", clock() - clk ); +//printf( "\n" ); +/* + printf( "Moves = %d. ", nMoves ); + printf( "MovesS = %d. ", nMovesS ); + printf( "Clauses = %d. ", nClauses ); + PRT( "Time", timeInv ); +*/ +// Ivy_ManRewriteSeq( pMan, 1, 0 ); +//printf( "Haig size = %d.\n", Ivy_ManNodeNum(pMan->pHaig) ); +// Ivy_ManHaigPostprocess( pMan, fVerbose ); +//timeRetime = clock() - timeRetime; + + // write working AIG into the current network +// pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); + // write HAIG into the current network + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan->pHaig, 1, 1 ); + + Ivy_ManHaigStop( pMan ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs ) +{ + extern void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs ); + Ivy_Man_t * pMan; + pMan = Abc_NtkIvyBefore( pNtk, 1, 0 ); + if ( pMan == NULL ) + return; + Ivy_CutComputeAll( pMan, nInputs ); + Ivy_ManStop( pMan ); +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan; + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + if ( pMan == NULL ) + return NULL; +//timeRetime = clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, fUseZeroCost, fVerbose ); +//timeRetime = clock() - timeRetime; + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan; + pMan = Abc_NtkIvyBefore( pNtk, 1, 1 ); + if ( pMan == NULL ) + return NULL; +//timeRetime = clock(); + Ivy_ManRewriteSeq( pMan, fUseZeroCost, fVerbose ); +//timeRetime = clock() - timeRetime; +// Ivy_ManRewriteSeq( pMan, 1, 0 ); +// Ivy_ManRewriteSeq( pMan, 1, 0 ); + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyResyn0( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan, * pTemp; + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + if ( pMan == NULL ) + return NULL; + pMan = Ivy_ManResyn0( pTemp = pMan, fUpdateLevel, fVerbose ); + Ivy_ManStop( pTemp ); + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan, * pTemp; + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + if ( pMan == NULL ) + return NULL; + pMan = Ivy_ManResyn( pTemp = pMan, fUpdateLevel, fVerbose ); + Ivy_ManStop( pTemp ); + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose ) +{ + Ivy_FraigParams_t Params, * pParams = &Params; + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan, * pTemp; + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + if ( pMan == NULL ) + return NULL; + Ivy_FraigParamsDefault( pParams ); + pParams->nBTLimitMiter = nConfLimit; + pParams->fVerbose = fVerbose; +// pMan = Ivy_FraigPerform( pTemp = pMan, pParams ); + pMan = Ivy_FraigMiter( pTemp = pMan, pParams ); + Ivy_ManStop( pTemp ); + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Sets the final nodes to point to the original nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTransferPointers( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig ) +{ + Abc_Obj_t * pObj; + Ivy_Obj_t * pObjIvy, * pObjFraig; + int i; + pObj = Abc_AigConst1(pNtk); + pObj->pCopy = Abc_AigConst1(pNtkAig); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkCi(pNtkAig, i); + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkCo(pNtkAig, i); + Abc_NtkForEachLatch( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkBox(pNtkAig, i); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + pObjIvy = (Ivy_Obj_t *)pObj->pCopy; + if ( pObjIvy == NULL ) + continue; + pObjFraig = Ivy_ObjEquiv( pObjIvy ); + if ( pObjFraig == NULL ) + continue; + pObj->pCopy = Abc_EdgeToNode( pNtkAig, Ivy_Regular(pObjFraig)->TravId ); + pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, Ivy_IsComplement(pObjFraig) ); + } +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ) +{ + Ivy_FraigParams_t Params, * pParams = &Params; + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan, * pTemp; + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + if ( pMan == NULL ) + return NULL; + Ivy_FraigParamsDefault( pParams ); + pParams->nBTLimitNode = nConfLimit; + pParams->fVerbose = fVerbose; + pParams->fProve = fProve; + pParams->fDoSparse = fDoSparse; + pMan = Ivy_FraigPerform( pTemp = pMan, pParams ); + // transfer the pointers + if ( fTransfer == 1 ) + { + Vec_Ptr_t * vCopies; + vCopies = Abc_NtkSaveCopy( pNtk ); + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); + Abc_NtkLoadCopy( pNtk, vCopies ); + Vec_PtrFree( vCopies ); + Abc_NtkTransferPointers( pNtk, pNtkAig ); + } + else + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); + Ivy_ManStop( pTemp ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ) +{ + Prove_Params_t * pParams = pPars; + Abc_Ntk_t * pNtk = *ppNtk, * pNtkTemp; + Abc_Obj_t * pObj, * pFanin; + Ivy_Man_t * pMan; + int RetValue; + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + // experiment with various parameters settings +// pParams->fUseBdds = 1; +// pParams->fBddReorder = 1; +// pParams->nTotalBacktrackLimit = 10000; + + // strash the network if it is not strashed already + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtk = Abc_NtkStrash( pNtkTemp = pNtk, 0, 1, 0 ); + Abc_NtkDelete( pNtkTemp ); + } + + // check the case when the 0000 simulation pattern detect the bug + pObj = Abc_NtkPo(pNtk,0); + pFanin = Abc_ObjFanin0(pObj); + if ( Abc_ObjFanin0(pObj)->fPhase != (unsigned)Abc_ObjFaninC0(pObj) ) + { + pNtk->pModel = ALLOC( int, Abc_NtkPiNum(pNtk) ); + memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkPiNum(pNtk) ); + return 0; + } + + // if SAT only, solve without iteration + RetValue = Abc_NtkMiterSat( pNtk, 2*(sint64)pParams->nMiteringLimitStart, (sint64)0, 0, NULL, NULL ); + if ( RetValue >= 0 ) + return RetValue; + + // apply AIG rewriting + if ( pParams->fUseRewriting && Abc_NtkNodeNum(pNtk) > 500 ) + { + pParams->fUseRewriting = 0; + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); + Abc_NtkDelete( pNtkTemp ); + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); + Abc_NtkDelete( pNtkTemp ); + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + } + + // convert ABC network into IVY network + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + + // solve the CEC problem + RetValue = Ivy_FraigProve( &pMan, pParams ); + // convert IVY network into ABC network + pNtk = Abc_NtkIvyAfter( pNtkTemp = pNtk, pMan, 0, 0 ); + Abc_NtkDelete( pNtkTemp ); + // transfer model if given + pNtk->pModel = pMan->pData; pMan->pData = NULL; + Ivy_ManStop( pMan ); + + // try to prove it using brute force SAT + if ( RetValue < 0 && pParams->fUseBdds ) + { + if ( pParams->fVerbose ) + { + printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit ); + fflush( stdout ); + } + pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 ); + if ( pNtk ) + { + Abc_NtkDelete( pNtkTemp ); + RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero(pNtk->pManFunc)) ); + } + else + pNtk = pNtkTemp; + } + + // return the result + *ppNtk = pNtk; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk ) +{ +// Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan;//, * pTemp; + int fCleanup = 1; +// int nNodes; + int nLatches = Abc_NtkLatchNum(pNtk); + Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, 0 ); + + assert( !Abc_NtkIsNetlist(pNtk) ); + if ( Abc_NtkIsBddLogic(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + Vec_IntFree( vInit ); + printf( "Abc_NtkIvy(): Converting to SOPs has failed.\n" ); + return NULL; + } + } + if ( Abc_NtkCountSelfFeedLatches(pNtk) ) + { + printf( "Warning: The network has %d self-feeding latches. Quitting.\n", Abc_NtkCountSelfFeedLatches(pNtk) ); + return NULL; + } + + // print warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" ); + + // convert to the AIG manager + pMan = Abc_NtkToIvy( pNtk ); + if ( !Ivy_ManCheck( pMan ) ) + { + Vec_IntFree( vInit ); + printf( "AIG check has failed.\n" ); + Ivy_ManStop( pMan ); + return NULL; + } + +// Ivy_MffcTest( pMan ); +// Ivy_ManPrintStats( pMan ); + +// pMan = Ivy_ManBalance( pTemp = pMan, 1 ); +// Ivy_ManStop( pTemp ); + +// Ivy_ManSeqRewrite( pMan, 0, 0 ); +// Ivy_ManTestCutsAlg( pMan ); +// Ivy_ManTestCutsBool( pMan ); +// Ivy_ManRewriteAlg( pMan, 1, 1 ); + +// pMan = Ivy_ManResyn( pTemp = pMan, 1, 0 ); +// Ivy_ManStop( pTemp ); + +// Ivy_ManTestCutsAll( pMan ); +// Ivy_ManTestCutsTravAll( pMan ); + +// Ivy_ManPrintStats( pMan ); + +// Ivy_ManPrintStats( pMan ); +// Ivy_ManRewritePre( pMan, 1, 0, 0 ); +// Ivy_ManPrintStats( pMan ); +// printf( "\n" ); + +// Ivy_ManPrintStats( pMan ); +// Ivy_ManMakeSeq( pMan, nLatches, pInit ); +// Ivy_ManPrintStats( pMan ); + +// Ivy_ManRequiredLevels( pMan ); + +// Ivy_FastMapPerform( pMan, 8 ); + Ivy_ManStop( pMan ); + return NULL; + + +/* + // convert from the AIG manager + pNtkAig = Abc_NtkFromIvy( pNtk, pMan ); +// pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan ); + Ivy_ManStop( pMan ); + + // report the cleanup results + if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) + printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + FREE( pInit ); + printf( "Abc_NtkStrash: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + + FREE( pInit ); + return pNtkAig; +*/ +} + + + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan ) +{ + Vec_Int_t * vNodes; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1; + Ivy_Obj_t * pNode; + int i; + // perform strashing + pNtk = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) ); + Abc_NtkForEachCi( pNtkOld, pObj, i ) + Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy ); + // rebuild the AIG + vNodes = Ivy_ManDfs( pMan ); + Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i ) + { + // add the first fanin + pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode ); + if ( Ivy_ObjIsBuf(pNode) ) + { + pNode->TravId = Abc_EdgeFromNode( pFaninNew0 ); + continue; + } + // add the second fanin + pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode ); + // create the new node + if ( Ivy_ObjIsExor(pNode) ) + pObjNew = Abc_AigXor( pNtk->pManFunc, pFaninNew0, pFaninNew1 ); + else + pObjNew = Abc_AigAnd( pNtk->pManFunc, pFaninNew0, pFaninNew1 ); + pNode->TravId = Abc_EdgeFromNode( pObjNew ); + } + // connect the PO nodes + Abc_NtkForEachCo( pNtkOld, pObj, i ) + { + pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) ); + Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); + } + Vec_IntFree( vNodes ); + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkFromIvy(): Network check has failed.\n" ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig ) +{ + Vec_Int_t * vNodes, * vLatches; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1; + Ivy_Obj_t * pNode, * pTemp; + int i; +// assert( Ivy_ManLatchNum(pMan) > 0 ); + // perform strashing + pNtk = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) ); + Abc_NtkForEachPi( pNtkOld, pObj, i ) + Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy ); + // create latches of the new network + vNodes = Ivy_ManDfsSeq( pMan, &vLatches ); + Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i ) + { + pObjNew = Abc_NtkCreateLatch( pNtk ); + pFaninNew0 = Abc_NtkCreateBi( pNtk ); + pFaninNew1 = Abc_NtkCreateBo( pNtk ); + Abc_ObjAddFanin( pObjNew, pFaninNew0 ); + Abc_ObjAddFanin( pFaninNew1, pObjNew ); + if ( fHaig || Ivy_ObjInit(pNode) == IVY_INIT_DC ) + Abc_LatchSetInitDc( pObjNew ); + else if ( Ivy_ObjInit(pNode) == IVY_INIT_1 ) + Abc_LatchSetInit1( pObjNew ); + else if ( Ivy_ObjInit(pNode) == IVY_INIT_0 ) + Abc_LatchSetInit0( pObjNew ); + else assert( 0 ); + pNode->TravId = Abc_EdgeFromNode( pFaninNew1 ); + } + Abc_NtkAddDummyBoxNames( pNtk ); + // rebuild the AIG + Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i ) + { + // add the first fanin + pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode ); + if ( Ivy_ObjIsBuf(pNode) ) + { + pNode->TravId = Abc_EdgeFromNode( pFaninNew0 ); + continue; + } + // add the second fanin + pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode ); + // create the new node + if ( Ivy_ObjIsExor(pNode) ) + pObjNew = Abc_AigXor( pNtk->pManFunc, pFaninNew0, pFaninNew1 ); + else + pObjNew = Abc_AigAnd( pNtk->pManFunc, pFaninNew0, pFaninNew1 ); + pNode->TravId = Abc_EdgeFromNode( pObjNew ); + // process the choice nodes + if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 ) + { + pFaninNew = Abc_EdgeToNode( pNtk, pNode->TravId ); +// pFaninNew->fPhase = 0; + assert( !Ivy_IsComplement(pNode->pEquiv) ); + for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { + pFaninNew1 = Abc_EdgeToNode( pNtk, pTemp->TravId ); +// pFaninNew1->fPhase = Ivy_IsComplement( pTemp->pEquiv ); + pFaninNew->pData = pFaninNew1; + pFaninNew = pFaninNew1; + } + pFaninNew->pData = NULL; +// printf( "Writing choice node %d.\n", pNode->Id ); + } + } + // connect the PO nodes + Abc_NtkForEachPo( pNtkOld, pObj, i ) + { + pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) ); + Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); + } + // connect the latches + Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i ) + { + pFaninNew = Abc_ObjFanin0Ivy( pNtk, pNode ); + Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(pNtk, i)), pFaninNew ); + } + Vec_IntFree( vLatches ); + Vec_IntFree( vNodes ); + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkFromIvySeq(): Network check has failed.\n" ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Abc_NtkToIvy( Abc_Ntk_t * pNtkOld ) +{ + Ivy_Man_t * pMan; + Abc_Obj_t * pObj; + Ivy_Obj_t * pFanin; + int i; + // create the manager + assert( Abc_NtkHasSop(pNtkOld) || Abc_NtkIsStrash(pNtkOld) ); + pMan = Ivy_ManStart(); + // create the PIs + if ( Abc_NtkIsStrash(pNtkOld) ) + Abc_AigConst1(pNtkOld)->pCopy = (Abc_Obj_t *)Ivy_ManConst1(pMan); + Abc_NtkForEachCi( pNtkOld, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Ivy_ObjCreatePi(pMan); + // perform the conversion of the internal nodes + Abc_NtkStrashPerformAig( pNtkOld, pMan ); + // create the POs + Abc_NtkForEachCo( pNtkOld, pObj, i ) + { + pFanin = (Ivy_Obj_t *)Abc_ObjFanin0(pObj)->pCopy; + pFanin = Ivy_NotCond( pFanin, Abc_ObjFaninC0(pObj) ); + Ivy_ObjCreatePo( pMan, pFanin ); + } + Ivy_ManCleanup( pMan ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Prepares the network for strashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ) +{ +// ProgressBar * pProgress; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + vNodes = Abc_NtkDfs( pNtk, 0 ); +// pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { +// Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNode->pCopy = (Abc_Obj_t *)Abc_NodeStrashAig( pMan, pNode ); + } +// Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode ) +{ + int fUseFactor = 1; + char * pSop; + Ivy_Obj_t * pFanin0, * pFanin1; + + assert( Abc_ObjIsNode(pNode) ); + + // consider the case when the graph is an AIG + if ( Abc_NtkIsStrash(pNode->pNtk) ) + { + if ( Abc_AigNodeIsConst(pNode) ) + return Ivy_ManConst1(pMan); + pFanin0 = (Ivy_Obj_t *)Abc_ObjFanin0(pNode)->pCopy; + pFanin0 = Ivy_NotCond( pFanin0, Abc_ObjFaninC0(pNode) ); + pFanin1 = (Ivy_Obj_t *)Abc_ObjFanin1(pNode)->pCopy; + pFanin1 = Ivy_NotCond( pFanin1, Abc_ObjFaninC1(pNode) ); + return Ivy_And( pMan, pFanin0, pFanin1 ); + } + + // get the SOP of the node + if ( Abc_NtkHasMapping(pNode->pNtk) ) + pSop = Mio_GateReadSop(pNode->pData); + else + pSop = pNode->pData; + + // consider the constant node + if ( Abc_NodeIsConst(pNode) ) + return Ivy_NotCond( Ivy_ManConst1(pMan), Abc_SopIsConst0(pSop) ); + + // consider the special case of EXOR function + if ( Abc_SopIsExorType(pSop) ) + return Abc_NodeStrashAigExorAig( pMan, pNode, pSop ); + + // decide when to use factoring + if ( fUseFactor && Abc_ObjFaninNum(pNode) > 2 && Abc_SopGetCubeNum(pSop) > 1 ) + return Abc_NodeStrashAigFactorAig( pMan, pNode, pSop ); + return Abc_NodeStrashAigSopAig( pMan, pNode, pSop ); +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ) +{ + Abc_Obj_t * pFanin; + Ivy_Obj_t * pAnd, * pSum; + char * pCube; + int i, nFanins; + + // get the number of node's fanins + nFanins = Abc_ObjFaninNum( pNode ); + assert( nFanins == Abc_SopGetVarNum(pSop) ); + // go through the cubes of the node's SOP + pSum = Ivy_Not( Ivy_ManConst1(pMan) ); + Abc_SopForEachCube( pSop, nFanins, pCube ) + { + // create the AND of literals + pAnd = Ivy_ManConst1(pMan); + Abc_ObjForEachFanin( pNode, pFanin, i ) // pFanin can be a net + { + if ( pCube[i] == '1' ) + pAnd = Ivy_And( pMan, pAnd, (Ivy_Obj_t *)pFanin->pCopy ); + else if ( pCube[i] == '0' ) + pAnd = Ivy_And( pMan, pAnd, Ivy_Not((Ivy_Obj_t *)pFanin->pCopy) ); + } + // add to the sum of cubes + pSum = Ivy_Or( pMan, pSum, pAnd ); + } + // decide whether to complement the result + if ( Abc_SopIsComplement(pSop) ) + pSum = Ivy_Not(pSum); + return pSum; +} + +/**Function************************************************************* + + Synopsis [Strashed n-input XOR function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ) +{ + Abc_Obj_t * pFanin; + Ivy_Obj_t * pSum; + int i, nFanins; + // get the number of node's fanins + nFanins = Abc_ObjFaninNum( pNode ); + assert( nFanins == Abc_SopGetVarNum(pSop) ); + // go through the cubes of the node's SOP + pSum = Ivy_Not( Ivy_ManConst1(pMan) ); + for ( i = 0; i < nFanins; i++ ) + { + pFanin = Abc_ObjFanin( pNode, i ); + pSum = Ivy_Exor( pMan, pSum, (Ivy_Obj_t *)pFanin->pCopy ); + } + if ( Abc_SopIsComplement(pSop) ) + pSum = Ivy_Not(pSum); + return pSum; +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pRoot, char * pSop ) +{ + Dec_Graph_t * pFForm; + Dec_Node_t * pNode; + Ivy_Obj_t * pAnd; + int i; + +// extern Ivy_Obj_t * Dec_GraphToNetworkAig( Ivy_Man_t * pMan, Dec_Graph_t * pGraph ); + extern Ivy_Obj_t * Dec_GraphToNetworkIvy( Ivy_Man_t * pMan, Dec_Graph_t * pGraph ); + +// assert( 0 ); + + // perform factoring + pFForm = Dec_Factor( pSop ); + // collect the fanins + Dec_GraphForEachLeaf( pFForm, pNode, i ) + pNode->pFunc = Abc_ObjFanin(pRoot,i)->pCopy; + // perform strashing +// pAnd = Dec_GraphToNetworkAig( pMan, pFForm ); + pAnd = Dec_GraphToNetworkIvy( pMan, pFForm ); +// pAnd = NULL; + + Dec_GraphFree( pFForm ); + return pAnd; +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs ) +{ + Abc_Obj_t * pLatch; + Vec_Int_t * vArray; + int i; + vArray = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( fUseDcs || Abc_LatchIsInitDc(pLatch) ) + Vec_IntPush( vArray, IVY_INIT_DC ); + else if ( Abc_LatchIsInit1(pLatch) ) + Vec_IntPush( vArray, IVY_INIT_1 ); + else if ( Abc_LatchIsInit0(pLatch) ) + Vec_IntPush( vArray, IVY_INIT_0 ); + else assert( 0 ); + } + return vArray; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcLut.c b/abc70930/src/base/abci/abcLut.c new file mode 100644 index 00000000..afa76cc8 --- /dev/null +++ b/abc70930/src/base/abci/abcLut.c @@ -0,0 +1,786 @@ +/**CFile**************************************************************** + + FileName [abcLut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Superchoicing for K-LUTs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "cut.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define SCL_LUT_MAX 6 // the maximum LUT size +#define SCL_VARS_MAX 15 // the maximum number of variables +#define SCL_NODE_MAX 1000 // the maximum number of nodes + +typedef struct Abc_ManScl_t_ Abc_ManScl_t; +struct Abc_ManScl_t_ +{ + // paramers + int nLutSize; // the LUT size + int nCutSizeMax; // the max number of leaves of the cone + int nNodesMax; // the max number of divisors in the cone + int nWords; // the number of machine words in sim info + // structural representation of the cone + Vec_Ptr_t * vLeaves; // leaves of the cut + Vec_Ptr_t * vVolume; // volume of the cut + int pBSet[SCL_VARS_MAX]; // bound set + // functional representation of the cone + unsigned * uTruth; // truth table of the cone + // representation of truth tables + unsigned ** uVars; // elementary truth tables + unsigned ** uSims; // truth tables of the nodes + unsigned ** uCofs; // truth tables of the cofactors +}; + +static Vec_Ptr_t * s_pLeaves = NULL; + +static Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize ); +static Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax ); +static void Abc_ManSclStop( Abc_ManScl_t * p ); +static void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj ); + +static Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * pManScl, Abc_Obj_t * pObj ); +static int Abc_NodeDecomposeStep( Abc_ManScl_t * pManScl ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs superchoicing for K-LUTs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose ) +{ + ProgressBar * pProgress; + Abc_ManCut_t * pManCut; + Abc_ManScl_t * pManScl; + Cut_Man_t * pManCuts; + Abc_Obj_t * pObj, * pFanin, * pObjTop; + int i, LevelMax, nNodes; + int nNodesTried, nNodesDec, nNodesExist, nNodesUsed; + + assert( Abc_NtkIsSopLogic(pNtk) ); + if ( nLutSize < 3 || nLutSize > SCL_LUT_MAX ) + { + printf( "LUT size (%d) does not belong to the interval: 3 <= LUT size <= %d\n", nLutSize, SCL_LUT_MAX ); + return 0; + } + if ( nCutSizeMax <= nLutSize || nCutSizeMax > SCL_VARS_MAX ) + { + printf( "Cut size (%d) does not belong to the interval: LUT size (%d) < Cut size <= %d\n", nCutSizeMax, nLutSize, SCL_VARS_MAX ); + return 0; + } + + assert( nLutSize <= SCL_LUT_MAX ); + assert( nCutSizeMax <= SCL_VARS_MAX ); + nNodesTried = nNodesDec = nNodesExist = nNodesUsed = 0; + + // set the delays of the CIs + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->Level = 0; + +//Abc_NtkLevel( pNtk ); + + // start the managers + pManScl = Abc_ManSclStart( nLutSize, nCutSizeMax, 1000 ); + pManCuts = Abc_NtkStartCutManForScl( pNtk, nLutSize ); + pManCut = Abc_NtkManCutStart( nCutSizeMax, 100000, 100000, 100000 ); + s_pLeaves = Abc_NtkManCutReadCutSmall( pManCut ); + pManScl->vVolume = Abc_NtkManCutReadVisited( pManCut ); + + // process each internal node (assuming topological order of nodes!!!) + nNodes = Abc_NtkObjNumMax(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { +// if ( i != nNodes-1 ) +// continue; + Extra_ProgressBarUpdate( pProgress, i, NULL ); + if ( i >= nNodes ) + break; + if ( Abc_ObjFaninNum(pObj) != 2 ) + continue; + nNodesTried++; + + // map this node using regular cuts +// pObj->Level = 0; + Abc_NodeLutMap( pManCuts, pObj ); + // compute the cut + pManScl->vLeaves = Abc_NodeFindCut( pManCut, pObj, 0 ); + if ( Vec_PtrSize(pManScl->vLeaves) <= nLutSize ) + continue; + // get the volume of the cut + if ( Vec_PtrSize(pManScl->vVolume) > SCL_NODE_MAX ) + continue; + nNodesDec++; + + // decompose the cut + pObjTop = Abc_NodeSuperChoiceLut( pManScl, pObj ); + if ( pObjTop == NULL ) + continue; + nNodesExist++; + + // if there is no delay improvement, skip; otherwise, update level + if ( pObjTop->Level >= pObj->Level ) + { + Abc_NtkDeleteObj_rec( pObjTop, 1 ); + continue; + } + pObj->Level = pObjTop->Level; + nNodesUsed++; + } + Extra_ProgressBarStop( pProgress ); + + // delete the managers + Abc_ManSclStop( pManScl ); + Abc_NtkManCutStop( pManCut ); + Cut_ManStop( pManCuts ); + + // get the largest arrival time + LevelMax = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pFanin = Abc_ObjFanin0( pObj ); + // skip inv/buf + if ( Abc_ObjFaninNum(pFanin) == 1 ) + pFanin = Abc_ObjFanin0( pFanin ); + // get the new level + LevelMax = ABC_MAX( LevelMax, (int)pFanin->Level ); + } + + if ( fVerbose ) + printf( "Try = %d. Dec = %d. Exist = %d. Use = %d. SUPER = %d levels of %d-LUTs.\n", + nNodesTried, nNodesDec, nNodesExist, nNodesUsed, LevelMax, nLutSize ); +// if ( fVerbose ) +// printf( "The network is superchoiced for %d levels of %d-LUTs.\n", LevelMax, nLutSize ); + + // clean the data field + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pNext = NULL; + + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkSuperChoiceLut: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs LUT mapping of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj ) +{ + Cut_Cut_t * pCut; + Abc_Obj_t * pFanin; + int i, DelayMax; + pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCuts, pObj, 0, 0 ); + assert( pCut != NULL ); + assert( pObj->Level == 0 ); + // go through the cuts + pObj->Level = ABC_INFINITY; + for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) + { + DelayMax = 0; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + pFanin = Abc_NtkObj( pObj->pNtk, pCut->pLeaves[i] ); +// assert( Abc_ObjIsCi(pFanin) || pFanin->Level > 0 ); // should hold if node ordering is topological + if ( DelayMax < (int)pFanin->Level ) + DelayMax = pFanin->Level; + } + if ( (int)pObj->Level > DelayMax ) + pObj->Level = DelayMax; + } + assert( pObj->Level < ABC_INFINITY ); + pObj->Level++; +// printf( "%d(%d) ", pObj->Id, pObj->Level ); +} + +/**Function************************************************************* + + Synopsis [Starts the cut manager for rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize ) +{ + static Cut_Params_t Params, * pParams = &Params; + Cut_Man_t * pManCut; + Abc_Obj_t * pObj; + int i; + // start the cut manager + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = nLutSize; // the max cut size ("k" of the k-feasible cuts) + pParams->nKeepMax = 500; // the max number of cuts kept at a node + pParams->fTruth = 0; // compute truth tables + pParams->fFilter = 1; // filter dominated cuts + pParams->fSeq = 0; // compute sequential cuts + pParams->fDrop = 0; // drop cuts on the fly + pParams->fVerbose = 0; // the verbosiness flag + pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); + pManCut = Cut_ManStart( pParams ); + if ( pParams->fDrop ) + Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); + // set cuts for PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_NodeSetTriv( pManCut, pObj->Id ); + return pManCut; +} + +/**Function************************************************************* + + Synopsis [Starts the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax ) +{ + Abc_ManScl_t * p; + int i, k; + assert( sizeof(unsigned) == 4 ); + p = ALLOC( Abc_ManScl_t, 1 ); + memset( p, 0, sizeof(Abc_ManScl_t) ); + p->nLutSize = nLutSize; + p->nCutSizeMax = nCutSizeMax; + p->nNodesMax = nNodesMax; + p->nWords = Extra_TruthWordNum(nCutSizeMax); + // allocate simulation info + p->uVars = (unsigned **)Extra_ArrayAlloc( nCutSizeMax, p->nWords, 4 ); + p->uSims = (unsigned **)Extra_ArrayAlloc( nNodesMax, p->nWords, 4 ); + p->uCofs = (unsigned **)Extra_ArrayAlloc( 2 << nLutSize, p->nWords, 4 ); + memset( p->uVars[0], 0, nCutSizeMax * p->nWords * 4 ); + // assign elementary truth tables + for ( k = 0; k < p->nCutSizeMax; k++ ) + for ( i = 0; i < p->nWords * 32; i++ ) + if ( i & (1 << k) ) + p->uVars[k][i>>5] |= (1 << (i&31)); + // other data structures +// p->vBound = Vec_IntAlloc( nCutSizeMax ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManSclStop( Abc_ManScl_t * p ) +{ +// Vec_IntFree( p->vBound ); + free( p->uVars ); + free( p->uSims ); + free( p->uCofs ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Abc_NodeSuperChoiceTruth( Abc_ManScl_t * pManScl ) +{ + Abc_Obj_t * pObj; + unsigned * puData0, * puData1, * puData; + char * pSop; + int i, k; + // set elementary truth tables + Vec_PtrForEachEntry( pManScl->vLeaves, pObj, i ) + pObj->pNext = (Abc_Obj_t *)pManScl->uVars[i]; + // compute truth tables for internal nodes + Vec_PtrForEachEntry( pManScl->vVolume, pObj, i ) + { + // set storage for the node's simulation info + pObj->pNext = (Abc_Obj_t *)pManScl->uSims[i]; + // get pointer to the simulation info + puData = (unsigned *)pObj->pNext; + puData0 = (unsigned *)Abc_ObjFanin0(pObj)->pNext; + puData1 = (unsigned *)Abc_ObjFanin1(pObj)->pNext; + // simulate + pSop = pObj->pData; + if ( pSop[0] == '0' && pSop[1] == '0' ) + for ( k = 0; k < pManScl->nWords; k++ ) + puData[k] = ~puData0[k] & ~puData1[k]; + else if ( pSop[0] == '0' ) + for ( k = 0; k < pManScl->nWords; k++ ) + puData[k] = ~puData0[k] & puData1[k]; + else if ( pSop[1] == '0' ) + for ( k = 0; k < pManScl->nWords; k++ ) + puData[k] = puData0[k] & ~puData1[k]; + else + for ( k = 0; k < pManScl->nWords; k++ ) + puData[k] = puData0[k] & puData1[k]; + } + return puData; +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSuperChoiceCollect2_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vVolume ) +{ + if ( pObj->fMarkC ) + return; + pObj->fMarkC = 1; + assert( Abc_ObjFaninNum(pObj) == 2 ); + Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin0(pObj), vVolume ); + Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin1(pObj), vVolume ); + Vec_PtrPush( vVolume, pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSuperChoiceCollect2( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) +{ + Abc_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->fMarkC = 1; + Vec_PtrClear( vVolume ); + Abc_NodeSuperChoiceCollect2_rec( pRoot, vVolume ); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->fMarkC = 0; + Vec_PtrForEachEntry( vVolume, pObj, i ) + pObj->fMarkC = 0; +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSuperChoiceCollect_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) +{ + if ( pObj->fMarkB ) + { + Vec_PtrPush( vLeaves, pObj ); + pObj->fMarkB = 0; + } + if ( pObj->fMarkC ) + return; + pObj->fMarkC = 1; + assert( Abc_ObjFaninNum(pObj) == 2 ); + Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin0(pObj), vLeaves, vVolume ); + Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin1(pObj), vLeaves, vVolume ); + Vec_PtrPush( vVolume, pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [Orders the leaves topologically.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSuperChoiceCollect( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) +{ + Abc_Obj_t * pObj; + int i, nLeaves; + nLeaves = Vec_PtrSize(vLeaves); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->fMarkB = pObj->fMarkC = 1; + Vec_PtrClear( vVolume ); + Vec_PtrClear( vLeaves ); + Abc_NodeSuperChoiceCollect_rec( pRoot, vLeaves, vVolume ); + assert( Vec_PtrSize(vLeaves) == nLeaves ); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->fMarkC = 0; + Vec_PtrForEachEntry( vVolume, pObj, i ) + pObj->fMarkC = 0; +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeLeavesRemove( Vec_Ptr_t * vLeaves, unsigned uPhase, int nVars ) +{ + int i; + for ( i = nVars - 1; i >= 0; i-- ) + if ( uPhase & (1 << i) ) + Vec_PtrRemove( vLeaves, Vec_PtrEntry(vLeaves, i) ); +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeGetLevel( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i, Level; + Level = 0; + Abc_ObjForEachFanin( pObj, pFanin, i ) + Level = ABC_MAX( Level, (int)pFanin->Level ); + return Level + 1; +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * p, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin, * pObjNew; + int i, nVars, uSupport, nSuppVars; + // collect the cone using DFS (excluding leaves) + Abc_NodeSuperChoiceCollect2( pObj, p->vLeaves, p->vVolume ); + assert( Vec_PtrEntryLast(p->vVolume) == pObj ); + // compute the truth table + p->uTruth = Abc_NodeSuperChoiceTruth( p ); + // get the support of this truth table + nVars = Vec_PtrSize(p->vLeaves); + uSupport = Extra_TruthSupport(p->uTruth, nVars); + nSuppVars = Extra_WordCountOnes(uSupport); + assert( nSuppVars <= nVars ); + if ( nSuppVars == 0 ) + { + pObj->Level = 0; + return NULL; + } + if ( nSuppVars == 1 ) + { + // find the variable + for ( i = 0; i < nVars; i++ ) + if ( uSupport & (1 << i) ) + break; + assert( i < nVars ); + pFanin = Vec_PtrEntry( p->vLeaves, i ); + pObj->Level = pFanin->Level; + return NULL; + } + // support-minimize the truth table + if ( nSuppVars != nVars ) + { + Extra_TruthShrink( p->uCofs[0], p->uTruth, nSuppVars, nVars, uSupport ); + Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars ); + Abc_NodeLeavesRemove( p->vLeaves, ((1 << nVars) - 1) & ~uSupport, nVars ); + } +// return NULL; + // decompose the truth table recursively + while ( Vec_PtrSize(p->vLeaves) > p->nLutSize ) + if ( !Abc_NodeDecomposeStep( p ) ) + { + Vec_PtrForEachEntry( p->vLeaves, pFanin, i ) + if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 0 ) + Abc_NtkDeleteObj_rec( pFanin, 1 ); + return NULL; + } + // create the topmost node + pObjNew = Abc_NtkCreateNode( pObj->pNtk ); + Vec_PtrForEachEntry( p->vLeaves, pFanin, i ) + Abc_ObjAddFanin( pObjNew, pFanin ); + // create the function + pObjNew->pData = Abc_SopCreateFromTruth( pObj->pNtk->pManFunc, Vec_PtrSize(p->vLeaves), p->uTruth ); // need ISOP + pObjNew->Level = Abc_NodeGetLevel( pObjNew ); + return pObjNew; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in increasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareLevelsInc( int * pp1, int * pp2 ) +{ + Abc_Obj_t * pNode1, * pNode2; + pNode1 = Vec_PtrEntry(s_pLeaves, *pp1); + pNode2 = Vec_PtrEntry(s_pLeaves, *pp2); + if ( pNode1->Level < pNode2->Level ) + return -1; + if ( pNode1->Level > pNode2->Level ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Selects the earliest arriving nodes from the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeDecomposeSort( Abc_Obj_t ** pLeaves, int nVars, int * pBSet, int nLutSize ) +{ + Abc_Obj_t * pTemp[SCL_VARS_MAX]; + int i, k, kBest, LevelMin; + assert( nLutSize < nVars ); + assert( nVars <= SCL_VARS_MAX ); + // copy nodes into the internal storage +// printf( "(" ); + for ( i = 0; i < nVars; i++ ) + { + pTemp[i] = pLeaves[i]; +// printf( " %d", pLeaves[i]->Level ); + } +// printf( " )\n" ); + // choose one node at a time + for ( i = 0; i < nLutSize; i++ ) + { + kBest = -1; + LevelMin = ABC_INFINITY; + for ( k = 0; k < nVars; k++ ) + if ( pTemp[k] && LevelMin > (int)pTemp[k]->Level ) + { + LevelMin = pTemp[k]->Level; + kBest = k; + } + pBSet[i] = kBest; + pTemp[kBest] = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeDecomposeStep( Abc_ManScl_t * p ) +{ + static char pCofClasses[1<<SCL_LUT_MAX][1<<SCL_LUT_MAX]; + static char nCofClasses[1<<SCL_LUT_MAX]; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObjNew, * pFanin, * pNodesNew[SCL_LUT_MAX]; + unsigned * pTruthCof, * pTruthClass, * pTruth, uPhase; + int i, k, c, v, w, nVars, nVarsNew, nClasses, nCofs; + // set the network + pNtk = ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, 0))->pNtk; + // find the earliest nodes + nVars = Vec_PtrSize(p->vLeaves); + assert( nVars > p->nLutSize ); +/* + for ( v = 0; v < nVars; v++ ) + p->pBSet[v] = v; + qsort( (void *)p->pBSet, nVars, sizeof(int), + (int (*)(const void *, const void *)) Abc_NodeCompareLevelsInc ); +*/ + Abc_NodeDecomposeSort( (Abc_Obj_t **)Vec_PtrArray(p->vLeaves), Vec_PtrSize(p->vLeaves), p->pBSet, p->nLutSize ); + assert( ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[0]))->Level <= + ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[1]))->Level ); + // cofactor w.r.t. the selected variables + Extra_TruthCopy( p->uCofs[1], p->uTruth, nVars ); + c = 2; + for ( v = 0; v < p->nLutSize; v++ ) + for ( k = 0; k < (1<<v); k++ ) + { + Extra_TruthCopy( p->uCofs[c], p->uCofs[c/2], nVars ); + Extra_TruthCopy( p->uCofs[c+1], p->uCofs[c/2], nVars ); + Extra_TruthCofactor0( p->uCofs[c], nVars, p->pBSet[v] ); + Extra_TruthCofactor1( p->uCofs[c+1], nVars, p->pBSet[v] ); + c += 2; + } + assert( c == (2 << p->nLutSize) ); + // count unique cofactors + nClasses = 0; + nCofs = (1 << p->nLutSize); + for ( i = 0; i < nCofs; i++ ) + { + pTruthCof = p->uCofs[ nCofs + i ]; + for ( k = 0; k < nClasses; k++ ) + { + pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ]; + if ( Extra_TruthIsEqual( pTruthCof, pTruthClass, nVars ) ) + { + pCofClasses[k][ nCofClasses[k]++ ] = i; + break; + } + } + if ( k != nClasses ) + continue; + // not found + pCofClasses[nClasses][0] = i; + nCofClasses[nClasses] = 1; + nClasses++; + if ( nClasses > nCofs/2 ) + return 0; + } + // the number of cofactors is acceptable + nVarsNew = Extra_Base2Log( nClasses ); + assert( nVarsNew < p->nLutSize ); + // create the remainder truth table + // for each class of cofactors, multiply cofactor truth table by its code + Extra_TruthClear( p->uTruth, nVars ); + for ( k = 0; k < nClasses; k++ ) + { + pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ]; + for ( v = 0; v < nVarsNew; v++ ) + if ( k & (1 << v) ) + Extra_TruthAnd( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars ); + else + Extra_TruthSharp( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars ); + Extra_TruthOr( p->uTruth, p->uTruth, pTruthClass, nVars ); + } + // create nodes + pTruth = p->uCofs[0]; + for ( v = 0; v < nVarsNew; v++ ) + { + Extra_TruthClear( pTruth, p->nLutSize ); + for ( k = 0; k < nClasses; k++ ) + if ( k & (1 << v) ) + for ( i = 0; i < nCofClasses[k]; i++ ) + { + pTruthCof = p->uCofs[1]; + Extra_TruthFill( pTruthCof, p->nLutSize ); + for ( w = 0; w < p->nLutSize; w++ ) + if ( pCofClasses[k][i] & (1 << (p->nLutSize-1-w)) ) + Extra_TruthAnd( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize ); + else + Extra_TruthSharp( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize ); + Extra_TruthOr( pTruth, pTruth, pTruthCof, p->nLutSize ); + } + // implement the node + pObjNew = Abc_NtkCreateNode( pNtk ); + for ( i = 0; i < p->nLutSize; i++ ) + { + pFanin = Vec_PtrEntry( p->vLeaves, p->pBSet[i] ); + Abc_ObjAddFanin( pObjNew, pFanin ); + } + // create the function + pObjNew->pData = Abc_SopCreateFromTruth( pNtk->pManFunc, p->nLutSize, pTruth ); // need ISOP + pObjNew->Level = Abc_NodeGetLevel( pObjNew ); + pNodesNew[v] = pObjNew; + } + // put the new nodes back into the list + for ( v = 0; v < nVarsNew; v++ ) + Vec_PtrWriteEntry( p->vLeaves, p->pBSet[v], pNodesNew[v] ); + // compute the variables that should be removed + uPhase = 0; + for ( v = nVarsNew; v < p->nLutSize; v++ ) + uPhase |= (1 << p->pBSet[v]); + // remove entries from the array + Abc_NodeLeavesRemove( p->vLeaves, uPhase, nVars ); + // update truth table + Extra_TruthShrink( p->uCofs[0], p->uTruth, nVars - p->nLutSize + nVarsNew, nVars, ((1 << nVars) - 1) & ~uPhase ); + Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars ); + assert( !Extra_TruthVarInSupport( p->uTruth, nVars, nVars - p->nLutSize + nVarsNew ) ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcMap.c b/abc70930/src/base/abci/abcMap.c new file mode 100644 index 00000000..d4d50923 --- /dev/null +++ b/abc70930/src/base/abci/abcMap.c @@ -0,0 +1,657 @@ +/**CFile**************************************************************** + + FileName [abcMap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface with the SC mapping package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +#include "mio.h" +#include "mapper.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose ); +static Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk ); +static Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ); +static Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ); +static Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ); + +static Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk ); +static void Abc_NodeSuperChoice( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ); +static void Abc_NodeFromMapCutPhase( Abc_Ntk_t * pNtkNew, Map_Cut_t * pCut, int fPhase ); +static Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Interface with the mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, int fSwitching, int fVerbose ) +{ + int fShowSwitching = 1; + Abc_Ntk_t * pNtkNew; + Map_Man_t * pMan; + Vec_Int_t * vSwitching; + float * pSwitching = NULL; + int clk; + + assert( Abc_NtkIsStrash(pNtk) ); + + // check that the library is available + if ( Abc_FrameReadLibGen() == NULL ) + { + printf( "The current library is not available.\n" ); + return 0; + } + + // derive the supergate library + if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() ) + { + printf( "A simple supergate library is derived from gate library \"%s\".\n", + Mio_LibraryReadName(Abc_FrameReadLibGen()) ); + Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() ); + } + + // print a warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Performing mapping with choices.\n" ); + + // compute switching activity + fShowSwitching |= fSwitching; + if ( fShowSwitching ) + { + extern Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ); + vSwitching = Sim_NtkComputeSwitching( pNtk, 4096 ); + pSwitching = (float *)vSwitching->pArray; + } + + // perform the mapping + pMan = Abc_NtkToMap( pNtk, DelayTarget, fRecovery, pSwitching, fVerbose ); + if ( pSwitching ) Vec_IntFree( vSwitching ); + if ( pMan == NULL ) + return NULL; +clk = clock(); + Map_ManSetSwitching( pMan, fSwitching ); + if ( !Map_Mapping( pMan ) ) + { + Map_ManFree( pMan ); + return NULL; + } +// Map_ManPrintStatsToFile( pNtk->pSpec, Map_ManReadAreaFinal(pMan), Map_ManReadRequiredGlo(pMan), clock()-clk ); + + // reconstruct the network after mapping + pNtkNew = Abc_NtkFromMap( pMan, pNtk ); + if ( pNtkNew == NULL ) + return NULL; + Map_ManFree( pMan ); + + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkMap: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Load the network into manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose ) +{ + Map_Man_t * pMan; + ProgressBar * pProgress; + Map_Node_t * pNodeMap; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pFanin, * pPrev; + int i; + + assert( Abc_NtkIsStrash(pNtk) ); + + // start the mapping manager and set its parameters + pMan = Map_ManCreate( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk), Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk), fVerbose ); + if ( pMan == NULL ) + return NULL; + Map_ManSetAreaRecovery( pMan, fRecovery ); + Map_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) ); + Map_ManSetDelayTarget( pMan, (float)DelayTarget ); + Map_ManSetInputArrivals( pMan, (Map_Time_t *)Abc_NtkGetCiArrivalTimes(pNtk) ); + + // create PIs and remember them in the old nodes + Abc_NtkCleanCopy( pNtk ); + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Map_ManReadConst1(pMan); + Abc_NtkForEachCi( pNtk, pNode, i ) + { + pNodeMap = Map_ManReadInputs(pMan)[i]; + pNode->pCopy = (Abc_Obj_t *)pNodeMap; + if ( pSwitching ) + Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); + } + + // load the AIG into the mapper + vNodes = Abc_AigDfs( pNtk, 0, 0 ); + pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // add the node to the mapper + pNodeMap = Map_NodeAnd( pMan, + Map_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), + Map_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); + assert( pNode->pCopy == NULL ); + // remember the node + pNode->pCopy = (Abc_Obj_t *)pNodeMap; + if ( pSwitching ) + Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); + // set up the choice node + if ( Abc_AigNodeIsChoice( pNode ) ) + for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) + { + Map_NodeSetNextE( (Map_Node_t *)pPrev->pCopy, (Map_Node_t *)pFanin->pCopy ); + Map_NodeSetRepr( (Map_Node_t *)pFanin->pCopy, (Map_Node_t *)pNode->pCopy ); + } + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + + // set the primary outputs in the required phase + Abc_NtkForEachCo( pNtk, pNode, i ) + Map_ManReadOutputs(pMan)[i] = Map_NotCond( (Map_Node_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Creates the mapped network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtkNew; + Map_Node_t * pNodeMap; + Abc_Obj_t * pNode, * pNodeNew; + int i, nDupGates; + // create the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_MAP ); + // make the mapper point to the new network + Map_ManCleanData( pMan ); + Abc_NtkForEachCi( pNtk, pNode, i ) + Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy ); + // assign the mapping of the required phase to the POs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNodeMap = Map_ManReadOutputs(pMan)[i]; + pNodeNew = Abc_NodeFromMap_rec( pNtkNew, Map_Regular(pNodeMap), !Map_IsComplement(pNodeMap) ); + assert( !Abc_ObjIsComplement(pNodeNew) ); + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + } + Extra_ProgressBarStop( pProgress ); + // decouple the PO driver nodes to reduce the number of levels + nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); +// if ( nDupGates && Map_ManReadVerbose(pMan) ) +// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Constructs the nodes corrresponding to one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ) +{ + Abc_Obj_t * pNodeNew, * pNodeInv; + + // check the case of constant node + if ( Map_NodeIsConst(pNodeMap) ) + return fPhase? Abc_NtkCreateNodeConst1(pNtkNew) : Abc_NtkCreateNodeConst0(pNtkNew); + + // check if the phase is already implemented + pNodeNew = (Abc_Obj_t *)Map_NodeReadData( pNodeMap, fPhase ); + if ( pNodeNew ) + return pNodeNew; + + // implement the node if the best cut is assigned + if ( Map_NodeReadCutBest(pNodeMap, fPhase) != NULL ) + return Abc_NodeFromMapPhase_rec( pNtkNew, pNodeMap, fPhase ); + + // if the cut is not assigned, implement the node + assert( Map_NodeReadCutBest(pNodeMap, !fPhase) != NULL || Map_NodeIsConst(pNodeMap) ); + pNodeNew = Abc_NodeFromMapPhase_rec( pNtkNew, pNodeMap, !fPhase ); + + // add the inverter + pNodeInv = Abc_NtkCreateNode( pNtkNew ); + Abc_ObjAddFanin( pNodeInv, pNodeNew ); + pNodeInv->pData = Mio_LibraryReadInv(Map_ManReadGenLib(Map_NodeReadMan(pNodeMap))); + + // set the inverter + Map_NodeSetData( pNodeMap, fPhase, (char *)pNodeInv ); + return pNodeInv; +} + +/**Function************************************************************* + + Synopsis [Constructs the nodes corrresponding to one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ) +{ + Abc_Obj_t * pNodePIs[10]; + Abc_Obj_t * pNodeNew; + Map_Node_t ** ppLeaves; + Map_Cut_t * pCutBest; + Map_Super_t * pSuperBest; + unsigned uPhaseBest; + int i, fInvPin, nLeaves; + + // make sure the node can be implemented in this phase + assert( Map_NodeReadCutBest(pNodeMap, fPhase) != NULL || Map_NodeIsConst(pNodeMap) ); + // check if the phase is already implemented + pNodeNew = (Abc_Obj_t *)Map_NodeReadData( pNodeMap, fPhase ); + if ( pNodeNew ) + return pNodeNew; + + // get the information about the best cut + pCutBest = Map_NodeReadCutBest( pNodeMap, fPhase ); + pSuperBest = Map_CutReadSuperBest( pCutBest, fPhase ); + uPhaseBest = Map_CutReadPhaseBest( pCutBest, fPhase ); + nLeaves = Map_CutReadLeavesNum( pCutBest ); + ppLeaves = Map_CutReadLeaves( pCutBest ); + + // collect the PI nodes + for ( i = 0; i < nLeaves; i++ ) + { + fInvPin = ((uPhaseBest & (1 << i)) > 0); + pNodePIs[i] = Abc_NodeFromMap_rec( pNtkNew, ppLeaves[i], !fInvPin ); + assert( pNodePIs[i] != NULL ); + } + + // implement the supergate + pNodeNew = Abc_NodeFromMapSuper_rec( pNtkNew, pNodeMap, pSuperBest, pNodePIs, nLeaves ); + Map_NodeSetData( pNodeMap, fPhase, (char *)pNodeNew ); + return pNodeNew; +} + +/**Function************************************************************* + + Synopsis [Constructs the nodes corrresponding to one supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ) +{ + Mio_Gate_t * pRoot; + Map_Super_t ** ppFanins; + Abc_Obj_t * pNodeNew, * pNodeFanin; + int nFanins, Number, i; + + // get the parameters of the supergate + pRoot = Map_SuperReadRoot(pSuper); + if ( pRoot == NULL ) + { + Number = Map_SuperReadNum(pSuper); + if ( Number < nNodePis ) + { + return pNodePis[Number]; + } + else + { +// assert( 0 ); + /* It might happen that a super gate with 5 inputs is constructed that + * actually depends only on the first four variables; i.e the fifth is a + * don't care -- in that case we connect constant node for the fifth + * (since the cut only has 4 variables). An interesting question is what + * if the first variable (and not the fifth one is the redundant one; + * can that happen?) */ + return Abc_NtkCreateNodeConst0(pNtkNew); + } + } + + // get information about the fanins of the supergate + nFanins = Map_SuperReadFaninNum( pSuper ); + ppFanins = Map_SuperReadFanins( pSuper ); + // create a new node with these fanins + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + for ( i = 0; i < nFanins; i++ ) + { + pNodeFanin = Abc_NodeFromMapSuper_rec( pNtkNew, pNodeMap, ppFanins[i], pNodePis, nNodePis ); + Abc_ObjAddFanin( pNodeNew, pNodeFanin ); + } + pNodeNew->pData = pRoot; + return pNodeNew; +} + + + + + +/**Function************************************************************* + + Synopsis [Interface with the mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + + Map_Man_t * pMan; + + assert( Abc_NtkIsStrash(pNtk) ); + + // check that the library is available + if ( Abc_FrameReadLibGen() == NULL ) + { + printf( "The current library is not available.\n" ); + return 0; + } + + // derive the supergate library + if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() ) + { + printf( "A simple supergate library is derived from gate library \"%s\".\n", + Mio_LibraryReadName(Abc_FrameReadLibGen()) ); + Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() ); + } + + // print a warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Performing mapping with choices.\n" ); + + // perform the mapping + pMan = Abc_NtkToMap( pNtk, -1, 1, NULL, 0 ); + if ( pMan == NULL ) + return NULL; + if ( !Map_Mapping( pMan ) ) + { + Map_ManFree( pMan ); + return NULL; + } + + // reconstruct the network after mapping + pNtkNew = Abc_NtkFromMapSuperChoice( pMan, pNtk ); + if ( pNtkNew == NULL ) + return NULL; + Map_ManFree( pMan ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkMap: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Creates the mapped network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); + ProgressBar * pProgress; + Abc_Ntk_t * pNtkNew, * pNtkNew2; + Abc_Obj_t * pNode; + int i; + + // save the pointer to the mapped nodes + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pNext = pNode->pCopy; + Abc_NtkForEachPo( pNtk, pNode, i ) + pNode->pNext = pNode->pCopy; + Abc_NtkForEachNode( pNtk, pNode, i ) + pNode->pNext = pNode->pCopy; + + // duplicate the network + pNtkNew2 = Abc_NtkDup( pNtk ); + pNtkNew = Abc_NtkMulti( pNtkNew2, 0, 20, 0, 0, 1, 0 ); + if ( !Abc_NtkBddToSop( pNtkNew, 0 ) ) + { + printf( "Abc_NtkFromMapSuperChoice(): Converting to SOPs has failed.\n" ); + return NULL; + } + + // set the old network to point to the new network + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = pNode->pCopy->pCopy; + Abc_NtkForEachPo( pNtk, pNode, i ) + pNode->pCopy = pNode->pCopy->pCopy; + Abc_NtkForEachNode( pNtk, pNode, i ) + pNode->pCopy = pNode->pCopy->pCopy; + Abc_NtkDelete( pNtkNew2 ); + + // set the pointers from the mapper to the new nodes + Abc_NtkForEachCi( pNtk, pNode, i ) + { + Map_NodeSetData( Map_ManReadInputs(pMan)[i], 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) ); + Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy ); + } + Abc_NtkForEachNode( pNtk, pNode, i ) + { +// if ( Abc_NodeIsConst(pNode) ) +// continue; + Map_NodeSetData( (Map_Node_t *)pNode->pNext, 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) ); + Map_NodeSetData( (Map_Node_t *)pNode->pNext, 1, (char *)pNode->pCopy ); + } + + // assign the mapping of the required phase to the POs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); +// if ( Abc_NodeIsConst(pNode) ) +// continue; + Abc_NodeSuperChoice( pNtkNew, pNode ); + } + Extra_ProgressBarStop( pProgress ); + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Creates the mapped network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSuperChoice( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ) +{ + Map_Node_t * pMapNode = (Map_Node_t *)pNode->pNext; + Map_Cut_t * pCuts, * pTemp; + + pCuts = Map_NodeReadCuts(pMapNode); + for ( pTemp = Map_CutReadNext(pCuts); pTemp; pTemp = Map_CutReadNext(pTemp) ) + { + Abc_NodeFromMapCutPhase( pNtkNew, pTemp, 0 ); + Abc_NodeFromMapCutPhase( pNtkNew, pTemp, 1 ); + } +} + + +/**Function************************************************************* + + Synopsis [Constructs the nodes corrresponding to one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeFromMapCutPhase( Abc_Ntk_t * pNtkNew, Map_Cut_t * pCut, int fPhase ) +{ + Abc_Obj_t * pNodePIs[10]; + Map_Node_t ** ppLeaves; + Map_Super_t * pSuperBest; + unsigned uPhaseBest; + int i, fInvPin, nLeaves; + + pSuperBest = Map_CutReadSuperBest( pCut, fPhase ); + if ( pSuperBest == NULL ) + return; + + // get the information about the best cut + uPhaseBest = Map_CutReadPhaseBest( pCut, fPhase ); + nLeaves = Map_CutReadLeavesNum( pCut ); + ppLeaves = Map_CutReadLeaves( pCut ); + + // collect the PI nodes + for ( i = 0; i < nLeaves; i++ ) + { + fInvPin = ((uPhaseBest & (1 << i)) > 0); + pNodePIs[i] = (Abc_Obj_t *)Map_NodeReadData( ppLeaves[i], !fInvPin ); + assert( pNodePIs[i] != NULL ); + } + + // implement the supergate + Abc_NodeFromMapSuperChoice_rec( pNtkNew, pSuperBest, pNodePIs, nLeaves ); +} + + +/**Function************************************************************* + + Synopsis [Constructs the nodes corrresponding to one supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ) +{ + Mio_Gate_t * pRoot; + Map_Super_t ** ppFanins; + Abc_Obj_t * pNodeNew, * pNodeFanin; + int nFanins, Number, i; + + // get the parameters of the supergate + pRoot = Map_SuperReadRoot(pSuper); + if ( pRoot == NULL ) + { + Number = Map_SuperReadNum(pSuper); + if ( Number < nNodePis ) + { + return pNodePis[Number]; + } + else + { +// assert( 0 ); + /* It might happen that a super gate with 5 inputs is constructed that + * actually depends only on the first four variables; i.e the fifth is a + * don't care -- in that case we connect constant node for the fifth + * (since the cut only has 4 variables). An interesting question is what + * if the first variable (and not the fifth one is the redundant one; + * can that happen?) */ + return Abc_NtkCreateNodeConst0(pNtkNew); + } + } + + // get information about the fanins of the supergate + nFanins = Map_SuperReadFaninNum( pSuper ); + ppFanins = Map_SuperReadFanins( pSuper ); + // create a new node with these fanins + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + for ( i = 0; i < nFanins; i++ ) + { + pNodeFanin = Abc_NodeFromMapSuperChoice_rec( pNtkNew, ppFanins[i], pNodePis, nNodePis ); + Abc_ObjAddFanin( pNodeNew, pNodeFanin ); + } + pNodeNew->pData = Abc_SopRegister( pNtkNew->pManFunc, Mio_GateReadSop(pRoot) ); + return pNodeNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcMeasure.c b/abc70930/src/base/abci/abcMeasure.c new file mode 100644 index 00000000..6604a0c4 --- /dev/null +++ b/abc70930/src/base/abci/abcMeasure.c @@ -0,0 +1,478 @@ +/**CFile**************************************************************** + + FileName [abc_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintMeasures( unsigned * pTruth, int nVars ) +{ + unsigned uCofs[10][32]; + int i, k, nOnes; + + // total pairs + nOnes = Kit_TruthCountOnes( uCofs[0], nVars ); + printf( "Total = %d.\n", nOnes * ((1 << nVars) - nOnes) ); + + // print measures for individual variables + for ( i = 0; i < nVars; i++ ) + { + Kit_TruthUniqueNew( uCofs[0], pTruth, nVars, i ); + nOnes = Kit_TruthCountOnes( uCofs[0], nVars ); + printf( "%7d ", nOnes ); + } + printf( "\n" ); + + // consider pairs + for ( i = 0; i < nVars; i++ ) + for ( k = 0; k < nVars; k++ ) + { + if ( i == k ) + { + printf( " " ); + continue; + } + Kit_TruthCofactor0New( uCofs[0], pTruth, nVars, i ); + Kit_TruthCofactor1New( uCofs[1], pTruth, nVars, i ); + + Kit_TruthCofactor0New( uCofs[2], uCofs[0], nVars, k ); // 00 + Kit_TruthCofactor1New( uCofs[3], uCofs[0], nVars, k ); // 01 + Kit_TruthCofactor0New( uCofs[4], uCofs[1], nVars, k ); // 10 + Kit_TruthCofactor1New( uCofs[5], uCofs[1], nVars, k ); // 11 + + Kit_TruthAndPhase( uCofs[6], uCofs[2], uCofs[5], nVars, 0, 1 ); // 00 & 11' + Kit_TruthAndPhase( uCofs[7], uCofs[2], uCofs[5], nVars, 1, 0 ); // 00' & 11 + Kit_TruthAndPhase( uCofs[8], uCofs[3], uCofs[4], nVars, 0, 1 ); // 01 & 10' + Kit_TruthAndPhase( uCofs[9], uCofs[3], uCofs[4], nVars, 1, 0 ); // 01' & 10 + + nOnes = Kit_TruthCountOnes( uCofs[6], nVars ) + + Kit_TruthCountOnes( uCofs[7], nVars ) + + Kit_TruthCountOnes( uCofs[8], nVars ) + + Kit_TruthCountOnes( uCofs[9], nVars ); + + printf( "%7d ", nOnes ); + if ( k == nVars - 1 ) + printf( "\n" ); + } + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Ntk4VarObjPrint_rec( Abc_Obj_t * pObj ) +{ + if ( pObj == Abc_AigConst1(pObj->pNtk) ) + { + printf( "1" ); + return; + } + if ( Abc_ObjIsPi(pObj) ) + { + printf( "%c", pObj->Id - 1 + 'a' ); + return; + } + + printf( "(" ); + Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) ); + if ( Abc_ObjFaninC0(pObj) ) + printf( "\'" ); + Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin1(pObj) ); + if ( Abc_ObjFaninC1(pObj) ) + printf( "\'" ); + printf( ")" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Abc_Ntk4VarObj( Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pObj; + unsigned uTruth0, uTruth1; + int i; + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + uTruth0 = (unsigned)(Abc_ObjFanin0(pObj)->pCopy); + uTruth1 = (unsigned)(Abc_ObjFanin1(pObj)->pCopy); + if ( Abc_ObjFaninC0(pObj) ) + uTruth0 = ~uTruth0; + if ( Abc_ObjFaninC1(pObj) ) + uTruth1 = ~uTruth1; + pObj->pCopy = (void *)(uTruth0 & uTruth1); + } + return uTruth0 & uTruth1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Ntk4VarTable( Abc_Ntk_t * pNtk ) +{ + static unsigned u4VarTruths[4] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00 }; + static unsigned u4VarTts[222] = { + 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, + 0x001b, 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, + 0x007f, 0x00ff, 0x0116, 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, + 0x012c, 0x012d, 0x012f, 0x013c, 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016a, + 0x016b, 0x016e, 0x016f, 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0186, + 0x0187, 0x0189, 0x018b, 0x018f, 0x0196, 0x0197, 0x0198, 0x0199, 0x019a, 0x019b, + 0x019e, 0x019f, 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x01af, + 0x01bc, 0x01bd, 0x01be, 0x01bf, 0x01e8, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, + 0x01fe, 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, + 0x035e, 0x035f, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, + 0x037c, 0x037d, 0x037e, 0x03c0, 0x03c1, 0x03c3, 0x03c5, 0x03c6, 0x03c7, 0x03cf, + 0x03d4, 0x03d5, 0x03d6, 0x03d7, 0x03d8, 0x03d9, 0x03db, 0x03dc, 0x03dd, 0x03de, + 0x03fc, 0x0660, 0x0661, 0x0662, 0x0663, 0x0666, 0x0667, 0x0669, 0x066b, 0x066f, + 0x0672, 0x0673, 0x0676, 0x0678, 0x0679, 0x067a, 0x067b, 0x067e, 0x0690, 0x0691, + 0x0693, 0x0696, 0x0697, 0x069f, 0x06b0, 0x06b1, 0x06b2, 0x06b3, 0x06b4, 0x06b5, + 0x06b6, 0x06b7, 0x06b9, 0x06bd, 0x06f0, 0x06f1, 0x06f2, 0x06f6, 0x06f9, 0x0776, + 0x0778, 0x0779, 0x077a, 0x077e, 0x07b0, 0x07b1, 0x07b4, 0x07b5, 0x07b6, 0x07bc, + 0x07e0, 0x07e1, 0x07e2, 0x07e3, 0x07e6, 0x07e9, 0x07f0, 0x07f1, 0x07f2, 0x07f8, + 0x0ff0, 0x1668, 0x1669, 0x166a, 0x166b, 0x166e, 0x167e, 0x1681, 0x1683, 0x1686, + 0x1687, 0x1689, 0x168b, 0x168e, 0x1696, 0x1697, 0x1698, 0x1699, 0x169a, 0x169b, + 0x169e, 0x16a9, 0x16ac, 0x16ad, 0x16bc, 0x16e9, 0x177e, 0x178e, 0x1796, 0x1798, + 0x179a, 0x17ac, 0x17e8, 0x18e7, 0x19e1, 0x19e3, 0x19e6, 0x1bd8, 0x1be4, 0x1ee1, + 0x3cc3, 0x6996 + }; + int Counters[222] = {0}; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + unsigned uTruth; + int i, k, Count = 0; + + unsigned short * puCanons = NULL; + unsigned char * puMap = NULL; + Extra_Truth4VarNPN( &puCanons, NULL, NULL, &puMap ); + + // set elementary truth tables + assert( Abc_NtkPiNum(pNtk) == 4 ); + Abc_AigConst1(pNtk)->pCopy = (void *)0xFFFFFFFF; + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = (void *)u4VarTruths[i]; + + // create truth tables + Abc_NtkForEachPo( pNtk, pObj, i ) + { + vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); + if ( Vec_PtrSize(vNodes) == 0 ) + uTruth = (unsigned)Abc_ObjFanin0(pObj)->pCopy; + else + uTruth = Abc_Ntk4VarObj( vNodes ); + + if ( (uTruth & 0xFFFF) < (~uTruth & 0xFFFF) ) + uTruth = uTruth & 0xFFFF; + else + uTruth = ~uTruth & 0xFFFF; + + for ( k = 0; k < 222; k++ ) + if ( u4VarTts[k] == uTruth ) + break; + if ( k == 222 ) + continue; +/* +// if ( uTruth == 1725 ) + if ( k == 96 ) + { + printf( "%d : ", Vec_PtrSize(vNodes) ); + Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) ); + printf( "\n" ); + } +*/ + Counters[k]++; + +// Counters[ puMap[uTruth & 0xFFFF] ]++; + Vec_PtrFree( vNodes ); + } + free( puCanons ); + free( puMap ); + + Count = 0; + for ( k = 0; k < 222; k++ ) + { + printf( "%d/%x/%d ", k, u4VarTts[k], Counters[k] ); + Count += Counters[k]; + } + printf( " Total = %d\n", Count ); +} + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if there are no more than 2 unique cofactors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkPrintOneDecompCheckCofList( unsigned * uCofs, int nCofs ) +{ + int i, Ind = -1; + assert( nCofs > 2 ); + for ( i = 1; i < nCofs; i++ ) + { + if ( uCofs[i] == uCofs[0] ) + continue; + if ( Ind == -1 ) + { + Ind = i; + continue; + } + if ( uCofs[i] == uCofs[Ind] ) + continue; + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks all cofactors with the given mask.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkPrintOneDecompCheck( unsigned * uCofs, int nCofs, unsigned uMask ) +{ + unsigned pCofs[32][32]; + int nCofNums[32] = {0}; + int uMasks[32]; + int nGroups = 0; + int i, k; + for ( i = 0; i < nCofs; i++ ) + { + // find group of this cof + for ( k = 0; k < nGroups; k++ ) + if ( (int)(i & uMask) == uMasks[k] ) + break; + if ( k == nGroups ) + { + uMasks[k] = (i & uMask); + nGroups++; + } + // save cof in the group + pCofs[k][ nCofNums[k]++ ] = uCofs[i]; + assert( nCofNums[k] <= 32 ); + assert( nGroups <= 32 ); + } + // check the groups + for ( i = 0; i < nGroups; i++ ) + if ( !Abc_NtkPrintOneDecompCheckCofList(pCofs[i], nCofNums[i]) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintOneDecomp_rec( unsigned * uCofs, int nCofs, int nVars, unsigned uMask, int * pBestSize, unsigned * puBestMask ) +{ + unsigned uMaskNew; + int v, last, Counter = 0; + // find the last variable in the mask + for ( v = 0; v < nVars; v++ ) + if ( uMask & (1<<v) ) + { + last = v; + Counter++; + } + if ( Counter > 3 ) + return; + // try adding one variable after the last + for ( v = last + 1; v < nVars; v++ ) + { + uMaskNew = uMask | (1 << v); + if ( !Abc_NtkPrintOneDecompCheck( uCofs, nCofs, uMaskNew ) ) + continue; + if ( *pBestSize < Counter + 1 ) + { + *pBestSize = Counter + 1; + *puBestMask = uMaskNew; + } + // try other masks + Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, uMaskNew, pBestSize, puBestMask ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintOneDecomp( unsigned * pTruth, int nVars ) +{ + int BoundSet = 6; + unsigned uCofs[64], uMask, uBestMask = 0; + int i, nCofs, nMints, nMintShift, BestSize = 1; + + assert( nVars > BoundSet ); + assert( nVars <= BoundSet + 5 ); // at most 5 variable cofactors + + // collect the cofactors + nCofs = (1 << BoundSet); + nMints = (1 << (nVars-BoundSet)); + nMintShift = 0; + uMask = Kit_CubeMask( nMints ); + for ( i = 0; i < nCofs; i++ ) + { + uCofs[i] = (pTruth[nMintShift/32] >> (nMintShift % 32)) & uMask; + nMintShift += nMints; + } + + // try removing variables + for ( i = 0; i < BoundSet; i++ ) + Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, (1 << i), &BestSize, &uBestMask ); + + printf( "Best size = %d ", BestSize ); + printf( "Best mask = " ); + Extra_PrintBinary( stdout, &uBestMask, nVars ); + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintOneDec( unsigned * pTruth, int nVars ) +{ + unsigned uCof[(1<<11)], * pOut = uCof, * pIn = pTruth, * pTemp; + int nDiffs[16]; + int Order[16]; + int i, fChange, Temp, Counter; + + // find the ordering + for ( i = 0; i < nVars; i++ ) + { + Kit_TruthUniqueNew( uCof, pTruth, nVars, i ); + nDiffs[i] = Kit_TruthCountOnes( uCof, nVars ); + Order[i] = i; + } + + // permute truth table to least active variable first + Counter = 0; + do { + fChange = 0; + for ( i = 0; i < nVars-1; i++ ) + { + if ( nDiffs[i] <= nDiffs[i+1] ) + continue; + fChange = 1; + Counter++; + + Temp = nDiffs[i]; + nDiffs[i] = nDiffs[i+1]; + nDiffs[i+1] = Temp; + + Temp = Order[i]; + Order[i] = Order[i+1]; + Order[i+1] = Temp; + + Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + } while ( fChange ); + + // swap if it was moved an even number of times + if ( Counter & 1 ) + Extra_TruthCopy( pOut, pIn, nVars ); + + // call the decomposition + Abc_NtkPrintOneDecomp( pTruth, nVars ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcMini.c b/abc70930/src/base/abci/abcMini.c new file mode 100644 index 00000000..92985423 --- /dev/null +++ b/abc70930/src/base/abci/abcMini.c @@ -0,0 +1,153 @@ +/**CFile**************************************************************** + + FileName [abcMini.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface to the minimalistic AIG package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMini.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Hop_Man_t * Abc_NtkToMini( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkFromMini( Abc_Ntk_t * pNtkOld, Hop_Man_t * pMan ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiniBalance( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkAig; + Hop_Man_t * pMan, * pTemp; + assert( Abc_NtkIsStrash(pNtk) ); + // convert to the AIG manager + pMan = Abc_NtkToMini( pNtk ); + if ( pMan == NULL ) + return NULL; + if ( !Hop_ManCheck( pMan ) ) + { + printf( "AIG check has failed.\n" ); + Hop_ManStop( pMan ); + return NULL; + } + // perform balance + Hop_ManPrintStats( pMan ); +// Hop_ManDumpBlif( pMan, "aig_temp.blif" ); + pMan = Hop_ManBalance( pTemp = pMan, 1 ); + Hop_ManStop( pTemp ); + Hop_ManPrintStats( pMan ); + // convert from the AIG manager + pNtkAig = Abc_NtkFromMini( pNtk, pMan ); + if ( pNtkAig == NULL ) + return NULL; + Hop_ManStop( pMan ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkStrash: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Man_t * Abc_NtkToMini( Abc_Ntk_t * pNtk ) +{ + Hop_Man_t * pMan; + Abc_Obj_t * pObj; + int i; + // create the manager + pMan = Hop_ManStart(); + // transfer the pointers to the basic nodes + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Hop_ManConst1(pMan); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Hop_ObjCreatePi(pMan); + // perform the conversion of the internal nodes (assumes DFS ordering) + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Hop_And( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj), (Hop_Obj_t *)Abc_ObjChild1Copy(pObj) ); + // create the POs + Abc_NtkForEachCo( pNtk, pObj, i ) + Hop_ObjCreatePo( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj) ); + Hop_ManCleanup( pMan ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromMini( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Hop_Obj_t * pObj; + int i; + // perform strashing + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Hop_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); + Hop_ManForEachPi( pMan, pObj, i ) + pObj->pData = Abc_NtkCi(pNtkNew, i); + // rebuild the AIG + vNodes = Hop_ManDfs( pMan ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); + Vec_PtrFree( vNodes ); + // connect the PO nodes + Hop_ManForEachPo( pMan, pObj, i ) + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Hop_ObjChild0Copy(pObj) ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkFromMini(): Network check has failed.\n" ); + return pNtkNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcMiter.c b/abc70930/src/base/abci/abcMiter.c new file mode 100644 index 00000000..adda6653 --- /dev/null +++ b/abc70930/src/base/abci/abcMiter.c @@ -0,0 +1,1138 @@ +/**CFile**************************************************************** + + FileName [abcMiter.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to derive the miter of two circuits.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMiter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ); +static void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ); +static void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter ); +static void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ); +static void Abc_NtkAddFrame( Abc_Ntk_t * pNetNew, Abc_Ntk_t * pNet, int iFrame ); + +// to be exported +typedef void (*AddFrameMapping)( Abc_Obj_t*, Abc_Obj_t*, int, void*); +extern Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg ); +static void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the miter of two networks.] + + Description [Preprocesses the networks to make sure that they are strashed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ) +{ + Abc_Ntk_t * pTemp = NULL; + int fRemove1, fRemove2; + assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); + // check that the networks have the same PIs/POs/latches + if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 0, fComb ) ) + return NULL; + // make sure the circuits are strashed + fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0, 0)); + fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0, 0)); + if ( pNtk1 && pNtk2 ) + pTemp = Abc_NtkMiterInt( pNtk1, pNtk2, fComb, nPartSize ); + if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); + if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [Derives the miter of two sequential networks.] + + Description [Assumes that the networks are strashed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ) +{ + char Buffer[1000]; + Abc_Ntk_t * pNtkMiter; + + assert( Abc_NtkIsStrash(pNtk1) ); + assert( Abc_NtkIsStrash(pNtk2) ); + + // start the new network + pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); + pNtkMiter->pName = Extra_UtilStrsav(Buffer); + + // perform strashing + Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize ); + Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); + Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); + Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize ); + Abc_AigCleanup(pNtkMiter->pManFunc); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkMiter ) ) + { + printf( "Abc_NtkMiter: The network check has failed.\n" ); + Abc_NtkDelete( pNtkMiter ); + return NULL; + } + return pNtkMiter; +} + +/**Function************************************************************* + + Synopsis [Prepares the network for mitering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ) +{ + Abc_Obj_t * pObj, * pObjNew; + int i; + // clean the copy field in all objects +// Abc_NtkCleanCopy( pNtk1 ); +// Abc_NtkCleanCopy( pNtk2 ); + Abc_AigConst1(pNtk1)->pCopy = Abc_AigConst1(pNtkMiter); + Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtkMiter); + + if ( fComb ) + { + // create new PIs and remember them in the old PIs + Abc_NtkForEachCi( pNtk1, pObj, i ) + { + pObjNew = Abc_NtkCreatePi( pNtkMiter ); + // remember this PI in the old PIs + pObj->pCopy = pObjNew; + pObj = Abc_NtkCi(pNtk2, i); + pObj->pCopy = pObjNew; + // add name + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); + } + if ( nPartSize <= 0 ) + { + // create the only PO + pObjNew = Abc_NtkCreatePo( pNtkMiter ); + // add the PO name + Abc_ObjAssignName( pObjNew, "miter", NULL ); + } + } + else + { + // create new PIs and remember them in the old PIs + Abc_NtkForEachPi( pNtk1, pObj, i ) + { + pObjNew = Abc_NtkCreatePi( pNtkMiter ); + // remember this PI in the old PIs + pObj->pCopy = pObjNew; + pObj = Abc_NtkPi(pNtk2, i); + pObj->pCopy = pObjNew; + // add name + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); + } + if ( nPartSize <= 0 ) + { + // create the only PO + pObjNew = Abc_NtkCreatePo( pNtkMiter ); + // add the PO name + Abc_ObjAssignName( pObjNew, "miter", NULL ); + } + // create the latches + Abc_NtkForEachLatch( pNtk1, pObj, i ) + { + pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 ); + // add names + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_1" ); + Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_1" ); + Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_1" ); + } + Abc_NtkForEachLatch( pNtk2, pObj, i ) + { + pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 ); + // add name + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_2" ); + Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_2" ); + Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_2" ); + } + } +} + +/**Function************************************************************* + + Synopsis [Performs mitering for one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsDfsOrdered(pNtk) ); + Abc_AigForEachAnd( pNtk, pNode, i ) + pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); +} + +/**Function************************************************************* + + Synopsis [Performs mitering for one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pRoot ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + // map the constant nodes + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkMiter); + // perform strashing + vNodes = Abc_NtkDfsNodes( pNtk, &pRoot, 1 ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + if ( Abc_AigNodeIsAnd(pNode) ) + pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); + Vec_PtrFree( vNodes ); +} + + +/**Function************************************************************* + + Synopsis [Finalizes the miter by adding the output part.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ) +{ + Vec_Ptr_t * vPairs; + Abc_Obj_t * pMiter, * pNode; + int i; + // collect the PO pairs from both networks + vPairs = Vec_PtrAlloc( 100 ); + if ( fComb ) + { + // collect the CO nodes for the miter + Abc_NtkForEachCo( pNtk1, pNode, i ) + { + Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); + pNode = Abc_NtkCo( pNtk2, i ); + Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); + } + } + else + { + // collect the PO nodes for the miter + Abc_NtkForEachPo( pNtk1, pNode, i ) + { + Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); + pNode = Abc_NtkPo( pNtk2, i ); + Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); + } + // connect new latches + Abc_NtkForEachLatch( pNtk1, pNode, i ) + Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) ); + Abc_NtkForEachLatch( pNtk2, pNode, i ) + Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) ); + } + // add the miter + if ( nPartSize <= 0 ) + { + pMiter = Abc_AigMiter( pNtkMiter->pManFunc, vPairs ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); + Vec_PtrFree( vPairs ); + } + else + { + char Buffer[1024]; + Vec_Ptr_t * vPairsPart; + int nParts, i, k, iCur; + assert( Vec_PtrSize(vPairs) == 2 * Abc_NtkCoNum(pNtk1) ); + // create partitions + nParts = Abc_NtkCoNum(pNtk1) / nPartSize + (int)((Abc_NtkCoNum(pNtk1) % nPartSize) > 0); + vPairsPart = Vec_PtrAlloc( nPartSize ); + for ( i = 0; i < nParts; i++ ) + { + Vec_PtrClear( vPairsPart ); + for ( k = 0; k < nPartSize; k++ ) + { + iCur = i * nPartSize + k; + if ( iCur >= Abc_NtkCoNum(pNtk1) ) + break; + Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur ) ); + Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur+1) ); + } + pMiter = Abc_AigMiter( pNtkMiter->pManFunc, vPairsPart ); + pNode = Abc_NtkCreatePo( pNtkMiter ); + Abc_ObjAddFanin( pNode, pMiter ); + // assign the name to the node + if ( nPartSize == 1 ) + sprintf( Buffer, "%s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) ); + else + sprintf( Buffer, "%d", i ); + Abc_ObjAssignName( pNode, "miter_", Buffer ); + } + Vec_PtrFree( vPairsPart ); + Vec_PtrFree( vPairs ); + } +} + + + +/**Function************************************************************* + + Synopsis [Derives the AND of two miters.] + + Description [The network should have the same names of PIs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 ) +{ + char Buffer[1000]; + Abc_Ntk_t * pNtkMiter; + Abc_Obj_t * pOutput1, * pOutput2; + Abc_Obj_t * pRoot1, * pRoot2, * pMiter; + + assert( Abc_NtkIsStrash(pNtk1) ); + assert( Abc_NtkIsStrash(pNtk2) ); + assert( 1 == Abc_NtkCoNum(pNtk1) ); + assert( 1 == Abc_NtkCoNum(pNtk2) ); + assert( 0 == Abc_NtkLatchNum(pNtk1) ); + assert( 0 == Abc_NtkLatchNum(pNtk2) ); + assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); + + // start the new network + pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); +// sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); + sprintf( Buffer, "product" ); + pNtkMiter->pName = Extra_UtilStrsav(Buffer); + + // perform strashing + Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, 1, -1 ); + Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); + Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); +// Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, 1 ); + pRoot1 = Abc_NtkPo(pNtk1,0); + pRoot2 = Abc_NtkPo(pNtk2,0); + pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot1)->pCopy, Abc_ObjFaninC0(pRoot1) ); + pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot2)->pCopy, Abc_ObjFaninC0(pRoot2) ^ fCompl2 ); + + // create the miter of the two outputs + if ( fOr ) + pMiter = Abc_AigOr( pNtkMiter->pManFunc, pOutput1, pOutput2 ); + else + pMiter = Abc_AigAnd( pNtkMiter->pManFunc, pOutput1, pOutput2 ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkMiter ) ) + { + printf( "Abc_NtkMiterAnd: The network check has failed.\n" ); + Abc_NtkDelete( pNtkMiter ); + return NULL; + } + return pNtkMiter; +} + + +/**Function************************************************************* + + Synopsis [Derives the cofactor of the miter w.r.t. the set of vars.] + + Description [The array of variable values contains -1/0/1 for each PI. + -1 means this PI remains, 0/1 means this PI is set to 0/1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ) +{ + char Buffer[1000]; + Abc_Ntk_t * pNtkMiter; + Abc_Obj_t * pRoot, * pOutput1; + int Value, i; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( 1 == Abc_NtkCoNum(pNtk) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + + // start the new network + pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + sprintf( Buffer, "%s_miter", pNtk->pName ); + pNtkMiter->pName = Extra_UtilStrsav(Buffer); + + // get the root output + pRoot = Abc_NtkCo( pNtk, 0 ); + + // perform strashing + Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 ); + // set the first cofactor + Vec_IntForEachEntry( vPiValues, Value, i ) + { + if ( Value == -1 ) + continue; + if ( Value == 0 ) + { + Abc_NtkCi(pNtk, i)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); + continue; + } + if ( Value == 1 ) + { + Abc_NtkCi(pNtk, i)->pCopy = Abc_AigConst1(pNtkMiter); + continue; + } + assert( 0 ); + } + // add the first cofactor + Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); + + // save the output + pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); + + // create the miter of the two outputs + Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pOutput1 ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkMiter ) ) + { + printf( "Abc_NtkMiterCofactor: The network check has failed.\n" ); + Abc_NtkDelete( pNtkMiter ); + return NULL; + } + return pNtkMiter; +} +/**Function************************************************************* + + Synopsis [Derives the miter of two cofactors of one output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 ) +{ + char Buffer[1000]; + Abc_Ntk_t * pNtkMiter; + Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( Out < Abc_NtkCoNum(pNtk) ); + assert( In1 < Abc_NtkCiNum(pNtk) ); + assert( In2 < Abc_NtkCiNum(pNtk) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + + // start the new network + pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + sprintf( Buffer, "%s_miter", Abc_ObjName(Abc_NtkCo(pNtk, Out)) ); + pNtkMiter->pName = Extra_UtilStrsav(Buffer); + + // get the root output + pRoot = Abc_NtkCo( pNtk, Out ); + + // perform strashing + Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 ); + // set the first cofactor + Abc_NtkCi(pNtk, In1)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); + if ( In2 >= 0 ) + Abc_NtkCi(pNtk, In2)->pCopy = Abc_AigConst1(pNtkMiter); + // add the first cofactor + Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); + + // save the output + pOutput1 = Abc_ObjFanin0(pRoot)->pCopy; + + // set the second cofactor + Abc_NtkCi(pNtk, In1)->pCopy = Abc_AigConst1(pNtkMiter); + if ( In2 >= 0 ) + Abc_NtkCi(pNtk, In2)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); + // add the second cofactor + Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); + + // save the output + pOutput2 = Abc_ObjFanin0(pRoot)->pCopy; + + // create the miter of the two outputs + pMiter = Abc_AigXor( pNtkMiter->pManFunc, pOutput1, pOutput2 ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkMiter ) ) + { + printf( "Abc_NtkMiter: The network check has failed.\n" ); + Abc_NtkDelete( pNtkMiter ); + return NULL; + } + return pNtkMiter; +} + + +/**Function************************************************************* + + Synopsis [Derives the miter of two cofactors of one output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist ) +{ + Abc_Ntk_t * pNtkMiter; + Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( 1 == Abc_NtkCoNum(pNtk) ); + assert( In < Abc_NtkCiNum(pNtk) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + + // start the new network + pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtkMiter->pName = Extra_UtilStrsav( Abc_ObjName(Abc_NtkCo(pNtk, 0)) ); + + // get the root output + pRoot = Abc_NtkCo( pNtk, 0 ); + + // perform strashing + Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 ); + // set the first cofactor + Abc_NtkCi(pNtk, In)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); + // add the first cofactor + Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); + // save the output +// pOutput1 = Abc_ObjFanin0(pRoot)->pCopy; + pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); + + // set the second cofactor + Abc_NtkCi(pNtk, In)->pCopy = Abc_AigConst1(pNtkMiter); + // add the second cofactor + Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); + // save the output +// pOutput2 = Abc_ObjFanin0(pRoot)->pCopy; + pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); + + // create the miter of the two outputs + if ( fExist ) + pMiter = Abc_AigOr( pNtkMiter->pManFunc, pOutput1, pOutput2 ); + else + pMiter = Abc_AigAnd( pNtkMiter->pManFunc, pOutput1, pOutput2 ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkMiter ) ) + { + printf( "Abc_NtkMiter: The network check has failed.\n" ); + Abc_NtkDelete( pNtkMiter ); + return NULL; + } + return pNtkMiter; +} + +/**Function************************************************************* + + Synopsis [Quantifies all the PIs existentially from the only PO of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkTemp; + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + + Abc_NtkForEachPi( pNtk, pObj, i ) + { + if ( Abc_ObjFanoutNum(pObj) == 0 ) + continue; + pNtk = Abc_NtkMiterQuantify( pNtkTemp = pNtk, i, 1 ); + Abc_NtkDelete( pNtkTemp ); + } + + return pNtk; +} + + + + +/**Function************************************************************* + + Synopsis [Checks the status of the miter.] + + Description [Return 0 if the miter is sat for at least one output. + Return 1 if the miter is unsat for all its outputs. Returns -1 if the + miter is undecided for some outputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter ) +{ + Abc_Obj_t * pNodePo, * pChild; + int i; + assert( Abc_NtkIsStrash(pMiter) ); + Abc_NtkForEachPo( pMiter, pNodePo, i ) + { + pChild = Abc_ObjChild0( pNodePo ); + if ( Abc_AigNodeIsConst(pChild) ) + { + assert( Abc_ObjRegular(pChild) == Abc_AigConst1(pMiter) ); + if ( !Abc_ObjIsComplement(pChild) ) + { + // if the miter is constant 1, return immediately +// printf( "MITER IS CONSTANT 1!\n" ); + return 0; + } + } + // if the miter is undecided (or satisfiable), return immediately + else + return -1; + } + // return 1, meaning all outputs are constant zero + return 1; +} + +/**Function************************************************************* + + Synopsis [Reports the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMiterReport( Abc_Ntk_t * pMiter ) +{ + Abc_Obj_t * pChild, * pNode; + int i; + if ( Abc_NtkPoNum(pMiter) == 1 ) + { + pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,0) ); + if ( Abc_AigNodeIsConst(pChild) ) + { + if ( Abc_ObjIsComplement(pChild) ) + printf( "Unsatisfiable.\n" ); + else + printf( "Satisfiable. (Constant 1).\n" ); + } + else + printf( "Satisfiable.\n" ); + } + else + { + Abc_NtkForEachPo( pMiter, pNode, i ) + { + pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) ); + printf( "Output #%2d : ", i ); + if ( Abc_AigNodeIsConst(pChild) ) + { + if ( Abc_ObjIsComplement(pChild) ) + printf( "Unsatisfiable.\n" ); + else + printf( "Satisfiable. (Constant 1).\n" ); + } + else + printf( "Satisfiable.\n" ); + } + } +} + + +/**Function************************************************************* + + Synopsis [Derives the timeframes of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial ) +{ + char Buffer[1000]; + ProgressBar * pProgress; + Abc_Ntk_t * pNtkFrames; + Abc_Obj_t * pLatch, * pLatchOut; + int i, Counter; + assert( nFrames > 0 ); + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkIsDfsOrdered(pNtk) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + // start the new network + pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames ); + pNtkFrames->pName = Extra_UtilStrsav(Buffer); + // map the constant nodes + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkFrames); + // create new latches (or their initial values) and remember them in the new latches + if ( !fInitial ) + { + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Abc_NtkDupBox( pNtkFrames, pLatch, 1 ); + } + else + { + Counter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + pLatchOut = Abc_ObjFanout0(pLatch); + if ( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI + { + pLatchOut->pCopy = Abc_NtkCreatePi(pNtkFrames); + Abc_ObjAssignName( pLatchOut->pCopy, Abc_ObjName(pLatchOut), NULL ); + Counter++; + } + else + pLatchOut->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) ); + } + if ( Counter ) + printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter ); + } + + // create the timeframes + pProgress = Extra_ProgressBarStart( stdout, nFrames ); + for ( i = 0; i < nFrames; i++ ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Abc_NtkAddFrame( pNtkFrames, pNtk, i ); + } + Extra_ProgressBarStop( pProgress ); + + // connect the new latches to the outputs of the last frame + if ( !fInitial ) + { + // we cannot use pLatch->pCopy here because pLatch->pCopy is used for temporary storage of strashed values + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Abc_ObjAddFanin( Abc_ObjFanin0(pLatch)->pCopy, Abc_ObjFanout0(pLatch)->pCopy ); + } + + // remove dangling nodes + Abc_AigCleanup( pNtkFrames->pManFunc ); + // reorder the latches + Abc_NtkOrderCisCos( pNtkFrames ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkFrames ) ) + { + printf( "Abc_NtkFrames: The network check has failed.\n" ); + Abc_NtkDelete( pNtkFrames ); + return NULL; + } + return pNtkFrames; +} + +/**Function************************************************************* + + Synopsis [Adds one time frame to the new network.] + + Description [Assumes that the latches of the old network point + to the outputs of the previous frame of the new network (pLatch->pCopy). + In the end, updates the latches of the old network to point to the + outputs of the current frame of the new network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame ) +{ + char Buffer[10]; + Abc_Obj_t * pNode, * pLatch; + int i; + // create the prefix to be added to the node names + sprintf( Buffer, "_%02d", iFrame ); + // add the new PI nodes + Abc_NtkForEachPi( pNtk, pNode, i ) + Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer ); + // add the internal nodes + Abc_AigForEachAnd( pNtk, pNode, i ) + pNode->pCopy = Abc_AigAnd( pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); + // add the new POs + Abc_NtkForEachPo( pNtk, pNode, i ) + { + Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer ); + Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) ); + } + // add the new asserts + Abc_NtkForEachAssert( pNtk, pNode, i ) + { + Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer ); + Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) ); + } + // transfer the implementation of the latch inputs to the latch outputs + Abc_NtkForEachLatch( pNtk, pLatch, i ) + pLatch->pCopy = Abc_ObjChild0Copy(Abc_ObjFanin0(pLatch)); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Abc_ObjFanout0(pLatch)->pCopy = pLatch->pCopy; +} + + + +/**Function************************************************************* + + Synopsis [Derives the timeframes of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg ) +{ +/* + char Buffer[1000]; + ProgressBar * pProgress; + Abc_Ntk_t * pNtkFrames; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pLatch, * pLatchNew; + int i, Counter; + assert( nFrames > 0 ); + assert( Abc_NtkIsStrash(pNtk) ); + // start the new network + pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames ); + pNtkFrames->pName = Extra_UtilStrsav(Buffer); + // create new latches (or their initial values) and remember them in the new latches + if ( !fInitial ) + { + Abc_NtkForEachLatch( pNtk, pLatch, i ) { + Abc_NtkDupObj( pNtkFrames, pLatch ); + if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg); + } + } + else + { + Counter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI + { + pLatch->pCopy = Abc_NtkCreatePi(pNtkFrames); + Abc_ObjAssignName( pLatch->pCopy, Abc_ObjName(pLatch), NULL ); + Counter++; + } + else { + pLatch->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) ); + } + + if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg); + } + if ( Counter ) + printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter ); + } + + // create the timeframes + vNodes = Abc_NtkDfs( pNtk, 0 ); + pProgress = Extra_ProgressBarStart( stdout, nFrames ); + for ( i = 0; i < nFrames; i++ ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Abc_NtkAddFrame2( pNtkFrames, pNtk, i, vNodes, addFrameMapping, arg ); + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + + // connect the new latches to the outputs of the last frame + if ( !fInitial ) + { + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + pLatchNew = Abc_NtkBox(pNtkFrames, i); + Abc_ObjAddFanin( pLatchNew, pLatch->pCopy ); + Abc_ObjAssignName( pLatchNew, Abc_ObjName(pLatch), NULL ); + } + } + Abc_NtkForEachLatch( pNtk, pLatch, i ) + pLatch->pNext = NULL; + + // remove dangling nodes + Abc_AigCleanup( pNtkFrames->pManFunc ); + + // reorder the latches + Abc_NtkOrderCisCos( pNtkFrames ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkFrames ) ) + { + printf( "Abc_NtkFrames: The network check has failed.\n" ); + Abc_NtkDelete( pNtkFrames ); + return NULL; + } + return pNtkFrames; +*/ + return NULL; +} + +/**Function************************************************************* + + Synopsis [Adds one time frame to the new network.] + + Description [Assumes that the latches of the old network point + to the outputs of the previous frame of the new network (pLatch->pCopy). + In the end, updates the latches of the old network to point to the + outputs of the current frame of the new network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg ) +{ +/* + char Buffer[10]; + Abc_Obj_t * pNode, * pNodeNew, * pLatch; + Abc_Obj_t * pConst1, * pConst1New; + int i; + // get the constant nodes + pConst1 = Abc_AigConst1(pNtk); + pConst1New = Abc_AigConst1(pNtkFrames); + // create the prefix to be added to the node names + sprintf( Buffer, "_%02d", iFrame ); + // add the new PI nodes + Abc_NtkForEachPi( pNtk, pNode, i ) + { + pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode ); + Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer ); + if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); + } + // add the internal nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( pNode == pConst1 ) + pNodeNew = pConst1New; + else + pNodeNew = Abc_AigAnd( pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); + pNode->pCopy = pNodeNew; + if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); + } + // add the new POs + Abc_NtkForEachPo( pNtk, pNode, i ) + { + pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode ); + Abc_ObjAddFanin( pNodeNew, Abc_ObjChild0Copy(pNode) ); + Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer ); + if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); + } + // transfer the implementation of the latch drivers to the latches + + // it is important that these two steps are performed it two loops + // and not in the same loop + Abc_NtkForEachLatch( pNtk, pLatch, i ) + pLatch->pNext = Abc_ObjChild0Copy(pLatch); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + pLatch->pCopy = pLatch->pNext; + + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if (addFrameMapping) { + // don't give Mike complemented pointers because he doesn't like it + if (Abc_ObjIsComplement(pLatch->pCopy)) { + pNodeNew = Abc_NtkCreateNode( pNtkFrames ); + Abc_ObjAddFanin( pNodeNew, pLatch->pCopy ); + assert(Abc_ObjFaninNum(pNodeNew) == 1); + pNodeNew->Level = 1 + Abc_ObjRegular(pLatch->pCopy)->Level; + + pLatch->pNext = pNodeNew; + pLatch->pCopy = pNodeNew; + } + addFrameMapping(pLatch->pCopy, pLatch, iFrame+1, arg); + } + } +*/ +} + + + +/**Function************************************************************* + + Synopsis [Splits the miter into two logic cones combined by an EXOR] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDemiter( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNodeC, * pNodeA, * pNodeB, * pNode; + Abc_Obj_t * pPoNew; + Vec_Ptr_t * vNodes1, * vNodes2; + int nCommon, i; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkPoNum(pNtk) == 1 ); + if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) ) + { + printf( "The root of the miter is not an EXOR gate.\n" ); + return 0; + } + pNodeC = Abc_NodeRecognizeMux( Abc_ObjFanin0(Abc_NtkPo(pNtk,0)), &pNodeA, &pNodeB ); + assert( Abc_ObjRegular(pNodeA) == Abc_ObjRegular(pNodeB) ); + if ( Abc_ObjFaninC0(Abc_NtkPo(pNtk,0)) ) + { + pNodeA = Abc_ObjNot(pNodeA); + pNodeB = Abc_ObjNot(pNodeB); + } + + // add the PO corresponding to control input + pPoNew = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pPoNew, pNodeC ); + Abc_ObjAssignName( pPoNew, "addOut1", NULL ); + + // add the PO corresponding to other input + pPoNew = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pPoNew, pNodeB ); + Abc_ObjAssignName( pPoNew, "addOut2", NULL ); + + // mark the nodes in the first cone + pNodeB = Abc_ObjRegular(pNodeB); + vNodes1 = Abc_NtkDfsNodes( pNtk, &pNodeC, 1 ); + vNodes2 = Abc_NtkDfsNodes( pNtk, &pNodeB, 1 ); + + Vec_PtrForEachEntry( vNodes1, pNode, i ) + pNode->fMarkA = 1; + nCommon = 0; + Vec_PtrForEachEntry( vNodes2, pNode, i ) + nCommon += pNode->fMarkA; + Vec_PtrForEachEntry( vNodes1, pNode, i ) + pNode->fMarkA = 0; + + printf( "First cone = %6d. Second cone = %6d. Common = %6d.\n", vNodes1->nSize, vNodes2->nSize, nCommon ); + Vec_PtrFree( vNodes1 ); + Vec_PtrFree( vNodes2 ); + + // reorder the latches + Abc_NtkOrderCisCos( pNtk ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtk ) ) + printf( "Abc_NtkDemiter: The network check has failed.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes OR or AND of the POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ) +{ + Abc_Obj_t * pNode, * pMiter; + int i; + assert( Abc_NtkIsStrash(pNtk) ); +// assert( Abc_NtkLatchNum(pNtk) == 0 ); + if ( Abc_NtkPoNum(pNtk) == 1 ) + return 1; + // start the result + if ( fAnd ) + pMiter = Abc_AigConst1(pNtk); + else + pMiter = Abc_ObjNot( Abc_AigConst1(pNtk) ); + // perform operations on the POs + Abc_NtkForEachPo( pNtk, pNode, i ) + if ( fAnd ) + pMiter = Abc_AigAnd( pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) ); + else + pMiter = Abc_AigOr( pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) ); + // remove the POs and their names + for ( i = Abc_NtkPoNum(pNtk) - 1; i >= 0; i-- ) + Abc_NtkDeleteObj( Abc_NtkPo(pNtk, i) ); + assert( Abc_NtkPoNum(pNtk) == 0 ); + // create the new PO + pNode = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pNode, pMiter ); + Abc_ObjAssignName( pNode, "miter", NULL ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkOrPos: The network check has failed.\n" ); + return 0; + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcMulti.c b/abc70930/src/base/abci/abcMulti.c new file mode 100644 index 00000000..e93360a0 --- /dev/null +++ b/abc70930/src/base/abci/abcMulti.c @@ -0,0 +1,643 @@ +/**CFile**************************************************************** + + FileName [abcMulti.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures which transform an AIG into multi-input AND-graph.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMulti.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +static Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld ); + +static DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFanins ); +static DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld ); + +static void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax ); +static void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk ); +static void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh ); +static void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk ); +static void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk ); +static void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transforms the AIG into nodes.] + + Description [Threhold is the max number of nodes duplicated at a node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ) +{ + Abc_Ntk_t * pNtkNew; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( nThresh >= 0 ); + assert( nFaninMax > 1 ); + + // print a warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Warning: The choice nodes in the AIG are removed by renoding.\n" ); + + // define the boundary + if ( fCnf ) + Abc_NtkMultiSetBoundsCnf( pNtk ); + else if ( fMulti ) + Abc_NtkMultiSetBoundsMulti( pNtk, nThresh ); + else if ( fSimple ) + Abc_NtkMultiSetBoundsSimple( pNtk ); + else if ( fFactor ) + Abc_NtkMultiSetBoundsFactor( pNtk ); + else + Abc_NtkMultiSetBounds( pNtk, nThresh, nFaninMax ); + + // perform renoding for this boundary + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); + Abc_NtkMultiInt( pNtk, pNtkNew ); + Abc_NtkFinalize( pNtk, pNtkNew ); + + // make the network minimum base + Abc_NtkMinimumBase( pNtkNew ); + + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + + // report the number of CNF objects + if ( fCnf ) + { +// int nClauses = Abc_NtkGetClauseNum(pNtkNew) + 2*Abc_NtkPoNum(pNtkNew) + 2*Abc_NtkLatchNum(pNtkNew); +// printf( "CNF variables = %d. CNF clauses = %d.\n", Abc_NtkNodeNum(pNtkNew), nClauses ); + } +//printf( "Maximum fanin = %d.\n", Abc_NtkGetFaninMax(pNtkNew) ); + + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkMulti: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transforms the AIG into nodes.] + + Description [Threhold is the max number of nodes duplicated at a node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pConst1, * pNodeNew; + int i; + + // set the constant node + pConst1 = Abc_AigConst1(pNtk); + if ( Abc_ObjFanoutNum(pConst1) > 0 ) + { + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Cudd_ReadOne( pNtkNew->pManFunc ); Cudd_Ref( pNodeNew->pData ); + pConst1->pCopy = pNodeNew; + } + + // perform renoding for POs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) + continue; + Abc_NtkMulti_rec( pNtkNew, Abc_ObjFanin0(pNode) ); + } + Extra_ProgressBarStop( pProgress ); + + // clean the boundaries and data field in the old network + Abc_NtkForEachObj( pNtk, pNode, i ) + { + pNode->fMarkA = 0; + pNode->pData = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Find the best multi-input node rooted at the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld ) +{ + Vec_Ptr_t * vCone; + Abc_Obj_t * pNodeNew; + int i; + + assert( !Abc_ObjIsComplement(pNodeOld) ); + // return if the result if known + if ( pNodeOld->pCopy ) + return pNodeOld->pCopy; + assert( Abc_ObjIsNode(pNodeOld) ); + assert( !Abc_AigNodeIsConst(pNodeOld) ); + assert( pNodeOld->fMarkA ); + +//printf( "%d ", Abc_NodeMffcSizeSupp(pNodeOld) ); + + // collect the renoding cone + vCone = Vec_PtrAlloc( 10 ); + Abc_NtkMultiCone( pNodeOld, vCone ); + + // create a new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + for ( i = 0; i < vCone->nSize; i++ ) + Abc_ObjAddFanin( pNodeNew, Abc_NtkMulti_rec(pNtkNew, vCone->pArray[i]) ); + + // derive the function of this node + pNodeNew->pData = Abc_NtkMultiDeriveBdd( pNtkNew->pManFunc, pNodeOld, vCone ); + Cudd_Ref( pNodeNew->pData ); + Vec_PtrFree( vCone ); + + // remember the node + pNodeOld->pCopy = pNodeNew; + return pNodeOld->pCopy; +} + + +/**Function************************************************************* + + Synopsis [Derives the local BDD of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld ) +{ + Abc_Obj_t * pFaninOld; + DdNode * bFunc; + int i; + assert( !Abc_AigNodeIsConst(pNodeOld) ); + assert( Abc_ObjIsNode(pNodeOld) ); + // set the elementary BDD variables for the input nodes + for ( i = 0; i < vFaninsOld->nSize; i++ ) + { + pFaninOld = vFaninsOld->pArray[i]; + pFaninOld->pData = Cudd_bddIthVar( dd, i ); Cudd_Ref( pFaninOld->pData ); + pFaninOld->fMarkC = 1; + } + // call the recursive BDD computation + bFunc = Abc_NtkMultiDeriveBdd_rec( dd, pNodeOld, vFaninsOld ); Cudd_Ref( bFunc ); + // dereference the intermediate nodes + for ( i = 0; i < vFaninsOld->nSize; i++ ) + { + pFaninOld = vFaninsOld->pArray[i]; + Cudd_RecursiveDeref( dd, pFaninOld->pData ); + pFaninOld->fMarkC = 0; + } + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Derives the local BDD of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins ) +{ + DdNode * bFunc, * bFunc0, * bFunc1; + assert( !Abc_ObjIsComplement(pNode) ); + // if the result is available return + if ( pNode->fMarkC ) + { + assert( pNode->pData ); // network has a cycle + return pNode->pData; + } + // mark the node as visited + pNode->fMarkC = 1; + Vec_PtrPush( vFanins, pNode ); + // compute the result for both branches + bFunc0 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,0), vFanins ); Cudd_Ref( bFunc0 ); + bFunc1 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,1), vFanins ); Cudd_Ref( bFunc1 ); + bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) ); + bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) ); + // get the final result + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bFunc0 ); + Cudd_RecursiveDeref( dd, bFunc1 ); + // set the result + pNode->pData = bFunc; + assert( pNode->pData ); + return bFunc; +} + + + +/**Function************************************************************* + + Synopsis [Limits the cones to be no more than the given size.] + + Description [Returns 1 if the last cone was limited. Returns 0 if no changes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMultiLimit_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax, int fCanStop, int fFirst ) +{ + int nNodes0, nNodes1; + assert( !Abc_ObjIsComplement(pNode) ); + // check if the node should be added to the fanins + if ( !fFirst && (pNode->fMarkA || !Abc_ObjIsNode(pNode)) ) + { + Vec_PtrPushUnique( vCone, pNode ); + return 0; + } + // if we cannot stop in this branch, collect all nodes + if ( !fCanStop ) + { + Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 0, 0 ); + Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 ); + return 0; + } + // if we can stop, try the left branch first, and return if we stopped + assert( vCone->nSize == 0 ); + if ( Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 1, 0 ) ) + return 1; + // save the number of nodes in the left branch and call for the right branch + nNodes0 = vCone->nSize; + assert( nNodes0 <= nFaninMax ); + Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 ); + // check the number of nodes + if ( vCone->nSize <= nFaninMax ) + return 0; + // the number of nodes exceeds the limit + + // get the number of nodes in the right branch + vCone->nSize = 0; + Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 ); + // if this number exceeds the limit, solve the problem for this branch + if ( vCone->nSize > nFaninMax ) + { + int RetValue; + vCone->nSize = 0; + RetValue = Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 1, 0 ); + assert( RetValue == 1 ); + return 1; + } + + nNodes1 = vCone->nSize; + assert( nNodes1 <= nFaninMax ); + if ( nNodes0 >= nNodes1 ) + { // the left branch is larger - cut it + assert( Abc_ObjFanin(pNode,0)->fMarkA == 0 ); + Abc_ObjFanin(pNode,0)->fMarkA = 1; + } + else + { // the right branch is larger - cut it + assert( Abc_ObjFanin(pNode,1)->fMarkA == 0 ); + Abc_ObjFanin(pNode,1)->fMarkA = 1; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Limits the cones to be no more than the given size.] + + Description [Returns 1 if the last cone was limited. Returns 0 if no changes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMultiLimit( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax ) +{ + vCone->nSize = 0; + return Abc_NtkMultiLimit_rec( pNode, vCone, nFaninMax, 1, 1 ); +} + +/**Function************************************************************* + + Synopsis [Sets the expansion boundary for multi-input nodes.] + + Description [The boundary includes the set of PIs and all nodes such that + when expanding over the node we duplicate no more than nThresh nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax ) +{ + Vec_Ptr_t * vCone = Vec_PtrAlloc(10); + Abc_Obj_t * pNode; + int i, nFanouts, nConeSize; + + // make sure the mark is not set + Abc_NtkForEachObj( pNtk, pNode, i ) + assert( pNode->fMarkA == 0 ); + + // mark the nodes where expansion stops using pNode->fMarkA + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip PI/PO nodes +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // mark the nodes with multiple fanouts + nFanouts = Abc_ObjFanoutNum(pNode); + nConeSize = Abc_NodeMffcSize(pNode); + if ( (nFanouts - 1) * nConeSize > nThresh ) + pNode->fMarkA = 1; + } + + // mark the PO drivers + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_ObjFanin0(pNode)->fMarkA = 1; + + // make sure the fanin limit is met + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip PI/PO nodes +// if ( Abc_NodeIsConst(pNode) ) +// continue; + if ( pNode->fMarkA == 0 ) + continue; + // continue cutting branches until it meets the fanin limit + while ( Abc_NtkMultiLimit(pNode, vCone, nFaninMax) ); + assert( vCone->nSize <= nFaninMax ); + } + Vec_PtrFree(vCone); +/* + // make sure the fanin limit is met + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip PI/PO nodes +// if ( Abc_NodeIsConst(pNode) ) +// continue; + if ( pNode->fMarkA == 0 ) + continue; + Abc_NtkMultiCone( pNode, vCone ); + assert( vCone->nSize <= nFaninMax ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Sets the expansion boundary for conversion into CNF.] + + Description [The boundary includes the set of PIs, the roots of MUXes, + the nodes with multiple fanouts and the nodes with complemented outputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nMuxes; + + // make sure the mark is not set + Abc_NtkForEachObj( pNtk, pNode, i ) + assert( pNode->fMarkA == 0 ); + + // mark the nodes where expansion stops using pNode->fMarkA + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip PI/PO nodes +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // mark the nodes with multiple fanouts + if ( Abc_ObjFanoutNum(pNode) > 1 ) + pNode->fMarkA = 1; + // mark the nodes that are roots of MUXes + if ( Abc_NodeIsMuxType( pNode ) ) + { + pNode->fMarkA = 1; + Abc_ObjFanin0( Abc_ObjFanin0(pNode) )->fMarkA = 1; + Abc_ObjFanin0( Abc_ObjFanin1(pNode) )->fMarkA = 1; + Abc_ObjFanin1( Abc_ObjFanin0(pNode) )->fMarkA = 1; + Abc_ObjFanin1( Abc_ObjFanin1(pNode) )->fMarkA = 1; + } + else // mark the complemented edges + { + if ( Abc_ObjFaninC0(pNode) ) + Abc_ObjFanin0(pNode)->fMarkA = 1; + if ( Abc_ObjFaninC1(pNode) ) + Abc_ObjFanin1(pNode)->fMarkA = 1; + } + } + + // mark the PO drivers + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_ObjFanin0(pNode)->fMarkA = 1; + + // count the number of MUXes + nMuxes = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip PI/PO nodes +// if ( Abc_NodeIsConst(pNode) ) +// continue; + if ( Abc_NodeIsMuxType(pNode) && + Abc_ObjFanin0(pNode)->fMarkA == 0 && + Abc_ObjFanin1(pNode)->fMarkA == 0 ) + nMuxes++; + } +// printf( "The number of MUXes detected = %d (%5.2f %% of logic).\n", nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) ); +} + +/**Function************************************************************* + + Synopsis [Sets the expansion boundary for conversion into multi-input AND graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh ) +{ + Abc_Obj_t * pNode; + int i, nFanouts, nConeSize; + + // make sure the mark is not set + Abc_NtkForEachObj( pNtk, pNode, i ) + assert( pNode->fMarkA == 0 ); + + // mark the nodes where expansion stops using pNode->fMarkA + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip PI/PO nodes +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // mark the nodes with multiple fanouts +// if ( Abc_ObjFanoutNum(pNode) > 1 ) +// pNode->fMarkA = 1; + // mark the nodes with multiple fanouts + nFanouts = Abc_ObjFanoutNum(pNode); + nConeSize = Abc_NodeMffcSizeStop(pNode); + if ( (nFanouts - 1) * nConeSize > nThresh ) + pNode->fMarkA = 1; + // mark the children if they are pointed by the complemented edges + if ( Abc_ObjFaninC0(pNode) ) + Abc_ObjFanin0(pNode)->fMarkA = 1; + if ( Abc_ObjFaninC1(pNode) ) + Abc_ObjFanin1(pNode)->fMarkA = 1; + } + + // mark the PO drivers + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_ObjFanin0(pNode)->fMarkA = 1; +} + +/**Function************************************************************* + + Synopsis [Sets a simple boundary.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + // make sure the mark is not set + Abc_NtkForEachObj( pNtk, pNode, i ) + assert( pNode->fMarkA == 0 ); + // mark the nodes where expansion stops using pNode->fMarkA + Abc_NtkForEachNode( pNtk, pNode, i ) + pNode->fMarkA = 1; +} + +/**Function************************************************************* + + Synopsis [Sets a factor-cut boundary.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + // make sure the mark is not set + Abc_NtkForEachObj( pNtk, pNode, i ) + assert( pNode->fMarkA == 0 ); + // mark the nodes where expansion stops using pNode->fMarkA + Abc_NtkForEachNode( pNtk, pNode, i ) + pNode->fMarkA = (pNode->vFanouts.nSize > 1 && !Abc_NodeIsMuxControlType(pNode)); + // mark the PO drivers + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_ObjFanin0(pNode)->fMarkA = 1; +} + +/**Function************************************************************* + + Synopsis [Collects the fanins of a large node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ) +{ + assert( !Abc_ObjIsComplement(pNode) ); + if ( pNode->fMarkA || !Abc_ObjIsNode(pNode) ) + { + Vec_PtrPushUnique( vCone, pNode ); + return; + } + Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone ); + Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone ); +} + +/**Function************************************************************* + + Synopsis [Collects the fanins of a large node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ) +{ + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + vCone->nSize = 0; + Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone ); + Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcMv.c b/abc70930/src/base/abci/abcMv.c new file mode 100644 index 00000000..2858b8a7 --- /dev/null +++ b/abc70930/src/base/abci/abcMv.c @@ -0,0 +1,369 @@ +/**CFile**************************************************************** + + FileName [abcMv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Multi-valued decomposition.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Mv_Man_t_ Mv_Man_t; +struct Mv_Man_t_ +{ + int nInputs; // the number of 4-valued input variables + int nFuncs; // the number of 4-valued functions + DdManager * dd; // representation of functions + DdNode * bValues[15][4]; // representation of i-sets + DdNode * bValueDcs[15][4]; // representation of i-sets don't-cares + DdNode * bFuncs[15]; // representation of functions +}; + +static void Abc_MvDecompose( Mv_Man_t * p ); +static void Abc_MvPrintStats( Mv_Man_t * p ); +static void Abc_MvRead( Mv_Man_t * p ); +static void Abc_MvDeref( Mv_Man_t * p ); +static DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MvExperiment() +{ + Mv_Man_t * p; + // get the functions + p = ALLOC( Mv_Man_t, 1 ); + memset( p, 0, sizeof(Mv_Man_t) ); + p->dd = Cudd_Init( 32, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->nFuncs = 15; + p->nInputs = 9; + Abc_MvRead( p ); + // process the functions + Abc_MvPrintStats( p ); +// Cudd_ReduceHeap( p->dd, CUDD_REORDER_SYMM_SIFT, 1 ); +// Abc_MvPrintStats( p ); + // try detecting support reducing bound set + Abc_MvDecompose( p ); + + // remove the manager + Abc_MvDeref( p ); + Extra_StopManager( p->dd ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MvPrintStats( Mv_Man_t * p ) +{ + int i, v; + for ( i = 0; i < 15; i++ ) + { + printf( "%2d : ", i ); + printf( "%3d (%2d) ", Cudd_DagSize(p->bFuncs[i])-1, Cudd_SupportSize(p->dd, p->bFuncs[i]) ); + for ( v = 0; v < 4; v++ ) + printf( "%d = %3d (%2d) ", v, Cudd_DagSize(p->bValues[i][v])-1, Cudd_SupportSize(p->dd, p->bValues[i][v]) ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars ) +{ + DdNode * bCube, * bVar, * bTemp; + int i; + bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); + for ( i = 0; i < nVars; i++ ) + { + if ( pLine[i] == '-' ) + continue; + else if ( pLine[i] == '0' ) // 0 + bVar = Cudd_Not( Cudd_bddIthVar(dd, 29-i) ); + else if ( pLine[i] == '1' ) // 1 + bVar = Cudd_bddIthVar(dd, 29-i); + else assert(0); + bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bCube ); + return bCube; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MvRead( Mv_Man_t * p ) +{ + FILE * pFile; + char Buffer[1000], * pLine; + DdNode * bCube, * bTemp, * bProd, * bVar0, * bVar1, * bCubeSum; + int i, v; + + // start the cube + bCubeSum = Cudd_ReadLogicZero(p->dd); Cudd_Ref( bCubeSum ); + + // start the values + for ( i = 0; i < 15; i++ ) + for ( v = 0; v < 4; v++ ) + { + p->bValues[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValues[i][v] ); + p->bValueDcs[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValueDcs[i][v] ); + } + + // read the file + pFile = fopen( "input.pla", "r" ); + while ( fgets( Buffer, 1000, pFile ) ) + { + if ( Buffer[0] == '#' ) + continue; + if ( Buffer[0] == '.' ) + { + if ( Buffer[1] == 'e' ) + break; + continue; + } + + // get the cube + bCube = Abc_MvReadCube( p->dd, Buffer, 18 ); Cudd_Ref( bCube ); + + // add it to the values of the output functions + pLine = Buffer + 19; + for ( i = 0; i < 15; i++ ) + { + if ( pLine[2*i] == '-' && pLine[2*i+1] == '-' ) + { + for ( v = 0; v < 4; v++ ) + { + p->bValueDcs[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValueDcs[i][v], bCube ); Cudd_Ref( p->bValueDcs[i][v] ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + continue; + } + else if ( pLine[2*i] == '0' && pLine[2*i+1] == '0' ) // 0 + v = 0; + else if ( pLine[2*i] == '1' && pLine[2*i+1] == '0' ) // 1 + v = 1; + else if ( pLine[2*i] == '0' && pLine[2*i+1] == '1' ) // 2 + v = 2; + else if ( pLine[2*i] == '1' && pLine[2*i+1] == '1' ) // 3 + v = 3; + else assert( 0 ); + // add the value + p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], bCube ); Cudd_Ref( p->bValues[i][v] ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + + // add the cube + bCubeSum = Cudd_bddOr( p->dd, bTemp = bCubeSum, bCube ); Cudd_Ref( bCubeSum ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + } + + // add the complement of the domain to all values + for ( i = 0; i < 15; i++ ) + for ( v = 0; v < 4; v++ ) + { + if ( p->bValues[i][v] == Cudd_Not(Cudd_ReadOne(p->dd)) ) + continue; + p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], p->bValueDcs[i][v] ); Cudd_Ref( p->bValues[i][v] ); + Cudd_RecursiveDeref( p->dd, bTemp ); + p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], Cudd_Not(bCubeSum) ); Cudd_Ref( p->bValues[i][v] ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + printf( "Domain = %5.2f %%.\n", 100.0*Cudd_CountMinterm(p->dd, bCubeSum, 32)/Cudd_CountMinterm(p->dd, Cudd_ReadOne(p->dd), 32) ); + Cudd_RecursiveDeref( p->dd, bCubeSum ); + + // create each output function + for ( i = 0; i < 15; i++ ) + { + p->bFuncs[i] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bFuncs[i] ); + for ( v = 0; v < 4; v++ ) + { + bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 30), ((v & 1) == 0) ); + bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 31), ((v & 2) == 0) ); + bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube ); + bProd = Cudd_bddAnd( p->dd, p->bValues[i][v], bCube ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( p->dd, bCube ); + // add the value + p->bFuncs[i] = Cudd_bddOr( p->dd, bTemp = p->bFuncs[i], bProd ); Cudd_Ref( p->bFuncs[i] ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bProd ); + } + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MvDeref( Mv_Man_t * p ) +{ + int i, v; + for ( i = 0; i < 15; i++ ) + for ( v = 0; v < 4; v++ ) + { + Cudd_RecursiveDeref( p->dd, p->bValues[i][v] ); + Cudd_RecursiveDeref( p->dd, p->bValueDcs[i][v] ); + } + for ( i = 0; i < 15; i++ ) + Cudd_RecursiveDeref( p->dd, p->bFuncs[i] ); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MvDecompose( Mv_Man_t * p ) +{ + DdNode * bCofs[16], * bVarCube1, * bVarCube2, * bVarCube, * bCube, * bVar0, * bVar1;//, * bRes; + int k, i1, i2, v1, v2;//, c1, c2, Counter; + + bVar0 = Cudd_bddIthVar(p->dd, 30); + bVar1 = Cudd_bddIthVar(p->dd, 31); + bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube ); + + for ( k = 0; k < p->nFuncs; k++ ) + { + printf( "FUNCTION %d\n", k ); + for ( i1 = 0; i1 < p->nFuncs; i1++ ) + for ( i2 = i1+1; i2 < p->nFuncs; i2++ ) + { + Vec_Ptr_t * vCofs; + + for ( v1 = 0; v1 < 4; v1++ ) + { + bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1 ), ((v1 & 1) == 0) ); + bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1-1), ((v1 & 2) == 0) ); + bVarCube1 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube1 ); + for ( v2 = 0; v2 < 4; v2++ ) + { + bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2 ), ((v2 & 1) == 0) ); + bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2-1), ((v2 & 2) == 0) ); + bVarCube2 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube2 ); + bVarCube = Cudd_bddAnd( p->dd, bVarCube1, bVarCube2 ); Cudd_Ref( bVarCube ); + bCofs[v1 * 4 + v2] = Cudd_Cofactor( p->dd, p->bFuncs[k], bVarCube ); Cudd_Ref( bCofs[v1 * 4 + v2] ); + Cudd_RecursiveDeref( p->dd, bVarCube ); + Cudd_RecursiveDeref( p->dd, bVarCube2 ); + } + Cudd_RecursiveDeref( p->dd, bVarCube1 ); + } +/* + // check the compatibility of cofactors + Counter = 0; + for ( c1 = 0; c1 < 16; c1++ ) + { + for ( c2 = 0; c2 <= c1; c2++ ) + printf( " " ); + for ( c2 = c1+1; c2 < 16; c2++ ) + { + bRes = Cudd_bddAndAbstract( p->dd, bCofs[c1], bCofs[c2], bCube ); Cudd_Ref( bRes ); + if ( bRes == Cudd_ReadOne(p->dd) ) + { + printf( "+" ); + Counter++; + } + else + { + printf( " " ); + } + Cudd_RecursiveDeref( p->dd, bRes ); + } + printf( "\n" ); + } +*/ + + vCofs = Vec_PtrAlloc( 16 ); + for ( v1 = 0; v1 < 4; v1++ ) + for ( v2 = 0; v2 < 4; v2++ ) + Vec_PtrPushUnique( vCofs, bCofs[v1 * 4 + v2] ); + printf( "%d ", Vec_PtrSize(vCofs) ); + Vec_PtrFree( vCofs ); + + // free the cofactors + for ( v1 = 0; v1 < 4; v1++ ) + for ( v2 = 0; v2 < 4; v2++ ) + Cudd_RecursiveDeref( p->dd, bCofs[v1 * 4 + v2] ); + + printf( "\n" ); +// printf( "%2d, %2d : %3d\n", i1, i2, Counter ); + } + } + + Cudd_RecursiveDeref( p->dd, bCube ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcNtbdd.c b/abc70930/src/base/abci/abcNtbdd.c new file mode 100644 index 00000000..f127811e --- /dev/null +++ b/abc70930/src/base/abci/abcNtbdd.c @@ -0,0 +1,582 @@ +/**CFile**************************************************************** + + FileName [abcNtbdd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to translate between the BDD and the network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcNtbdd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +static Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ); +static Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st_table * tBdd2Node ); +static DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Constructs the network isomorphic to the given BDD.] + + Description [Assumes that the BDD depends on the variables whose indexes + correspond to the names in the array (pNamesPi). Otherwise, returns NULL. + The resulting network comes with one node, whose functionality is + equal to the given BDD. To decompose this BDD into the network of + multiplexers use Abc_NtkBddToMuxes(). To decompose this BDD into + an And-Inverter Graph, use Abc_NtkStrash().] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ) +{ + Abc_Ntk_t * pNtk; + Vec_Ptr_t * vNamesPiFake = NULL; + Abc_Obj_t * pNode, * pNodePi, * pNodePo; + DdNode * bSupp, * bTemp; + char * pName; + int i; + + // supply fake names if real names are not given + if ( pNamePo == NULL ) + pNamePo = "F"; + if ( vNamesPi == NULL ) + { + vNamesPiFake = Abc_NodeGetFakeNames( dd->size ); + vNamesPi = vNamesPiFake; + } + + // make sure BDD depends on the variables whose index + // does not exceed the size of the array with PI names + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) ) + if ( (int)Cudd_NodeReadIndex(bTemp) >= Vec_PtrSize(vNamesPi) ) + break; + Cudd_RecursiveDeref( dd, bSupp ); + if ( bTemp != Cudd_ReadOne(dd) ) + return NULL; + + // start the network + pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 ); + pNtk->pName = Extra_UtilStrsav(pNamePo); + // make sure the new manager has enough inputs + Cudd_bddIthVar( pNtk->pManFunc, Vec_PtrSize(vNamesPi) ); + // add the PIs corresponding to the names + Vec_PtrForEachEntry( vNamesPi, pName, i ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), pName, NULL ); + // create the node + pNode = Abc_NtkCreateNode( pNtk ); + pNode->pData = Cudd_bddTransfer( dd, pNtk->pManFunc, bFunc ); Cudd_Ref(pNode->pData); + Abc_NtkForEachPi( pNtk, pNodePi, i ) + Abc_ObjAddFanin( pNode, pNodePi ); + // create the only PO + pNodePo = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pNodePo, pNode ); + Abc_ObjAssignName( pNodePo, pNamePo, NULL ); + // make the network minimum base + Abc_NtkMinimumBase( pNtk ); + if ( vNamesPiFake ) + Abc_NodeFreeNames( vNamesPiFake ); + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkDeriveFromBdd(): Network check has failed.\n" ); + return pNtk; +} + + + +/**Function************************************************************* + + Synopsis [Creates the network isomorphic to the union of local BDDs of the nodes.] + + Description [The nodes of the local BDDs are converted into the network nodes + with logic functions equal to the MUX.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + assert( Abc_NtkIsBddLogic(pNtk) ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + Abc_NtkBddToMuxesPerform( pNtk, pNtkNew ); + Abc_NtkFinalize( pNtk, pNtkNew ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkBddToMuxes: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the network to MUXes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pNodeNew; + Vec_Ptr_t * vNodes; + int i; + // perform conversion in the topological order + vNodes = Abc_NtkDfs( pNtk, 0 ); + pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // convert one node + assert( Abc_ObjIsNode(pNode) ); + pNodeNew = Abc_NodeBddToMuxes( pNode, pNtkNew ); + // mark the old node with the new one + assert( pNode->pCopy == NULL ); + pNode->pCopy = pNodeNew; + } + Vec_PtrFree( vNodes ); + Extra_ProgressBarStop( pProgress ); +} + +/**Function************************************************************* + + Synopsis [Converts the node to MUXes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ) +{ + DdManager * dd = pNodeOld->pNtk->pManFunc; + DdNode * bFunc = pNodeOld->pData; + Abc_Obj_t * pFaninOld, * pNodeNew; + st_table * tBdd2Node; + int i; + // create the table mapping BDD nodes into the ABC nodes + tBdd2Node = st_init_table( st_ptrcmp, st_ptrhash ); + // add the constant and the elementary vars + Abc_ObjForEachFanin( pNodeOld, pFaninOld, i ) + st_insert( tBdd2Node, (char *)Cudd_bddIthVar(dd, i), (char *)pFaninOld->pCopy ); + // create the new nodes recursively + pNodeNew = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(bFunc), pNtkNew, tBdd2Node ); + st_free_table( tBdd2Node ); + if ( Cudd_IsComplement(bFunc) ) + pNodeNew = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew ); + return pNodeNew; +} + +/**Function************************************************************* + + Synopsis [Converts the node to MUXes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st_table * tBdd2Node ) +{ + Abc_Obj_t * pNodeNew, * pNodeNew0, * pNodeNew1, * pNodeNewC; + assert( !Cudd_IsComplement(bFunc) ); + if ( bFunc == b1 ) + return Abc_NtkCreateNodeConst1(pNtkNew); + if ( st_lookup( tBdd2Node, (char *)bFunc, (char **)&pNodeNew ) ) + return pNodeNew; + // solve for the children nodes + pNodeNew0 = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(cuddE(bFunc)), pNtkNew, tBdd2Node ); + if ( Cudd_IsComplement(cuddE(bFunc)) ) + pNodeNew0 = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew0 ); + pNodeNew1 = Abc_NodeBddToMuxes_rec( dd, cuddT(bFunc), pNtkNew, tBdd2Node ); + if ( !st_lookup( tBdd2Node, (char *)Cudd_bddIthVar(dd, bFunc->index), (char **)&pNodeNewC ) ) + assert( 0 ); + // create the MUX node + pNodeNew = Abc_NtkCreateNodeMux( pNtkNew, pNodeNewC, pNodeNew1, pNodeNew0 ); + st_insert( tBdd2Node, (char *)bFunc, (char *)pNodeNew ); + return pNodeNew; +} + + +/**Function************************************************************* + + Synopsis [Derives global BDDs for the COs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pObj, * pFanin; + Vec_Att_t * pAttMan; + DdManager * dd; + DdNode * bFunc; + int i, k, Counter; + + // remove dangling nodes + Abc_AigCleanup( pNtk->pManFunc ); + + // start the manager + assert( Abc_NtkGlobalBdd(pNtk) == NULL ); + dd = Cudd_Init( Abc_NtkCiNum(pNtk), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + pAttMan = Vec_AttAlloc( 0, Abc_NtkObjNumMax(pNtk) + 1, dd, Extra_StopManager, NULL, Cudd_RecursiveDeref ); + Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD, pAttMan ); + + // set reordering + if ( fReorder ) + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + + // assign the constant node BDD + pObj = Abc_AigConst1(pNtk); + if ( Abc_ObjFanoutNum(pObj) > 0 ) + { + bFunc = dd->one; + Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc ); + } + // set the elementary variables + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + { + bFunc = dd->vars[i]; +// bFunc = dd->vars[Abc_NtkCiNum(pNtk) - 1 - i]; + Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc ); + } + + // collect the global functions of the COs + Counter = 0; + // construct the BDDs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose ); + if ( bFunc == NULL ) + { + if ( fVerbose ) + printf( "Constructing global BDDs is aborted.\n" ); + Abc_NtkFreeGlobalBdds( pNtk, 0 ); + Cudd_Quit( dd ); + return NULL; + } + bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pObj) ); Cudd_Ref( bFunc ); + Abc_ObjSetGlobalBdd( pObj, bFunc ); + } + Extra_ProgressBarStop( pProgress ); + +/* + // derefence the intermediate BDDs + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( pObj->pCopy ) + { + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pCopy ); + pObj->pCopy = NULL; + } +*/ +/* + // make sure all nodes are derefed + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->pCopy != NULL ) + printf( "Abc_NtkBuildGlobalBdds() error: Node %d has BDD assigned\n", pObj->Id ); + if ( pObj->vFanouts.nSize > 0 ) + printf( "Abc_NtkBuildGlobalBdds() error: Node %d has refs assigned\n", pObj->Id ); + } +*/ + // reset references + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + pFanin->vFanouts.nSize++; + + // reorder one more time + if ( fReorder ) + { + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); + Cudd_AutodynDisable( dd ); + } +// Cudd_PrintInfo( dd, stdout ); + return dd; +} + +/**Function************************************************************* + + Synopsis [Derives the global BDD for one AIG node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ) +{ + DdNode * bFunc, * bFunc0, * bFunc1, * bFuncC; + int fDetectMuxes = 1; + assert( !Abc_ObjIsComplement(pNode) ); + if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax ) + { + Extra_ProgressBarStop( pProgress ); + if ( fVerbose ) + printf( "The number of live nodes reached %d.\n", nBddSizeMax ); + fflush( stdout ); + return NULL; + } + // if the result is available return + if ( Abc_ObjGlobalBdd(pNode) == NULL ) + { + Abc_Obj_t * pNodeC, * pNode0, * pNode1; + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + // check for the special case when it is MUX/EXOR + if ( fDetectMuxes && + Abc_ObjGlobalBdd(pNode0) == NULL && Abc_ObjGlobalBdd(pNode1) == NULL && + Abc_ObjIsNode(pNode0) && Abc_ObjFanoutNum(pNode0) == 1 && + Abc_ObjIsNode(pNode1) && Abc_ObjFanoutNum(pNode1) == 1 && + Abc_NodeIsMuxType(pNode) ) + { + // deref the fanins + pNode0->vFanouts.nSize--; + pNode1->vFanouts.nSize--; + // recognize the MUX + pNodeC = Abc_NodeRecognizeMux( pNode, &pNode1, &pNode0 ); + assert( Abc_ObjFanoutNum(pNodeC) > 1 ); + // dereference the control once (the second time it will be derefed when BDDs are computed) + pNodeC->vFanouts.nSize--; + + // compute the result for all branches + bFuncC = Abc_NodeGlobalBdds_rec( dd, pNodeC, nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFuncC == NULL ) + return NULL; + Cudd_Ref( bFuncC ); + bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFunc0 == NULL ) + return NULL; + Cudd_Ref( bFunc0 ); + bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFunc1 == NULL ) + return NULL; + Cudd_Ref( bFunc1 ); + + // complement the branch BDDs + bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjIsComplement(pNode0) ); + bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjIsComplement(pNode1) ); + // get the final result + bFunc = Cudd_bddIte( dd, bFuncC, bFunc1, bFunc0 ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bFunc0 ); + Cudd_RecursiveDeref( dd, bFunc1 ); + Cudd_RecursiveDeref( dd, bFuncC ); + // add the number of used nodes + (*pCounter) += 3; + } + else + { + // compute the result for both branches + bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFunc0 == NULL ) + return NULL; + Cudd_Ref( bFunc0 ); + bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFunc1 == NULL ) + return NULL; + Cudd_Ref( bFunc1 ); + bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) ); + bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) ); + // get the final result + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bFunc0 ); + Cudd_RecursiveDeref( dd, bFunc1 ); + // add the number of used nodes + (*pCounter)++; + } + // set the result + assert( Abc_ObjGlobalBdd(pNode) == NULL ); + Abc_ObjSetGlobalBdd( pNode, bFunc ); + // increment the progress bar + if ( pProgress ) + Extra_ProgressBarUpdate( pProgress, *pCounter, NULL ); + } + // prepare the return value + bFunc = Abc_ObjGlobalBdd(pNode); + // dereference BDD at the node + if ( --pNode->vFanouts.nSize == 0 && fDropInternal ) + { + Cudd_Deref( bFunc ); + Abc_ObjSetGlobalBdd( pNode, NULL ); + } + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Frees the global BDDs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ) +{ + return Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, fFreeMan ); +} + +/**Function************************************************************* + + Synopsis [Returns the shared size of global BDDs of the COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vFuncsGlob; + Abc_Obj_t * pObj; + int RetValue, i; + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); + RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) ); + Vec_PtrFree( vFuncsGlob ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Computes the BDD of the logic cone of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ) +{ + /* + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pNodeR; + DdManager * dd; + DdNode * bFunc; + double Result; + int i; + pNodeR = Abc_ObjRegular(pNode); + assert( Abc_NtkIsStrash(pNodeR->pNtk) ); + Abc_NtkCleanCopy( pNodeR->pNtk ); + // get the CIs in the support of the node + vNodes = Abc_NtkNodeSupport( pNodeR->pNtk, &pNodeR, 1 ); + // start the manager + dd = Cudd_Init( Vec_PtrSize(vNodes), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + // assign elementary BDDs for the CIs + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)dd->vars[i]; + // build the BDD of the cone + bFunc = Abc_NodeGlobalBdds_rec( dd, pNodeR, 10000000, 1, NULL, NULL, 1 ); Cudd_Ref( bFunc ); + bFunc = Cudd_NotCond( bFunc, pNode != pNodeR ); + // count minterms + Result = Cudd_CountMinterm( dd, bFunc, dd->size ); + // get the percentagle + Result *= 100.0; + for ( i = 0; i < dd->size; i++ ) + Result /= 2; + // clean up + Cudd_Quit( dd ); + Vec_PtrFree( vNodes ); + return Result; + */ + return 0.0; +} + + + + +/**Function************************************************************* + + Synopsis [Experiment with BDD-based representation of implications.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBddImplicationTest() +{ + DdManager * dd; + DdNode * bImp, * bSum, * bTemp; + int nVars = 200; + int nImps = 200; + int i, clk; +clk = clock(); + dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SIFT ); + bSum = b0; Cudd_Ref( bSum ); + for ( i = 0; i < nImps; i++ ) + { + printf( "." ); + bImp = Cudd_bddAnd( dd, dd->vars[rand()%nVars], dd->vars[rand()%nVars] ); Cudd_Ref( bImp ); + bSum = Cudd_bddOr( dd, bTemp = bSum, bImp ); Cudd_Ref( bSum ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bImp ); + } + printf( "The BDD before = %d.\n", Cudd_DagSize(bSum) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SIFT, 1 ); + printf( "The BDD after = %d.\n", Cudd_DagSize(bSum) ); +PRT( "Time", clock() - clk ); + Cudd_RecursiveDeref( dd, bSum ); + Cudd_Quit( dd ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcOdc.c b/abc70930/src/base/abci/abcOdc.c new file mode 100644 index 00000000..d6e59328 --- /dev/null +++ b/abc70930/src/base/abci/abcOdc.c @@ -0,0 +1,1134 @@ +/**CFile**************************************************************** + + FileName [abcOdc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Scalable computation of observability don't-cares.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcOdc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_DC_MAX_NODES (1<<15) + +typedef unsigned short Odc_Lit_t; + +typedef struct Odc_Obj_t_ Odc_Obj_t; // 16 bytes +struct Odc_Obj_t_ +{ + Odc_Lit_t iFan0; // first fanin + Odc_Lit_t iFan1; // second fanin + Odc_Lit_t iNext; // next node in the hash table + unsigned short TravId; // the traversal ID + unsigned uData; // the computed data + unsigned uMask; // the variable mask +}; + +typedef struct Odc_Man_t_ Odc_Man_t; +struct Odc_Man_t_ +{ + // dont'-care parameters + int nVarsMax; // the max number of cut variables + int nLevels; // the number of ODC levels + int fVerbose; // the verbosiness flag + int fVeryVerbose;// the verbosiness flag to print per-node stats + int nPercCutoff; // cutoff percentage + + // windowing + Abc_Obj_t * pNode; // the node for windowing + Vec_Ptr_t * vLeaves; // the number of the cut + Vec_Ptr_t * vRoots; // the roots of the cut + Vec_Ptr_t * vBranches; // additional inputs + + // internal AIG package + // objects + int nPis; // number of PIs (nVarsMax + 32) + int nObjs; // number of objects (Const1, PIs, ANDs) + int nObjsAlloc; // number of objects allocated + Odc_Obj_t * pObjs; // objects + Odc_Lit_t iRoot; // the root object + unsigned short nTravIds; // the number of travIDs + // structural hashing + Odc_Lit_t * pTable; // hash table + int nTableSize; // hash table size + Vec_Int_t * vUsedSpots; // the used spots + + // truth tables + int nBits; // the number of bits + int nWords; // the number of words + Vec_Ptr_t * vTruths; // truth tables for each node + Vec_Ptr_t * vTruthsElem; // elementary truth tables for the PIs + unsigned * puTruth; // the place where the resulting truth table does + + // statistics + int nWins; // the number of windows processed + int nWinsEmpty; // the number of empty windows + int nSimsEmpty; // the number of empty simulation infos + int nQuantsOver; // the number of quantification overflows + int nWinsFinish; // the number of windows that finished + int nTotalDcs; // total percentage of DCs + + // runtime + int timeClean; // windowing + int timeWin; // windowing + int timeMiter; // computing the miter + int timeSim; // simulation + int timeQuant; // quantification + int timeTruth; // truth table + int timeTotal; // useful runtime + int timeAbort; // aborted runtime +}; + + +// quantity of different objects +static inline int Odc_PiNum( Odc_Man_t * p ) { return p->nPis; } +static inline int Odc_NodeNum( Odc_Man_t * p ) { return p->nObjs - p->nPis - 1; } +static inline int Odc_ObjNum( Odc_Man_t * p ) { return p->nObjs; } + +// complemented attributes of objects +static inline int Odc_IsComplement( Odc_Lit_t Lit ) { return Lit & (Odc_Lit_t)1; } +static inline Odc_Lit_t Odc_Regular( Odc_Lit_t Lit ) { return Lit & ~(Odc_Lit_t)1; } +static inline Odc_Lit_t Odc_Not( Odc_Lit_t Lit ) { return Lit ^ (Odc_Lit_t)1; } +static inline Odc_Lit_t Odc_NotCond( Odc_Lit_t Lit, int c ) { return Lit ^ (Odc_Lit_t)(c!=0); } + +// specialized Literals +static inline Odc_Lit_t Odc_Const0() { return 1; } +static inline Odc_Lit_t Odc_Const1() { return 0; } +static inline Odc_Lit_t Odc_Var( Odc_Man_t * p, int i ) { assert( i >= 0 && i < p->nPis ); return (i+1) << 1; } +static inline int Odc_IsConst( Odc_Lit_t Lit ) { return Lit < (Odc_Lit_t)2; } +static inline int Odc_IsTerm( Odc_Man_t * p, Odc_Lit_t Lit ) { return (int)(Lit>>1) <= p->nPis; } + +// accessing internal storage +static inline Odc_Obj_t * Odc_ObjNew( Odc_Man_t * p ) { assert( p->nObjs < p->nObjsAlloc ); return p->pObjs + p->nObjs++; } +static inline Odc_Lit_t Odc_Obj2Lit( Odc_Man_t * p, Odc_Obj_t * pObj ) { assert( pObj ); return (pObj - p->pObjs) << 1; } +static inline Odc_Obj_t * Odc_Lit2Obj( Odc_Man_t * p, Odc_Lit_t Lit ) { assert( !(Lit & 1) && (int)(Lit>>1) < p->nObjs ); return p->pObjs + (Lit>>1); } + +// fanins and their complements +static inline Odc_Lit_t Odc_ObjChild0( Odc_Obj_t * pObj ) { return pObj->iFan0; } +static inline Odc_Lit_t Odc_ObjChild1( Odc_Obj_t * pObj ) { return pObj->iFan1; } +static inline Odc_Lit_t Odc_ObjFanin0( Odc_Obj_t * pObj ) { return Odc_Regular(pObj->iFan0); } +static inline Odc_Lit_t Odc_ObjFanin1( Odc_Obj_t * pObj ) { return Odc_Regular(pObj->iFan1); } +static inline int Odc_ObjFaninC0( Odc_Obj_t * pObj ) { return Odc_IsComplement(pObj->iFan0); } +static inline int Odc_ObjFaninC1( Odc_Obj_t * pObj ) { return Odc_IsComplement(pObj->iFan1); } + +// traversal IDs +static inline void Odc_ManIncrementTravId( Odc_Man_t * p ) { p->nTravIds++; } +static inline void Odc_ObjSetTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } +static inline int Odc_ObjIsTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); } + +// truth tables +static inline unsigned * Odc_ObjTruth( Odc_Man_t * p, Odc_Lit_t Lit ) { assert( !(Lit & 1) ); return Vec_PtrEntry(p->vTruths, Lit >> 1); } + +// iterators +#define Odc_ForEachPi( p, Lit, i ) \ + for ( i = 0; (i < Odc_PiNum(p)) && (((Lit) = Odc_Var(p, i)), 1); i++ ) +#define Odc_ForEachAnd( p, pObj, i ) \ + for ( i = 1 + Odc_CiNum(p); (i < Odc_ObjNum(p)) && ((pObj) = (p)->pObjs + i); i++ ) + + +// exported functions +extern Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose ); +extern void Abc_NtkDontCareClear( Odc_Man_t * p ); +extern void Abc_NtkDontCareFree( Odc_Man_t * p ); +extern int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the don't-care manager.] + + Description [The parameters are the max number of cut variables, + the number of fanout levels used for the ODC computation, and verbosiness.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose ) +{ + Odc_Man_t * p; + unsigned * pData; + int i, k; + p = ALLOC( Odc_Man_t, 1 ); + memset( p, 0, sizeof(Odc_Man_t) ); + assert( nVarsMax > 4 && nVarsMax < 16 ); + assert( nLevels > 0 && nLevels < 10 ); + + srand( 0xABC ); + + // dont'-care parameters + p->nVarsMax = nVarsMax; + p->nLevels = nLevels; + p->fVerbose = fVerbose; + p->fVeryVerbose = fVeryVerbose; + p->nPercCutoff = 10; + + // windowing + p->vRoots = Vec_PtrAlloc( 128 ); + p->vBranches = Vec_PtrAlloc( 128 ); + + // internal AIG package + // allocate room for objects + p->nObjsAlloc = ABC_DC_MAX_NODES; + p->pObjs = ALLOC( Odc_Obj_t, p->nObjsAlloc * sizeof(Odc_Obj_t) ); + p->nPis = nVarsMax + 32; + p->nObjs = 1 + p->nPis; + memset( p->pObjs, 0, p->nObjs * sizeof(Odc_Obj_t) ); + // set the PI masks + for ( i = 0; i < 32; i++ ) + p->pObjs[1 + p->nVarsMax + i].uMask = (1 << i); + // allocate hash table + p->nTableSize = p->nObjsAlloc/3 + 1; + p->pTable = ALLOC( Odc_Lit_t, p->nTableSize * sizeof(Odc_Lit_t) ); + memset( p->pTable, 0, p->nTableSize * sizeof(Odc_Lit_t) ); + p->vUsedSpots = Vec_IntAlloc( 1000 ); + + // truth tables + p->nWords = Abc_TruthWordNum( p->nVarsMax ); + p->nBits = p->nWords * 8 * sizeof(unsigned); + p->vTruths = Vec_PtrAllocSimInfo( p->nObjsAlloc, p->nWords ); + p->vTruthsElem = Vec_PtrAllocSimInfo( p->nVarsMax, p->nWords ); + + // set elementary truth tables + Abc_InfoFill( Vec_PtrEntry(p->vTruths, 0), p->nWords ); + for ( k = 0; k < p->nVarsMax; k++ ) + { +// pData = Odc_ObjTruth( p, Odc_Var(p, k) ); + pData = Vec_PtrEntry( p->vTruthsElem, k ); + Abc_InfoClear( pData, p->nWords ); + for ( i = 0; i < p->nBits; i++ ) + if ( i & (1 << k) ) + pData[i>>5] |= (1 << (i&31)); + } + + // set random truth table for the additional inputs + for ( k = p->nVarsMax; k < p->nPis; k++ ) + { + pData = Odc_ObjTruth( p, Odc_Var(p, k) ); + Abc_InfoRandom( pData, p->nWords ); + } + + // set the miter to the unused value + p->iRoot = 0xffff; + return p; +} + +/**Function************************************************************* + + Synopsis [Clears the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareClear( Odc_Man_t * p ) +{ + int clk = clock(); + // clean the structural hashing table + if ( Vec_IntSize(p->vUsedSpots) > p->nTableSize/3 ) // more than one third + memset( p->pTable, 0, sizeof(Odc_Lit_t) * p->nTableSize ); + else + { + int iSpot, i; + Vec_IntForEachEntry( p->vUsedSpots, iSpot, i ) + p->pTable[iSpot] = 0; + } + Vec_IntClear( p->vUsedSpots ); + // reset the number of nodes + p->nObjs = 1 + p->nPis; + // reset the root node + p->iRoot = 0xffff; + +p->timeClean += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [Frees the don't-care manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareFree( Odc_Man_t * p ) +{ + if ( p->fVerbose ) + { + printf( "Wins = %5d. Empty = %5d. SimsEmpty = %5d. QuantOver = %5d. WinsFinish = %5d.\n", + p->nWins, p->nWinsEmpty, p->nSimsEmpty, p->nQuantsOver, p->nWinsFinish ); + printf( "Ave DCs per window = %6.2f %%. Ave DCs per finished window = %6.2f %%.\n", + 1.0*p->nTotalDcs/p->nWins, 1.0*p->nTotalDcs/p->nWinsFinish ); + printf( "Runtime stats of the ODC manager:\n" ); + PRT( "Cleaning ", p->timeClean ); + PRT( "Windowing ", p->timeWin ); + PRT( "Miter ", p->timeMiter ); + PRT( "Simulation ", p->timeSim ); + PRT( "Quantifying ", p->timeQuant ); + PRT( "Truth table ", p->timeTruth ); + PRT( "TOTAL ", p->timeTotal ); + PRT( "Aborted ", p->timeAbort ); + } + Vec_PtrFree( p->vRoots ); + Vec_PtrFree( p->vBranches ); + Vec_PtrFree( p->vTruths ); + Vec_PtrFree( p->vTruthsElem ); + Vec_IntFree( p->vUsedSpots ); + free( p->pObjs ); + free( p->pTable ); + free( p ); +} + + + +/**Function************************************************************* + + Synopsis [Marks the TFO of the collected nodes up to the given level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareWinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i; + if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit || pObj == pNode ) + return; + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return; + Abc_NodeSetTravIdCurrent( pObj ); + //////////////////////////////////////// + // try to reduce the runtime + if ( Abc_ObjFanoutNum(pObj) > 100 ) + return; + //////////////////////////////////////// + Abc_ObjForEachFanout( pObj, pFanout, i ) + Abc_NtkDontCareWinSweepLeafTfo_rec( pFanout, nLevelLimit, pNode ); +} + +/**Function************************************************************* + + Synopsis [Marks the TFO of the collected nodes up to the given level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareWinSweepLeafTfo( Odc_Man_t * p ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkIncrementTravId( p->pNode->pNtk ); + Vec_PtrForEachEntry( p->vLeaves, pObj, i ) + Abc_NtkDontCareWinSweepLeafTfo_rec( pObj, p->pNode->Level + p->nLevels, p->pNode ); +} + +/**Function************************************************************* + + Synopsis [Recursively collects the roots.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareWinCollectRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots ) +{ + Abc_Obj_t * pFanout; + int i; + assert( Abc_ObjIsNode(pObj) ); + assert( Abc_NodeIsTravIdCurrent(pObj) ); + // check if the node has all fanouts marked + Abc_ObjForEachFanout( pObj, pFanout, i ) + if ( !Abc_NodeIsTravIdCurrent(pFanout) ) + break; + // if some of the fanouts are unmarked, add the node to the root + if ( i < Abc_ObjFanoutNum(pObj) ) + { + Vec_PtrPushUnique( vRoots, pObj ); + return; + } + // otherwise, call recursively + Abc_ObjForEachFanout( pObj, pFanout, i ) + Abc_NtkDontCareWinCollectRoots_rec( pFanout, vRoots ); +} + +/**Function************************************************************* + + Synopsis [Collects the roots of the window.] + + Description [Roots of the window are the nodes that have at least + one fanout that it not in the TFO of the leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareWinCollectRoots( Odc_Man_t * p ) +{ + assert( !Abc_NodeIsTravIdCurrent(p->pNode) ); + // mark the node with the old traversal ID + Abc_NodeSetTravIdCurrent( p->pNode ); + // collect the roots + Vec_PtrClear( p->vRoots ); + Abc_NtkDontCareWinCollectRoots_rec( p->pNode, p->vRoots ); +} + +/**Function************************************************************* + + Synopsis [Recursively adds missing nodes and leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareWinAddMissing_rec( Odc_Man_t * p, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + // skip the already collected leaves and branches + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 1; + // if this is not an internal node - make it a new branch + if ( !Abc_NodeIsTravIdPrevious(pObj) || Abc_ObjIsCi(pObj) ) //|| (int)pObj->Level <= p->nLevLeaves ) + { + Abc_NodeSetTravIdCurrent( pObj ); + Vec_PtrPush( p->vBranches, pObj ); + return Vec_PtrSize(p->vBranches) <= 32; + } + // visit the fanins of the node + Abc_ObjForEachFanin( pObj, pFanin, i ) + if ( !Abc_NtkDontCareWinAddMissing_rec( p, pFanin ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds to the window nodes and leaves in the TFI of the roots.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareWinAddMissing( Odc_Man_t * p ) +{ + Abc_Obj_t * pObj; + int i; + // set the leaves + Abc_NtkIncrementTravId( p->pNode->pNtk ); + Vec_PtrForEachEntry( p->vLeaves, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + // explore from the roots + Vec_PtrClear( p->vBranches ); + Vec_PtrForEachEntry( p->vRoots, pObj, i ) + if ( !Abc_NtkDontCareWinAddMissing_rec( p, pObj ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes window for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareWindow( Odc_Man_t * p ) +{ + // mark the TFO of the collected nodes up to the given level (p->pNode->Level + p->nWinTfoMax) + Abc_NtkDontCareWinSweepLeafTfo( p ); + // find the roots of the window + Abc_NtkDontCareWinCollectRoots( p ); + if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode ) + { +// printf( "Empty window\n" ); + return 0; + } + // add the nodes in the TFI of the roots that are not yet in the window + if ( !Abc_NtkDontCareWinAddMissing( p ) ) + { +// printf( "Too many branches (%d)\n", Vec_PtrSize(p->vBranches) ); + return 0; + } + return 1; +} + + + + + +/**Function************************************************************* + + Synopsis [Performing hashing of two AIG Literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Odc_HashKey( Odc_Lit_t iFan0, Odc_Lit_t iFan1, int TableSize ) +{ + unsigned Key = 0; + Key ^= Odc_Regular(iFan0) * 7937; + Key ^= Odc_Regular(iFan1) * 2971; + Key ^= Odc_IsComplement(iFan0) * 911; + Key ^= Odc_IsComplement(iFan1) * 353; + return Key % TableSize; +} + +/**Function************************************************************* + + Synopsis [Checks if the given name node already exists in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Odc_Lit_t * Odc_HashLookup( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) +{ + Odc_Obj_t * pObj; + Odc_Lit_t * pEntry; + unsigned uHashKey; + assert( iFan0 < iFan1 ); + // get the hash key for this node + uHashKey = Odc_HashKey( iFan0, iFan1, p->nTableSize ); + // remember the spot in the hash table that will be used + if ( p->pTable[uHashKey] == 0 ) + Vec_IntPush( p->vUsedSpots, uHashKey ); + // find the entry + for ( pEntry = p->pTable + uHashKey; *pEntry; pEntry = &pObj->iNext ) + { + pObj = Odc_Lit2Obj( p, *pEntry ); + if ( pObj->iFan0 == iFan0 && pObj->iFan1 == iFan1 ) + return pEntry; + } + return pEntry; +} + +/**Function************************************************************* + + Synopsis [Finds node by structural hashing or creates a new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Odc_Lit_t Odc_And( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) +{ + Odc_Obj_t * pObj; + Odc_Lit_t * pEntry; + unsigned uMask0, uMask1; + int Temp; + // consider trivial cases + if ( iFan0 == iFan1 ) + return iFan0; + if ( iFan0 == Odc_Not(iFan1) ) + return Odc_Const0(); + if ( Odc_Regular(iFan0) == Odc_Const1() ) + return iFan0 == Odc_Const1() ? iFan1 : Odc_Const0(); + if ( Odc_Regular(iFan1) == Odc_Const1() ) + return iFan1 == Odc_Const1() ? iFan0 : Odc_Const0(); + // canonicize the fanin order + if ( iFan0 > iFan1 ) + Temp = iFan0, iFan0 = iFan1, iFan1 = Temp; + // check if a node with these fanins exists + pEntry = Odc_HashLookup( p, iFan0, iFan1 ); + if ( *pEntry ) + return *pEntry; + // create a new node + pObj = Odc_ObjNew( p ); + pObj->iFan0 = iFan0; + pObj->iFan1 = iFan1; + pObj->iNext = 0; + pObj->TravId = 0; + // set the mask + uMask0 = Odc_Lit2Obj(p, Odc_Regular(iFan0))->uMask; + uMask1 = Odc_Lit2Obj(p, Odc_Regular(iFan1))->uMask; + pObj->uMask = uMask0 | uMask1; + // add to the table + *pEntry = Odc_Obj2Lit( p, pObj ); + return *pEntry; +} + +/**Function************************************************************* + + Synopsis [Boolean OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Odc_Lit_t Odc_Or( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) +{ + return Odc_Not( Odc_And(p, Odc_Not(iFan0), Odc_Not(iFan1)) ); +} + +/**Function************************************************************* + + Synopsis [Boolean XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Odc_Lit_t Odc_Xor( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) +{ + return Odc_Or( p, Odc_And(p, iFan0, Odc_Not(iFan1)), Odc_And(p, Odc_Not(iFan0), iFan1) ); +} + + + + + +/**Function************************************************************* + + Synopsis [Transfers the window into the AIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NtkDontCareTransfer_rec( Odc_Man_t * p, Abc_Obj_t * pNode, Abc_Obj_t * pPivot ) +{ + unsigned uData0, uData1; + Odc_Lit_t uLit0, uLit1, uRes0, uRes1; + assert( !Abc_ObjIsComplement(pNode) ); + // skip visited objects + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return pNode->pCopy; + Abc_NodeSetTravIdCurrent(pNode); + assert( Abc_ObjIsNode(pNode) ); + // consider the case when the node is the pivot + if ( pNode == pPivot ) + return pNode->pCopy = (void *)((Odc_Const1() << 16) | Odc_Const0()); + // compute the cofactors + uData0 = (unsigned)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin0(pNode), pPivot ); + uData1 = (unsigned)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin1(pNode), pPivot ); + // find the 0-cofactor + uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Abc_ObjFaninC0(pNode) ); + uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Abc_ObjFaninC1(pNode) ); + uRes0 = Odc_And( p, uLit0, uLit1 ); + // find the 1-cofactor + uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Abc_ObjFaninC0(pNode) ); + uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Abc_ObjFaninC1(pNode) ); + uRes1 = Odc_And( p, uLit0, uLit1 ); + // find the result + return pNode->pCopy = (void *)((uRes1 << 16) | uRes0); +} + +/**Function************************************************************* + + Synopsis [Transfers the window into the AIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareTransfer( Odc_Man_t * p ) +{ + Abc_Obj_t * pObj; + Odc_Lit_t uRes0, uRes1; + Odc_Lit_t uLit; + unsigned uData; + int i; + Abc_NtkIncrementTravId( p->pNode->pNtk ); + // set elementary variables at the leaves + Vec_PtrForEachEntry( p->vLeaves, pObj, i ) + { + uLit = Odc_Var( p, i ); + pObj->pCopy = (void *)((uLit << 16) | uLit); + Abc_NodeSetTravIdCurrent(pObj); + } + // set elementary variables at the branched + Vec_PtrForEachEntry( p->vBranches, pObj, i ) + { + uLit = Odc_Var( p, i+p->nVarsMax ); + pObj->pCopy = (void *)((uLit << 16) | uLit); + Abc_NodeSetTravIdCurrent(pObj); + } + // compute the AIG for the window + p->iRoot = Odc_Const0(); + Vec_PtrForEachEntry( p->vRoots, pObj, i ) + { + uData = (unsigned)Abc_NtkDontCareTransfer_rec( p, pObj, p->pNode ); + // get the cofactors + uRes0 = uData & 0xffff; + uRes1 = uData >> 16; + // compute the miter +// assert( uRes0 != uRes1 ); // may be false if the node is redundant w.r.t. this root + uLit = Odc_Xor( p, uRes0, uRes1 ); + p->iRoot = Odc_Or( p, p->iRoot, uLit ); + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Recursively computes the pair of cofactors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Abc_NtkDontCareCofactors_rec( Odc_Man_t * p, Odc_Lit_t Lit, unsigned uMask ) +{ + Odc_Obj_t * pObj; + unsigned uData0, uData1; + Odc_Lit_t uLit0, uLit1, uRes0, uRes1; + assert( !Odc_IsComplement(Lit) ); + // skip visited objects + pObj = Odc_Lit2Obj( p, Lit ); + if ( Odc_ObjIsTravIdCurrent(p, pObj) ) + return pObj->uData; + Odc_ObjSetTravIdCurrent(p, pObj); + // skip objects out of the cone + if ( (pObj->uMask & uMask) == 0 ) + return pObj->uData = ((Lit << 16) | Lit); + // consider the case when the node is the var + if ( pObj->uMask == uMask && Odc_IsTerm(p, Lit) ) + return pObj->uData = ((Odc_Const1() << 16) | Odc_Const0()); + // compute the cofactors + uData0 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin0(pObj), uMask ); + uData1 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin1(pObj), uMask ); + // find the 0-cofactor + uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Odc_ObjFaninC0(pObj) ); + uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Odc_ObjFaninC1(pObj) ); + uRes0 = Odc_And( p, uLit0, uLit1 ); + // find the 1-cofactor + uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Odc_ObjFaninC0(pObj) ); + uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Odc_ObjFaninC1(pObj) ); + uRes1 = Odc_And( p, uLit0, uLit1 ); + // find the result + return pObj->uData = ((uRes1 << 16) | uRes0); +} + +/**Function************************************************************* + + Synopsis [Quantifies the branch variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareQuantify( Odc_Man_t * p ) +{ + Odc_Lit_t uRes0, uRes1; + unsigned uData; + int i; + assert( p->iRoot < 0xffff ); + assert( Vec_PtrSize(p->vBranches) <= 32 ); // the mask size + for ( i = 0; i < Vec_PtrSize(p->vBranches); i++ ) + { + // compute the cofactors w.r.t. this variable + Odc_ManIncrementTravId( p ); + uData = Abc_NtkDontCareCofactors_rec( p, Odc_Regular(p->iRoot), (1 << i) ); + uRes0 = Odc_NotCond( (Odc_Lit_t)(uData & 0xffff), Odc_IsComplement(p->iRoot) ); + uRes1 = Odc_NotCond( (Odc_Lit_t)(uData >> 16), Odc_IsComplement(p->iRoot) ); + // quantify this variable existentially + p->iRoot = Odc_Or( p, uRes0, uRes1 ); + // check the limit + if ( Odc_ObjNum(p) > ABC_DC_MAX_NODES/2 ) + return 0; + } + assert( p->nObjs <= p->nObjsAlloc ); + return 1; +} + + + +/**Function************************************************************* + + Synopsis [Set elementary truth tables for PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareSimulateSetElem2( Odc_Man_t * p ) +{ + unsigned * pData; + int i, k; + for ( k = 0; k < p->nVarsMax; k++ ) + { + pData = Odc_ObjTruth( p, Odc_Var(p, k) ); + Abc_InfoClear( pData, p->nWords ); + for ( i = 0; i < p->nBits; i++ ) + if ( i & (1 << k) ) + pData[i>>5] |= (1 << (i&31)); + } +} + +/**Function************************************************************* + + Synopsis [Set elementary truth tables for PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareSimulateSetElem( Odc_Man_t * p ) +{ + unsigned * pData, * pData2; + int k; + for ( k = 0; k < p->nVarsMax; k++ ) + { + pData = Odc_ObjTruth( p, Odc_Var(p, k) ); + pData2 = Vec_PtrEntry( p->vTruthsElem, k ); + Abc_InfoCopy( pData, pData2, p->nWords ); + } +} + +/**Function************************************************************* + + Synopsis [Set random simulation words for PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareSimulateSetRand( Odc_Man_t * p ) +{ + unsigned * pData; + int w, k, Number; + for ( w = 0; w < p->nWords; w++ ) + { + Number = rand(); + for ( k = 0; k < p->nVarsMax; k++ ) + { + pData = Odc_ObjTruth( p, Odc_Var(p, k) ); + pData[w] = (Number & (1<<k)) ? ~0 : 0; + } + } +} + +/**Function************************************************************* + + Synopsis [Set random simulation words for PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareCountMintsWord( Odc_Man_t * p, unsigned * puTruth ) +{ + int w, Counter = 0; + for ( w = 0; w < p->nWords; w++ ) + if ( puTruth[w] ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareTruthOne( Odc_Man_t * p, Odc_Lit_t Lit ) +{ + Odc_Obj_t * pObj; + unsigned * pInfo, * pInfo1, * pInfo2; + int k, fComp1, fComp2; + assert( !Odc_IsComplement( Lit ) ); + assert( !Odc_IsTerm( p, Lit ) ); + // get the truth tables + pObj = Odc_Lit2Obj( p, Lit ); + pInfo = Odc_ObjTruth( p, Lit ); + pInfo1 = Odc_ObjTruth( p, Odc_ObjFanin0(pObj) ); + pInfo2 = Odc_ObjTruth( p, Odc_ObjFanin1(pObj) ); + fComp1 = Odc_ObjFaninC0( pObj ); + fComp2 = Odc_ObjFaninC1( pObj ); + // simulate + if ( fComp1 && fComp2 ) + for ( k = 0; k < p->nWords; k++ ) + pInfo[k] = ~pInfo1[k] & ~pInfo2[k]; + else if ( fComp1 && !fComp2 ) + for ( k = 0; k < p->nWords; k++ ) + pInfo[k] = ~pInfo1[k] & pInfo2[k]; + else if ( !fComp1 && fComp2 ) + for ( k = 0; k < p->nWords; k++ ) + pInfo[k] = pInfo1[k] & ~pInfo2[k]; + else // if ( fComp1 && fComp2 ) + for ( k = 0; k < p->nWords; k++ ) + pInfo[k] = pInfo1[k] & pInfo2[k]; +} + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareSimulate_rec( Odc_Man_t * p, Odc_Lit_t Lit ) +{ + Odc_Obj_t * pObj; + assert( !Odc_IsComplement(Lit) ); + // skip terminals + if ( Odc_IsTerm(p, Lit) ) + return; + // skip visited objects + pObj = Odc_Lit2Obj( p, Lit ); + if ( Odc_ObjIsTravIdCurrent(p, pObj) ) + return; + Odc_ObjSetTravIdCurrent(p, pObj); + // call recursively + Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin0(pObj) ); + Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin1(pObj) ); + // construct the truth table + Abc_NtkDontCareTruthOne( p, Lit ); +} + +/**Function************************************************************* + + Synopsis [Computes the truth table of the care set.] + + Description [Returns the number of ones in the simulation info.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareSimulate( Odc_Man_t * p, unsigned * puTruth ) +{ + Odc_ManIncrementTravId( p ); + Abc_NtkDontCareSimulate_rec( p, Odc_Regular(p->iRoot) ); + Abc_InfoCopy( puTruth, Odc_ObjTruth(p, Odc_Regular(p->iRoot)), p->nWords ); + if ( Odc_IsComplement(p->iRoot) ) + Abc_InfoNot( puTruth, p->nWords ); + return Extra_TruthCountOnes( puTruth, p->nVarsMax ); +} + +/**Function************************************************************* + + Synopsis [Computes the truth table of the care set.] + + Description [Returns the number of ones in the simulation info.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareSimulateBefore( Odc_Man_t * p, unsigned * puTruth ) +{ + int nIters = 2; + int nRounds, Counter, r; + // decide how many rounds to simulate + nRounds = p->nBits / p->nWords; + Counter = 0; + for ( r = 0; r < nIters; r++ ) + { + Abc_NtkDontCareSimulateSetRand( p ); + Abc_NtkDontCareSimulate( p, puTruth ); + Counter += Abc_NtkDontCareCountMintsWord( p, puTruth ); + } + // normalize + Counter = Counter * nRounds / nIters; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Computes ODCs for the node in terms of the cut variables.] + + Description [Returns the number of don't care minterms in the truth table. + In particular, this procedure returns 0 if there is no don't-cares.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth ) +{ + int nMints, RetValue; + int clk, clkTotal = clock(); + + p->nWins++; + + // set the parameters + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + assert( Vec_PtrSize(vLeaves) <= p->nVarsMax ); + p->vLeaves = vLeaves; + p->pNode = pNode; + + // compute the window +clk = clock(); + RetValue = Abc_NtkDontCareWindow( p ); +p->timeWin += clock() - clk; + if ( !RetValue ) + { +p->timeAbort += clock() - clkTotal; + Abc_InfoFill( puTruth, p->nWords ); + p->nWinsEmpty++; + return 0; + } + + if ( p->fVeryVerbose ) + { + printf( " %5d : ", pNode->Id ); + printf( "Leaf = %2d ", Vec_PtrSize(p->vLeaves) ); + printf( "Root = %2d ", Vec_PtrSize(p->vRoots) ); + printf( "Bran = %2d ", Vec_PtrSize(p->vBranches) ); + printf( " | " ); + } + + // transfer the window into the AIG package +clk = clock(); + Abc_NtkDontCareTransfer( p ); +p->timeMiter += clock() - clk; + + // simulate to estimate the amount of don't-cares +clk = clock(); + nMints = Abc_NtkDontCareSimulateBefore( p, puTruth ); +p->timeSim += clock() - clk; + if ( p->fVeryVerbose ) + { + printf( "AIG = %5d ", Odc_NodeNum(p) ); + printf( "%6.2f %% ", 100.0 * (p->nBits - nMints) / p->nBits ); + } + + // if there is less then the given percentage of don't-cares, skip + if ( 100.0 * (p->nBits - nMints) / p->nBits < 1.0 * p->nPercCutoff ) + { +p->timeAbort += clock() - clkTotal; + if ( p->fVeryVerbose ) + printf( "Simulation cutoff.\n" ); + Abc_InfoFill( puTruth, p->nWords ); + p->nSimsEmpty++; + return 0; + } + + // quantify external variables +clk = clock(); + RetValue = Abc_NtkDontCareQuantify( p ); +p->timeQuant += clock() - clk; + if ( !RetValue ) + { +p->timeAbort += clock() - clkTotal; + if ( p->fVeryVerbose ) + printf( "=== Overflow! ===\n" ); + Abc_InfoFill( puTruth, p->nWords ); + p->nQuantsOver++; + return 0; + } + + // get the truth table +clk = clock(); + Abc_NtkDontCareSimulateSetElem( p ); + nMints = Abc_NtkDontCareSimulate( p, puTruth ); +p->timeTruth += clock() - clk; + if ( p->fVeryVerbose ) + { + printf( "AIG = %5d ", Odc_NodeNum(p) ); + printf( "%6.2f %% ", 100.0 * (p->nBits - nMints) / p->nBits ); + printf( "\n" ); + } +p->timeTotal += clock() - clkTotal; + p->nWinsFinish++; + p->nTotalDcs += (int)(100.0 * (p->nBits - nMints) / p->nBits); + return nMints; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcOrder.c b/abc70930/src/base/abci/abcOrder.c new file mode 100644 index 00000000..04417f77 --- /dev/null +++ b/abc70930/src/base/abci/abcOrder.c @@ -0,0 +1,131 @@ +/**CFile**************************************************************** + + FileName [abcOrder.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Exploring static BDD variable orders.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcOrder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Changes the order of primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose ) +{ + Vec_Ptr_t * vSupp; + vSupp = Abc_NtkSupport( pNtk ); + Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse ); + Vec_PtrFree( vSupp ); +} + +/**Function************************************************************* + + Synopsis [Implements the given variable order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose ) +{ + char Buffer[1000]; + FILE * pFile; + Vec_Ptr_t * vSupp; + Abc_Obj_t * pObj; + pFile = fopen( pFileName, "r" ); + vSupp = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) ); + while ( fscanf( pFile, "%s", Buffer ) == 1 ) + { + pObj = Abc_NtkFindCi( pNtk, Buffer ); + if ( pObj == NULL || !Abc_ObjIsCi(pObj) ) + { + printf( "Name \"%s\" is not a PI name. Cannot use this order.\n", Buffer ); + Vec_PtrFree( vSupp ); + fclose( pFile ); + return; + } + Vec_PtrPush( vSupp, pObj ); + } + fclose( pFile ); + if ( Vec_PtrSize(vSupp) != Abc_NtkCiNum(pNtk) ) + { + printf( "The number of names in the order (%d) is not the same as the number of PIs (%d).\n", Vec_PtrSize(vSupp), Abc_NtkCiNum(pNtk) ); + Vec_PtrFree( vSupp ); + return; + } + Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse ); + Vec_PtrFree( vSupp ); +} + +/**Function************************************************************* + + Synopsis [Changes the order of primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse ) +{ + Abc_Obj_t * pObj; + int i; + assert( Vec_PtrSize(vSupp) == Abc_NtkCiNum(pNtk) ); + // order CIs using the array + if ( fReverse ) + Vec_PtrForEachEntry( vSupp, pObj, i ) + Vec_PtrWriteEntry( pNtk->vCis, Vec_PtrSize(vSupp)-1-i, pObj ); + else + Vec_PtrForEachEntry( vSupp, pObj, i ) + Vec_PtrWriteEntry( pNtk->vCis, i, pObj ); + // order PIs accordingly + Vec_PtrClear( pNtk->vPis ); + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjIsPi(pObj) ) + Vec_PtrPush( pNtk->vPis, pObj ); +// Abc_NtkForEachCi( pNtk, pObj, i ) +// printf( "%s ", Abc_ObjName(pObj) ); +// printf( "\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcPart.c b/abc70930/src/base/abci/abcPart.c new file mode 100644 index 00000000..85c4e918 --- /dev/null +++ b/abc70930/src/base/abci/abcPart.c @@ -0,0 +1,1205 @@ +/**CFile**************************************************************** + + FileName [abcPart.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Output partitioning package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcPart.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Supp_Man_t_ Supp_Man_t; +struct Supp_Man_t_ +{ + int nChunkSize; // the size of one chunk of memory (~1 Mb) + int nStepSize; // the step size in saving memory (~64 bytes) + char * pFreeBuf; // the pointer to free memory + int nFreeSize; // the size of remaining free memory + Vec_Ptr_t * vMemory; // the memory allocated + Vec_Ptr_t * vFree; // the vector of free pieces of memory +}; + +typedef struct Supp_One_t_ Supp_One_t; +struct Supp_One_t_ +{ + int nRefs; // the number of references + int nOuts; // the number of outputs + int nOutsAlloc; // the array size + int pOuts[0]; // the array of outputs +}; + +static inline int Supp_SizeType( int nSize, int nStepSize ) { return nSize / nStepSize + ((nSize % nStepSize) > 0); } +static inline char * Supp_OneNext( char * pPart ) { return *((char **)pPart); } +static inline void Supp_OneSetNext( char * pPart, char * pNext ) { *((char **)pPart) = pNext; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Supp_Man_t * Supp_ManStart( int nChunkSize, int nStepSize ) +{ + Supp_Man_t * p; + p = ALLOC( Supp_Man_t, 1 ); + memset( p, 0, sizeof(Supp_Man_t) ); + p->nChunkSize = nChunkSize; + p->nStepSize = nStepSize; + p->vMemory = Vec_PtrAlloc( 1000 ); + p->vFree = Vec_PtrAlloc( 1000 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Supp_ManStop( Supp_Man_t * p ) +{ + void * pMemory; + int i; + Vec_PtrForEachEntry( p->vMemory, pMemory, i ) + free( pMemory ); + Vec_PtrFree( p->vMemory ); + Vec_PtrFree( p->vFree ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Fetches the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Supp_ManFetch( Supp_Man_t * p, int nSize ) +{ + int Type, nSizeReal; + char * pMemory; + assert( nSize > 0 ); + Type = Supp_SizeType( nSize, p->nStepSize ); + Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); + if ( pMemory = Vec_PtrEntry( p->vFree, Type ) ) + { + Vec_PtrWriteEntry( p->vFree, Type, Supp_OneNext(pMemory) ); + return pMemory; + } + nSizeReal = p->nStepSize * Type; + if ( p->nFreeSize < nSizeReal ) + { + p->pFreeBuf = ALLOC( char, p->nChunkSize ); + p->nFreeSize = p->nChunkSize; + Vec_PtrPush( p->vMemory, p->pFreeBuf ); + } + assert( p->nFreeSize >= nSizeReal ); + pMemory = p->pFreeBuf; + p->pFreeBuf += nSizeReal; + p->nFreeSize -= nSizeReal; + return pMemory; +} + +/**Function************************************************************* + + Synopsis [Recycles the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Supp_ManRecycle( Supp_Man_t * p, char * pMemory, int nSize ) +{ + int Type; + Type = Supp_SizeType( nSize, p->nStepSize ); + Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); + Supp_OneSetNext( pMemory, Vec_PtrEntry(p->vFree, Type) ); + Vec_PtrWriteEntry( p->vFree, Type, pMemory ); +} + +/**Function************************************************************* + + Synopsis [Fetches the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Supp_One_t * Supp_ManFetchEntry( Supp_Man_t * p, int nWords, int nRefs ) +{ + Supp_One_t * pPart; + pPart = (Supp_One_t *)Supp_ManFetch( p, sizeof(Supp_One_t) + sizeof(int) * nWords ); + pPart->nRefs = nRefs; + pPart->nOuts = 0; + pPart->nOutsAlloc = nWords; + return pPart; +} + +/**Function************************************************************* + + Synopsis [Recycles the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Supp_ManRecycleEntry( Supp_Man_t * p, Supp_One_t * pEntry ) +{ + assert( pEntry->nOuts <= pEntry->nOutsAlloc ); + assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 ); + Supp_ManRecycle( p, (char *)pEntry, sizeof(Supp_One_t) + sizeof(int) * pEntry->nOutsAlloc ); +} + +/**Function************************************************************* + + Synopsis [Merges two entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Supp_One_t * Supp_ManMergeEntry( Supp_Man_t * pMan, Supp_One_t * p1, Supp_One_t * p2, int nRefs ) +{ + Supp_One_t * p = Supp_ManFetchEntry( pMan, p1->nOuts + p2->nOuts, nRefs ); + int * pBeg1 = p1->pOuts; + int * pBeg2 = p2->pOuts; + int * pBeg = p->pOuts; + int * pEnd1 = p1->pOuts + p1->nOuts; + int * pEnd2 = p2->pOuts + p2->nOuts; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( *pBeg1 == *pBeg2 ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( *pBeg1 < *pBeg2 ) + *pBeg++ = *pBeg1++; + else + *pBeg++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + *pBeg++ = *pBeg1++; + while ( pBeg2 < pEnd2 ) + *pBeg++ = *pBeg2++; + p->nOuts = pBeg - p->pOuts; + assert( p->nOuts <= p->nOutsAlloc ); + assert( p->nOuts >= p1->nOuts ); + assert( p->nOuts >= p2->nOuts ); + return p; +} + +/**Function************************************************************* + + Synopsis [Tranfers the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Supp_ManTransferEntry( Supp_One_t * p ) +{ + Vec_Int_t * vSupp; + int i; + vSupp = Vec_IntAlloc( p->nOuts ); + for ( i = 0; i < p->nOuts; i++ ) + Vec_IntPush( vSupp, p->pOuts[i] ); + return vSupp; +} + +/**Function************************************************************* + + Synopsis [Computes supports of the POs in the multi-output AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsNatural( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pNext; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); + vNodes = Vec_PtrAlloc( Abc_NtkObjNum(pNtk) ); + Abc_NtkIncrementTravId( pNtk ); + // add the constant-1 nodes + pObj = Abc_AigConst1(pNtk); + Abc_NodeSetTravIdCurrent( pObj ); + Vec_PtrPush( vNodes, pObj ); + // add the CIs/nodes/COs in the topological order + Abc_NtkForEachNode( pNtk, pObj, i ) + { + // check the fanins and add CIs + Abc_ObjForEachFanin( pObj, pNext, k ) + if ( Abc_ObjIsCi(pNext) && !Abc_NodeIsTravIdCurrent(pNext) ) + { + Abc_NodeSetTravIdCurrent( pNext ); + Vec_PtrPush( vNodes, pNext ); + } + // add the node + Vec_PtrPush( vNodes, pObj ); + // check the fanouts and add COs + Abc_ObjForEachFanout( pObj, pNext, k ) + if ( Abc_ObjIsCo(pNext) && !Abc_NodeIsTravIdCurrent(pNext) ) + { + Abc_NodeSetTravIdCurrent( pNext ); + Vec_PtrPush( vNodes, pNext ); + } + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes supports of the POs.] + + Description [Returns the ptr-vector of int-vectors.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkComputeSupportsSmart( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSupports; + Vec_Ptr_t * vNodes; + Vec_Int_t * vSupp; + Supp_Man_t * p; + Supp_One_t * pPart0, * pPart1; + Abc_Obj_t * pObj; + int i; + // set the number of PIs/POs + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pNext = (Abc_Obj_t *)i; + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->pNext = (Abc_Obj_t *)i; + // start the support computation manager + p = Supp_ManStart( 1 << 20, 1 << 6 ); + // consider objects in the topological order + vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkCleanCopy(pNtk); + // order the nodes so that the PIs and POs follow naturally + vNodes = Abc_NtkDfsNatural( pNtk ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + if ( Abc_ObjIsNode(pObj) ) + { + pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy; + pPart1 = (Supp_One_t *)Abc_ObjFanin1(pObj)->pCopy; + pObj->pCopy = (Abc_Obj_t *)Supp_ManMergeEntry( p, pPart0, pPart1, Abc_ObjFanoutNum(pObj) ); + assert( pPart0->nRefs > 0 ); + if ( --pPart0->nRefs == 0 ) + Supp_ManRecycleEntry( p, pPart0 ); + assert( pPart1->nRefs > 0 ); + if ( --pPart1->nRefs == 0 ) + Supp_ManRecycleEntry( p, pPart1 ); + continue; + } + if ( Abc_ObjIsCo(pObj) ) + { + pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy; + // only save the CO if it is non-trivial + if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) + { + vSupp = Supp_ManTransferEntry(pPart0); + Vec_IntPush( vSupp, (int)pObj->pNext ); + Vec_PtrPush( vSupports, vSupp ); + } + assert( pPart0->nRefs > 0 ); + if ( --pPart0->nRefs == 0 ) + Supp_ManRecycleEntry( p, pPart0 ); + continue; + } + if ( Abc_ObjIsCi(pObj) ) + { + if ( Abc_ObjFanoutNum(pObj) ) + { + pPart0 = (Supp_One_t *)Supp_ManFetchEntry( p, 1, Abc_ObjFanoutNum(pObj) ); + pPart0->pOuts[ pPart0->nOuts++ ] = (int)pObj->pNext; + pObj->pCopy = (Abc_Obj_t *)pPart0; + } + continue; + } + if ( pObj == Abc_AigConst1(pNtk) ) + { + if ( Abc_ObjFanoutNum(pObj) ) + pObj->pCopy = (Abc_Obj_t *)Supp_ManFetchEntry( p, 0, Abc_ObjFanoutNum(pObj) ); + continue; + } + assert( 0 ); + } + Vec_PtrFree( vNodes ); +//printf( "Memory usage = %d Mb.\n", Vec_PtrSize(p->vMemory) * p->nChunkSize / (1<<20) ); + Supp_ManStop( p ); + // sort supports by size + Vec_VecSort( (Vec_Vec_t *)vSupports, 1 ); + // clear the number of PIs/POs + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pNext = NULL; + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->pNext = NULL; +/* + Vec_PtrForEachEntry( vSupports, vSupp, i ) + printf( "%d ", Vec_IntSize(vSupp) ); + printf( "\n" ); +*/ + return vSupports; +} + + +/**Function************************************************************* + + Synopsis [Computes supports of the POs using naive method.] + + Description [Returns the ptr-vector of int-vectors.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkComputeSupportsNaive( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSupp, * vSupports; + Vec_Int_t * vSuppI; + Abc_Obj_t * pObj, * pTemp; + int i, k; + // set the PI numbers + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pNext = (void *)i; + // save the CI numbers + vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( !Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) + continue; + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + vSuppI = (Vec_Int_t *)vSupp; + Vec_PtrForEachEntry( vSupp, pTemp, k ) + Vec_IntWriteEntry( vSuppI, k, (int)pTemp->pNext ); + Vec_IntSort( vSuppI, 0 ); + // append the number of this output + Vec_IntPush( vSuppI, i ); + // save the support in the vector + Vec_PtrPush( vSupports, vSuppI ); + } + // clean the CI numbers + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pNext = NULL; + // sort supports by size + Vec_VecSort( (Vec_Vec_t *)vSupports, 1 ); +/* + Vec_PtrForEachEntry( vSupports, vSuppI, i ) + printf( "%d ", Vec_IntSize(vSuppI) ); + printf( "\n" ); +*/ + return vSupports; +} + +/**Function************************************************************* + + Synopsis [Start bitwise support representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Abc_NtkSuppCharStart( Vec_Int_t * vOne, int nPis ) +{ + unsigned * pBuffer; + int i, Entry; + int nWords = Abc_BitWordNum(nPis); + pBuffer = ALLOC( unsigned, nWords ); + memset( pBuffer, 0, sizeof(unsigned) * nWords ); + Vec_IntForEachEntry( vOne, Entry, i ) + { + assert( Entry < nPis ); + Abc_InfoSetBit( pBuffer, Entry ); + } + return pBuffer; +} + +/**Function************************************************************* + + Synopsis [Add to bitwise support representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSuppCharAdd( unsigned * pBuffer, Vec_Int_t * vOne, int nPis ) +{ + int i, Entry; + Vec_IntForEachEntry( vOne, Entry, i ) + { + assert( Entry < nPis ); + Abc_InfoSetBit( pBuffer, Entry ); + } +} + +/**Function************************************************************* + + Synopsis [Find the common variables using bitwise support representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSuppCharCommon( unsigned * pBuffer, Vec_Int_t * vOne ) +{ + int i, Entry, nCommon = 0; + Vec_IntForEachEntry( vOne, Entry, i ) + nCommon += Abc_InfoHasBit(pBuffer, Entry); + return nCommon; +} + +/**Function************************************************************* + + Synopsis [Find the best partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsChar, int nSuppSizeLimit, Vec_Int_t * vOne ) +{ +/* + Vec_Int_t * vPartSupp, * vPart; + double Attract, Repulse, Cost, CostBest; + int i, nCommon, iBest; + iBest = -1; + CostBest = 0.0; + Vec_PtrForEachEntry( vPartSuppsAll, vPartSupp, i ) + { + vPart = Vec_PtrEntry( vPartsAll, i ); + if ( nPartSizeLimit > 0 && Vec_IntSize(vPart) >= nPartSizeLimit ) + continue; + nCommon = Vec_IntTwoCountCommon( vPartSupp, vOne ); + if ( nCommon == 0 ) + continue; + if ( nCommon == Vec_IntSize(vOne) ) + return i; + Attract = 1.0 * nCommon / Vec_IntSize(vOne); + if ( Vec_IntSize(vPartSupp) < 100 ) + Repulse = 1.0; + else + Repulse = log10( Vec_IntSize(vPartSupp) / 10.0 ); + Cost = pow( Attract, pow(Repulse, 5.0) ); + if ( CostBest < Cost ) + { + CostBest = Cost; + iBest = i; + } + } + if ( CostBest < 0.6 ) + return -1; + return iBest; +*/ + + Vec_Int_t * vPartSupp;//, * vPart; + int Attract, Repulse, Value, ValueBest; + int i, nCommon, iBest; +// int nCommon2; + iBest = -1; + ValueBest = 0; + Vec_PtrForEachEntry( vPartSuppsAll, vPartSupp, i ) + { + // skip partitions with too many outputs +// vPart = Vec_PtrEntry( vPartsAll, i ); +// if ( nSuppSizeLimit > 0 && Vec_IntSize(vPart) >= nSuppSizeLimit ) +// continue; + // find the number of common variables between this output and the partitions +// nCommon2 = Vec_IntTwoCountCommon( vPartSupp, vOne ); + nCommon = Abc_NtkSuppCharCommon( Vec_PtrEntry(vPartSuppsChar, i), vOne ); +// assert( nCommon2 == nCommon ); + // if no common variables, continue searching + if ( nCommon == 0 ) + continue; + // if all variables are common, the best partition if found + if ( nCommon == Vec_IntSize(vOne) ) + return i; + // skip partitions whose size exceeds the limit + if ( nSuppSizeLimit > 0 && Vec_IntSize(vPartSupp) >= 2 * nSuppSizeLimit ) + continue; + // figure out might be the good partition for this one + Attract = 1000 * nCommon / Vec_IntSize(vOne); + if ( Vec_IntSize(vPartSupp) < 100 ) + Repulse = 1; + else + Repulse = 1+Extra_Base2Log(Vec_IntSize(vPartSupp)-100); + Value = Attract/Repulse; + if ( ValueBest < Value ) + { + ValueBest = Value; + iBest = i; + } + } + if ( ValueBest < 75 ) + return -1; + return iBest; +} + +/**Function************************************************************* + + Synopsis [Perform the smart partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPartitionPrint( Abc_Ntk_t * pNtk, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll ) +{ + Vec_Int_t * vOne; + int i, nOutputs, Counter; + + Counter = 0; + Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) + { + nOutputs = Vec_IntSize(Vec_PtrEntry(vPartsAll, i)); + printf( "%d=(%d,%d) ", i, Vec_IntSize(vOne), nOutputs ); + Counter += nOutputs; + if ( i == Vec_PtrSize(vPartsAll) - 1 ) + break; + } +// assert( Counter == Abc_NtkCoNum(pNtk) ); + printf( "\nTotal = %d. Outputs = %d.\n", Counter, Abc_NtkCoNum(pNtk) ); +} + +/**Function************************************************************* + + Synopsis [Perform the smart partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nSuppSizeLimit ) +{ + Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; + int i, iPart; + + if ( nSuppSizeLimit == 0 ) + nSuppSizeLimit = 200; + + // pack smaller partitions into larger blocks + iPart = 0; + vPart = vPartSupp = NULL; + Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) + { + if ( Vec_IntSize(vOne) < nSuppSizeLimit ) + { + if ( vPartSupp == NULL ) + { + assert( vPart == NULL ); + vPartSupp = Vec_IntDup(vOne); + vPart = Vec_PtrEntry(vPartsAll, i); + } + else + { + vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); + Vec_IntFree( vTemp ); + vPart = Vec_IntTwoMerge( vTemp = vPart, Vec_PtrEntry(vPartsAll, i) ); + Vec_IntFree( vTemp ); + Vec_IntFree( Vec_PtrEntry(vPartsAll, i) ); + } + if ( Vec_IntSize(vPartSupp) < nSuppSizeLimit ) + continue; + } + else + vPart = Vec_PtrEntry(vPartsAll, i); + // add the partition + Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); + vPart = NULL; + if ( vPartSupp ) + { + Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) ); + Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); + vPartSupp = NULL; + } + iPart++; + } + // add the last one + if ( vPart ) + { + Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); + vPart = NULL; + + assert( vPartSupp != NULL ); + Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) ); + Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); + vPartSupp = NULL; + iPart++; + } + Vec_PtrShrink( vPartsAll, iPart ); + Vec_PtrShrink( vPartsAll, iPart ); +} + +/**Function************************************************************* + + Synopsis [Perform the smart partitioning.] + + Description [Returns the ptr-vector of int-vectors.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nSuppSizeLimit, int fVerbose ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vPartSuppsChar; + Vec_Ptr_t * vSupps, * vPartsAll, * vPartsAll2, * vPartSuppsAll; + Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; + int i, iPart, iOut, clk, clk2, timeFind = 0; + + // compute the supports for all outputs +clk = clock(); +// vSupps = Abc_NtkComputeSupportsNaive( pNtk ); + vSupps = Abc_NtkComputeSupportsSmart( pNtk ); +if ( fVerbose ) +{ +PRT( "Supps", clock() - clk ); +} + // start char-based support representation + vPartSuppsChar = Vec_PtrAlloc( 1000 ); + + // create partitions +clk = clock(); + vPartsAll = Vec_PtrAlloc( 256 ); + vPartSuppsAll = Vec_PtrAlloc( 256 ); + pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vSupps) ); + Vec_PtrForEachEntry( vSupps, vOne, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); +// if ( i % 1000 == 0 ) +// printf( "CIs = %6d. COs = %6d. Processed = %6d (out of %6d). Parts = %6d.\r", +// Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), i, Vec_PtrSize(vSupps), Vec_PtrSize(vPartsAll) ); + // get the output number + iOut = Vec_IntPop(vOne); + // find closely matching part +clk2 = clock(); + iPart = Abc_NtkPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsChar, nSuppSizeLimit, vOne ); +timeFind += clock() - clk2; + if ( iPart == -1 ) + { + // create new partition + vPart = Vec_IntAlloc( 32 ); + Vec_IntPush( vPart, iOut ); + // create new partition support + vPartSupp = Vec_IntDup( vOne ); + // add this partition and its support + Vec_PtrPush( vPartsAll, vPart ); + Vec_PtrPush( vPartSuppsAll, vPartSupp ); + + Vec_PtrPush( vPartSuppsChar, Abc_NtkSuppCharStart(vOne, Abc_NtkCiNum(pNtk)) ); + } + else + { + // add output to this partition + vPart = Vec_PtrEntry( vPartsAll, iPart ); + Vec_IntPush( vPart, iOut ); + // merge supports + vPartSupp = Vec_PtrEntry( vPartSuppsAll, iPart ); + vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); + Vec_IntFree( vTemp ); + // reinsert new support + Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); + + Abc_NtkSuppCharAdd( Vec_PtrEntry(vPartSuppsChar, iPart), vOne, Abc_NtkCiNum(pNtk) ); + } + } + Extra_ProgressBarStop( pProgress ); + + // stop char-based support representation + Vec_PtrForEachEntry( vPartSuppsChar, vTemp, i ) + free( vTemp ); + Vec_PtrFree( vPartSuppsChar ); + +//printf( "\n" ); +if ( fVerbose ) +{ +PRT( "Parts", clock() - clk ); +//PRT( "Find ", timeFind ); +} + +clk = clock(); + // remember number of supports + Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) + Vec_IntPush( vOne, i ); + // sort the supports in the decreasing order + Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 ); + // reproduce partitions + vPartsAll2 = Vec_PtrAlloc( 256 ); + Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) + Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) ); + Vec_PtrFree( vPartsAll ); + vPartsAll = vPartsAll2; + + // compact small partitions +// Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll ); + Abc_NtkPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit ); + +if ( fVerbose ) +{ +PRT( "Comps", clock() - clk ); +} + if ( fVerbose ) + printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) ); +// Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll ); + + // cleanup + Vec_VecFree( (Vec_Vec_t *)vSupps ); + Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll ); +/* + // converts from intergers to nodes + Vec_PtrForEachEntry( vPartsAll, vPart, iPart ) + { + vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) ); + Vec_IntForEachEntry( vPart, iOut, i ) + Vec_PtrPush( vPartPtr, Abc_NtkCo(pNtk, iOut) ); + Vec_IntFree( vPart ); + Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr ); + } +*/ + return vPartsAll; +} + +/**Function************************************************************* + + Synopsis [Perform the naive partitioning.] + + Description [Returns the ptr-vector of int-vectors.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkPartitionNaive( Abc_Ntk_t * pNtk, int nPartSize ) +{ + Vec_Ptr_t * vParts; + Abc_Obj_t * pObj; + int nParts, i; + nParts = (Abc_NtkCoNum(pNtk) / nPartSize) + ((Abc_NtkCoNum(pNtk) % nPartSize) > 0); + vParts = (Vec_Ptr_t *)Vec_VecStart( nParts ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_IntPush( Vec_PtrEntry(vParts, i / nPartSize), i ); + return vParts; +} + +/**Function************************************************************* + + Synopsis [Converts from intergers to pointers for the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOutsPtr ) +{ + int Out, i; + Vec_PtrClear( vOutsPtr ); + Vec_IntForEachEntry( vOuts, Out, i ) + Vec_PtrPush( vOutsPtr, Abc_NtkCo(pNtk, Out) ); +} + +/**Function************************************************************* + + Synopsis [Returns representative of the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkPartStitchFindRepr_rec( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pRepr; + pRepr = Vec_PtrEntry( vEquiv, pObj->Id ); + if ( pRepr == NULL || pRepr == pObj ) + return pObj; + return Abc_NtkPartStitchFindRepr_rec( vEquiv, pRepr ); +} + +/**Function************************************************************* + + Synopsis [Returns the representative of the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Abc_Obj_t * Abc_NtkPartStitchCopy0( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFan = Abc_ObjFanin0( pObj ); + Abc_Obj_t * pRepr = Abc_NtkPartStitchFindRepr_rec( vEquiv, pFan ); + return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ Abc_ObjFaninC1(pObj) ); +} +static inline Abc_Obj_t * Abc_NtkPartStitchCopy1( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFan = Abc_ObjFanin1( pObj ); + Abc_Obj_t * pRepr = Abc_NtkPartStitchFindRepr_rec( vEquiv, pFan ); + return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ Abc_ObjFaninC1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Hop_Obj_t * Hop_ObjChild0Next( Abc_Obj_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Abc_ObjFanin0(pObj)->pNext, Abc_ObjFaninC0(pObj) ); } +static inline Hop_Obj_t * Hop_ObjChild1Next( Abc_Obj_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Abc_ObjFanin1(pObj)->pNext, Abc_ObjFaninC1(pObj) ); } + + +/**Function************************************************************* + + Synopsis [Stitches together several networks with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Man_t * Abc_NtkPartStartHop( Abc_Ntk_t * pNtk ) +{ + Hop_Man_t * pMan; + Abc_Obj_t * pObj; + int i; + // start the HOP package + pMan = Hop_ManStart(); + pMan->vObjs = Vec_PtrAlloc( Abc_NtkObjNumMax(pNtk) + 1 ); + Vec_PtrPush( pMan->vObjs, Hop_ManConst1(pMan) ); + // map constant node and PIs + Abc_AigConst1(pNtk)->pNext = (Abc_Obj_t *)Hop_ManConst1(pMan); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pNext = (Abc_Obj_t *)Hop_ObjCreatePi(pMan); + // map the internal nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + { + pObj->pNext = (Abc_Obj_t *)Hop_And( pMan, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) ); + assert( !Abc_ObjIsComplement(pObj->pNext) ); + } + // set the choice nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + { + if ( pObj->pCopy ) + ((Hop_Obj_t *)pObj->pNext)->pData = pObj->pCopy->pNext; + } + // transfer the POs + Abc_NtkForEachCo( pNtk, pObj, i ) + Hop_ObjCreatePo( pMan, Hop_ObjChild0Next(pObj) ); + // check the new manager + if ( !Hop_ManCheck(pMan) ) + printf( "Abc_NtkPartStartHop: HOP manager check has failed.\n" ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Stitches together several networks with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts ) +{ + extern Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ); + + Hop_Man_t * pMan; + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew, * pNtkTemp; + Abc_Obj_t * pObj, * pFanin; + int i, k, iNodeId; + + // start a new network similar to the original one + assert( Abc_NtkIsStrash(pNtk) ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + + // annotate parts to point to the new network + Vec_PtrForEachEntry( vParts, pNtkTemp, i ) + { + assert( Abc_NtkIsStrash(pNtkTemp) ); + Abc_NtkCleanCopy( pNtkTemp ); + + // map the CI nodes + Abc_AigConst1(pNtkTemp)->pCopy = Abc_AigConst1(pNtkNew); + Abc_NtkForEachCi( pNtkTemp, pObj, k ) + { + iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); + if ( iNodeId == -1 ) + { + printf( "Cannot find CI node %s in the original network.\n", Abc_ObjName(pObj) ); + return NULL; + } + pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); + } + + // add the internal nodes while saving representatives + vNodes = Abc_AigDfs( pNtkTemp, 1, 0 ); + Vec_PtrForEachEntry( vNodes, pObj, k ) + { + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + assert( !Abc_ObjIsComplement(pObj->pCopy) ); + if ( Abc_AigNodeIsChoice(pObj) ) + for ( pFanin = pObj->pData; pFanin; pFanin = pFanin->pData ) + pFanin->pCopy->pCopy = pObj->pCopy; + } + Vec_PtrFree( vNodes ); + + // map the CO nodes + Abc_NtkForEachCo( pNtkTemp, pObj, k ) + { + iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI ); + if ( iNodeId == -1 ) + { + printf( "Cannot find CO node %s in the original network.\n", Abc_ObjName(pObj) ); + return NULL; + } + pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); + } + } + + // connect the remaining POs +/* + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkCi( pNtkNew, i ); + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkCo( pNtkNew, i ); +*/ + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( Abc_ObjFaninNum(pObj->pCopy) == 0 ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); + } + + // transform into the HOP manager + pMan = Abc_NtkPartStartHop( pNtkNew ); + pNtkNew = Abc_NtkHopRemoveLoops( pNtkTemp = pNtkNew, pMan ); + Abc_NtkDelete( pNtkTemp ); + + // check correctness of the new network + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkPartStitchChoices: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Stitches together several networks with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams ) +{ + extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); + extern void * Abc_FrameGetGlobalFrame(); + + Vec_Ptr_t * vParts, * vFraigs, * vOnePtr; + Vec_Int_t * vOne; + Abc_Ntk_t * pNtk, * pNtk2, * pNtkAig, * pNtkFraig; + int i, k; + + // perform partitioning + pNtk = Vec_PtrEntry( vStore, 0 ); + assert( Abc_NtkIsStrash(pNtk) ); +// vParts = Abc_NtkPartitionNaive( pNtk, 20 ); + vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 ); + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); + + // fraig each partition + vOnePtr = Vec_PtrAlloc( 1000 ); + vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) ); + Vec_PtrForEachEntry( vParts, vOne, i ) + { + // start the partition + Abc_NtkConvertCos( pNtk, vOne, vOnePtr ); + pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 ); + // add nodes to the partition + Vec_PtrForEachEntryStart( vStore, pNtk2, k, 1 ) + { + Abc_NtkConvertCos( pNtk2, vOne, vOnePtr ); + Abc_NtkAppendToCone( pNtkAig, pNtk2, vOnePtr ); + } + printf( "Fraiging part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", + i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pNtkAig), Abc_NtkPoNum(pNtkAig), + Abc_NtkNodeNum(pNtkAig), Abc_AigLevel(pNtkAig) ); + // fraig the partition + pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 1, 0 ); + Vec_PtrPush( vFraigs, pNtkFraig ); + Abc_NtkDelete( pNtkAig ); + } + printf( " \r" ); + Vec_VecFree( (Vec_Vec_t *)vParts ); + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); + + // derive the final network + pNtkFraig = Abc_NtkPartStitchChoices( pNtk, vFraigs ); + Vec_PtrForEachEntry( vFraigs, pNtkAig, i ) + Abc_NtkDelete( pNtkAig ); + Vec_PtrFree( vFraigs ); + Vec_PtrFree( vOnePtr ); + return pNtkFraig; +} + +/**Function************************************************************* + + Synopsis [Stitches together several networks with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams ) +{ + extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); + extern void * Abc_FrameGetGlobalFrame(); + + Vec_Ptr_t * vParts, * vFraigs, * vOnePtr; + Vec_Int_t * vOne; + Abc_Ntk_t * pNtkAig, * pNtkFraig; + int i; + int clk = clock(); + + // perform partitioning + assert( Abc_NtkIsStrash(pNtk) ); +// vParts = Abc_NtkPartitionNaive( pNtk, 20 ); + vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 ); + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); + + // fraig each partition + vOnePtr = Vec_PtrAlloc( 1000 ); + vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) ); + Vec_PtrForEachEntry( vParts, vOne, i ) + { + Abc_NtkConvertCos( pNtk, vOne, vOnePtr ); + pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 ); + pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 0, 0 ); + Vec_PtrPush( vFraigs, pNtkFraig ); + Abc_NtkDelete( pNtkAig ); + + printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) ); + } + Vec_VecFree( (Vec_Vec_t *)vParts ); + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); + + // derive the final network + Vec_PtrForEachEntry( vFraigs, pNtkAig, i ) + Abc_NtkDelete( pNtkAig ); + Vec_PtrFree( vFraigs ); + Vec_PtrFree( vOnePtr ); + PRT( "Partitioned fraiging time", clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcPlace.c b/abc70930/src/base/abci/abcPlace.c new file mode 100644 index 00000000..87c99e99 --- /dev/null +++ b/abc70930/src/base/abci/abcPlace.c @@ -0,0 +1,255 @@ +/**CFile**************************************************************** + + FileName [abcPlace.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface with a placer.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcPlace.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +// placement includes +#include "place_base.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +AbstractCell *abstractCells = NULL; +ConcreteCell *cells = NULL; +ConcreteNet *nets = NULL; +int nAllocSize = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates a new cell.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_PlaceCreateCell( Abc_Obj_t * pObj, int fAnd ) +{ + assert( cells[pObj->Id].m_id == 0 ); + + cells[pObj->Id].m_id = pObj->Id; + cells[pObj->Id].m_label = ""; + cells[pObj->Id].m_parent = &(abstractCells[fAnd]); + cells[pObj->Id].m_fixed = 0; + addConcreteCell(&(cells[pObj->Id])); +} + +/**Function************************************************************* + + Synopsis [Updates the net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_PlaceUpdateNet( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int k; + // free the old array of net terminals + if ( nets[pObj->Id].m_terms ) + free( nets[pObj->Id].m_terms ); + // fill in the net with the new information + nets[pObj->Id].m_id = pObj->Id; + nets[pObj->Id].m_weight = 1.0; + nets[pObj->Id].m_numTerms = Abc_ObjFanoutNum(pObj); //fanout + nets[pObj->Id].m_terms = ALLOC(ConcreteCell*, Abc_ObjFanoutNum(pObj)); + Abc_ObjForEachFanout( pObj, pFanout, k ) + nets[pObj->Id].m_terms[k] = &(cells[pFanout->Id]); + addConcreteNet(&(nets[pObj->Id])); +} + +/**Function************************************************************* + + Synopsis [Returns the placement cost of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins ) +{ + Abc_Obj_t * pObj; +// double x, y; + int i; + Vec_PtrForEachEntry( vFanins, pObj, i ) + { +// pObj->Id + } + return 0.0; +} + +/**Function************************************************************* + + Synopsis [Updates placement after one step of rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets ) +{ + Abc_Obj_t * pObj, * pFanin; + int i, k; + Vec_Ptr_t * vCells, * vNets; + + // start the arrays of new cells and nets + vCells = Vec_PtrAlloc( 16 ); + vNets = Vec_PtrAlloc( 32 ); + + // go through the new nodes + Vec_PtrForEachEntry( vAddedCells, pObj, i ) + { + assert( !Abc_ObjIsComplement(pObj) ); + Abc_PlaceCreateCell( pObj, 1 ); + Abc_PlaceUpdateNet( pObj ); + + // add the new cell and its fanin nets to temporary storage + Vec_PtrPush( vCells, &(cells[pObj->Id]) ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Vec_PtrPushUnique( vNets, &(nets[pFanin->Id]) ); + } + + // go through the modified nets + Vec_PtrForEachEntry( vUpdatedNets, pObj, i ) + { + assert( !Abc_ObjIsComplement(pObj) ); + if ( Abc_ObjType(pObj) == ABC_OBJ_NONE ) // dead node + continue; + Abc_PlaceUpdateNet( pObj ); + } + + // update the placement +// fastPlace( Vec_PtrSize(vCells), (ConcreteCell **)Vec_PtrArray(vCells), +// Vec_PtrSize(vNets), (ConcreteNet **)Vec_PtrArray(vNets) ); + + // clean up + Vec_PtrFree( vCells ); + Vec_PtrFree( vNets ); +} + +/**Function************************************************************* + + Synopsis [This procedure is called before the writing start.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_PlaceBegin( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + // allocate and clean internal storage + nAllocSize = 5 * Abc_NtkObjNumMax(pNtk); + cells = REALLOC(ConcreteCell, cells, nAllocSize); + nets = REALLOC(ConcreteNet, nets, nAllocSize); + memset( cells, 0, sizeof(ConcreteCell) * nAllocSize ); + memset( nets, 0, sizeof(ConcreteNet) * nAllocSize ); + + // create AbstractCells + // 1: pad + // 2: and + if (!abstractCells) + abstractCells = ALLOC(AbstractCell,2); + + abstractCells[0].m_height = 1.0; + abstractCells[0].m_width = 1.0; + abstractCells[0].m_label = "pio"; + abstractCells[0].m_pad = 1; + + abstractCells[1].m_height = 1.0; + abstractCells[1].m_width = 1.0; + abstractCells[1].m_label = "and"; + abstractCells[1].m_pad = 0; + + // input pads + Abc_NtkForEachCi( pNtk, pObj, i ) + Abc_PlaceCreateCell( pObj, 0 ); + + // ouput pads + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_PlaceCreateCell( pObj, 0 ); + + // AND nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + Abc_PlaceCreateCell( pObj, 1 ); + + // all nets + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( !Abc_ObjIsCi(pObj) && !Abc_ObjIsNode(pObj) ) + continue; + Abc_PlaceUpdateNet( pObj ); + } + + globalPreplace((float)0.8); + globalPlace(); +} + +/**Function************************************************************* + + Synopsis [This procedure is called after the writing completes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_PlaceEnd( Abc_Ntk_t * pNtk ) +{ + int i; + + + // clean up + for ( i = 0; i < nAllocSize; i++ ) + FREE( nets[i].m_terms ); + FREE( abstractCells ); + FREE( cells ); + FREE( nets ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcPrint.c b/abc70930/src/base/abci/abcPrint.c new file mode 100644 index 00000000..bfb380f3 --- /dev/null +++ b/abc70930/src/base/abci/abcPrint.c @@ -0,0 +1,953 @@ +/**CFile**************************************************************** + + FileName [abcPrint.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Printing statistics.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcPrint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dec.h" +#include "main.h" +#include "mio.h" +//#include "seq.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//extern int s_TotalNodes = 0; +//extern int s_TotalChanges = 0; + +int s_MappingTime = 0; +int s_MappingMem = 0; +int s_ResubTime = 0; +int s_ResynTime = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Print the vital stats of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) +{ + int Num; + +// if ( Abc_NtkIsStrash(pNtk) ) +// Abc_AigCountNext( pNtk->pManFunc ); + + fprintf( pFile, "%-13s:", pNtk->pName ); + if ( Abc_NtkAssertNum(pNtk) ) + fprintf( pFile, " i/o/a = %4d/%4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkAssertNum(pNtk) ); + else + fprintf( pFile, " i/o = %4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) ); + fprintf( pFile, " lat = %4d", Abc_NtkLatchNum(pNtk) ); + if ( Abc_NtkIsNetlist(pNtk) ) + { + fprintf( pFile, " net = %5d", Abc_NtkNetNum(pNtk) ); + fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) ); + fprintf( pFile, " wbox = %3d", Abc_NtkWhiteboxNum(pNtk) ); + fprintf( pFile, " bbox = %3d", Abc_NtkBlackboxNum(pNtk) ); + } + else if ( Abc_NtkIsStrash(pNtk) ) + { + fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) ); + if ( Num = Abc_NtkGetChoiceNum(pNtk) ) + fprintf( pFile, " (choice = %d)", Num ); + if ( Num = Abc_NtkGetExorNum(pNtk) ) + fprintf( pFile, " (exor = %d)", Num ); +// if ( Num2 = Abc_NtkGetMuxNum(pNtk) ) +// fprintf( pFile, " (mux = %d)", Num2-Num ); +// if ( Num2 ) +// fprintf( pFile, " (other = %d)", Abc_NtkNodeNum(pNtk)-3*Num2 ); + } + else + { + fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) ); + fprintf( pFile, " net = %5d", Abc_NtkGetTotalFanins(pNtk) ); + } + + if ( Abc_NtkIsStrash(pNtk) || Abc_NtkIsNetlist(pNtk) ) + { + } + else if ( Abc_NtkHasSop(pNtk) ) + { + + fprintf( pFile, " cube = %5d", Abc_NtkGetCubeNum(pNtk) ); +// fprintf( pFile, " lit(sop) = %5d", Abc_NtkGetLitNum(pNtk) ); + if ( fFactored ) + fprintf( pFile, " lit(fac) = %5d", Abc_NtkGetLitFactNum(pNtk) ); + } + else if ( Abc_NtkHasAig(pNtk) ) + fprintf( pFile, " aig = %5d", Abc_NtkGetAigNodeNum(pNtk) ); + else if ( Abc_NtkHasBdd(pNtk) ) + fprintf( pFile, " bdd = %5d", Abc_NtkGetBddNodeNum(pNtk) ); + else if ( Abc_NtkHasMapping(pNtk) ) + { + fprintf( pFile, " area = %5.2f", Abc_NtkGetMappedArea(pNtk) ); + fprintf( pFile, " delay = %5.2f", Abc_NtkDelayTrace(pNtk) ); + } + else if ( !Abc_NtkHasBlackbox(pNtk) ) + { + assert( 0 ); + } + + if ( Abc_NtkIsStrash(pNtk) ) + fprintf( pFile, " lev = %3d", Abc_AigLevel(pNtk) ); + else + fprintf( pFile, " lev = %3d", Abc_NtkLevel(pNtk) ); + + fprintf( pFile, "\n" ); + +// Abc_NtkCrossCut( pNtk ); + + // print the statistic into a file +/* + { + FILE * pTable; + pTable = fopen( "ibm/seq_stats.txt", "a+" ); +// fprintf( pTable, "%s ", pNtk->pName ); +// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); + fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ + +/* + // print the statistic into a file + { + FILE * pTable; + pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%s ", pNtk->pSpec ); + fprintf( pTable, "%.0f ", Abc_NtkGetMappedArea(pNtk) ); + fprintf( pTable, "%.2f ", Abc_NtkDelayTrace(pNtk) ); + fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ + +/* + // print the statistic into a file + { + FILE * pTable; + pTable = fopen( "x/stats_new.txt", "a+" ); + fprintf( pTable, "%s ", pNtk->pName ); +// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkGetTotalFanins(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); +// fprintf( pTable, "%.2f ", (float)(s_MappingMem)/(float)(1<<20) ); + fprintf( pTable, "%.2f", (float)(s_MappingTime)/(float)(CLOCKS_PER_SEC) ); +// fprintf( pTable, "%.2f", (float)(s_ResynTime)/(float)(CLOCKS_PER_SEC) ); + fprintf( pTable, "\n" ); + fclose( pTable ); + + s_ResynTime = 0; + } +*/ + +/* + // print the statistic into a file + { + static int Counter = 0; + extern int timeRetime; + FILE * pTable; + Counter++; + pTable = fopen( "a/ret__stats.txt", "a+" ); + fprintf( pTable, "%s ", pNtk->pName ); + fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); + fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) ); + if ( Counter % 4 == 0 ) + fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ + +/* + // print the statistic into a file + { + static int Counter = 0; + extern int timeRetime; + FILE * pTable; + Counter++; + pTable = fopen( "d/stats.txt", "a+" ); + fprintf( pTable, "%s ", pNtk->pName ); +// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); + fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) ); + fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ + +/* + s_TotalNodes += Abc_NtkNodeNum(pNtk); + printf( "Total nodes = %6d %6.2f Mb Changes = %6d.\n", + s_TotalNodes, s_TotalNodes * 20.0 / (1<<20), s_TotalChanges ); +*/ + +// if ( Abc_NtkHasSop(pNtk) ) +// printf( "The total number of cube pairs = %d.\n", Abc_NtkGetCubePairNum(pNtk) ); +} + +/**Function************************************************************* + + Synopsis [Prints PIs/POs and LIs/LOs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + fprintf( pFile, "Primary inputs (%d): ", Abc_NtkPiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, " %s", Abc_ObjName(pObj) ); +// fprintf( pFile, " %s(%d)", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) ); + fprintf( pFile, "\n" ); + + fprintf( pFile, "Primary outputs (%d):", Abc_NtkPoNum(pNtk) ); + Abc_NtkForEachPo( pNtk, pObj, i ) + fprintf( pFile, " %s", Abc_ObjName(pObj) ); + fprintf( pFile, "\n" ); + + fprintf( pFile, "Latches (%d): ", Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + fprintf( pFile, " %s(%s=%s)", Abc_ObjName(pObj), + Abc_ObjName(Abc_ObjFanout0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints statistics about latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pLatch, * pFanin; + int i, Counter0, Counter1, Counter2; + int InitNums[4], Init; + + assert( !Abc_NtkIsNetlist(pNtk) ); + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + fprintf( pFile, "The network is combinational.\n" ); + return; + } + + for ( i = 0; i < 4; i++ ) + InitNums[i] = 0; + Counter0 = Counter1 = Counter2 = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + Init = Abc_LatchInit( pLatch ); + assert( Init < 4 ); + InitNums[Init]++; + + pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); + if ( Abc_NtkIsLogic(pNtk) ) + { + if ( !Abc_NodeIsConst(pFanin) ) + continue; + } + else if ( Abc_NtkIsStrash(pNtk) ) + { + if ( !Abc_AigNodeIsConst(pFanin) ) + continue; + } + else + assert( 0 ); + + // the latch input is a constant node + Counter0++; + if ( Abc_LatchIsInitDc(pLatch) ) + { + Counter1++; + continue; + } + // count the number of cases when the constant is equal to the initial value + if ( Abc_NtkIsStrash(pNtk) ) + { + if ( Abc_LatchIsInit1(pLatch) == !Abc_ObjFaninC0(pLatch) ) + Counter2++; + } + else + { + if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(Abc_ObjFanin0(Abc_ObjFanin0(pLatch))) ) + Counter2++; + } + } + fprintf( pFile, "%-15s: ", pNtk->pName ); + fprintf( pFile, "Latch = %6d. No = %4d. Zero = %4d. One = %4d. DC = %4d.\n", + Abc_NtkLatchNum(pNtk), InitNums[0], InitNums[1], InitNums[2], InitNums[3] ); + fprintf( pFile, "Const fanin = %3d. DC init = %3d. Matching init = %3d. ", Counter0, Counter1, Counter2 ); + fprintf( pFile, "Self-feed latches = %2d.\n", -1 ); //Abc_NtkCountSelfFeedLatches(pNtk) ); +} + +/**Function************************************************************* + + Synopsis [Prints the distribution of fanins/fanouts in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, k, nFanins, nFanouts; + Vec_Int_t * vFanins, * vFanouts; + int nOldSize, nNewSize; + + vFanins = Vec_IntAlloc( 0 ); + vFanouts = Vec_IntAlloc( 0 ); + Vec_IntFill( vFanins, 100, 0 ); + Vec_IntFill( vFanouts, 100, 0 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + nFanins = Abc_ObjFaninNum(pNode); + if ( Abc_NtkIsNetlist(pNtk) ) + nFanouts = Abc_ObjFanoutNum( Abc_ObjFanout0(pNode) ); + else + nFanouts = Abc_ObjFanoutNum(pNode); +// nFanouts = Abc_NodeMffcSize(pNode); + if ( nFanins > vFanins->nSize || nFanouts > vFanouts->nSize ) + { + nOldSize = vFanins->nSize; + nNewSize = ABC_MAX(nFanins, nFanouts) + 10; + Vec_IntGrow( vFanins, nNewSize ); + Vec_IntGrow( vFanouts, nNewSize ); + for ( k = nOldSize; k < nNewSize; k++ ) + { + Vec_IntPush( vFanins, 0 ); + Vec_IntPush( vFanouts, 0 ); + } + } + vFanins->pArray[nFanins]++; + vFanouts->pArray[nFanouts]++; + } + fprintf( pFile, "The distribution of fanins and fanouts in the network:\n" ); + fprintf( pFile, " Number Nodes with fanin Nodes with fanout\n" ); + for ( k = 0; k < vFanins->nSize; k++ ) + { + if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 ) + continue; + fprintf( pFile, "%5d : ", k ); + if ( vFanins->pArray[k] == 0 ) + fprintf( pFile, " " ); + else + fprintf( pFile, "%12d ", vFanins->pArray[k] ); + fprintf( pFile, " " ); + if ( vFanouts->pArray[k] == 0 ) + fprintf( pFile, " " ); + else + fprintf( pFile, "%12d ", vFanouts->pArray[k] ); + fprintf( pFile, "\n" ); + } + Vec_IntFree( vFanins ); + Vec_IntFree( vFanouts ); +} + +/**Function************************************************************* + + Synopsis [Prints the fanins/fanouts of a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode2; + int i; + if ( Abc_ObjIsPo(pNode) ) + pNode = Abc_ObjFanin0(pNode); + + fprintf( pFile, "Node %s", Abc_ObjName(pNode) ); + fprintf( pFile, "\n" ); + + fprintf( pFile, "Fanins (%d): ", Abc_ObjFaninNum(pNode) ); + Abc_ObjForEachFanin( pNode, pNode2, i ) + fprintf( pFile, " %s", Abc_ObjName(pNode2) ); + fprintf( pFile, "\n" ); + + fprintf( pFile, "Fanouts (%d): ", Abc_ObjFaninNum(pNode) ); + Abc_ObjForEachFanout( pNode, pNode2, i ) + fprintf( pFile, " %s", Abc_ObjName(pNode2) ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints the MFFCs of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + extern void Abc_NodeMffsConeSuppPrint( Abc_Obj_t * pNode ); + Abc_NtkForEachNode( pNtk, pNode, i ) + Abc_NodeMffsConeSuppPrint( pNode ); +} + +/**Function************************************************************* + + Synopsis [Prints the factored form of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsSopLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + Abc_NodePrintFactor( pFile, pNode, fUseRealNames ); +} + +/**Function************************************************************* + + Synopsis [Prints the factored form of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ) +{ + Dec_Graph_t * pGraph; + Vec_Ptr_t * vNamesIn; + if ( Abc_ObjIsCo(pNode) ) + pNode = Abc_ObjFanin0(pNode); + if ( Abc_ObjIsPi(pNode) ) + { + fprintf( pFile, "Skipping the PI node.\n" ); + return; + } + if ( Abc_ObjIsLatch(pNode) ) + { + fprintf( pFile, "Skipping the latch.\n" ); + return; + } + assert( Abc_ObjIsNode(pNode) ); + pGraph = Dec_Factor( pNode->pData ); + if ( fUseRealNames ) + { + vNamesIn = Abc_NodeGetFaninNames(pNode); + Dec_GraphPrint( stdout, pGraph, (char **)vNamesIn->pArray, Abc_ObjName(pNode) ); + Abc_NodeFreeNames( vNamesIn ); + } + else + Dec_GraphPrint( stdout, pGraph, (char **)NULL, Abc_ObjName(pNode) ); + Dec_GraphFree( pGraph ); +} + + +/**Function************************************************************* + + Synopsis [Prints the level stats of the PO node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes ) +{ + Abc_Obj_t * pNode; + int i, k, Length; + + if ( fListNodes ) + { + int nLevels; + nLevels = Abc_NtkLevel(pNtk); + printf( "Nodes by level:\n" ); + for ( i = 0; i <= nLevels; i++ ) + { + printf( "%2d : ", i ); + Abc_NtkForEachNode( pNtk, pNode, k ) + if ( (int)pNode->Level == i ) + printf( " %s", Abc_ObjName(pNode) ); + printf( "\n" ); + } + return; + } + + // print the delay profile + if ( fProfile && Abc_NtkHasMapping(pNtk) ) + { + int nIntervals = 12; + float DelayMax, DelayCur, DelayDelta; + int * pLevelCounts; + int DelayInt, nOutsSum, nOutsTotal; + + // get the max delay and delta + DelayMax = Abc_NtkDelayTrace( pNtk ); + DelayDelta = DelayMax/nIntervals; + // collect outputs by delay + pLevelCounts = ALLOC( int, nIntervals ); + memset( pLevelCounts, 0, sizeof(int) * nIntervals ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + DelayCur = Abc_NodeReadArrival( Abc_ObjFanin0(pNode) )->Worst; + DelayInt = (int)(DelayCur / DelayDelta); + if ( DelayInt >= nIntervals ) + DelayInt = nIntervals - 1; + pLevelCounts[DelayInt]++; + } + + nOutsSum = 0; + nOutsTotal = Abc_NtkCoNum(pNtk); + for ( i = 0; i < nIntervals; i++ ) + { + nOutsSum += pLevelCounts[i]; + printf( "[%8.2f - %8.2f] : COs = %4d. %5.1f %%\n", + DelayDelta * i, DelayDelta * (i+1), pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal ); + } + free( pLevelCounts ); + return; + } + else if ( fProfile ) + { + int LevelMax, * pLevelCounts; + int nOutsSum, nOutsTotal; + + if ( !Abc_NtkIsStrash(pNtk) ) + Abc_NtkLevel(pNtk); + + LevelMax = 0; + Abc_NtkForEachCo( pNtk, pNode, i ) + if ( LevelMax < (int)Abc_ObjFanin0(pNode)->Level ) + LevelMax = Abc_ObjFanin0(pNode)->Level; + pLevelCounts = ALLOC( int, LevelMax + 1 ); + memset( pLevelCounts, 0, sizeof(int) * (LevelMax + 1) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + pLevelCounts[Abc_ObjFanin0(pNode)->Level]++; + + nOutsSum = 0; + nOutsTotal = Abc_NtkCoNum(pNtk); + for ( i = 0; i <= LevelMax; i++ ) + if ( pLevelCounts[i] ) + { + nOutsSum += pLevelCounts[i]; + printf( "Level = %4d. COs = %4d. %5.1f %%\n", i, pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal ); + } + free( pLevelCounts ); + return; + } + assert( Abc_NtkIsStrash(pNtk) ); + + // find the longest name + Length = 0; + Abc_NtkForEachCo( pNtk, pNode, i ) + if ( Length < (int)strlen(Abc_ObjName(pNode)) ) + Length = strlen(Abc_ObjName(pNode)); + if ( Length < 5 ) + Length = 5; + // print stats for each output + Abc_NtkForEachCo( pNtk, pNode, i ) + { + fprintf( pFile, "CO %4d : %*s ", i, Length, Abc_ObjName(pNode) ); + Abc_NodePrintLevel( pFile, pNode ); + } +} + +/**Function************************************************************* + + Synopsis [Prints the factored form of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pDriver; + Vec_Ptr_t * vNodes; + + pDriver = Abc_ObjIsCo(pNode)? Abc_ObjFanin0(pNode) : pNode; + if ( Abc_ObjIsPi(pDriver) ) + { + fprintf( pFile, "Primary input.\n" ); + return; + } + if ( Abc_ObjIsLatch(pDriver) ) + { + fprintf( pFile, "Latch.\n" ); + return; + } + if ( Abc_NodeIsConst(pDriver) ) + { + fprintf( pFile, "Constant %d.\n", !Abc_ObjFaninC0(pNode) ); + return; + } + // print the level + fprintf( pFile, "Level = %3d. ", pDriver->Level ); + // print the size of MFFC + fprintf( pFile, "Mffc = %5d. ", Abc_NodeMffcSize(pDriver) ); + // print the size of the shole cone + vNodes = Abc_NtkDfsNodes( pNode->pNtk, &pDriver, 1 ); + fprintf( pFile, "Cone = %5d. ", Vec_PtrSize(vNodes) ); + Vec_PtrFree( vNodes ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints the factored form of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames ) +{ + Vec_Ptr_t * vNamesIn; + if ( fUseRealNames ) + { + vNamesIn = Abc_NodeGetFaninNames(pNode); + Extra_PrintKMap( stdout, pNode->pNtk->pManFunc, pNode->pData, Cudd_Not(pNode->pData), + Abc_ObjFaninNum(pNode), NULL, 0, (char **)vNamesIn->pArray ); + Abc_NodeFreeNames( vNamesIn ); + } + else + Extra_PrintKMap( stdout, pNode->pNtk->pManFunc, pNode->pData, Cudd_Not(pNode->pData), + Abc_ObjFaninNum(pNode), NULL, 0, NULL ); + +} + +/**Function************************************************************* + + Synopsis [Prints statistics about gates used in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary ) +{ + Abc_Obj_t * pObj; + int fHasBdds, i; + int CountConst, CountBuf, CountInv, CountAnd, CountOr, CountOther, CounterTotal; + char * pSop; + + if ( fUseLibrary && Abc_NtkHasMapping(pNtk) ) + { + stmm_table * tTable; + stmm_generator * gen; + char * pName; + int * pCounter, Counter; + double Area, AreaTotal; + + // count the gates by name + CounterTotal = 0; + tTable = stmm_init_table(strcmp, stmm_strhash); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) continue; + if ( !stmm_find_or_add( tTable, Mio_GateReadName(pObj->pData), (char ***)&pCounter ) ) + *pCounter = 0; + (*pCounter)++; + CounterTotal++; + } + // print the gates + AreaTotal = Abc_NtkGetMappedArea(pNtk); + stmm_foreach_item( tTable, gen, (char **)&pName, (char **)&Counter ) + { + Area = Counter * Mio_GateReadArea(Mio_LibraryReadGateByName(pNtk->pManFunc,pName)); + printf( "%-12s = %8d %10.2f %6.2f %%\n", pName, Counter, Area, 100.0 * Area / AreaTotal ); + } + printf( "%-12s = %8d %10.2f %6.2f %%\n", "TOTAL", CounterTotal, AreaTotal, 100.0 ); + stmm_free_table( tTable ); + return; + } + + if ( Abc_NtkIsAigLogic(pNtk) ) + return; + + // transform logic functions from BDD to SOP + if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Abc_NtkPrintGates(): Converting to SOPs has failed.\n" ); + return; + } + } + + // get hold of the SOP of the node + CountConst = CountBuf = CountInv = CountAnd = CountOr = CountOther = CounterTotal = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) continue; + if ( Abc_NtkHasMapping(pNtk) ) + pSop = Mio_GateReadSop(pObj->pData); + else + pSop = pObj->pData; + // collect the stats + if ( Abc_SopIsConst0(pSop) || Abc_SopIsConst1(pSop) ) + CountConst++; + else if ( Abc_SopIsBuf(pSop) ) + CountBuf++; + else if ( Abc_SopIsInv(pSop) ) + CountInv++; + else if ( !Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop) || Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop) ) + CountAnd++; + else if ( Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop) || !Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop) ) + CountOr++; + else + CountOther++; + CounterTotal++; + } + printf( "Const = %8d %6.2f %%\n", CountConst , 100.0 * CountConst / CounterTotal ); + printf( "Buffer = %8d %6.2f %%\n", CountBuf , 100.0 * CountBuf / CounterTotal ); + printf( "Inverter = %8d %6.2f %%\n", CountInv , 100.0 * CountInv / CounterTotal ); + printf( "And = %8d %6.2f %%\n", CountAnd , 100.0 * CountAnd / CounterTotal ); + printf( "Or = %8d %6.2f %%\n", CountOr , 100.0 * CountOr / CounterTotal ); + printf( "Other = %8d %6.2f %%\n", CountOther , 100.0 * CountOther / CounterTotal ); + printf( "TOTAL = %8d %6.2f %%\n", CounterTotal, 100.0 * CounterTotal / CounterTotal ); + + // convert the network back into BDDs if this is how it was + if ( fHasBdds ) + Abc_NtkSopToBdd(pNtk); +} + +/**Function************************************************************* + + Synopsis [Prints statistics about gates used in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes1, * vNodes2; + Abc_Obj_t * pObj1, * pObj2, * pNode1, * pNode2; + int i, k, m, n, Counter; + + // print the template + printf( "Statistics about sharing of logic nodes among the CO pairs.\n" ); + printf( "(CO1,CO2)=NumShared : " ); + // go though the CO pairs + Abc_NtkForEachCo( pNtk, pObj1, i ) + { + vNodes1 = Abc_NtkDfsNodes( pNtk, &pObj1, 1 ); + // mark the nodes + Vec_PtrForEachEntry( vNodes1, pNode1, m ) + pNode1->fMarkA = 1; + // go through the second COs + Abc_NtkForEachCo( pNtk, pObj2, k ) + { + if ( i >= k ) + continue; + vNodes2 = Abc_NtkDfsNodes( pNtk, &pObj2, 1 ); + // count the number of marked + Counter = 0; + Vec_PtrForEachEntry( vNodes2, pNode2, n ) + Counter += pNode2->fMarkA; + // print + printf( "(%d,%d)=%d ", i, k, Counter ); + Vec_PtrFree( vNodes2 ); + } + // unmark the nodes + Vec_PtrForEachEntry( vNodes1, pNode1, m ) + pNode1->fMarkA = 0; + Vec_PtrFree( vNodes1 ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints info for each output cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSupp, * vNodes; + Abc_Obj_t * pObj; + int i; + printf( "Structural support info:\n" ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); + printf( "%20s : Cone = %5d. Supp = %5d.\n", + Abc_ObjName(pObj), vNodes->nSize, vSupp->nSize ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vSupp ); + } +} + +/**Function************************************************************* + + Synopsis [Prints information about the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + fprintf( pFile, "Object %5d : ", pObj->Id ); + switch ( pObj->Type ) + { + case ABC_OBJ_NONE: + fprintf( pFile, "NONE " ); + break; + case ABC_OBJ_CONST1: + fprintf( pFile, "Const1 " ); + break; + case ABC_OBJ_PIO: + fprintf( pFile, "PIO " ); + break; + case ABC_OBJ_PI: + fprintf( pFile, "PI " ); + break; + case ABC_OBJ_PO: + fprintf( pFile, "PO " ); + break; + case ABC_OBJ_BI: + fprintf( pFile, "BI " ); + break; + case ABC_OBJ_BO: + fprintf( pFile, "BO " ); + break; + case ABC_OBJ_ASSERT: + fprintf( pFile, "Assert " ); + break; + case ABC_OBJ_NET: + fprintf( pFile, "Net " ); + break; + case ABC_OBJ_NODE: + fprintf( pFile, "Node " ); + break; + case ABC_OBJ_LATCH: + fprintf( pFile, "Latch " ); + break; + case ABC_OBJ_WHITEBOX: + fprintf( pFile, "Whitebox" ); + break; + case ABC_OBJ_BLACKBOX: + fprintf( pFile, "Blackbox" ); + break; + default: + assert(0); + break; + } + // print the fanins + fprintf( pFile, " Fanins ( " ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + fprintf( pFile, "%d ", pFanin->Id ); + fprintf( pFile, ") " ); +/* + fprintf( pFile, " Fanouts ( " ); + Abc_ObjForEachFanout( pObj, pFanin, i ) + fprintf( pFile, "%d(%c) ", pFanin->Id, Abc_NodeIsTravIdCurrent(pFanin)? '+' : '-' ); + fprintf( pFile, ") " ); +*/ + // print the logic function + if ( Abc_ObjIsNode(pObj) && Abc_NtkIsSopLogic(pObj->pNtk) ) + fprintf( pFile, " %s", pObj->pData ); + else + fprintf( pFile, "\n" ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcProve.c b/abc70930/src/base/abci/abcProve.c new file mode 100644 index 00000000..a4220216 --- /dev/null +++ b/abc70930/src/base/abci/abcProve.c @@ -0,0 +1,343 @@ +/**CFile**************************************************************** + + FileName [abcProve.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Proves the miter using AIG rewriting, FRAIGing, and SAT solving.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcProve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fraig.h" +#include "math.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ); +extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); + +static Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, sint64 nInspLimit, int * pRetValue, int * pNumFails, sint64 * pNumConfs, sint64 * pNumInspects ); +static void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Attempts to solve the miter using a number of tricks.] + + Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT. Returns + a simplified version of the original network (or a constant 0 network). + In case the network is not a constant zero and a SAT assignment is found, + pNtk->pModel contains a satisfying assignment.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pPars ) +{ + Prove_Params_t * pParams = pPars; + Abc_Ntk_t * pNtk, * pNtkTemp; + int RetValue, nIter, nSatFails, Counter, clk, timeStart = clock(); + sint64 nSatConfs, nSatInspects, nInspectLimit; + + // get the starting network + pNtk = *ppNtk; + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkPoNum(pNtk) == 1 ); + + if ( pParams->fVerbose ) + { + printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n", + pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" ); + printf( "Mitering = %d (%3.1f). Rewriting = %d (%3.1f). Fraiging = %d (%3.1f).\n", + pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, + pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, + pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti ); + printf( "Mitering last = %d.\n", + pParams->nMiteringLimitLast ); + } + + // if SAT only, solve without iteration + if ( !pParams->fUseRewriting && !pParams->fUseFraiging ) + { + clk = clock(); + RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)0, 0, NULL, NULL ); + Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); + *ppNtk = pNtk; + return RetValue; + } + + // check the current resource limits + for ( nIter = 0; nIter < pParams->nItersMax; nIter++ ) + { + if ( pParams->fVerbose ) + { + printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, + (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), + (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) ); + fflush( stdout ); + } + + // try brute-force SAT + clk = clock(); + nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; + RetValue = Abc_NtkMiterSat( pNtk, (sint64)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), (sint64)nInspectLimit, 0, &nSatConfs, &nSatInspects ); + Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); + if ( RetValue >= 0 ) + break; + + // add to the number of backtracks and inspects + pParams->nTotalBacktracksMade += nSatConfs; + pParams->nTotalInspectsMade += nSatInspects; + // check if global resource limit is reached + if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || + (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) + { + printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); + *ppNtk = pNtk; + return -1; + } + + // try rewriting + if ( pParams->fUseRewriting ) + { + clk = clock(); + Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); +// Counter = 1; + while ( 1 ) + { +/* + extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ); + pNtk = Abc_NtkIvyResyn( pNtkTemp = pNtk, 0, 0 ); Abc_NtkDelete( pNtkTemp ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + if ( --Counter == 0 ) + break; +*/ +/* + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + if ( --Counter == 0 ) + break; +*/ + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + if ( --Counter == 0 ) + break; + Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + if ( --Counter == 0 ) + break; + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + if ( --Counter == 0 ) + break; + } + Abc_NtkMiterPrint( pNtk, "Rewriting ", clk, pParams->fVerbose ); + } + + if ( pParams->fUseFraiging ) + { + // try FRAIGing + clk = clock(); + nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; + pNtk = Abc_NtkMiterFraig( pNtkTemp = pNtk, (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)), nInspectLimit, &RetValue, &nSatFails, &nSatConfs, &nSatInspects ); Abc_NtkDelete( pNtkTemp ); + Abc_NtkMiterPrint( pNtk, "FRAIGing ", clk, pParams->fVerbose ); +// printf( "NumFails = %d\n", nSatFails ); + if ( RetValue >= 0 ) + break; + + // add to the number of backtracks and inspects + pParams->nTotalBacktracksMade += nSatConfs; + pParams->nTotalInspectsMade += nSatInspects; + // check if global resource limit is reached + if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || + (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) + { + printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); + *ppNtk = pNtk; + return -1; + } + } + + } + + // try to prove it using brute force SAT + if ( RetValue < 0 && pParams->fUseBdds ) + { + if ( pParams->fVerbose ) + { + printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit ); + fflush( stdout ); + } + clk = clock(); + pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 ); + if ( pNtk ) + { + Abc_NtkDelete( pNtkTemp ); + RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero(pNtk->pManFunc)) ); + } + else + pNtk = pNtkTemp; + Abc_NtkMiterPrint( pNtk, "BDD building", clk, pParams->fVerbose ); + } + + if ( RetValue < 0 ) + { + if ( pParams->fVerbose ) + { + printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); + fflush( stdout ); + } + clk = clock(); + nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; + RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)nInspectLimit, 0, NULL, NULL ); + Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); + } + + // assign the model if it was proved by rewriting (const 1 miter) + if ( RetValue == 0 && pNtk->pModel == NULL ) + { + pNtk->pModel = ALLOC( int, Abc_NtkCiNum(pNtk) ); + memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) ); + } + *ppNtk = pNtk; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Attempts to solve the miter using a number of tricks.] + + Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, sint64 nInspLimit, int * pRetValue, int * pNumFails, sint64 * pNumConfs, sint64 * pNumInspects ) +{ + Abc_Ntk_t * pNtkNew; + Fraig_Params_t Params, * pParams = &Params; + Fraig_Man_t * pMan; + int nWords1, nWords2, nWordsMin, RetValue; + int * pModel; + + // to determine the number of simulation patterns + // use the following strategy + // at least 64 words (32 words random and 32 words dynamic) + // no more than 256M for one circuit (128M + 128M) + nWords1 = 32; + nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk)); + nWordsMin = ABC_MIN( nWords1, nWords2 ); + + // set the FRAIGing parameters + Fraig_ParamsSetDefault( pParams ); + pParams->nPatsRand = nWordsMin * 32; // the number of words of random simulation info + pParams->nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info + pParams->nBTLimit = nBTLimit; // the max number of backtracks + pParams->nSeconds = -1; // the runtime limit + pParams->fTryProve = 0; // do not try to prove the final miter + pParams->fDoSparse = 1; // try proving sparse functions + pParams->fVerbose = 0; + pParams->nInspLimit = nInspLimit; + + // transform the target into a fraig + pMan = Abc_NtkToFraig( pNtk, pParams, 0, 0 ); + Fraig_ManProveMiter( pMan ); + RetValue = Fraig_ManCheckMiter( pMan ); + + // create the network + pNtkNew = Abc_NtkFromFraig( pMan, pNtk ); + + // save model + if ( RetValue == 0 ) + { + pModel = Fraig_ManReadModel( pMan ); + FREE( pNtkNew->pModel ); + pNtkNew->pModel = ALLOC( int, Abc_NtkCiNum(pNtkNew) ); + memcpy( pNtkNew->pModel, pModel, sizeof(int) * Abc_NtkCiNum(pNtkNew) ); + } + + // save the return values + *pRetValue = RetValue; + *pNumFails = Fraig_ManReadSatFails( pMan ); + *pNumConfs = Fraig_ManReadConflicts( pMan ); + *pNumInspects = Fraig_ManReadInspects( pMan ); + + // delete the fraig manager + Fraig_ManFree( pMan ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Attempts to solve the miter using a number of tricks.] + + Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose ) +{ + if ( !fVerbose ) + return; + printf( "Nodes = %7d. Levels = %4d. ", Abc_NtkNodeNum(pNtk), + Abc_NtkIsStrash(pNtk)? Abc_AigLevel(pNtk) : Abc_NtkLevel(pNtk) ); + PRT( pString, clock() - clk ); +} + + +/**Function************************************************************* + + Synopsis [Implements resynthesis for CEC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterRwsat( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkTemp; + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + return pNtk; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcQbf.c b/abc70930/src/base/abci/abcQbf.c new file mode 100644 index 00000000..b839f812 --- /dev/null +++ b/abc70930/src/base/abci/abcQbf.c @@ -0,0 +1,260 @@ +/**CFile**************************************************************** + + FileName [abcQbf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Implementation of a simple QBF solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcQbf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +/* + Implementation of a simple QBF solver along the lines of + A. Solar-Lezama, L. Tancau, R. Bodik, V. Saraswat, and S. Seshia, + "Combinatorial sketching for finite programs", 12th International + Conference on Architectural Support for Programming Languages and + Operating Systems (ASPLOS 2006), San Jose, CA, October 2006. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ); +static void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars ); +static void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ); +static void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars ); +static void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Solve the QBF problem EpAx[M(p,x)].] + + Description [Variables p go first, followed by variable x. + The number of parameters is nPars. The miter is in pNtk. + The miter expresses EQUALITY of the implementation and spec.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int fVerbose ) +{ + Abc_Ntk_t * pNtkVer, * pNtkSyn, * pNtkSyn2, * pNtkTemp; + Vec_Int_t * vPiValues; + int clkTotal = clock(), clkS, clkV; + int nIters, nIterMax = 500, nInputs, RetValue, fFound = 0; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkIsComb(pNtk) ); + assert( Abc_NtkPoNum(pNtk) == 1 ); + assert( nPars > 0 && nPars < Abc_NtkPiNum(pNtk) ); + assert( Abc_NtkPiNum(pNtk)-nPars < 32 ); + nInputs = Abc_NtkPiNum(pNtk) - nPars; + + // initialize the synthesized network with 0000-combination + vPiValues = Vec_IntStart( Abc_NtkPiNum(pNtk) ); + Abc_NtkVectorClearPars( vPiValues, nPars ); + pNtkSyn = Abc_NtkMiterCofactor( pNtk, vPiValues ); + if ( fVerbose ) + { + printf( "Iter %2d : ", 0 ); + printf( "AIG = %6d ", Abc_NtkNodeNum(pNtkSyn) ); + Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars ); + printf( "\n" ); + } + + // iteratively solve + for ( nIters = 0; nIters < nIterMax; nIters++ ) + { + // solve the synthesis instance +clkS = clock(); + RetValue = Abc_NtkMiterSat( pNtkSyn, 0, 0, 0, NULL, NULL ); +clkS = clock() - clkS; + if ( RetValue == 0 ) + Abc_NtkModelToVector( pNtkSyn, vPiValues ); + if ( RetValue == 1 ) + { + break; + } + if ( RetValue == -1 ) + { + printf( "Synthesis timed out.\n" ); + break; + } + // there is a counter-example + + // construct the verification instance + Abc_NtkVectorClearVars( pNtk, vPiValues, nPars ); + pNtkVer = Abc_NtkMiterCofactor( pNtk, vPiValues ); + // complement the output + Abc_ObjXorFaninC( Abc_NtkPo(pNtkVer,0), 0 ); + + // solve the verification instance +clkV = clock(); + RetValue = Abc_NtkMiterSat( pNtkVer, 0, 0, 0, NULL, NULL ); +clkV = clock() - clkV; + if ( RetValue == 0 ) + Abc_NtkModelToVector( pNtkVer, vPiValues ); + Abc_NtkDelete( pNtkVer ); + if ( RetValue == 1 ) + { + fFound = 1; + break; + } + if ( RetValue == -1 ) + { + printf( "Verification timed out.\n" ); + break; + } + // there is a counter-example + + // create a new synthesis network + Abc_NtkVectorClearPars( vPiValues, nPars ); + pNtkSyn2 = Abc_NtkMiterCofactor( pNtk, vPiValues ); + // add to the synthesis instance + pNtkSyn = Abc_NtkMiterAnd( pNtkTemp = pNtkSyn, pNtkSyn2, 0, 0 ); + Abc_NtkDelete( pNtkSyn2 ); + Abc_NtkDelete( pNtkTemp ); + + if ( fVerbose ) + { + printf( "Iter %2d : ", nIters+1 ); + printf( "AIG = %6d ", Abc_NtkNodeNum(pNtkSyn) ); + Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars ); + printf( " " ); +// PRTn( "Syn", clkS ); + PRT( "Ver", clkV ); + } + } + Abc_NtkDelete( pNtkSyn ); + // report the results + if ( fFound ) + { + printf( "Parameters: " ); + Abc_NtkVectorPrintPars( vPiValues, nPars ); + printf( "\n" ); + printf( "Solved after %d interations. ", nIters ); + } + else if ( nIters == nIterMax ) + printf( "Unsolved after %d interations. ", nIters ); + else + printf( "Implementation does not exist. " ); + PRT( "Total runtime", clock() - clkTotal ); + Vec_IntFree( vPiValues ); +} + + +/**Function************************************************************* + + Synopsis [Translates model into the vector of values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ) +{ + int * pModel, i; + pModel = pNtk->pModel; + for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) + Vec_IntWriteEntry( vPiValues, i, pModel[i] ); +} + +/**Function************************************************************* + + Synopsis [Clears parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars ) +{ + int i; + for ( i = 0; i < nPars; i++ ) + Vec_IntWriteEntry( vPiValues, i, -1 ); +} + +/**Function************************************************************* + + Synopsis [Clears variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ) +{ + int i; + for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ ) + Vec_IntWriteEntry( vPiValues, i, -1 ); +} + +/**Function************************************************************* + + Synopsis [Clears variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars ) +{ + int i; + for ( i = 0; i < nPars; i++ ) + printf( "%d", Vec_IntEntry(vPiValues,i) ); +} + +/**Function************************************************************* + + Synopsis [Clears variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ) +{ + int i; + for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ ) + printf( "%d", Vec_IntEntry(vPiValues,i) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcQuant.c b/abc70930/src/base/abci/abcQuant.c new file mode 100644 index 00000000..0f2bd72f --- /dev/null +++ b/abc70930/src/base/abci/abcQuant.c @@ -0,0 +1,419 @@ +/**CFile**************************************************************** + + FileName [abcQuant.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [AIG-based variable quantification.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcQuant.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs fast synthesis.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSynthesize( Abc_Ntk_t ** ppNtk, int fMoreEffort ) +{ + Abc_Ntk_t * pNtk, * pNtkTemp; + + pNtk = *ppNtk; + + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); + Abc_NtkDelete( pNtkTemp ); + + if ( fMoreEffort ) + { + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); + Abc_NtkDelete( pNtkTemp ); + } + + *ppNtk = pNtk; +} + +/**Function************************************************************* + + Synopsis [Existentially quantifies one variable.] + + Description [] + + SideEffects [This procedure creates dangling nodes in the AIG.] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pNext, * pFanin; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + assert( iVar < Abc_NtkCiNum(pNtk) ); + + // collect the internal nodes + pObj = Abc_NtkCi( pNtk, iVar ); + vNodes = Abc_NtkDfsReverseNodes( pNtk, &pObj, 1 ); + + // assign the cofactors of the CI node to be constants + pObj->pCopy = Abc_ObjNot( Abc_AigConst1(pNtk) ); + pObj->pData = Abc_AigConst1(pNtk); + + // quantify the nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + for ( pNext = pObj? pObj->pCopy : pObj; pObj; pObj = pNext, pNext = pObj? pObj->pCopy : pObj ) + { + pFanin = Abc_ObjFanin0(pObj); + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + pFanin->pCopy = pFanin->pData = pFanin; + pFanin = Abc_ObjFanin1(pObj); + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + pFanin->pCopy = pFanin->pData = pFanin; + pObj->pCopy = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + pObj->pData = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Data(pObj), Abc_ObjChild1Data(pObj) ); + } + } + Vec_PtrFree( vNodes ); + + // update the affected COs + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + continue; + pFanin = Abc_ObjFanin0(pObj); + // get the result of quantification + if ( fUniv ) + pNext = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) ); + else + pNext = Abc_AigOr( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) ); + pNext = Abc_ObjNotCond( pNext, Abc_ObjFaninC0(pObj) ); + if ( Abc_ObjRegular(pNext) == pFanin ) + continue; + // update the fanins of the CO + Abc_ObjPatchFanin( pObj, pFanin, pNext ); +// if ( Abc_ObjFanoutNum(pFanin) == 0 ) +// Abc_AigDeleteNode( pNtk->pManFunc, pFanin ); + } + + // make sure the node has no fanouts +// pObj = Abc_NtkCi( pNtk, iVar ); +// assert( Abc_ObjFanoutNum(pObj) == 0 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Constructs the transition relation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose ) +{ + char Buffer[1000]; + Vec_Ptr_t * vPairs; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pMiter; + int i, nLatches; + int fSynthesis = 1; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkLatchNum(pNtk) ); + nLatches = Abc_NtkLatchNum(pNtk); + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + // duplicate the name and the spec + sprintf( Buffer, "%s_TR", pNtk->pName ); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); +// pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + Abc_NtkCleanCopy( pNtk ); + // create current state variables + Abc_NtkForEachLatchOutput( pNtk, pObj, i ) + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + // create next state variables + Abc_NtkForEachLatchInput( pNtk, pObj, i ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pObj), NULL ); + // create PI variables + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + // create the PO + Abc_NtkCreatePo( pNtkNew ); + // restrash the nodes (assuming a topological order of the old network) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // create the function of the primary output + assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); + vPairs = Vec_PtrAlloc( 2*nLatches ); + Abc_NtkForEachLatchInput( pNtk, pObj, i ) + { + Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pObj) ); + Vec_PtrPush( vPairs, Abc_NtkPi(pNtkNew, i+nLatches) ); + } + pMiter = Abc_AigMiter( pNtkNew->pManFunc, vPairs ); + Vec_PtrFree( vPairs ); + // add the primary output + Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), Abc_ObjNot(pMiter) ); + Abc_ObjAssignName( Abc_NtkPo(pNtkNew,0), "rel", NULL ); + + // quantify inputs + if ( fInputs ) + { + assert( Abc_NtkPiNum(pNtkNew) == Abc_NtkPiNum(pNtk) + 2*nLatches ); + for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- ) +// for ( i = 2*nLatches; i < Abc_NtkPiNum(pNtkNew); i++ ) + { + Abc_NtkQuantify( pNtkNew, 0, i, fVerbose ); +// if ( fSynthesis && (i % 3 == 2) ) + if ( fSynthesis ) + { + Abc_NtkCleanData( pNtkNew ); + Abc_AigCleanup( pNtkNew->pManFunc ); + Abc_NtkSynthesize( &pNtkNew, 1 ); + } +// printf( "Var = %3d. Nodes = %6d. ", Abc_NtkPiNum(pNtkNew) - 1 - i, Abc_NtkNodeNum(pNtkNew) ); +// printf( "Var = %3d. Nodes = %6d. ", i - 2*nLatches, Abc_NtkNodeNum(pNtkNew) ); + } +// printf( "\n" ); + Abc_NtkCleanData( pNtkNew ); + Abc_AigCleanup( pNtkNew->pManFunc ); + for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- ) + { + pObj = Abc_NtkPi( pNtkNew, i ); + assert( Abc_ObjFanoutNum(pObj) == 0 ); + Abc_NtkDeleteObj( pObj ); + } + } + + // check consistency of the network + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkTransRel: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Performs one image computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkInitialState( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pMiter; + int i, nVars = Abc_NtkPiNum(pNtk)/2; + assert( Abc_NtkIsStrash(pNtk) ); + // start the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // compute the all-zero state in terms of the CS variables + pMiter = Abc_AigConst1(pNtkNew); + for ( i = 0; i < nVars; i++ ) + pMiter = Abc_AigAnd( pNtkNew->pManFunc, pMiter, Abc_ObjNot( Abc_NtkPi(pNtkNew, i) ) ); + // add the PO + Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Swaps current state and next state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkSwapVariables( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pMiter, * pObj, * pObj0, * pObj1; + int i, nVars = Abc_NtkPiNum(pNtk)/2; + assert( Abc_NtkIsStrash(pNtk) ); + // start the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // update the PIs + for ( i = 0; i < nVars; i++ ) + { + pObj0 = Abc_NtkPi( pNtk, i ); + pObj1 = Abc_NtkPi( pNtk, i+nVars ); + pMiter = pObj0->pCopy; + pObj0->pCopy = pObj1->pCopy; + pObj1->pCopy = pMiter; + } + // restrash + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // add the PO + pMiter = Abc_ObjChild0Copy( Abc_NtkPo(pNtk,0) ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Performs reachability analisys.] + + Description [Assumes that the input is the transition relation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtkRel, int nIters, int fVerbose ) +{ + Abc_Obj_t * pObj; + Abc_Ntk_t * pNtkFront, * pNtkReached, * pNtkNext, * pNtkTemp; + int clk, i, v, nVars, nNodesOld, nNodesNew, nNodesPrev; + int fFixedPoint = 0; + int fSynthesis = 1; + int fMoreEffort = 1; + + assert( Abc_NtkIsStrash(pNtkRel) ); + assert( Abc_NtkLatchNum(pNtkRel) == 0 ); + assert( Abc_NtkPiNum(pNtkRel) % 2 == 0 ); + + // compute the network composed of the initial states + pNtkFront = Abc_NtkInitialState( pNtkRel ); + pNtkReached = Abc_NtkDup( pNtkFront ); +//Abc_NtkShow( pNtkReached, 0, 0, 0 ); + +// if ( fVerbose ) +// printf( "Transition relation = %6d.\n", Abc_NtkNodeNum(pNtkRel) ); + + // perform iterations of reachability analysis + nNodesPrev = Abc_NtkNodeNum(pNtkFront); + nVars = Abc_NtkPiNum(pNtkRel)/2; + for ( i = 0; i < nIters; i++ ) + { + clk = clock(); + // get the set of next states + pNtkNext = Abc_NtkMiterAnd( pNtkRel, pNtkFront, 0, 0 ); + Abc_NtkDelete( pNtkFront ); + // quantify the current state variables + for ( v = 0; v < nVars; v++ ) + { + Abc_NtkQuantify( pNtkNext, 0, v, fVerbose ); + if ( fSynthesis && (v % 3 == 2) ) + { + Abc_NtkCleanData( pNtkNext ); + Abc_AigCleanup( pNtkNext->pManFunc ); + Abc_NtkSynthesize( &pNtkNext, fMoreEffort ); + } + } + Abc_NtkCleanData( pNtkNext ); + Abc_AigCleanup( pNtkNext->pManFunc ); + if ( fSynthesis ) + Abc_NtkSynthesize( &pNtkNext, 1 ); + // map the next states into the current states + pNtkNext = Abc_NtkSwapVariables( pNtkTemp = pNtkNext ); + Abc_NtkDelete( pNtkTemp ); + // check the termination condition + if ( Abc_ObjFanin0(Abc_NtkPo(pNtkNext,0)) == Abc_AigConst1(pNtkNext) ) + { + fFixedPoint = 1; + printf( "Fixed point is reached!\n" ); + Abc_NtkDelete( pNtkNext ); + break; + } + // compute new front + pNtkFront = Abc_NtkMiterAnd( pNtkNext, pNtkReached, 0, 1 ); + Abc_NtkDelete( pNtkNext ); + // add the reached states + pNtkReached = Abc_NtkMiterAnd( pNtkTemp = pNtkReached, pNtkFront, 1, 0 ); + Abc_NtkDelete( pNtkTemp ); + // compress the size of Front + nNodesOld = Abc_NtkNodeNum(pNtkFront); + if ( fSynthesis ) + { + Abc_NtkSynthesize( &pNtkFront, fMoreEffort ); + Abc_NtkSynthesize( &pNtkReached, fMoreEffort ); + } + nNodesNew = Abc_NtkNodeNum(pNtkFront); + // print statistics + if ( fVerbose ) + { + printf( "I = %3d : Reach = %6d Fr = %6d FrM = %6d %7.2f %% ", + i + 1, Abc_NtkNodeNum(pNtkReached), nNodesOld, nNodesNew, 100.0*(nNodesNew-nNodesPrev)/nNodesPrev ); + PRT( "T", clock() - clk ); + } + nNodesPrev = Abc_NtkNodeNum(pNtkFront); + } + if ( !fFixedPoint ) + fprintf( stdout, "Reachability analysis stopped after %d iterations.\n", nIters ); + + // complement the output to represent the set of unreachable states + Abc_ObjXorFaninC( Abc_NtkPo(pNtkReached,0), 0 ); + + // remove next state variables + for ( i = 2*nVars - 1; i >= nVars; i-- ) + { + pObj = Abc_NtkPi( pNtkReached, i ); + assert( Abc_ObjFanoutNum(pObj) == 0 ); + Abc_NtkDeleteObj( pObj ); + } + + // check consistency of the network + if ( !Abc_NtkCheck( pNtkReached ) ) + { + printf( "Abc_NtkReachability: The network check has failed.\n" ); + Abc_NtkDelete( pNtkReached ); + return NULL; + } + return pNtkReached; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcRec.c b/abc70930/src/base/abci/abcRec.c new file mode 100644 index 00000000..a6ec6981 --- /dev/null +++ b/abc70930/src/base/abci/abcRec.c @@ -0,0 +1,1173 @@ +/**CFile**************************************************************** + + FileName [abcRec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Record of semi-canonical AIG subgraphs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "if.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Abc_ManRec_t_ Abc_ManRec_t; +struct Abc_ManRec_t_ +{ + Abc_Ntk_t * pNtk; // the record + Vec_Ptr_t * vTtElems; // the elementary truth tables + Vec_Ptr_t * vTtNodes; // the node truth tables + Abc_Obj_t ** pBins; // hash table mapping truth tables into nodes + int nBins; // the number of allocated bins + int nVars; // the number of variables + int nVarsInit; // the number of variables requested initially + int nWords; // the number of TT words + int nCuts; // the max number of cuts to use + // temporaries + int * pBytes; // temporary storage for minterms + int * pMints; // temporary storage for minterm counters + unsigned * pTemp1; // temporary truth table + unsigned * pTemp2; // temporary truth table + Vec_Ptr_t * vNodes; // the temporary nodes + Vec_Ptr_t * vTtTemps; // the truth tables for the internal nodes of the cut + Vec_Ptr_t * vLabels; // temporary storage for AIG node labels + Vec_Str_t * vCosts; // temporary storage for costs + Vec_Int_t * vMemory; // temporary memory for truth tables + // statistics + int nTried; // the number of cuts tried + int nFilterSize; // the number of same structures + int nFilterRedund; // the number of same structures + int nFilterVolume; // the number of same structures + int nFilterTruth; // the number of same structures + int nFilterError; // the number of same structures + int nFilterSame; // the number of same structures + int nAdded; // the number of subgraphs added + int nAddedFuncs; // the number of functions added + // rewriting + int nFunsFound; // the found functions + int nFunsNotFound; // the missing functions + // runtime + int timeCollect; // the runtime to canonicize + int timeTruth; // the runtime to canonicize + int timeCanon; // the runtime to canonicize + int timeOther; // the runtime to canonicize + int timeTotal; // the runtime to canonicize +}; + +// the truth table is canonicized in such a way that for (00000) its value is 0 + +static Abc_Obj_t ** Abc_NtkRecTableLookup( Abc_ManRec_t * p, unsigned * pTruth, int nVars ); +static int Abc_NtkRecComputeTruth( Abc_Obj_t * pObj, Vec_Ptr_t * vTtNodes, int nVars ); +static int Abc_NtkRecAddCutCheckCycle_rec( Abc_Obj_t * pRoot, Abc_Obj_t * pObj ); + +static Abc_ManRec_t * s_pMan = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the record for the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecIsRunning() +{ + return s_pMan != NULL; +} + +/**Function************************************************************* + + Synopsis [Starts the record for the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecVarNum() +{ + return (s_pMan != NULL)? s_pMan->nVars : -1; +} + +/**Function************************************************************* + + Synopsis [Starts the record for the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkRecMemory() +{ + return s_pMan->vMemory; +} + +/**Function************************************************************* + + Synopsis [Starts the record for the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecStart( Abc_Ntk_t * pNtk, int nVars, int nCuts ) +{ + Abc_ManRec_t * p; + Abc_Obj_t * pObj, ** ppSpot; + char Buffer[10]; + unsigned * pTruth; + int i, RetValue; + int clkTotal = clock(), clk; + + assert( s_pMan == NULL ); + if ( pNtk == NULL ) + { + assert( nVars > 2 && nVars <= 16 ); + pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtk->pName = Extra_UtilStrsav( "record" ); + } + else + { + if ( Abc_NtkGetChoiceNum(pNtk) > 0 ) + { + printf( "The starting record should be a network without choice nodes.\n" ); + return; + } + if ( Abc_NtkPiNum(pNtk) > 16 ) + { + printf( "The starting record should be a network with no more than %d primary inputs.\n", 16 ); + return; + } + if ( Abc_NtkPiNum(pNtk) > nVars ) + printf( "The starting record has %d inputs (warning only).\n", Abc_NtkPiNum(pNtk) ); + pNtk = Abc_NtkDup( pNtk ); + } + // create the primary inputs + for ( i = Abc_NtkPiNum(pNtk); i < nVars; i++ ) + { + pObj = Abc_NtkCreatePi( pNtk ); + Buffer[0] = 'a' + i; + Buffer[1] = 0; + Abc_ObjAssignName( pObj, Buffer, NULL ); + } + Abc_NtkCleanCopy( pNtk ); + Abc_NtkCleanEquiv( pNtk ); + + // start the manager + p = ALLOC( Abc_ManRec_t, 1 ); + memset( p, 0, sizeof(Abc_ManRec_t) ); + p->pNtk = pNtk; + p->nVars = Abc_NtkPiNum(pNtk); + p->nWords = Kit_TruthWordNum( p->nVars ); + p->nCuts = nCuts; + p->nVarsInit = nVars; + + // create elementary truth tables + p->vTtElems = Vec_PtrAlloc( 0 ); assert( p->vTtElems->pArray == NULL ); + p->vTtElems->nSize = p->nVars; + p->vTtElems->nCap = p->nVars; + p->vTtElems->pArray = (void *)Extra_TruthElementary( p->nVars ); + + // allocate room for node truth tables + if ( Abc_NtkObjNum(pNtk) > (1<<14) ) + p->vTtNodes = Vec_PtrAllocSimInfo( 2 * Abc_NtkObjNum(pNtk), p->nWords ); + else + p->vTtNodes = Vec_PtrAllocSimInfo( 1<<14, p->nWords ); + + // create hash table + p->nBins = 50011; + p->pBins = ALLOC( Abc_Obj_t *, p->nBins ); + memset( p->pBins, 0, sizeof(Abc_Obj_t *) * p->nBins ); + + // set elementary tables + Kit_TruthFill( Vec_PtrEntry(p->vTtNodes, 0), p->nVars ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Kit_TruthCopy( Vec_PtrEntry(p->vTtNodes, pObj->Id), Vec_PtrEntry(p->vTtElems, i), p->nVars ); + + // compute the tables +clk = clock(); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + RetValue = Abc_NtkRecComputeTruth( pObj, p->vTtNodes, p->nVars ); + assert( RetValue ); + } +p->timeTruth += clock() - clk; + + // insert the PO nodes into the table + Abc_NtkForEachPo( pNtk, pObj, i ) + { + p->nTried++; + p->nAdded++; + + pObj = Abc_ObjFanin0(pObj); + pTruth = Vec_PtrEntry( p->vTtNodes, pObj->Id ); + + if ( pTruth[0] == 1128481603 ) + { + int x = 0; + } + + // add the resulting truth table to the hash table + ppSpot = Abc_NtkRecTableLookup( p, pTruth, p->nVars ); + assert( pObj->pEquiv == NULL ); + assert( pObj->pCopy == NULL ); + if ( *ppSpot == NULL ) + { + p->nAddedFuncs++; + *ppSpot = pObj; + } + else + { + pObj->pEquiv = (*ppSpot)->pEquiv; + (*ppSpot)->pEquiv = (Hop_Obj_t *)pObj; + if ( !Abc_NtkRecAddCutCheckCycle_rec(*ppSpot, pObj) ) + printf( "Loop!\n" ); + } + } + + // temporaries + p->pBytes = ALLOC( int, 4*p->nWords ); + p->pMints = ALLOC( int, 2*p->nVars ); + p->pTemp1 = ALLOC( unsigned, p->nWords ); + p->pTemp2 = ALLOC( unsigned, p->nWords ); + p->vNodes = Vec_PtrAlloc( 100 ); + p->vTtTemps = Vec_PtrAllocSimInfo( 64, p->nWords ); + p->vMemory = Vec_IntAlloc( Abc_TruthWordNum(p->nVars) * 1000 ); + + // set the manager + s_pMan = p; +p->timeTotal += clock() - clkTotal; +} + +/**Function************************************************************* + + Synopsis [Returns the given record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecStop() +{ + assert( s_pMan != NULL ); + if ( s_pMan->pNtk ) + Abc_NtkDelete( s_pMan->pNtk ); + Vec_PtrFree( s_pMan->vTtNodes ); + Vec_PtrFree( s_pMan->vTtElems ); + free( s_pMan->pBins ); + + // temporaries + free( s_pMan->pBytes ); + free( s_pMan->pMints ); + free( s_pMan->pTemp1 ); + free( s_pMan->pTemp2 ); + Vec_PtrFree( s_pMan->vNodes ); + Vec_PtrFree( s_pMan->vTtTemps ); + if ( s_pMan->vLabels ) + Vec_PtrFree( s_pMan->vLabels ); + if ( s_pMan->vCosts ) + Vec_StrFree( s_pMan->vCosts ); + Vec_IntFree( s_pMan->vMemory ); + + free( s_pMan ); + s_pMan = NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the given record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkRecUse() +{ + Abc_ManRec_t * p = s_pMan; + Abc_Ntk_t * pNtk = p->pNtk; + assert( p != NULL ); + Abc_NtkRecPs(); + p->pNtk = NULL; + Abc_NtkRecStop(); + return pNtk; +} + +static inline void Abc_ObjSetMax( Abc_Obj_t * pObj, int Value ) { assert( pObj->Level < 0xff ); pObj->Level = (Value << 8) | (pObj->Level & 0xff); } +static inline void Abc_ObjClearMax( Abc_Obj_t * pObj ) { pObj->Level = (pObj->Level & 0xff); } +static inline int Abc_ObjGetMax( Abc_Obj_t * pObj ) { return (pObj->Level >> 8) & 0xff; } + +/**Function************************************************************* + + Synopsis [Print statistics about the current record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecPs() +{ + int Counter, Counters[17] = {0}; + int CounterS, CountersS[17] = {0}; + Abc_ManRec_t * p = s_pMan; + Abc_Ntk_t * pNtk = p->pNtk; + Abc_Obj_t * pObj, * pEntry, * pTemp; + int i; + + // set the max PI number + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetMax( pObj, i+1 ); + Abc_AigForEachAnd( pNtk, pObj, i ) + Abc_ObjSetMax( pObj, ABC_MAX( Abc_ObjGetMax(Abc_ObjFanin0(pObj)), Abc_ObjGetMax(Abc_ObjFanin1(pObj)) ) ); + // go through the table + Counter = CounterS = 0; + for ( i = 0; i < p->nBins; i++ ) + for ( pEntry = p->pBins[i]; pEntry; pEntry = pEntry->pCopy ) + { + Counters[ Abc_ObjGetMax(pEntry) ]++; + Counter++; + for ( pTemp = pEntry; pTemp; pTemp = (Abc_Obj_t *)pTemp->pEquiv ) + { + assert( Abc_ObjGetMax(pTemp) == Abc_ObjGetMax(pEntry) ); + CountersS[ Abc_ObjGetMax(pTemp) ]++; + CounterS++; + } + } +// printf( "Functions = %d. Expected = %d.\n", Counter, p->nAddedFuncs ); +// printf( "Subgraphs = %d. Expected = %d.\n", CounterS, p->nAdded ); + assert( Counter == p->nAddedFuncs ); + assert( CounterS == p->nAdded ); + + // clean + Abc_NtkForEachObj( pNtk, pObj, i ) + { + Abc_ObjClearMax( pObj ); + } + + printf( "The record with %d AND nodes in %d subgraphs for %d functions with %d inputs:\n", + Abc_NtkNodeNum(pNtk), Abc_NtkPoNum(pNtk), p->nAddedFuncs, Abc_NtkPiNum(pNtk) ); + for ( i = 0; i <= 16; i++ ) + { + if ( Counters[i] ) + printf( "Inputs = %2d. Funcs = %8d. Subgrs = %8d. Ratio = %6.2f.\n", i, Counters[i], CountersS[i], 1.0*CountersS[i]/Counters[i] ); + } + + printf( "Subgraphs tried = %8d. (%6.2f %%)\n", p->nTried, !p->nTried? 0 : 100.0*p->nTried/p->nTried ); + printf( "Subgraphs filtered by support size = %8d. (%6.2f %%)\n", p->nFilterSize, !p->nTried? 0 : 100.0*p->nFilterSize/p->nTried ); + printf( "Subgraphs filtered by structural redundancy = %8d. (%6.2f %%)\n", p->nFilterRedund, !p->nTried? 0 : 100.0*p->nFilterRedund/p->nTried ); + printf( "Subgraphs filtered by volume = %8d. (%6.2f %%)\n", p->nFilterVolume, !p->nTried? 0 : 100.0*p->nFilterVolume/p->nTried ); + printf( "Subgraphs filtered by TT redundancy = %8d. (%6.2f %%)\n", p->nFilterTruth, !p->nTried? 0 : 100.0*p->nFilterTruth/p->nTried ); + printf( "Subgraphs filtered by error = %8d. (%6.2f %%)\n", p->nFilterError, !p->nTried? 0 : 100.0*p->nFilterError/p->nTried ); + printf( "Subgraphs filtered by isomorphism = %8d. (%6.2f %%)\n", p->nFilterSame, !p->nTried? 0 : 100.0*p->nFilterSame/p->nTried ); + printf( "Subgraphs added = %8d. (%6.2f %%)\n", p->nAdded, !p->nTried? 0 : 100.0*p->nAdded/p->nTried ); + printf( "Functions added = %8d. (%6.2f %%)\n", p->nAddedFuncs, !p->nTried? 0 : 100.0*p->nAddedFuncs/p->nTried ); + + p->timeOther = p->timeTotal - p->timeCollect - p->timeTruth - p->timeCanon; + PRTP( "Collecting nodes ", p->timeCollect, p->timeTotal ); + PRTP( "Computing truth ", p->timeTruth, p->timeTotal ); + PRTP( "Canonicizing ", p->timeCanon, p->timeTotal ); + PRTP( "Other ", p->timeOther, p->timeTotal ); + PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + if ( p->nFunsFound ) + printf( "During rewriting found = %d and not found = %d functions.\n", p->nFunsFound, p->nFunsNotFound ); +} + +/**Function************************************************************* + + Synopsis [Filters the current record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecFilter( int iVar, int iPlus ) +{ +} + +/**Function************************************************************* + + Synopsis [Returns the hash key.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Abc_NtkRecTableHash( unsigned * pTruth, int nVars, int nBins, int * pPrimes ) +{ + int i, nWords = Kit_TruthWordNum( nVars ); + unsigned uHash = 0; + for ( i = 0; i < nWords; i++ ) + uHash ^= pTruth[i] * pPrimes[i & 0x7]; + return uHash % nBins; +} + +/**Function************************************************************* + + Synopsis [Returns the given record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t ** Abc_NtkRecTableLookup( Abc_ManRec_t * p, unsigned * pTruth, int nVars ) +{ + static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 }; + Abc_Obj_t ** ppSpot, * pEntry; + ppSpot = p->pBins + Abc_NtkRecTableHash( pTruth, nVars, p->nBins, s_Primes ); + for ( pEntry = *ppSpot; pEntry; ppSpot = &pEntry->pCopy, pEntry = pEntry->pCopy ) + if ( Kit_TruthIsEqualWithPhase(Vec_PtrEntry(p->vTtNodes, pEntry->Id), pTruth, nVars) ) + return ppSpot; + return ppSpot; +} + +/**Function************************************************************* + + Synopsis [Computes the truth table of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecComputeTruth( Abc_Obj_t * pObj, Vec_Ptr_t * vTtNodes, int nVars ) +{ + unsigned * pTruth, * pTruth0, * pTruth1; + int RetValue; + assert( Abc_ObjIsNode(pObj) ); + pTruth = Vec_PtrEntry( vTtNodes, pObj->Id ); + pTruth0 = Vec_PtrEntry( vTtNodes, Abc_ObjFaninId0(pObj) ); + pTruth1 = Vec_PtrEntry( vTtNodes, Abc_ObjFaninId1(pObj) ); + Kit_TruthAndPhase( pTruth, pTruth0, pTruth1, nVars, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); + assert( (pTruth[0] & 1) == pObj->fPhase ); + RetValue = ((pTruth[0] & 1) == pObj->fPhase); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Performs renoding as technology mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecAdd( Abc_Ntk_t * pNtk ) +{ + extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); + extern int Abc_NtkRecAddCut( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut ); + + If_Par_t Pars, * pPars = &Pars; + Abc_Ntk_t * pNtkNew; + int clk = clock(); + + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Performing renoding with choices.\n" ); + + // set defaults + memset( pPars, 0, sizeof(If_Par_t) ); + // user-controlable paramters + pPars->nLutSize = s_pMan->nVarsInit; + pPars->nCutsMax = s_pMan->nCuts; + pPars->nFlowIters = 0; + pPars->nAreaIters = 0; + pPars->DelayTarget = -1; + pPars->fPreprocess = 0; + pPars->fArea = 1; + pPars->fFancy = 0; + pPars->fExpRed = 0; + pPars->fLatchPaths = 0; + pPars->fSeqMap = 0; + pPars->fVerbose = 0; + // internal parameters + pPars->fTruth = 0; + pPars->fUsePerm = 0; + pPars->nLatches = 0; + pPars->pLutLib = NULL; // Abc_FrameReadLibLut(); + pPars->pTimesArr = NULL; + pPars->pTimesArr = NULL; + pPars->fUseBdds = 0; + pPars->fUseSops = 0; + pPars->fUseCnfs = 0; + pPars->fUseMv = 0; + pPars->pFuncCost = NULL; + pPars->pFuncUser = Abc_NtkRecAddCut; + + // perform recording + pNtkNew = Abc_NtkIf( pNtk, pPars ); + Abc_NtkDelete( pNtkNew ); +s_pMan->timeTotal += clock() - clk; + +// if ( !Abc_NtkCheck( s_pMan->pNtk ) ) +// printf( "Abc_NtkRecAdd: The network check has failed.\n" ); +} + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecCollectNodes_rec( If_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + if ( pNode->fMark ) + return; + pNode->fMark = 1; + assert( If_ObjIsAnd(pNode) ); + Abc_NtkRecCollectNodes_rec( If_ObjFanin0(pNode), vNodes ); + Abc_NtkRecCollectNodes_rec( If_ObjFanin1(pNode), vNodes ); + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecCollectNodes( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes ) +{ + If_Obj_t * pLeaf; + int i, RetValue = 1; + + // collect the internal nodes of the cut + Vec_PtrClear( vNodes ); + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + { + Vec_PtrPush( vNodes, pLeaf ); + assert( pLeaf->fMark == 0 ); + pLeaf->fMark = 1; + } + + // collect other nodes + Abc_NtkRecCollectNodes_rec( pRoot, vNodes ); + + // check if there are leaves, such that both of their fanins are marked + // this indicates a redundant cut + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + { + if ( !If_ObjIsAnd(pLeaf) ) + continue; + if ( If_ObjFanin0(pLeaf)->fMark && If_ObjFanin1(pLeaf)->fMark ) + { + RetValue = 0; + break; + } + } + + // clean the mark + Vec_PtrForEachEntry( vNodes, pLeaf, i ) + pLeaf->fMark = 0; +/* + if ( pRoot->Id == 2639 ) + { + // print the cut + Vec_PtrForEachEntry( vNodes, pLeaf, i ) + { + if ( If_ObjIsAnd(pLeaf) ) + printf( "%4d = %c%4d & %c%4d\n", pLeaf->Id, + (If_ObjFaninC0(pLeaf)? '-':'+'), If_ObjFanin0(pLeaf)->Id, + (If_ObjFaninC1(pLeaf)? '-':'+'), If_ObjFanin1(pLeaf)->Id ); + else + printf( "%4d = pi\n", pLeaf->Id ); + } + printf( "\n" ); + } +*/ + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Computes truth tables of nodes in the cut.] + + Description [Returns 0 if the TT does not depend on some cut variables. + Or if the TT can be expressed simpler using other nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecCutTruth( Vec_Ptr_t * vNodes, int nLeaves, Vec_Ptr_t * vTtTemps, Vec_Ptr_t * vTtElems ) +{ + unsigned * pSims, * pSims0, * pSims1; + unsigned * pTemp = s_pMan->pTemp2; + unsigned uWord; + If_Obj_t * pObj, * pObj2, * pRoot; + int i, k, nLimit, nInputs = s_pMan->nVars; + + assert( Vec_PtrSize(vNodes) > nLeaves ); + + // set the elementary truth tables and compute the truth tables of the nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + pObj->pCopy = Vec_PtrEntry(vTtTemps, i); + pSims = (unsigned *)pObj->pCopy; + if ( i < nLeaves ) + { + Kit_TruthCopy( pSims, Vec_PtrEntry(vTtElems, i), nInputs ); + continue; + } + assert( If_ObjIsAnd(pObj) ); + // get hold of the simulation information + pSims0 = (unsigned *)If_ObjFanin0(pObj)->pCopy; + pSims1 = (unsigned *)If_ObjFanin1(pObj)->pCopy; + // simulate the node + Kit_TruthAndPhase( pSims, pSims0, pSims1, nInputs, If_ObjFaninC0(pObj), If_ObjFaninC1(pObj) ); + } + + // check the support size + pRoot = Vec_PtrEntryLast( vNodes ); + pSims = (unsigned *)pRoot->pCopy; + if ( Kit_TruthSupport(pSims, nInputs) != Kit_BitMask(nLeaves) ) + return 0; + + // make sure none of the nodes has the same simulation info as the output + // check pairwise comparisons + nLimit = Vec_PtrSize(vNodes) - 1; + Vec_PtrForEachEntryStop( vNodes, pObj, i, nLimit ) + { + pSims0 = (unsigned *)pObj->pCopy; + if ( Kit_TruthIsEqualWithPhase(pSims, pSims0, nInputs) ) + return 0; + Vec_PtrForEachEntryStop( vNodes, pObj2, k, i ) + { + if ( (If_ObjFanin0(pRoot) == pObj && If_ObjFanin1(pRoot) == pObj2) || + (If_ObjFanin1(pRoot) == pObj && If_ObjFanin0(pRoot) == pObj2) ) + continue; + pSims1 = (unsigned *)pObj2->pCopy; + + uWord = pSims0[0] & pSims1[0]; + if ( pSims[0] == uWord || pSims[0] == ~uWord ) + { + Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 0, 0 ); + if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) + return 0; + } + + uWord = pSims0[0] & ~pSims1[0]; + if ( pSims[0] == uWord || pSims[0] == ~uWord ) + { + Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 0, 1 ); + if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) + return 0; + } + + uWord = ~pSims0[0] & pSims1[0]; + if ( pSims[0] == uWord || pSims[0] == ~uWord ) + { + Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 1, 0 ); + if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) + return 0; + } + + uWord = ~pSims0[0] & ~pSims1[0]; + if ( pSims[0] == uWord || pSims[0] == ~uWord ) + { + Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 1, 1 ); + if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) + return 0; + } + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecAddCutCheckCycle_rec( Abc_Obj_t * pRoot, Abc_Obj_t * pObj ) +{ + assert( pRoot->Level > 0 ); + if ( pObj->Level < pRoot->Level ) + return 1; + if ( pObj == pRoot ) + return 0; + if ( !Abc_NtkRecAddCutCheckCycle_rec(pRoot, Abc_ObjFanin0(pObj)) ) + return 0; + if ( !Abc_NtkRecAddCutCheckCycle_rec(pRoot, Abc_ObjFanin1(pObj)) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecAddCut( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut ) +{ + static int s_MaxSize[16] = { 0 }; + char Buffer[40], Name[20], Truth[20]; + char pCanonPerm[16]; + Abc_Obj_t * pObj, * pFanin0, * pFanin1, ** ppSpot, * pObjPo; + Abc_Ntk_t * pAig = s_pMan->pNtk; + If_Obj_t * pIfObj; + Vec_Ptr_t * vNodes = s_pMan->vNodes; + unsigned * pInOut = s_pMan->pTemp1; + unsigned * pTemp = s_pMan->pTemp2; + unsigned * pTruth; + int i, RetValue, nNodes, nNodesBeg, nInputs = s_pMan->nVars, nLeaves = If_CutLeaveNum(pCut); + unsigned uCanonPhase; + int clk; + + if ( pRoot->Id == 2639 ) + { + int y = 0; + } + + assert( nInputs <= 16 ); + assert( nInputs == (int)pCut->nLimit ); + s_pMan->nTried++; + + // skip small cuts + if ( nLeaves < 3 ) + { + s_pMan->nFilterSize++; + return 1; + } + + // collect internal nodes and skip redundant cuts +clk = clock(); + RetValue = Abc_NtkRecCollectNodes( pIfMan, pRoot, pCut, vNodes ); +s_pMan->timeCollect += clock() - clk; + if ( !RetValue ) + { + s_pMan->nFilterRedund++; + return 1; + } + + // skip cuts with very large volume + if ( Vec_PtrSize(vNodes) > nLeaves + 3*(nLeaves-1) + s_MaxSize[nLeaves] ) + { + s_pMan->nFilterVolume++; + return 1; + } + + // compute truth table and skip the redundant structures +clk = clock(); + RetValue = Abc_NtkRecCutTruth( vNodes, nLeaves, s_pMan->vTtTemps, s_pMan->vTtElems ); +s_pMan->timeTruth += clock() - clk; + if ( !RetValue ) + { + s_pMan->nFilterTruth++; + return 1; + } + + // copy the truth table + Kit_TruthCopy( pInOut, (unsigned *)pRoot->pCopy, nInputs ); + + // set permutation + for ( i = 0; i < nInputs; i++ ) + pCanonPerm[i] = i; + + // semi-canonicize the truth table +clk = clock(); + uCanonPhase = Kit_TruthSemiCanonicize( pInOut, pTemp, nInputs, pCanonPerm, (short *)s_pMan->pMints ); +s_pMan->timeCanon += clock() - clk; + // pCanonPerm and uCanonPhase show what was the variable corresponding to each var in the current truth + + // go through the variables in the new truth table + for ( i = 0; i < nLeaves; i++ ) + { + // get hold of the corresponding leaf + pIfObj = If_ManObj( pIfMan, pCut->pLeaves[pCanonPerm[i]] ); + // get hold of the corresponding new node + pObj = Abc_NtkPi( pAig, i ); + pObj = Abc_ObjNotCond( pObj, (uCanonPhase & (1 << i)) ); + // map them + pIfObj->pCopy = pObj; +/* + if ( pRoot->Id == 2639 ) + { + unsigned uSupp; + printf( "Node %6d : ", pIfObj->Id ); + printf( "Support " ); + uSupp = Kit_TruthSupport(Vec_PtrEntry( s_pMan->vTtNodes, Abc_ObjRegular(pObj)->Id ), nInputs); + Extra_PrintBinary( stdout, &uSupp, nInputs ); + printf( " " ); + Extra_PrintBinary( stdout, Vec_PtrEntry( s_pMan->vTtNodes, Abc_ObjRegular(pObj)->Id ), 1<<6 ); + printf( "\n" ); + } +*/ + } + + // build the node and compute its truth table + nNodesBeg = Abc_NtkObjNumMax( pAig ); + Vec_PtrForEachEntryStart( vNodes, pIfObj, i, nLeaves ) + { + pFanin0 = Abc_ObjNotCond( If_ObjFanin0(pIfObj)->pCopy, If_ObjFaninC0(pIfObj) ); + pFanin1 = Abc_ObjNotCond( If_ObjFanin1(pIfObj)->pCopy, If_ObjFaninC1(pIfObj) ); + + nNodes = Abc_NtkObjNumMax( pAig ); + pObj = Abc_AigAnd( pAig->pManFunc, pFanin0, pFanin1 ); + assert( !Abc_ObjIsComplement(pObj) ); + pIfObj->pCopy = pObj; + + if ( pObj->Id == nNodes ) + { + // increase storage for truth tables + if ( Vec_PtrSize(s_pMan->vTtNodes) <= pObj->Id ) + Vec_PtrDoubleSimInfo(s_pMan->vTtNodes); + // compute the truth table + RetValue = Abc_NtkRecComputeTruth( pObj, s_pMan->vTtNodes, nInputs ); + if ( RetValue == 0 ) + { + s_pMan->nFilterError++; + printf( "T" ); + return 1; + } + } + } + + pTruth = Vec_PtrEntry( s_pMan->vTtNodes, pObj->Id ); + if ( Kit_TruthSupport(pTruth, nInputs) != Kit_BitMask(nLeaves) ) + { + s_pMan->nFilterError++; + printf( "S" ); + return 1; + } + + // compare the truth tables + if ( !Kit_TruthIsEqualWithPhase( pTruth, pInOut, nInputs ) ) + { + s_pMan->nFilterError++; + printf( "F" ); + return 1; + } +// Extra_PrintBinary( stdout, pInOut, 8 ); printf( "\n" ); + + // if not new nodes were added and the node has a CO fanout + if ( nNodesBeg == Abc_NtkObjNumMax(pAig) && Abc_NodeFindCoFanout(pObj) != NULL ) + { + s_pMan->nFilterSame++; + return 1; + } + s_pMan->nAdded++; + + // create PO for this node + pObjPo = Abc_NtkCreatePo(pAig); + Abc_ObjAddFanin( pObjPo, pObj ); + + // assign the name to this PO + sprintf( Name, "%d_%06d", nLeaves, Abc_NtkPoNum(pAig) ); + if ( (nInputs <= 6) && 0 ) + { + Extra_PrintHexadecimalString( Truth, pInOut, nInputs ); + sprintf( Buffer, "%s_%s", Name, Truth ); + } + else + { + sprintf( Buffer, "%s", Name ); + } + Abc_ObjAssignName( pObjPo, Buffer, NULL ); + + // add the resulting truth table to the hash table + ppSpot = Abc_NtkRecTableLookup( s_pMan, pTruth, nInputs ); + assert( pObj->pEquiv == NULL ); + assert( pObj->pCopy == NULL ); + if ( *ppSpot == NULL ) + { + s_pMan->nAddedFuncs++; + *ppSpot = pObj; + } + else + { + pObj->pEquiv = (*ppSpot)->pEquiv; + (*ppSpot)->pEquiv = (Hop_Obj_t *)pObj; + if ( !Abc_NtkRecAddCutCheckCycle_rec(*ppSpot, pObj) ) + printf( "Loop!\n" ); + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Labels the record AIG with the corresponding new AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkRecStrashNodeLabel_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fBuild, Vec_Ptr_t * vLabels ) +{ + Abc_Obj_t * pFanin0New, * pFanin1New, * pLabel; + assert( !Abc_ObjIsComplement(pObj) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return Vec_PtrEntry( vLabels, pObj->Id ); + assert( Abc_ObjIsNode(pObj) ); + // mark the node as visited + Abc_NodeSetTravIdCurrent( pObj ); + // label the fanins + pFanin0New = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, Abc_ObjFanin0(pObj), fBuild, vLabels ); + pFanin1New = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, Abc_ObjFanin1(pObj), fBuild, vLabels ); + // label the node if possible + pLabel = NULL; + if ( pFanin0New && pFanin1New ) + { + pFanin0New = Abc_ObjNotCond( pFanin0New, Abc_ObjFaninC0(pObj) ); + pFanin1New = Abc_ObjNotCond( pFanin1New, Abc_ObjFaninC1(pObj) ); + if ( fBuild ) + pLabel = Abc_AigAnd( pNtkNew->pManFunc, pFanin0New, pFanin1New ); + else + pLabel = Abc_AigAndLookup( pNtkNew->pManFunc, pFanin0New, pFanin1New ); + } + Vec_PtrWriteEntry( vLabels, pObj->Id, pLabel ); + return pLabel; +} + +/**Function************************************************************* + + Synopsis [Counts the area of the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecStrashNodeCount_rec( Abc_Obj_t * pObj, Vec_Str_t * vCosts, Vec_Ptr_t * vLabels ) +{ + int Cost0, Cost1; + if ( Vec_PtrEntry( vLabels, pObj->Id ) ) + return 0; + assert( Abc_ObjIsNode(pObj) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return Vec_StrEntry( vCosts, pObj->Id ); + // mark the node as visited + Abc_NodeSetTravIdCurrent( pObj ); + // count for the fanins + Cost0 = Abc_NtkRecStrashNodeCount_rec( Abc_ObjFanin0(pObj), vCosts, vLabels ); + Cost1 = Abc_NtkRecStrashNodeCount_rec( Abc_ObjFanin1(pObj), vCosts, vLabels ); + Vec_StrWriteEntry( vCosts, pObj->Id, (char)(Cost0 + Cost1 + 1) ); + return Cost0 + Cost1 + 1; +} + +/**Function************************************************************* + + Synopsis [Strashes the given node using its local function.] + + Description [Assumes that the fanins are already strashed. + Returns 0 if the function is not found in the table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars ) +{ + char pCanonPerm[16]; + Abc_Ntk_t * pAig = s_pMan->pNtk; + unsigned * pInOut = s_pMan->pTemp1; + unsigned * pTemp = s_pMan->pTemp2; + unsigned * pTruthRec; + Abc_Obj_t * pCand, * pCandMin, * pLeaf, * pFanin, ** ppSpot; + unsigned uCanonPhase; + int i, nLeaves, CostMin, Cost, nOnes, fCompl; + + // check if the record works + nLeaves = Abc_ObjFaninNum(pObj); + assert( nLeaves >= 3 && nLeaves <= s_pMan->nVars ); + pFanin = Abc_ObjFanin0(pObj); + assert( Abc_ObjRegular(pFanin->pCopy)->pNtk == pNtkNew ); + assert( s_pMan != NULL ); + assert( nVars == s_pMan->nVars ); + + // copy the truth table + Kit_TruthCopy( pInOut, pTruth, nVars ); + + // set permutation + for ( i = 0; i < nVars; i++ ) + pCanonPerm[i] = i; + + // canonicize the truth table + uCanonPhase = Kit_TruthSemiCanonicize( pInOut, pTemp, nVars, pCanonPerm, (short *)s_pMan->pMints ); + + // get hold of the curresponding class + ppSpot = Abc_NtkRecTableLookup( s_pMan, pInOut, nVars ); + if ( *ppSpot == NULL ) + { + s_pMan->nFunsNotFound++; +// printf( "The class of a function with %d inputs is not found.\n", nLeaves ); + return 0; + } + s_pMan->nFunsFound++; + + // make sure the truth table is the same + pTruthRec = Vec_PtrEntry( s_pMan->vTtNodes, (*ppSpot)->Id ); + if ( !Kit_TruthIsEqualWithPhase( pTruthRec, pInOut, nVars ) ) + { + assert( 0 ); + return 0; + } + + + // allocate storage for costs + if ( s_pMan->vLabels && Vec_PtrSize(s_pMan->vLabels) < Abc_NtkObjNumMax(pAig) ) + { + Vec_PtrFree( s_pMan->vLabels ); + s_pMan->vLabels = NULL; + } + if ( s_pMan->vLabels == NULL ) + s_pMan->vLabels = Vec_PtrStart( Abc_NtkObjNumMax(pAig) ); + + // go through the variables in the new truth table + Abc_NtkIncrementTravId( pAig ); + for ( i = 0; i < nLeaves; i++ ) + { + // get hold of the corresponding fanin + pFanin = Abc_ObjFanin( pObj, pCanonPerm[i] )->pCopy; + pFanin = Abc_ObjNotCond( pFanin, (uCanonPhase & (1 << i)) ); + // label the PI of the AIG subgraphs with this fanin + pLeaf = Abc_NtkPi( pAig, i ); + Vec_PtrWriteEntry( s_pMan->vLabels, pLeaf->Id, pFanin ); + Abc_NodeSetTravIdCurrent( pLeaf ); + } + + // go through the candidates - and recursively label them + for ( pCand = *ppSpot; pCand; pCand = (Abc_Obj_t *)pCand->pEquiv ) + Abc_NtkRecStrashNodeLabel_rec( pNtkNew, pCand, 0, s_pMan->vLabels ); + + + // allocate storage for costs + if ( s_pMan->vCosts && Vec_StrSize(s_pMan->vCosts) < Abc_NtkObjNumMax(pAig) ) + { + Vec_StrFree( s_pMan->vCosts ); + s_pMan->vCosts = NULL; + } + if ( s_pMan->vCosts == NULL ) + s_pMan->vCosts = Vec_StrStart( Abc_NtkObjNumMax(pAig) ); + + // find the best subgraph + CostMin = ABC_INFINITY; + pCandMin = NULL; + for ( pCand = *ppSpot; pCand; pCand = (Abc_Obj_t *)pCand->pEquiv ) + { + // label the leaves + Abc_NtkIncrementTravId( pAig ); + // count the number of non-labeled nodes + Cost = Abc_NtkRecStrashNodeCount_rec( pCand, s_pMan->vCosts, s_pMan->vLabels ); + if ( CostMin > Cost ) + { +// printf( "%d ", Cost ); + CostMin = Cost; + pCandMin = pCand; + } + } +// printf( "\n" ); + assert( pCandMin != NULL ); + if ( pCandMin == NULL ) + return 0; + + + // label the leaves + Abc_NtkIncrementTravId( pAig ); + for ( i = 0; i < nLeaves; i++ ) + Abc_NodeSetTravIdCurrent( Abc_NtkPi(pAig, i) ); + + // implement the subgraph + pObj->pCopy = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, pCandMin, 1, s_pMan->vLabels ); + assert( Abc_ObjRegular(pObj->pCopy)->pNtk == pNtkNew ); + + // determine phase difference + nOnes = Kit_TruthCountOnes(pTruth, nVars); + fCompl = (nOnes > (1<< nVars)/2); +// assert( fCompl == ((uCanonPhase & (1 << nVars)) > 0) ); + + nOnes = Kit_TruthCountOnes(pTruthRec, nVars); + fCompl ^= (nOnes > (1<< nVars)/2); + // complement + pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, fCompl ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcReconv.c b/abc70930/src/base/abci/abcReconv.c new file mode 100644 index 00000000..e77f055a --- /dev/null +++ b/abc70930/src/base/abci/abcReconv.c @@ -0,0 +1,762 @@ +/**CFile**************************************************************** + + FileName [abcReconv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Computation of reconvergence-driven cuts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcReconv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Abc_ManCut_t_ +{ + // user specified parameters + int nNodeSizeMax; // the limit on the size of the supernode + int nConeSizeMax; // the limit on the size of the containing cone + int nNodeFanStop; // the limit on the size of the supernode + int nConeFanStop; // the limit on the size of the containing cone + // internal parameters + Vec_Ptr_t * vNodeLeaves; // fanins of the collapsed node (the cut) + Vec_Ptr_t * vConeLeaves; // fanins of the containing cone + Vec_Ptr_t * vVisited; // the visited nodes + Vec_Vec_t * vLevels; // the data structure to compute TFO nodes + Vec_Ptr_t * vNodesTfo; // the nodes in the TFO of the cut +}; + +static int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit ); +static int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit ); +static void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Unmarks the TFI cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_NodesMark( Vec_Ptr_t * vVisited ) +{ + Abc_Obj_t * pNode; + int i; + Vec_PtrForEachEntry( vVisited, pNode, i ) + pNode->fMarkA = 1; +} + +/**Function************************************************************* + + Synopsis [Unmarks the TFI cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_NodesUnmark( Vec_Ptr_t * vVisited ) +{ + Abc_Obj_t * pNode; + int i; + Vec_PtrForEachEntry( vVisited, pNode, i ) + pNode->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Unmarks the TFI cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_NodesUnmarkB( Vec_Ptr_t * vVisited ) +{ + Abc_Obj_t * pNode; + int i; + Vec_PtrForEachEntry( vVisited, pNode, i ) + pNode->fMarkB = 0; +} + +/**Function************************************************************* + + Synopsis [Evaluate the cost of removing the node from the set of leaves.] + + Description [Returns the number of new leaves that will be brought in. + Returns large number if the node cannot be removed from the set of leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_NodeGetLeafCostOne( Abc_Obj_t * pNode, int nFaninLimit ) +{ + int Cost; + // make sure the node is in the construction zone + assert( pNode->fMarkB == 1 ); + // cannot expand over the PI node + if ( Abc_ObjIsCi(pNode) ) + return 999; + // get the cost of the cone + Cost = (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB); + // always accept if the number of leaves does not increase + if ( Cost < 2 ) + return Cost; + // skip nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > nFaninLimit ) + return 999; + // return the number of nodes that will be on the leaves if this node is removed + return Cost; +} + +/**Function************************************************************* + + Synopsis [Evaluate the cost of removing the node from the set of leaves.] + + Description [Returns the number of new leaves that will be brought in. + Returns large number if the node cannot be removed from the set of leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_NodeGetLeafCostTwo( Abc_Obj_t * pNode, int nFaninLimit, + Abc_Obj_t ** ppLeafToAdd, Abc_Obj_t ** pNodeToMark1, Abc_Obj_t ** pNodeToMark2 ) +{ + Abc_Obj_t * pFanin0, * pFanin1, * pTemp; + Abc_Obj_t * pGrand, * pGrandToAdd; + // make sure the node is in the construction zone + assert( pNode->fMarkB == 1 ); + // cannot expand over the PI node + if ( Abc_ObjIsCi(pNode) ) + return 999; + // skip nodes with many fanouts +// if ( Abc_ObjFanoutNum(pNode) > nFaninLimit ) +// return 999; + // get the children + pFanin0 = Abc_ObjFanin0(pNode); + pFanin1 = Abc_ObjFanin1(pNode); + assert( !pFanin0->fMarkB && !pFanin1->fMarkB ); + // count the number of unique grandchildren that will be included + // return infinite cost if this number if more than 1 + if ( Abc_ObjIsCi(pFanin0) && Abc_ObjIsCi(pFanin1) ) + return 999; + // consider the special case when a non-CI fanin can be dropped + if ( !Abc_ObjIsCi(pFanin0) && Abc_ObjFanin0(pFanin0)->fMarkB && Abc_ObjFanin1(pFanin0)->fMarkB ) + { + *ppLeafToAdd = pFanin1; + *pNodeToMark1 = pFanin0; + *pNodeToMark2 = NULL; + return 1; + } + if ( !Abc_ObjIsCi(pFanin1) && Abc_ObjFanin0(pFanin1)->fMarkB && Abc_ObjFanin1(pFanin1)->fMarkB ) + { + *ppLeafToAdd = pFanin0; + *pNodeToMark1 = pFanin1; + *pNodeToMark2 = NULL; + return 1; + } + + // make the first node CI if any + if ( Abc_ObjIsCi(pFanin1) ) + pTemp = pFanin0, pFanin0 = pFanin1, pFanin1 = pTemp; + // consider the first node + pGrandToAdd = NULL; + if ( Abc_ObjIsCi(pFanin0) ) + { + *pNodeToMark1 = NULL; + pGrandToAdd = pFanin0; + } + else + { + *pNodeToMark1 = pFanin0; + pGrand = Abc_ObjFanin0(pFanin0); + if ( !pGrand->fMarkB ) + { + if ( pGrandToAdd && pGrandToAdd != pGrand ) + return 999; + pGrandToAdd = pGrand; + } + pGrand = Abc_ObjFanin1(pFanin0); + if ( !pGrand->fMarkB ) + { + if ( pGrandToAdd && pGrandToAdd != pGrand ) + return 999; + pGrandToAdd = pGrand; + } + } + // consider the second node + *pNodeToMark2 = pFanin1; + pGrand = Abc_ObjFanin0(pFanin1); + if ( !pGrand->fMarkB ) + { + if ( pGrandToAdd && pGrandToAdd != pGrand ) + return 999; + pGrandToAdd = pGrand; + } + pGrand = Abc_ObjFanin1(pFanin1); + if ( !pGrand->fMarkB ) + { + if ( pGrandToAdd && pGrandToAdd != pGrand ) + return 999; + pGrandToAdd = pGrand; + } + assert( pGrandToAdd != NULL ); + *ppLeafToAdd = pGrandToAdd; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Finds a fanin-limited, reconvergence-driven cut for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, bool fContain ) +{ + Abc_Obj_t * pNode; + int i; + + assert( !Abc_ObjIsComplement(pRoot) ); + assert( Abc_ObjIsNode(pRoot) ); + + // start the visited nodes and mark them + Vec_PtrClear( p->vVisited ); + Vec_PtrPush( p->vVisited, pRoot ); + Vec_PtrPush( p->vVisited, Abc_ObjFanin0(pRoot) ); + Vec_PtrPush( p->vVisited, Abc_ObjFanin1(pRoot) ); + pRoot->fMarkB = 1; + Abc_ObjFanin0(pRoot)->fMarkB = 1; + Abc_ObjFanin1(pRoot)->fMarkB = 1; + + // start the cut + Vec_PtrClear( p->vNodeLeaves ); + Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin0(pRoot) ); + Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin1(pRoot) ); + + // compute the cut + while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vNodeLeaves, p->nNodeSizeMax, p->nNodeFanStop ) ); + assert( Vec_PtrSize(p->vNodeLeaves) <= p->nNodeSizeMax ); + + // return if containing cut is not requested + if ( !fContain ) + { + // unmark both fMarkA and fMarkB in tbe TFI + Abc_NodesUnmarkB( p->vVisited ); + return p->vNodeLeaves; + } + +//printf( "\n\n\n" ); + // compute the containing cut + assert( p->nNodeSizeMax < p->nConeSizeMax ); + // copy the current boundary + Vec_PtrClear( p->vConeLeaves ); + Vec_PtrForEachEntry( p->vNodeLeaves, pNode, i ) + Vec_PtrPush( p->vConeLeaves, pNode ); + // compute the containing cut + while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vConeLeaves, p->nConeSizeMax, p->nConeFanStop ) ); + assert( Vec_PtrSize(p->vConeLeaves) <= p->nConeSizeMax ); + // unmark TFI using fMarkA and fMarkB + Abc_NodesUnmarkB( p->vVisited ); + return p->vNodeLeaves; +} + +/**Function************************************************************* + + Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] + + Description [This procedure looks at the current leaves and tries to change + one leaf at a time in such a way that the cut grows as little as possible. + In evaluating the fanins, this procedure looks only at their immediate + predecessors (this is why it is called a one-level construction procedure).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit ) +{ + Abc_Obj_t * pNode, * pFaninBest, * pNext; + int CostBest, CostCur, i; + // find the best fanin + CostBest = 100; + pFaninBest = NULL; +//printf( "Evaluating fanins of the cut:\n" ); + Vec_PtrForEachEntry( vLeaves, pNode, i ) + { + CostCur = Abc_NodeGetLeafCostOne( pNode, nFaninLimit ); +//printf( " Fanin %s has cost %d.\n", Abc_ObjName(pNode), CostCur ); +// if ( CostBest > CostCur ) // performance improvement: expand the variable with the smallest level + if ( CostBest > CostCur || + (CostBest == CostCur && pNode->Level > pFaninBest->Level) ) + { + CostBest = CostCur; + pFaninBest = pNode; + } + if ( CostBest == 0 ) + break; + } + if ( pFaninBest == NULL ) + return 0; +// return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit ); + + assert( CostBest < 3 ); + if ( vLeaves->nSize - 1 + CostBest > nSizeLimit ) + return 0; +// return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit ); + + assert( Abc_ObjIsNode(pFaninBest) ); + // remove the node from the array + Vec_PtrRemove( vLeaves, pFaninBest ); +//printf( "Removing fanin %s.\n", Abc_ObjName(pFaninBest) ); + + // add the left child to the fanins + pNext = Abc_ObjFanin0(pFaninBest); + if ( !pNext->fMarkB ) + { +//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) ); + pNext->fMarkB = 1; + Vec_PtrPush( vLeaves, pNext ); + Vec_PtrPush( vVisited, pNext ); + } + // add the right child to the fanins + pNext = Abc_ObjFanin1(pFaninBest); + if ( !pNext->fMarkB ) + { +//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) ); + pNext->fMarkB = 1; + Vec_PtrPush( vLeaves, pNext ); + Vec_PtrPush( vVisited, pNext ); + } + assert( vLeaves->nSize <= nSizeLimit ); + // keep doing this + return 1; +} + +/**Function************************************************************* + + Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] + + Description [This procedure looks at the current leaves and tries to change + one leaf at a time in such a way that the cut grows as little as possible. + In evaluating the fanins, this procedure looks across two levels of fanins + (this is why it is called a two-level construction procedure).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit ) +{ + Abc_Obj_t * pNode, * pLeafToAdd, * pNodeToMark1, * pNodeToMark2; + int CostCur, i; + // find the best fanin + Vec_PtrForEachEntry( vLeaves, pNode, i ) + { + CostCur = Abc_NodeGetLeafCostTwo( pNode, nFaninLimit, &pLeafToAdd, &pNodeToMark1, &pNodeToMark2 ); + if ( CostCur < 2 ) + break; + } + if ( CostCur > 2 ) + return 0; + // remove the node from the array + Vec_PtrRemove( vLeaves, pNode ); + // add the node to the leaves + if ( pLeafToAdd ) + { + assert( !pLeafToAdd->fMarkB ); + pLeafToAdd->fMarkB = 1; + Vec_PtrPush( vLeaves, pLeafToAdd ); + Vec_PtrPush( vVisited, pLeafToAdd ); + } + // mark the other nodes + if ( pNodeToMark1 ) + { + assert( !pNodeToMark1->fMarkB ); + pNodeToMark1->fMarkB = 1; + Vec_PtrPush( vVisited, pNodeToMark1 ); + } + if ( pNodeToMark2 ) + { + assert( !pNodeToMark2->fMarkB ); + pNodeToMark2->fMarkB = 1; + Vec_PtrPush( vVisited, pNodeToMark2 ); + } + // keep doing this + return 1; +} + + +/**Function************************************************************* + + Synopsis [Get the nodes contained in the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited, int fIncludeFanins ) +{ + Abc_Obj_t * pTemp; + int i; + // mark the fanins of the cone + Abc_NodesMark( vLeaves ); + // collect the nodes in the DFS order + Vec_PtrClear( vVisited ); + // add the fanins + if ( fIncludeFanins ) + Vec_PtrForEachEntry( vLeaves, pTemp, i ) + Vec_PtrPush( vVisited, pTemp ); + // add other nodes + for ( i = 0; i < nRoots; i++ ) + Abc_NodeConeMarkCollect_rec( ppRoots[i], vVisited ); + // unmark both sets + Abc_NodesUnmark( vLeaves ); + Abc_NodesUnmark( vVisited ); +} + +/**Function************************************************************* + + Synopsis [Marks the TFI cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ) +{ + if ( pNode->fMarkA == 1 ) + return; + // visit transitive fanin + if ( Abc_ObjIsNode(pNode) ) + { + Abc_NodeConeMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited ); + Abc_NodeConeMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited ); + } + assert( pNode->fMarkA == 0 ); + pNode->fMarkA = 1; + Vec_PtrPush( vVisited, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns BDD representing the logic function of the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited ) +{ + Abc_Obj_t * pNode; + DdNode * bFunc0, * bFunc1, * bFunc; + int i; + // get the nodes in the cut without fanins in the DFS order + Abc_NodeConeCollect( &pRoot, 1, vLeaves, vVisited, 0 ); + // set the elementary BDDs + Vec_PtrForEachEntry( vLeaves, pNode, i ) + pNode->pCopy = (Abc_Obj_t *)pbVars[i]; + // compute the BDDs for the collected nodes + Vec_PtrForEachEntry( vVisited, pNode, i ) + { + assert( !Abc_ObjIsPi(pNode) ); + bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ); + bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ); + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); + pNode->pCopy = (Abc_Obj_t *)bFunc; + } + Cudd_Ref( bFunc ); + // dereference the intermediate ones + Vec_PtrForEachEntry( vVisited, pNode, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy ); + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Returns BDD representing the transition relation of the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited ) +{ + DdNode * bFunc0, * bFunc1, * bFunc, * bTrans, * bTemp, * bCube, * bResult; + Abc_Obj_t * pNode; + int i; + // get the nodes in the cut without fanins in the DFS order + Abc_NodeConeCollect( (Abc_Obj_t **)vRoots->pArray, vRoots->nSize, vLeaves, vVisited, 0 ); + // set the elementary BDDs + Vec_PtrForEachEntry( vLeaves, pNode, i ) + pNode->pCopy = (Abc_Obj_t *)pbVarsX[i]; + // compute the BDDs for the collected nodes + Vec_PtrForEachEntry( vVisited, pNode, i ) + { + bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ); + bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ); + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); + pNode->pCopy = (Abc_Obj_t *)bFunc; + } + // compute the transition relation of the cone + bTrans = b1; Cudd_Ref( bTrans ); + Vec_PtrForEachEntry( vRoots, pNode, i ) + { + bFunc = Cudd_bddXnor( dd, (DdNode *)pNode->pCopy, pbVarsY[i] ); Cudd_Ref( bFunc ); + bTrans = Cudd_bddAnd( dd, bTemp = bTrans, bFunc ); Cudd_Ref( bTrans ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bFunc ); + } + // dereference the intermediate ones + Vec_PtrForEachEntry( vVisited, pNode, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy ); + // compute don't-cares + bCube = Extra_bddComputeRangeCube( dd, vRoots->nSize, vRoots->nSize + vLeaves->nSize ); Cudd_Ref( bCube ); + bResult = Cudd_bddExistAbstract( dd, bTrans, bCube ); Cudd_Ref( bResult ); + bResult = Cudd_Not( bResult ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_RecursiveDeref( dd, bTrans ); + Cudd_Deref( bResult ); + return bResult; +} + +/**Function************************************************************* + + Synopsis [Starts the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ) +{ + Abc_ManCut_t * p; + p = ALLOC( Abc_ManCut_t, 1 ); + memset( p, 0, sizeof(Abc_ManCut_t) ); + p->vNodeLeaves = Vec_PtrAlloc( 100 ); + p->vConeLeaves = Vec_PtrAlloc( 100 ); + p->vVisited = Vec_PtrAlloc( 100 ); + p->vLevels = Vec_VecAlloc( 100 ); + p->vNodesTfo = Vec_PtrAlloc( 100 ); + p->nNodeSizeMax = nNodeSizeMax; + p->nConeSizeMax = nConeSizeMax; + p->nNodeFanStop = nNodeFanStop; + p->nConeFanStop = nConeFanStop; + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkManCutStop( Abc_ManCut_t * p ) +{ + Vec_PtrFree( p->vNodeLeaves ); + Vec_PtrFree( p->vConeLeaves ); + Vec_PtrFree( p->vVisited ); + Vec_VecFree( p->vLevels ); + Vec_PtrFree( p->vNodesTfo ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the leaves of the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p ) +{ + return p->vConeLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the leaves of the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p ) +{ + return p->vNodeLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the leaves of the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p ) +{ + return p->vVisited; +} + + + +/**Function************************************************************* + + Synopsis [Collects the TFO of the cut in the topological order.] + + Description [TFO of the cut is defined as a set of nodes, for which the cut + is a cut, that is, every path from the collected nodes to the CIs goes through + a node in the cut. The nodes are collected if their level does not exceed + the given number (LevelMax). The nodes are returned in the topological order. + If the root node is given, its MFFC is marked, so that the collected nodes + do not contain any nodes in the MFFC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int LevelMax ) +{ + Abc_Ntk_t * pNtk = pRoot->pNtk; + Vec_Ptr_t * vVec; + Abc_Obj_t * pNode, * pFanout; + int i, k, v, LevelMin; + assert( Abc_NtkIsStrash(pNtk) ); + + // assuming that the structure is clean + Vec_VecForEachLevel( p->vLevels, vVec, i ) + assert( vVec->nSize == 0 ); + + // put fanins into the structure while labeling them + Abc_NtkIncrementTravId( pNtk ); + LevelMin = -1; + Vec_PtrForEachEntry( vLeaves, pNode, i ) + { + if ( pNode->Level > (unsigned)LevelMax ) + continue; + Abc_NodeSetTravIdCurrent( pNode ); + Vec_VecPush( p->vLevels, pNode->Level, pNode ); + if ( LevelMin < (int)pNode->Level ) + LevelMin = pNode->Level; + } + assert( LevelMin >= 0 ); + + // mark MFFC + if ( pRoot ) + Abc_NodeMffcLabelAig( pRoot ); + + // go through the levels up + Vec_PtrClear( p->vNodesTfo ); + Vec_VecForEachEntryStart( p->vLevels, pNode, i, k, LevelMin ) + { + if ( i > LevelMax ) + break; + // if the node is not marked, it is not a fanin + if ( !Abc_NodeIsTravIdCurrent(pNode) ) + { + // check if it belongs to the TFO + if ( !Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pNode)) || + !Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pNode)) ) + continue; + // save the node in the TFO and label it + Vec_PtrPush( p->vNodesTfo, pNode ); + Abc_NodeSetTravIdCurrent( pNode ); + } + // go through the fanouts and add them to the structure if they meet the conditions + Abc_ObjForEachFanout( pNode, pFanout, v ) + { + // skip if fanout is a CO or its level exceeds + if ( Abc_ObjIsCo(pFanout) || pFanout->Level > (unsigned)LevelMax ) + continue; + // skip if it is already added or if it is in MFFC + if ( Abc_NodeIsTravIdCurrent(pFanout) ) + continue; + // add it to the structure but do not mark it (until tested later) + Vec_VecPushUnique( p->vLevels, pFanout->Level, pFanout ); + } + } + + // clear the levelized structure + Vec_VecForEachLevelStart( p->vLevels, vVec, i, LevelMin ) + { + if ( i > LevelMax ) + break; + Vec_PtrClear( vVec ); + } + return p->vNodesTfo; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcRefactor.c b/abc70930/src/base/abci/abcRefactor.c new file mode 100644 index 00000000..d2b77ed2 --- /dev/null +++ b/abc70930/src/base/abci/abcRefactor.c @@ -0,0 +1,379 @@ +/**CFile**************************************************************** + + FileName [abcRefactor.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Resynthesis based on collapsing and refactoring.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRefactor.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Abc_ManRef_t_ Abc_ManRef_t; +struct Abc_ManRef_t_ +{ + // user specified parameters + int nNodeSizeMax; // the limit on the size of the supernode + int nConeSizeMax; // the limit on the size of the containing cone + int fVerbose; // the verbosity flag + // internal data structures + DdManager * dd; // the BDD manager + Vec_Str_t * vCube; // temporary + Vec_Int_t * vForm; // temporary + Vec_Ptr_t * vVisited; // temporary + Vec_Ptr_t * vLeaves; // temporary + // node statistics + int nLastGain; + int nNodesConsidered; + int nNodesRefactored; + int nNodesGained; + int nNodesBeg; + int nNodesEnd; + // runtime statistics + int timeCut; + int timeBdd; + int timeDcs; + int timeSop; + int timeFact; + int timeEval; + int timeRes; + int timeNtk; + int timeTotal; +}; + +static void Abc_NtkManRefPrintStats( Abc_ManRef_t * p ); +static Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, bool fUseDcs, bool fVerbose ); +static void Abc_NtkManRefStop( Abc_ManRef_t * p ); +static Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs incremental resynthesis of the AIG.] + + Description [Starting from each node, computes a reconvergence-driven cut, + derives BDD of the cut function, constructs ISOP, factors the ISOP, + and replaces the current implementation of the MFFC of the node by the + new factored form, if the number of AIG nodes is reduced and the total + number of levels of the AIG network is not increated. Returns the + number of AIG nodes saved.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ) +{ + ProgressBar * pProgress; + Abc_ManRef_t * pManRef; + Abc_ManCut_t * pManCut; + Dec_Graph_t * pFForm; + Vec_Ptr_t * vFanins; + Abc_Obj_t * pNode; + int clk, clkStart = clock(); + int i, nNodes; + + assert( Abc_NtkIsStrash(pNtk) ); + // cleanup the AIG + Abc_AigCleanup(pNtk->pManFunc); + // start the managers + pManCut = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, 1000 ); + pManRef = Abc_NtkManRefStart( nNodeSizeMax, nConeSizeMax, fUseDcs, fVerbose ); + pManRef->vLeaves = Abc_NtkManCutReadCutLarge( pManCut ); + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Abc_NtkStartReverseLevels( pNtk, 0 ); + + // resynthesize each node once + pManRef->nNodesBeg = Abc_NtkNodeNum(pNtk); + nNodes = Abc_NtkObjNumMax(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // skip the constant node +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // skip persistant nodes + if ( Abc_NodeIsPersistant(pNode) ) + continue; + // skip the nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > 1000 ) + continue; + // stop if all nodes have been tried once + if ( i >= nNodes ) + break; + // compute a reconvergence-driven cut +clk = clock(); + vFanins = Abc_NodeFindCut( pManCut, pNode, fUseDcs ); +pManRef->timeCut += clock() - clk; + // evaluate this cut +clk = clock(); + pFForm = Abc_NodeRefactor( pManRef, pNode, vFanins, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ); +pManRef->timeRes += clock() - clk; + if ( pFForm == NULL ) + continue; + // acceptable replacement found, update the graph +clk = clock(); + Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRef->nLastGain ); +pManRef->timeNtk += clock() - clk; + Dec_GraphFree( pFForm ); +// { +// extern int s_TotalChanges; +// s_TotalChanges++; +// } + } + Extra_ProgressBarStop( pProgress ); +pManRef->timeTotal = clock() - clkStart; + pManRef->nNodesEnd = Abc_NtkNodeNum(pNtk); + + // print statistics of the manager + if ( fVerbose ) + Abc_NtkManRefPrintStats( pManRef ); + // delete the managers + Abc_NtkManCutStop( pManCut ); + Abc_NtkManRefStop( pManRef ); + // put the nodes into the DFS order and reassign their IDs + Abc_NtkReassignIds( pNtk ); +// Abc_AigCheckFaninOrder( pNtk->pManFunc ); + // fix the levels + if ( fUpdateLevel ) + Abc_NtkStopReverseLevels( pNtk ); + else + Abc_NtkLevel( pNtk ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkRefactor: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Resynthesizes the node using refactoring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ) +{ + int fVeryVerbose = 0; + Abc_Obj_t * pFanin; + Dec_Graph_t * pFForm; + DdNode * bNodeFunc; + int nNodesSaved, nNodesAdded, i, clk; + char * pSop; + int Required; + + Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY; + + p->nNodesConsidered++; + + // get the function of the cut +clk = clock(); + bNodeFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pNode, vFanins, p->vVisited ); Cudd_Ref( bNodeFunc ); +p->timeBdd += clock() - clk; + + // if don't-care are used, transform the function into ISOP + if ( fUseDcs ) + { + DdNode * bNodeDc, * bNodeOn, * bNodeOnDc; + int nMints, nMintsDc; +clk = clock(); + // get the don't-cares + bNodeDc = Abc_NodeConeDcs( p->dd, p->dd->vars + vFanins->nSize, p->dd->vars, p->vLeaves, vFanins, p->vVisited ); Cudd_Ref( bNodeDc ); + nMints = (1 << vFanins->nSize); + nMintsDc = (int)Cudd_CountMinterm( p->dd, bNodeDc, vFanins->nSize ); +// printf( "Percentage of minterms = %5.2f.\n", 100.0 * nMintsDc / nMints ); + // get the ISF + bNodeOn = Cudd_bddAnd( p->dd, bNodeFunc, Cudd_Not(bNodeDc) ); Cudd_Ref( bNodeOn ); + bNodeOnDc = Cudd_bddOr ( p->dd, bNodeFunc, bNodeDc ); Cudd_Ref( bNodeOnDc ); + Cudd_RecursiveDeref( p->dd, bNodeFunc ); + Cudd_RecursiveDeref( p->dd, bNodeDc ); + // get the ISOP + bNodeFunc = Cudd_bddIsop( p->dd, bNodeOn, bNodeOnDc ); Cudd_Ref( bNodeFunc ); + Cudd_RecursiveDeref( p->dd, bNodeOn ); + Cudd_RecursiveDeref( p->dd, bNodeOnDc ); +p->timeDcs += clock() - clk; + } + + // always accept the case of constant node + if ( Cudd_IsConstant(bNodeFunc) ) + { + p->nLastGain = Abc_NodeMffcSize( pNode ); + p->nNodesGained += p->nLastGain; + p->nNodesRefactored++; + Cudd_RecursiveDeref( p->dd, bNodeFunc ); + if ( Cudd_IsComplement(bNodeFunc) ) + return Dec_GraphCreateConst0(); + return Dec_GraphCreateConst1(); + } + + // get the SOP of the cut +clk = clock(); + pSop = Abc_ConvertBddToSop( NULL, p->dd, bNodeFunc, bNodeFunc, vFanins->nSize, 0, p->vCube, -1 ); +p->timeSop += clock() - clk; + + // get the factored form +clk = clock(); + pFForm = Dec_Factor( pSop ); + free( pSop ); +p->timeFact += clock() - clk; + + // mark the fanin boundary + // (can mark only essential fanins, belonging to bNodeFunc!) + Vec_PtrForEachEntry( vFanins, pFanin, i ) + pFanin->vFanouts.nSize++; + // label MFFC with current traversal ID + Abc_NtkIncrementTravId( pNode->pNtk ); + nNodesSaved = Abc_NodeMffcLabelAig( pNode ); + // unmark the fanin boundary and set the fanins as leaves in the form + Vec_PtrForEachEntry( vFanins, pFanin, i ) + { + pFanin->vFanouts.nSize--; + Dec_GraphNode(pFForm, i)->pFunc = pFanin; + } + + // detect how many new nodes will be added (while taking into account reused nodes) +clk = clock(); + nNodesAdded = Dec_GraphToNetworkCount( pNode, pFForm, nNodesSaved, Required ); +p->timeEval += clock() - clk; + // quit if there is no improvement + if ( nNodesAdded == -1 || nNodesAdded == nNodesSaved && !fUseZeros ) + { + Cudd_RecursiveDeref( p->dd, bNodeFunc ); + Dec_GraphFree( pFForm ); + return NULL; + } + + // compute the total gain in the number of nodes + p->nLastGain = nNodesSaved - nNodesAdded; + p->nNodesGained += p->nLastGain; + p->nNodesRefactored++; + + // report the progress + if ( fVeryVerbose ) + { + printf( "Node %6s : ", Abc_ObjName(pNode) ); + printf( "Cone = %2d. ", vFanins->nSize ); + printf( "BDD = %2d. ", Cudd_DagSize(bNodeFunc) ); + printf( "FF = %2d. ", 1 + Dec_GraphNodeNum(pFForm) ); + printf( "MFFC = %2d. ", nNodesSaved ); + printf( "Add = %2d. ", nNodesAdded ); + printf( "GAIN = %2d. ", p->nLastGain ); + printf( "\n" ); + } + Cudd_RecursiveDeref( p->dd, bNodeFunc ); + return pFForm; +} + + +/**Function************************************************************* + + Synopsis [Starts the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, bool fUseDcs, bool fVerbose ) +{ + Abc_ManRef_t * p; + p = ALLOC( Abc_ManRef_t, 1 ); + memset( p, 0, sizeof(Abc_ManRef_t) ); + p->vCube = Vec_StrAlloc( 100 ); + p->vVisited = Vec_PtrAlloc( 100 ); + p->nNodeSizeMax = nNodeSizeMax; + p->nConeSizeMax = nConeSizeMax; + p->fVerbose = fVerbose; + // start the BDD manager + if ( fUseDcs ) + p->dd = Cudd_Init( p->nNodeSizeMax + p->nConeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + else + p->dd = Cudd_Init( p->nNodeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_zddVarsFromBddVars( p->dd, 2 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkManRefStop( Abc_ManRef_t * p ) +{ + Extra_StopManager( p->dd ); + Vec_PtrFree( p->vVisited ); + Vec_StrFree( p->vCube ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkManRefPrintStats( Abc_ManRef_t * p ) +{ + printf( "Refactoring statistics:\n" ); + printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); + printf( "Nodes refactored = %8d.\n", p->nNodesRefactored ); + printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg ); + PRT( "Cuts ", p->timeCut ); + PRT( "Resynthesis", p->timeRes ); + PRT( " BDD ", p->timeBdd ); + PRT( " DCs ", p->timeDcs ); + PRT( " SOP ", p->timeSop ); + PRT( " FF ", p->timeFact ); + PRT( " Eval ", p->timeEval ); + PRT( "AIG update ", p->timeNtk ); + PRT( "TOTAL ", p->timeTotal ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcRenode.c b/abc70930/src/base/abci/abcRenode.c new file mode 100644 index 00000000..8e8e8719 --- /dev/null +++ b/abc70930/src/base/abci/abcRenode.c @@ -0,0 +1,311 @@ +/**CFile**************************************************************** + + FileName [abcRenode.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRenode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "reo.h" +#include "if.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NtkRenodeEvalAig( If_Cut_t * pCut ); +static int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut ); +static int Abc_NtkRenodeEvalSop( If_Cut_t * pCut ); +static int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut ); +static int Abc_NtkRenodeEvalMv( If_Cut_t * pCut ); + +static reo_man * s_pReo = NULL; +static DdManager * s_pDd = NULL; +static Vec_Int_t * s_vMemory = NULL; +static Vec_Int_t * s_vMemory2 = NULL; + +static int nDsdCounter = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs renoding as technology mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose ) +{ + extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); + If_Par_t Pars, * pPars = &Pars; + Abc_Ntk_t * pNtkNew; + + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Performing renoding with choices.\n" ); + + nDsdCounter = 0; + + // set defaults + memset( pPars, 0, sizeof(If_Par_t) ); + // user-controlable paramters + pPars->nLutSize = nFaninMax; + pPars->nCutsMax = nCubeMax; + pPars->nFlowIters = nFlowIters; + pPars->nAreaIters = nAreaIters; + pPars->DelayTarget = -1; + pPars->fPreprocess = 1; + pPars->fArea = fArea; + pPars->fFancy = 0; + pPars->fExpRed = 0; // + pPars->fLatchPaths = 0; + pPars->fSeqMap = 0; + pPars->fVerbose = fVerbose; + // internal parameters + pPars->fTruth = 1; + pPars->fUsePerm = 1; + pPars->nLatches = 0; + pPars->pLutLib = NULL; // Abc_FrameReadLibLut(); + pPars->pTimesArr = NULL; + pPars->pTimesArr = NULL; + pPars->fUseBdds = fUseBdds; + pPars->fUseSops = fUseSops; + pPars->fUseCnfs = fUseCnfs; + pPars->fUseMv = fUseMv; + if ( fUseBdds ) + pPars->pFuncCost = Abc_NtkRenodeEvalBdd; + else if ( fUseSops ) + pPars->pFuncCost = Abc_NtkRenodeEvalSop; + else if ( fUseCnfs ) + { + pPars->fArea = 1; + pPars->pFuncCost = Abc_NtkRenodeEvalCnf; + } + else if ( fUseMv ) + pPars->pFuncCost = Abc_NtkRenodeEvalMv; + else + pPars->pFuncCost = Abc_NtkRenodeEvalAig; + + // start the manager + if ( fUseBdds ) + { + assert( s_pReo == NULL ); + s_pDd = Cudd_Init( nFaninMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + s_pReo = Extra_ReorderInit( nFaninMax, 100 ); + pPars->pReoMan = s_pReo; + } + else + { + assert( s_vMemory == NULL ); + s_vMemory = Vec_IntAlloc( 1 << 16 ); + s_vMemory2 = Vec_IntAlloc( 1 << 16 ); + } + + // perform mapping/renoding + pNtkNew = Abc_NtkIf( pNtk, pPars ); + + // start the manager + if ( fUseBdds ) + { + Extra_StopManager( s_pDd ); + Extra_ReorderQuit( s_pReo ); + s_pReo = NULL; + s_pDd = NULL; + } + else + { + Vec_IntFree( s_vMemory ); + Vec_IntFree( s_vMemory2 ); + s_vMemory = NULL; + s_vMemory2 = NULL; + } + +// printf( "Decomposed %d functions.\n", nDsdCounter ); + + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Computes the cost based on the factored form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRenodeEvalAig( If_Cut_t * pCut ) +{ + Kit_Graph_t * pGraph; + int i, nNodes; +/* +extern void Kit_DsdTest( unsigned * pTruth, int nVars ); +if ( If_CutLeaveNum(pCut) == 8 ) +{ + nDsdCounter++; + Kit_DsdTest( If_CutTruth(pCut), If_CutLeaveNum(pCut) ); +} +*/ + pGraph = Kit_TruthToGraph( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory ); + if ( pGraph == NULL ) + { + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + pCut->pPerm[i] = 100; + return IF_COST_MAX; + } + nNodes = Kit_GraphNodeNum( pGraph ); + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + pCut->pPerm[i] = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeLast(pGraph), Kit_GraphNode(pGraph, i) ); + Kit_GraphFree( pGraph ); + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the cost based on the BDD size after reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut ) +{ + int pOrder[IF_MAX_LUTSIZE]; + DdNode * bFunc, * bFuncNew; + int i, k, nNodes; + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + pCut->pPerm[i] = pOrder[i] = -100; + bFunc = Kit_TruthToBdd( s_pDd, If_CutTruth(pCut), If_CutLeaveNum(pCut), 0 ); Cudd_Ref( bFunc ); + bFuncNew = Extra_Reorder( s_pReo, s_pDd, bFunc, pOrder ); Cudd_Ref( bFuncNew ); + for ( i = k = 0; i < If_CutLeaveNum(pCut); i++ ) + if ( pOrder[i] >= 0 ) + pCut->pPerm[pOrder[i]] = ++k; // double-check this! + nNodes = -1 + Cudd_DagSize( bFuncNew ); + Cudd_RecursiveDeref( s_pDd, bFuncNew ); + Cudd_RecursiveDeref( s_pDd, bFunc ); + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the cost based on ISOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRenodeEvalSop( If_Cut_t * pCut ) +{ + int i, RetValue; + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + pCut->pPerm[i] = 1; + RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 1 ); + if ( RetValue == -1 ) + return IF_COST_MAX; + assert( RetValue == 0 || RetValue == 1 ); + return Vec_IntSize( s_vMemory ); +} + +/**Function************************************************************* + + Synopsis [Computes the cost based on two ISOPs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut ) +{ + int i, RetValue, nClauses; + // set internal mapper parameters + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + pCut->pPerm[i] = 1; + // compute ISOP for the positive phase + RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 ); + if ( RetValue == -1 ) + return IF_COST_MAX; + assert( RetValue == 0 || RetValue == 1 ); + nClauses = Vec_IntSize( s_vMemory ); + // compute ISOP for the negative phase + Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) ); + RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 ); + Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) ); + if ( RetValue == -1 ) + return IF_COST_MAX; + assert( RetValue == 0 || RetValue == 1 ); + nClauses += Vec_IntSize( s_vMemory ); + return nClauses; +} + +/**Function************************************************************* + + Synopsis [Computes the cost of MV-SOP of the cut function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRenodeEvalMv( If_Cut_t * pCut ) +{ + int i, RetValue; + // set internal mapper parameters + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + pCut->pPerm[i] = 1; + // compute ISOP for the positive phase + RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 ); + if ( RetValue == -1 ) + return IF_COST_MAX; + assert( RetValue == 0 || RetValue == 1 ); + // compute ISOP for the negative phase + Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) ); + RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory2, 0 ); + Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) ); + if ( RetValue == -1 ) + return IF_COST_MAX; + assert( RetValue == 0 || RetValue == 1 ); + // return the cost of the cut + RetValue = Abc_NodeEvalMvCost( If_CutLeaveNum(pCut), s_vMemory, s_vMemory2 ); + if ( RetValue >= IF_COST_MAX ) + return IF_COST_MAX; + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcReorder.c b/abc70930/src/base/abci/abcReorder.c new file mode 100644 index 00000000..d6dee49b --- /dev/null +++ b/abc70930/src/base/abci/abcReorder.c @@ -0,0 +1,100 @@ +/**CFile**************************************************************** + + FileName [abcReorder.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Reordering local BDDs of the nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcReorder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "reo.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reorders BDD of the local function of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeBddReorder( reo_man * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + DdNode * bFunc; + int * pOrder, i; + // create the temporary array for the variable order + pOrder = ALLOC( int, Abc_ObjFaninNum(pNode) ); + for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) + pOrder[i] = -1; + // reorder the BDD + bFunc = Extra_Reorder( p, pNode->pNtk->pManFunc, pNode->pData, pOrder ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( pNode->pNtk->pManFunc, pNode->pData ); + pNode->pData = bFunc; + // update the fanin order + Abc_ObjForEachFanin( pNode, pFanin, i ) + pOrder[i] = pNode->vFanins.pArray[ pOrder[i] ]; + Abc_ObjForEachFanin( pNode, pFanin, i ) + pNode->vFanins.pArray[i] = pOrder[i]; + free( pOrder ); +} + +/**Function************************************************************* + + Synopsis [Reorders BDDs of the local functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ) +{ + reo_man * p; + Abc_Obj_t * pNode; + int i; + p = Extra_ReorderInit( Abc_NtkGetFaninMax(pNtk), 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_ObjFaninNum(pNode) < 3 ) + continue; + if ( fVerbose ) + fprintf( stdout, "%10s: ", Abc_ObjName(pNode) ); + if ( fVerbose ) + fprintf( stdout, "Before = %5d BDD nodes. ", Cudd_DagSize(pNode->pData) ); + Abc_NodeBddReorder( p, pNode ); + if ( fVerbose ) + fprintf( stdout, "After = %5d BDD nodes.\n", Cudd_DagSize(pNode->pData) ); + } + Extra_ReorderQuit( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcRestruct.c b/abc70930/src/base/abci/abcRestruct.c new file mode 100644 index 00000000..326d1543 --- /dev/null +++ b/abc70930/src/base/abci/abcRestruct.c @@ -0,0 +1,1496 @@ +/**CFile**************************************************************** + + FileName [abcRestruct.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRestruct.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dec.h" +#include "dsd.h" +#include "cut.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define RST_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) + +typedef struct Abc_ManRst_t_ Abc_ManRst_t; +struct Abc_ManRst_t_ +{ + // the network + Abc_Ntk_t * pNtk; // the network for restructuring + // user specified parameters + int nCutMax; // the limit on the size of the supernode + int fUpdateLevel; // turns on watching the number of levels + int fUseZeros; // turns on zero-cost replacements + int fVerbose; // the verbosity flag + // internal data structures + DdManager * dd; // the BDD manager + Dsd_Manager_t * pManDsd; // the DSD manager + Vec_Ptr_t * vVisited; // temporary + Vec_Ptr_t * vLeaves; // temporary + Vec_Ptr_t * vDecs; // temporary + Vec_Ptr_t * vTemp; // temporary + Vec_Int_t * vSims; // temporary + Vec_Int_t * vRands; // temporary + Vec_Int_t * vOnes; // temporary + Vec_Int_t * vBinate; // temporary + Vec_Int_t * vTwos; // temporary + // node statistics + int nLastGain; + int nCutsConsidered; + int nCutsExplored; + int nNodesConsidered; + int nNodesRestructured; + int nNodesGained; + // runtime statistics + int timeCut; + int timeBdd; + int timeDsd; + int timeEval; + int timeRes; + int timeNtk; + int timeTotal; +}; + +static Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ); + +static Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ); +static Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCut ); +static Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded ); + +static Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag ); +static Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ); +static void Abc_NtkManRstStop( Abc_ManRst_t * p ); +static void Abc_NtkManRstPrintStats( Abc_ManRst_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Implements AIG restructuring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ) +{ + ProgressBar * pProgress; + Abc_ManRst_t * pManRst; + Cut_Man_t * pManCut; + Cut_Cut_t * pCutList; + Dec_Graph_t * pGraph; + Abc_Obj_t * pNode; + int clk, clkStart = clock(); + int fMulti = 1; + int fResub = 0; + int i, nNodes; + + assert( Abc_NtkIsStrash(pNtk) ); + // cleanup the AIG + Abc_AigCleanup(pNtk->pManFunc); + Abc_NtkCleanCopy(pNtk); + + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Abc_NtkStartReverseLevels( pNtk, 0 ); + + // start the restructuring manager + pManRst = Abc_NtkManRstStart( nCutMax, fUpdateLevel, fUseZeros, fVerbose ); + pManRst->pNtk = pNtk; + // start the cut manager +clk = clock(); + pManCut = Abc_NtkStartCutManForRestruct( pNtk, nCutMax, fMulti ); +pManRst->timeCut += clock() - clk; +// pNtk->pManCut = pManCut; + + // resynthesize each node once + nNodes = Abc_NtkObjNumMax(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // skip the constant node +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // skip persistant nodes + if ( Abc_NodeIsPersistant(pNode) ) + continue; + // skip the node if it is inside the tree +// if ( Abc_ObjFanoutNum(pNode) < 2 ) +// continue; + // skip the nodes with too many fanouts + if ( Abc_ObjFanoutNum(pNode) > 1000 ) + continue; + // stop if all nodes have been tried once + if ( i >= nNodes ) + break; + // get the cuts for the given node +clk = clock(); + pCutList = Abc_NodeGetCutsRecursive( pManCut, pNode, fMulti, 0 ); +pManRst->timeCut += clock() - clk; + + // perform restructuring +clk = clock(); + if ( fResub ) + pGraph = Abc_NodeResubstitute( pManRst, pNode, pCutList ); + else + pGraph = Abc_NodeRestructure( pManRst, pNode, pCutList ); +pManRst->timeRes += clock() - clk; + if ( pGraph == NULL ) + continue; + + // acceptable replacement found, update the graph +clk = clock(); + Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, pManRst->nLastGain ); +pManRst->timeNtk += clock() - clk; + Dec_GraphFree( pGraph ); + } + Extra_ProgressBarStop( pProgress ); +pManRst->timeTotal = clock() - clkStart; + + // print statistics of the manager +// if ( fVerbose ) + Abc_NtkManRstPrintStats( pManRst ); + // delete the managers + Cut_ManStop( pManCut ); + Abc_NtkManRstStop( pManRst ); + // put the nodes into the DFS order and reassign their IDs + Abc_NtkReassignIds( pNtk ); +// Abc_AigCheckFaninOrder( pNtk->pManFunc ); + // fix the levels + if ( fUpdateLevel ) + Abc_NtkStopReverseLevels( pNtk ); + else + Abc_NtkLevel( pNtk ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkRefactor: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RestructNodeDivisors( Abc_ManRst_t * p, Abc_Obj_t * pRoot, int nNodesSaved ) +{ + Abc_Obj_t * pNode, * pFanout;//, * pFanin; + int i, k; + // start with the leaves + Vec_PtrClear( p->vDecs ); + Vec_PtrForEachEntry( p->vLeaves, pNode, i ) + { + Vec_PtrPush( p->vDecs, pNode ); + assert( pNode->fMarkC == 0 ); + pNode->fMarkC = 1; + } + // explore the fanouts + Vec_PtrForEachEntry( p->vDecs, pNode, i ) + { + // if the fanout has both fanins in the set, add it + Abc_ObjForEachFanout( pNode, pFanout, k ) + { + if ( pFanout->fMarkC || Abc_ObjIsPo(pFanout) ) + continue; + if ( Abc_ObjFanin0(pFanout)->fMarkC && Abc_ObjFanin1(pFanout)->fMarkC ) + { + Vec_PtrPush( p->vDecs, pFanout ); + pFanout->fMarkC = 1; + } + } + } + // unmark the nodes + Vec_PtrForEachEntry( p->vDecs, pNode, i ) + pNode->fMarkC = 0; +/* + // print the nodes + Vec_PtrForEachEntryStart( p->vDecs, pNode, i, Vec_PtrSize(p->vLeaves) ) + { + printf( "%2d %s = ", i, Abc_NodeIsTravIdCurrent(pNode)? "*" : " " ); + // find the first fanin + Vec_PtrForEachEntry( p->vDecs, pFanin, k ) + if ( Abc_ObjFanin0(pNode) == pFanin ) + break; + if ( k < Vec_PtrSize(p->vLeaves) ) + printf( "%c", 'a' + k ); + else + printf( "%d", k ); + printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" ); + // find the second fanin + Vec_PtrForEachEntry( p->vDecs, pFanin, k ) + if ( Abc_ObjFanin1(pNode) == pFanin ) + break; + if ( k < Vec_PtrSize(p->vLeaves) ) + printf( "%c", 'a' + k ); + else + printf( "%d", k ); + printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" ); + printf( "\n" ); + } +*/ + printf( "%d\n", Vec_PtrSize(p->vDecs)-nNodesSaved-Vec_PtrSize(p->vLeaves) ); +} + + +/**Function************************************************************* + + Synopsis [Starts the cut manager for rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ) +{ + Dec_Graph_t * pGraph; + Cut_Cut_t * pCut; +// int nCuts; + p->nNodesConsidered++; +/* + // count the number of cuts with four inputs or more + nCuts = 0; + for ( pCut = pCutList; pCut; pCut = pCut->pNext ) + nCuts += (int)(pCut->nLeaves > 3); + printf( "-----------------------------------\n" ); + printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts ); +*/ + // go through the interesting cuts + for ( pCut = pCutList; pCut; pCut = pCut->pNext ) + { + if ( pCut->nLeaves < 4 ) + continue; + if ( pGraph = Abc_NodeRestructureCut( p, pNode, pCut ) ) + return pGraph; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Starts the cut manager for rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut ) +{ + Dec_Graph_t * pGraph; + Dsd_Node_t * pNodeDsd; + Abc_Obj_t * pLeaf; + DdNode * bFunc; + int nNodesSaved, nNodesAdded; + int Required, nMaxSize, clk, i; + int fVeryVerbose = 0; + + p->nCutsConsidered++; + + // get the required time for the node + Required = p->fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY; + + // collect the leaves of the cut + Vec_PtrClear( p->vLeaves ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + pLeaf = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]); + if ( pLeaf == NULL ) // the so-called "bad cut phenomenon" is due to removed nodes + return NULL; + Vec_PtrPush( p->vLeaves, pLeaf ); + } + + if ( pRoot->Id == 29 ) + { + int x = 0; + } + +clk = clock(); + // collect the internal nodes of the cut +// Abc_NodeConeCollect( &pRoot, 1, p->vLeaves, p->vVisited, 0 ); + // derive the BDD of the cut + bFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pRoot, p->vLeaves, p->vVisited ); Cudd_Ref( bFunc ); +p->timeBdd += clock() - clk; + + // consider the special case, when the function is a constant + if ( Cudd_IsConstant(bFunc) ) + { + p->nLastGain = Abc_NodeMffcSize( pRoot ); + p->nNodesGained += p->nLastGain; + p->nNodesRestructured++; + Cudd_RecursiveDeref( p->dd, bFunc ); + if ( Cudd_IsComplement(bFunc) ) + return Dec_GraphCreateConst0(); + return Dec_GraphCreateConst1(); + } + +clk = clock(); + // try disjoint support decomposition + pNodeDsd = Dsd_DecomposeOne( p->pManDsd, bFunc ); +p->timeDsd += clock() - clk; + + // skip nodes with non-decomposable blocks + Dsd_TreeNodeGetInfoOne( pNodeDsd, NULL, &nMaxSize ); + if ( nMaxSize > 3 ) + { + Cudd_RecursiveDeref( p->dd, bFunc ); + return NULL; + } + + +/* + // skip nodes that cannot be improved + if ( Vec_PtrSize(p->vVisited) <= Dsd_TreeGetAigCost(pNodeDsd) ) + { + Cudd_RecursiveDeref( p->dd, bFunc ); + return NULL; + } +*/ + + p->nCutsExplored++; + + // mark the fanin boundary + // (can mark only essential fanins, belonging to bNodeFunc!) + Vec_PtrForEachEntry( p->vLeaves, pLeaf, i ) + pLeaf->vFanouts.nSize++; + // label MFFC with current traversal ID + Abc_NtkIncrementTravId( pRoot->pNtk ); + nNodesSaved = Abc_NodeMffcLabelAig( pRoot ); + // unmark the fanin boundary and set the fanins as leaves in the form + Vec_PtrForEachEntry( p->vLeaves, pLeaf, i ) + pLeaf->vFanouts.nSize--; +/* + if ( nNodesSaved < 3 ) + { + Cudd_RecursiveDeref( p->dd, bFunc ); + return NULL; + } +*/ + +/* + printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d.\n", + pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd), + nNodesSaved ); + Dsd_NodePrint( stdout, pNodeDsd ); + + Abc_RestructNodeDivisors( p, pRoot ); + + if ( pRoot->Id == 433 ) + { + int x = 0; + } +*/ +// Abc_RestructNodeDivisors( p, pRoot, nNodesSaved ); + + + // detect how many new nodes will be added (while taking into account reused nodes) +clk = clock(); + if ( nMaxSize > 3 ) + pGraph = NULL; + else + pGraph = Abc_NodeEvaluateDsd( p, pNodeDsd, pRoot, Required, nNodesSaved, &nNodesAdded ); +// pGraph = NULL; +p->timeEval += clock() - clk; + + // quit if there is no improvement + if ( pGraph == NULL || nNodesAdded == -1 || nNodesAdded == nNodesSaved && !p->fUseZeros ) + { + Cudd_RecursiveDeref( p->dd, bFunc ); + if ( pGraph ) Dec_GraphFree( pGraph ); + return NULL; + } + +/* + // print stats + printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d. New MFFC = %2d. Gain = %d.\n", + pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd), + nNodesSaved, nNodesAdded, (nNodesAdded == -1)? 0 : nNodesSaved-nNodesAdded ); +// Dsd_NodePrint( stdout, pNodeDsd ); +// Dec_GraphPrint( stdout, pGraph, NULL, NULL ); +*/ + + // compute the total gain in the number of nodes + p->nLastGain = nNodesSaved - nNodesAdded; + p->nNodesGained += p->nLastGain; + p->nNodesRestructured++; + + // report the progress + if ( fVeryVerbose ) + { + printf( "Node %6s : ", Abc_ObjName(pRoot) ); + printf( "Cone = %2d. ", p->vLeaves->nSize ); + printf( "BDD = %2d. ", Cudd_DagSize(bFunc) ); + printf( "FF = %2d. ", 1 + Dec_GraphNodeNum(pGraph) ); + printf( "MFFC = %2d. ", nNodesSaved ); + printf( "Add = %2d. ", nNodesAdded ); + printf( "GAIN = %2d. ", p->nLastGain ); + printf( "\n" ); + } + Cudd_RecursiveDeref( p->dd, bFunc ); + return pGraph; +} + + +/**Function************************************************************* + + Synopsis [Moves closer to the end the node that is best for sharing.] + + Description [If the flag is set, tries to find an EXOR, otherwise, tries + to find an OR.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeEdgeDsdPermute( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Vec_Int_t * vEdges, int fExor ) +{ + Dec_Edge_t eNode1, eNode2, eNode3; + Abc_Obj_t * pNode1, * pNode2, * pNode3, * pTemp; + int LeftBound = 0, RightBound, i; + // get the right bound + RightBound = Vec_IntSize(vEdges) - 2; + assert( LeftBound <= RightBound ); + if ( LeftBound == RightBound ) + return; + // get the two last nodes + eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound + 1) ); + eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound ) ); + pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; + pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc; + pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); + pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); + // quit if the last node does not exist + if ( pNode1 == NULL ) + return; + // find the first node that can be shared + for ( i = RightBound; i >= LeftBound; i-- ) + { + // get the third node + eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, i) ); + pNode3 = Dec_GraphNode( pGraph, eNode3.Node )->pFunc; + pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl ); + if ( pNode3 == NULL ) + continue; + // check if the node exists + if ( fExor ) + { + if ( pNode1 && pNode3 ) + { + pTemp = Abc_AigXorLookup( pManRst->pNtk->pManFunc, pNode1, pNode3, NULL ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + continue; + + if ( pNode3 == pNode2 ) + return; + Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) ); + Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) ); + return; + } + } + else + { + if ( pNode1 && pNode3 ) + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + continue; + + if ( eNode3.Node == eNode2.Node ) + return; + Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) ); + Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) ); + return; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Adds the new edge in the given order.] + + Description [Similar to Vec_IntPushOrder, except in decreasing order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeEdgeDsdPushOrdered( Dec_Graph_t * pGraph, Vec_Int_t * vEdges, int Edge ) +{ + int i, NodeOld, NodeNew; + vEdges->nSize++; + for ( i = vEdges->nSize-2; i >= 0; i-- ) + { + NodeOld = Dec_IntToEdge(vEdges->pArray[i]).Node; + NodeNew = Dec_IntToEdge(Edge).Node; + // use <= because we are trying to push the new (non-existent) nodes as far as possible + if ( Dec_GraphNode(pGraph, NodeOld)->Level <= Dec_GraphNode(pGraph, NodeNew)->Level ) + vEdges->pArray[i+1] = vEdges->pArray[i]; + else + break; + } + vEdges->pArray[i+1] = Edge; +} + +/**Function************************************************************* + + Synopsis [Evaluation one DSD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Abc_NodeEvaluateDsd_rec( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, int Required, int nNodesSaved, int * pnNodesAdded ) +{ + Dec_Edge_t eNode1, eNode2, eNode3, eResult, eQuit = { 0, 2006 }; + Abc_Obj_t * pNode1, * pNode2, * pNode3, * pNode4, * pTemp; + Dsd_Node_t * pChildDsd; + Dsd_Type_t DecType; + Vec_Int_t * vEdges; + int Level1, Level2, Level3, Level4; + int i, Index, fCompl, Type; + + // remove the complemented attribute + fCompl = Dsd_IsComplement( pNodeDsd ); + pNodeDsd = Dsd_Regular( pNodeDsd ); + + // consider the trivial case + DecType = Dsd_NodeReadType( pNodeDsd ); + if ( DecType == DSD_NODE_BUF ) + { + Index = Dsd_NodeReadFunc(pNodeDsd)->index; + assert( Index < Dec_GraphLeaveNum(pGraph) ); + eResult = Dec_EdgeCreate( Index, fCompl ); + return eResult; + } + assert( DecType == DSD_NODE_OR || DecType == DSD_NODE_EXOR || DecType == DSD_NODE_PRIME ); + + // solve the problem for the children + vEdges = Vec_IntAlloc( Dsd_NodeReadDecsNum(pNodeDsd) ); + Dsd_NodeForEachChild( pNodeDsd, i, pChildDsd ) + { + eResult = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pChildDsd, Required, nNodesSaved, pnNodesAdded ); + if ( eResult.Node == eQuit.Node ) // infeasible + { + Vec_IntFree( vEdges ); + return eQuit; + } + // order the inputs only if this is OR or EXOR + if ( DecType == DSD_NODE_PRIME ) + Vec_IntPush( vEdges, Dec_EdgeToInt(eResult) ); + else + Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eResult) ); + } + // the edges are sorted by the level of their nodes in decreasing order + + + // consider special cases + if ( DecType == DSD_NODE_OR ) + { + // try to balance the nodes by delay + assert( Vec_IntSize(vEdges) > 1 ); + while ( Vec_IntSize(vEdges) > 1 ) + { + // permute the last two entries + if ( Vec_IntSize(vEdges) > 2 ) + Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 0 ); + // get the two last nodes + eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) ); + eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) ); + pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; + pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc; + pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); + pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); + // check if the new node exists + pNode3 = NULL; + if ( pNode1 && pNode2 ) + { + pNode3 = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + pNode3 = !pNode3? NULL : Abc_ObjNot(pNode3); + } + // create the new node + eNode3 = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 ); + // set level + Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level; + Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level; + Dec_GraphNode( pGraph, eNode3.Node )->Level = 1 + ABC_MAX(Level1, Level2); + // get the new node if possible + if ( pNode3 ) + { + Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl); + Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level; + assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level ); + } + if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) ) + { + (*pnNodesAdded)++; + if ( *pnNodesAdded > nNodesSaved ) + { + Vec_IntFree( vEdges ); + return eQuit; + } + } + // add the resulting node to the form + Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) ); + } + // get the last node + eResult = Dec_IntToEdge( Vec_IntPop(vEdges) ); + Vec_IntFree( vEdges ); + // complement the graph if the node was complemented + eResult.fCompl ^= fCompl; + return eResult; + } + if ( DecType == DSD_NODE_EXOR ) + { + // try to balance the nodes by delay + assert( Vec_IntSize(vEdges) > 1 ); + while ( Vec_IntSize(vEdges) > 1 ) + { + // permute the last two entries + if ( Vec_IntSize(vEdges) > 2 ) + Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 1 ); + // get the two last nodes + eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) ); + eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) ); + pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; + pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc; + pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); + pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); + // check if the new node exists + Type = 0; + pNode3 = NULL; + if ( pNode1 && pNode2 ) + pNode3 = Abc_AigXorLookup( pManRst->pNtk->pManFunc, pNode1, pNode2, &Type ); + // create the new node + eNode3 = Dec_GraphAddNodeXor( pGraph, eNode1, eNode2, Type ); // should have the same structure as in AIG + // set level + Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level; + Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level; + Dec_GraphNode( pGraph, eNode3.Node )->Level = 2 + ABC_MAX(Level1, Level2); + // get the new node if possible + if ( pNode3 ) + { + Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl); + Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level; + assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level ); + } + if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) ) + { + (*pnNodesAdded)++; + if ( !pNode1 || !pNode2 ) + (*pnNodesAdded) += 2; + else if ( Type == 0 ) + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode2 ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + else + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, pNode2 ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + if ( *pnNodesAdded > nNodesSaved ) + { + Vec_IntFree( vEdges ); + return eQuit; + } + } + // add the resulting node to the form + Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) ); + } + // get the last node + eResult = Dec_IntToEdge( Vec_IntPop(vEdges) ); + Vec_IntFree( vEdges ); + // complement the graph if the node is complemented + eResult.fCompl ^= fCompl; + return eResult; + } + if ( DecType == DSD_NODE_PRIME ) + { + DdNode * bLocal, * bVar, * bCofT, * bCofE; + bLocal = Dsd_TreeGetPrimeFunction( pManRst->dd, pNodeDsd ); Cudd_Ref( bLocal ); +//Extra_bddPrint( pManRst->dd, bLocal ); + + bVar = pManRst->dd->vars[0]; + bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE ); + bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT ); + if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) ) + { + Cudd_RecursiveDeref( pManRst->dd, bCofE ); + Cudd_RecursiveDeref( pManRst->dd, bCofT ); + bVar = pManRst->dd->vars[1]; + bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE ); + bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT ); + if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) ) + { + Cudd_RecursiveDeref( pManRst->dd, bCofE ); + Cudd_RecursiveDeref( pManRst->dd, bCofT ); + bVar = pManRst->dd->vars[2]; + bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE ); + bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT ); + if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) ) + { + Cudd_RecursiveDeref( pManRst->dd, bCofE ); + Cudd_RecursiveDeref( pManRst->dd, bCofT ); + Cudd_RecursiveDeref( pManRst->dd, bLocal ); + Vec_IntFree( vEdges ); + return eQuit; + } + } + } + Cudd_RecursiveDeref( pManRst->dd, bLocal ); + // we found the control variable (bVar) and the var-cofactors (bCofT, bCofE) + + // find the graph nodes + eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, bVar->index) ); + eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofT)->index) ); + eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofE)->index) ); + // add the complements to the graph nodes + eNode2.fCompl ^= Cudd_IsComplement(bCofT); + eNode3.fCompl ^= Cudd_IsComplement(bCofE); + + // because the cofactors are vars, we can just as well deref them here + Cudd_RecursiveDeref( pManRst->dd, bCofE ); + Cudd_RecursiveDeref( pManRst->dd, bCofT ); + + // find the ABC nodes + pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; + pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc; + pNode3 = Dec_GraphNode( pGraph, eNode3.Node )->pFunc; + pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); + pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); + pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl ); + + // check if the new node exists + Type = 0; + pNode4 = NULL; + if ( pNode1 && pNode2 && pNode3 ) + pNode4 = Abc_AigMuxLookup( pManRst->pNtk->pManFunc, pNode1, pNode2, pNode3, &Type ); + + // create the new node + eResult = Dec_GraphAddNodeMux( pGraph, eNode1, eNode2, eNode3, Type ); // should have the same structure as AIG + + // set level + Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level; + Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level; + Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level; + Dec_GraphNode( pGraph, eResult.Node )->Level = 2 + ABC_MAX( ABC_MAX(Level1, Level2), Level3 ); + // get the new node if possible + if ( pNode4 ) + { + Dec_GraphNode( pGraph, eResult.Node )->pFunc = Abc_ObjNotCond(pNode4, eResult.fCompl); + Level4 = Dec_GraphNode( pGraph, eResult.Node )->Level; + assert( Required == ABC_INFINITY || Level4 == (int)Abc_ObjRegular(pNode4)->Level ); + } + if ( !pNode4 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode4)) ) + { + (*pnNodesAdded)++; + if ( Type == 0 ) + { + if ( !pNode1 || !pNode2 ) + (*pnNodesAdded)++; + else + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, pNode2 ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + if ( !pNode1 || !pNode3 ) + (*pnNodesAdded)++; + else + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode3 ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + } + else + { + if ( !pNode1 || !pNode2 ) + (*pnNodesAdded)++; + else + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + if ( !pNode1 || !pNode3 ) + (*pnNodesAdded)++; + else + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + } + if ( *pnNodesAdded > nNodesSaved ) + { + Vec_IntFree( vEdges ); + return eQuit; + } + } + + Vec_IntFree( vEdges ); + // complement the graph if the node was complemented + eResult.fCompl ^= fCompl; + return eResult; + } + Vec_IntFree( vEdges ); + return eQuit; +} + +/**Function************************************************************* + + Synopsis [Evaluation one DSD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t gEdge; + Abc_Obj_t * pLeaf; + Dec_Node_t * pNode; + int i; + + // create the graph and set the leaves + pGraph = Dec_GraphCreate( Vec_PtrSize(pManRst->vLeaves) ); + Dec_GraphForEachLeaf( pGraph, pNode, i ) + { + pLeaf = Vec_PtrEntry( pManRst->vLeaves, i ); + pNode->pFunc = pLeaf; + pNode->Level = pLeaf->Level; + } + + // create the decomposition structure from the DSD + *pnNodesAdded = 0; + gEdge = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pNodeDsd, Required, nNodesSaved, pnNodesAdded ); + if ( gEdge.Node > 1000 ) // infeasible + { + *pnNodesAdded = -1; + Dec_GraphFree( pGraph ); + return NULL; + } + + // quit if the root node is the same + pLeaf = Dec_GraphNode( pGraph, gEdge.Node )->pFunc; + if ( Abc_ObjRegular(pLeaf) == pRoot ) + { + *pnNodesAdded = -1; + Dec_GraphFree( pGraph ); + return NULL; + } + + Dec_GraphSetRoot( pGraph, gEdge ); + return pGraph; +} + + + +/**Function************************************************************* + + Synopsis [Starts the cut manager for rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag ) +{ + static Cut_Params_t Params, * pParams = &Params; + Cut_Man_t * pManCut; + Abc_Obj_t * pObj; + int i; + // start the cut manager + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = nCutMax; // the max cut size ("k" of the k-feasible cuts) + pParams->nKeepMax = 250; // the max number of cuts kept at a node + pParams->fTruth = 0; // compute truth tables + pParams->fFilter = 1; // filter dominated cuts + pParams->fSeq = 0; // compute sequential cuts + pParams->fDrop = 0; // drop cuts on the fly + pParams->fDag = fDag; // compute DAG cuts + pParams->fTree = 0; // compute tree cuts + pParams->fVerbose = 0; // the verbosiness flag + pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); + pManCut = Cut_ManStart( pParams ); + if ( pParams->fDrop ) + Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); + // set cuts for PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_NodeSetTriv( pManCut, pObj->Id ); + return pManCut; +} + +/**Function************************************************************* + + Synopsis [Starts the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ) +{ + Abc_ManRst_t * p; + p = ALLOC( Abc_ManRst_t, 1 ); + memset( p, 0, sizeof(Abc_ManRst_t) ); + // set the parameters + p->nCutMax = nCutMax; + p->fUpdateLevel = fUpdateLevel; + p->fUseZeros = fUseZeros; + p->fVerbose = fVerbose; + // start the BDD manager + p->dd = Cudd_Init( p->nCutMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_zddVarsFromBddVars( p->dd, 2 ); + // start the DSD manager + p->pManDsd = Dsd_ManagerStart( p->dd, p->dd->size, 0 ); + // other temp datastructures + p->vVisited = Vec_PtrAlloc( 100 ); + p->vLeaves = Vec_PtrAlloc( 100 ); + p->vDecs = Vec_PtrAlloc( 100 ); + p->vTemp = Vec_PtrAlloc( 100 ); + p->vSims = Vec_IntAlloc( 100 ); + p->vOnes = Vec_IntAlloc( 100 ); + p->vBinate = Vec_IntAlloc( 100 ); + p->vTwos = Vec_IntAlloc( 100 ); + p->vRands = Vec_IntAlloc( 20 ); + + { + int i; + for ( i = 0; i < 20; i++ ) + Vec_IntPush( p->vRands, (int)RST_RANDOM_UNSIGNED ); + } + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkManRstStop( Abc_ManRst_t * p ) +{ + Dsd_ManagerStop( p->pManDsd ); + Extra_StopManager( p->dd ); + Vec_PtrFree( p->vDecs ); + Vec_PtrFree( p->vLeaves ); + Vec_PtrFree( p->vVisited ); + Vec_PtrFree( p->vTemp ); + Vec_IntFree( p->vSims ); + Vec_IntFree( p->vOnes ); + Vec_IntFree( p->vBinate ); + Vec_IntFree( p->vTwos ); + Vec_IntFree( p->vRands ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkManRstPrintStats( Abc_ManRst_t * p ) +{ + printf( "Refactoring statistics:\n" ); + printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); + printf( "Cuts considered = %8d.\n", p->nCutsConsidered ); + printf( "Cuts explored = %8d.\n", p->nCutsExplored ); + printf( "Nodes restructured = %8d.\n", p->nNodesRestructured ); + printf( "Calculated gain = %8d.\n", p->nNodesGained ); + PRT( "Cuts ", p->timeCut ); + PRT( "Resynthesis", p->timeRes ); + PRT( " BDD ", p->timeBdd ); + PRT( " DSD ", p->timeDsd ); + PRT( " Eval ", p->timeEval ); + PRT( "AIG update ", p->timeNtk ); + PRT( "TOTAL ", p->timeTotal ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_Abc_NodeResubCollectDivs( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut ) +{ + Abc_Obj_t * pNode, * pFanout; + int i, k; + // collect the leaves of the cut + Vec_PtrClear( p->vDecs ); + Abc_NtkIncrementTravId( pRoot->pNtk ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + pNode = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]); + if ( pNode == NULL ) // the so-called "bad cut phenomenon" is due to removed nodes + return 0; + Vec_PtrPush( p->vDecs, pNode ); + Abc_NodeSetTravIdCurrent( pNode ); + } + // explore the fanouts + Vec_PtrForEachEntry( p->vDecs, pNode, i ) + { + // if the fanout has both fanins in the set, add it + Abc_ObjForEachFanout( pNode, pFanout, k ) + { + if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsPo(pFanout) ) + continue; + if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) ) + { + Vec_PtrPush( p->vDecs, pFanout ); + Abc_NodeSetTravIdCurrent( pFanout ); + } + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeResubMffc_rec( Abc_Obj_t * pNode ) +{ + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return 0; + Abc_NodeSetTravIdCurrent( pNode ); + return 1 + Abc_NodeResubMffc_rec( Abc_ObjFanin0(pNode) ) + + Abc_NodeResubMffc_rec( Abc_ObjFanin1(pNode) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeResubMffc( Abc_ManRst_t * p, Vec_Ptr_t * vDecs, int nLeaves, Abc_Obj_t * pRoot ) +{ + Abc_Obj_t * pObj; + int Counter, i, k; + // increment the traversal ID for the leaves + Abc_NtkIncrementTravId( pRoot->pNtk ); + // label the leaves + Vec_PtrForEachEntryStop( vDecs, pObj, i, nLeaves ) + Abc_NodeSetTravIdCurrent( pObj ); + // make sure the node is in the cone and is no one of the leaves + assert( Abc_NodeIsTravIdPrevious(pRoot) ); + Counter = Abc_NodeResubMffc_rec( pRoot ); + // move the labeled nodes to the end + Vec_PtrClear( p->vTemp ); + k = 0; + Vec_PtrForEachEntryStart( vDecs, pObj, i, nLeaves ) + if ( Abc_NodeIsTravIdCurrent(pObj) ) + Vec_PtrPush( p->vTemp, pObj ); + else + Vec_PtrWriteEntry( vDecs, k++, pObj ); + // add the labeled nodes + Vec_PtrForEachEntry( p->vTemp, pObj, i ) + Vec_PtrWriteEntry( vDecs, k++, pObj ); + assert( k == Vec_PtrSize(p->vDecs) ); + assert( pRoot == Vec_PtrEntryLast(p->vDecs) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Performs simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffcSimulate( Vec_Ptr_t * vDecs, int nLeaves, Vec_Int_t * vRands, Vec_Int_t * vSims ) +{ + Abc_Obj_t * pObj; + unsigned uData0, uData1, uData; + int i; + // initialize random simulation data + Vec_IntClear( vSims ); + Vec_PtrForEachEntryStop( vDecs, pObj, i, nLeaves ) + { + uData = (unsigned)Vec_IntEntry( vRands, i ); + pObj->pData = (void *)uData; + Vec_IntPush( vSims, uData ); + } + // simulate + Vec_PtrForEachEntryStart( vDecs, pObj, i, nLeaves ) + { + uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; + uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData; + uData = (Abc_ObjFaninC0(pObj)? ~uData0 : uData0) & (Abc_ObjFaninC1(pObj)? ~uData1 : uData1); + pObj->pData = (void *)uData; + Vec_IntPush( vSims, uData ); + } +} + +/**Function************************************************************* + + Synopsis [Full equality check.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCheckFull( Abc_ManRst_t * p, Dec_Graph_t * pGraph ) +{ + return 1; +} +/**Function************************************************************* + + Synopsis [Detect contants.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeMffcConstants( Abc_ManRst_t * p, Vec_Int_t * vSims ) +{ + Dec_Graph_t * pGraph; + unsigned uRoot; + // get the root node + uRoot = (unsigned)Vec_IntEntryLast( vSims ); + // get the graph if the node looks constant + if ( uRoot == 0 ) + pGraph = Dec_GraphCreateConst0(); + else if ( uRoot == ~(unsigned)0 ) + pGraph = Dec_GraphCreateConst1(); + // check the graph + if ( Abc_NodeCheckFull( p, pGraph ) ) + return pGraph; + Dec_GraphFree( pGraph ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Detect single non-overlaps.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeMffcSingleVar( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes ) +{ + Dec_Graph_t * pGraph; + unsigned uRoot, uNode; + int i; + + Vec_IntClear( vOnes ); + Vec_IntClear( p->vBinate ); + uRoot = (unsigned)Vec_IntEntryLast( vSims ); + for ( i = 0; i < nNodes; i++ ) + { + uNode = (unsigned)Vec_IntEntry( vSims, i ); + if ( uRoot == uNode || uRoot == ~uNode ) + { + pGraph = Dec_GraphCreate( 1 ); + Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, i ); + Dec_GraphSetRoot( pGraph, Dec_IntToEdge( (int)(uRoot == ~uNode) ) ); + // check the graph + if ( Abc_NodeCheckFull( p, pGraph ) ) + return pGraph; + Dec_GraphFree( pGraph ); + } + if ( (uRoot & uNode) == 0 ) + Vec_IntPush( vOnes, i << 1 ); + else if ( (uRoot & ~uNode) == 0 ) + Vec_IntPush( vOnes, (i << 1) + 1 ); + else + Vec_IntPush( p->vBinate, i ); + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Detect single non-overlaps.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeMffcSingleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eNode0, eNode1, eRoot; + unsigned uRoot; + int i, k; + uRoot = (unsigned)Vec_IntEntryLast( vSims ); + for ( i = 0; i < vOnes->nSize; i++ ) + for ( k = i+1; k < vOnes->nSize; k++ ) + if ( ~uRoot == ((unsigned)vOnes->pArray[i] | (unsigned)vOnes->pArray[k]) ) + { + eNode0 = Dec_IntToEdge( vOnes->pArray[i] ^ 1 ); + eNode1 = Dec_IntToEdge( vOnes->pArray[k] ^ 1 ); + pGraph = Dec_GraphCreate( 2 ); + Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, eNode0.Node ); + Dec_GraphNode( pGraph, 1 )->pFunc = Vec_PtrEntry( p->vDecs, eNode1.Node ); + eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); + Dec_GraphSetRoot( pGraph, eRoot ); + if ( Abc_NodeCheckFull( p, pGraph ) ) + return pGraph; + Dec_GraphFree( pGraph ); + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Detect single non-overlaps.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeMffcDoubleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes ) +{ +// Dec_Graph_t * pGraph; +// unsigned uRoot, uNode; +// int i; + + + return NULL; +} + +/**Function************************************************************* + + Synopsis [Evaluates resubstution of one cut.] + + Description [Returns the graph to add if any.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeResubEval( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut ) +{ + Dec_Graph_t * pGraph; + int nNodesSaved; + + // collect the nodes in the cut + if ( !Abc_Abc_NodeResubCollectDivs( p, pRoot, pCut ) ) + return NULL; + + // label MFFC and count its size + nNodesSaved = Abc_NodeResubMffc( p, p->vDecs, pCut->nLeaves, pRoot ); + assert( nNodesSaved > 0 ); + + // simulate MFFC + Abc_NodeMffcSimulate( p->vDecs, pCut->nLeaves, p->vRands, p->vSims ); + + // check for constant output + pGraph = Abc_NodeMffcConstants( p, p->vSims ); + if ( pGraph ) + { + p->nNodesGained += nNodesSaved; + p->nNodesRestructured++; + return pGraph; + } + + // check for one literal (fill up the ones array) + pGraph = Abc_NodeMffcSingleVar( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes ); + if ( pGraph ) + { + p->nNodesGained += nNodesSaved; + p->nNodesRestructured++; + return pGraph; + } + if ( nNodesSaved == 1 ) + return NULL; + + // look for one node + pGraph = Abc_NodeMffcSingleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes ); + if ( pGraph ) + { + p->nNodesGained += nNodesSaved - 1; + p->nNodesRestructured++; + return pGraph; + } + if ( nNodesSaved == 2 ) + return NULL; + + // look for two nodes + pGraph = Abc_NodeMffcDoubleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes ); + if ( pGraph ) + { + p->nNodesGained += nNodesSaved - 2; + p->nNodesRestructured++; + return pGraph; + } + if ( nNodesSaved == 3 ) + return NULL; +/* + // look for MUX/EXOR + pGraph = Abc_NodeMffcMuxNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved ); + if ( pGraph ) + { + p->nNodesGained += nNodesSaved - 1; + p->nNodesRestructured++; + return pGraph; + } +*/ + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs resubstution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ) +{ + Dec_Graph_t * pGraph, * pGraphBest = NULL; + Cut_Cut_t * pCut; + int nCuts; + p->nNodesConsidered++; + + // count the number of cuts with four inputs or more + nCuts = 0; + for ( pCut = pCutList; pCut; pCut = pCut->pNext ) + nCuts += (int)(pCut->nLeaves > 3); + printf( "-----------------------------------\n" ); + printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts ); + + // go through the interesting cuts + for ( pCut = pCutList; pCut; pCut = pCut->pNext ) + { + if ( pCut->nLeaves < 4 ) + continue; + pGraph = Abc_NodeResubEval( p, pNode, pCut ); + if ( pGraph == NULL ) + continue; + if ( !pGraphBest || Dec_GraphNodeNum(pGraph) < Dec_GraphNodeNum(pGraphBest) ) + { + if ( pGraphBest ) + Dec_GraphFree(pGraphBest); + pGraphBest = pGraph; + } + else + Dec_GraphFree(pGraph); + } + return pGraphBest; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcResub.c b/abc70930/src/base/abci/abcResub.c new file mode 100644 index 00000000..309c328d --- /dev/null +++ b/abc70930/src/base/abci/abcResub.c @@ -0,0 +1,1951 @@ +/**CFile**************************************************************** + + FileName [abcResub.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Resubstitution manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_RS_DIV1_MAX 150 // the max number of divisors to consider +#define ABC_RS_DIV2_MAX 500 // the max number of pair-wise divisors to consider + +typedef struct Abc_ManRes_t_ Abc_ManRes_t; +struct Abc_ManRes_t_ +{ + // paramers + int nLeavesMax; // the max number of leaves in the cone + int nDivsMax; // the max number of divisors in the cone + // representation of the cone + Abc_Obj_t * pRoot; // the root of the cone + int nLeaves; // the number of leaves + int nDivs; // the number of all divisor (including leaves) + int nMffc; // the size of MFFC + int nLastGain; // the gain the number of nodes + Vec_Ptr_t * vDivs; // the divisors + // representation of the simulation info + int nBits; // the number of simulation bits + int nWords; // the number of unsigneds for siminfo + Vec_Ptr_t * vSims; // simulation info + unsigned * pInfo; // pointer to simulation info + // observability don't-cares + unsigned * pCareSet; + // internal divisor storage + Vec_Ptr_t * vDivs1UP; // the single-node unate divisors + Vec_Ptr_t * vDivs1UN; // the single-node unate divisors + Vec_Ptr_t * vDivs1B; // the single-node binate divisors + Vec_Ptr_t * vDivs2UP0; // the double-node unate divisors + Vec_Ptr_t * vDivs2UP1; // the double-node unate divisors + Vec_Ptr_t * vDivs2UN0; // the double-node unate divisors + Vec_Ptr_t * vDivs2UN1; // the double-node unate divisors + // other data + Vec_Ptr_t * vTemp; // temporary array of nodes + // runtime statistics + int timeCut; + int timeTruth; + int timeRes; + int timeDiv; + int timeMffc; + int timeSim; + int timeRes1; + int timeResD; + int timeRes2; + int timeRes3; + int timeNtk; + int timeTotal; + // improvement statistics + int nUsedNodeC; + int nUsedNode0; + int nUsedNode1Or; + int nUsedNode1And; + int nUsedNode2Or; + int nUsedNode2And; + int nUsedNode2OrAnd; + int nUsedNode2AndOr; + int nUsedNode3OrAnd; + int nUsedNode3AndOr; + int nUsedNodeTotal; + int nTotalDivs; + int nTotalLeaves; + int nTotalGain; + int nNodesBeg; + int nNodesEnd; +}; + +// external procedures +static Abc_ManRes_t* Abc_ManResubStart( int nLeavesMax, int nDivsMax ); +static void Abc_ManResubStop( Abc_ManRes_t * p ); +static Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, bool fUpdateLevel, int fVerbose ); +static void Abc_ManResubCleanup( Abc_ManRes_t * p ); +static void Abc_ManResubPrint( Abc_ManRes_t * p ); + +// other procedures +static int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required ); +static void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords ); +static void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ); + +static void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required ); +static void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required ); +static Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p ); +static Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p ); +static Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required ); +static Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required ); +static Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required ); +static Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required ); + +static Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax ); +static int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ); + +// don't-care manager +extern void * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose ); +extern void Abc_NtkDontCareClear( void * p ); +extern void Abc_NtkDontCareFree( void * p ); +extern int Abc_NtkDontCareCompute( void * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth ); + +extern int s_ResubTime; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs incremental resynthesis of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, int nLevelsOdc, bool fUpdateLevel, bool fVerbose, bool fVeryVerbose ) +{ + ProgressBar * pProgress; + Abc_ManRes_t * pManRes; + Abc_ManCut_t * pManCut; + void * pManOdc = NULL; + Dec_Graph_t * pFForm; + Vec_Ptr_t * vLeaves; + Abc_Obj_t * pNode; + int clk, clkStart = clock(); + int i, nNodes; + + assert( Abc_NtkIsStrash(pNtk) ); + + // cleanup the AIG + Abc_AigCleanup(pNtk->pManFunc); + // start the managers + pManCut = Abc_NtkManCutStart( nCutMax, 100000, 100000, 100000 ); + pManRes = Abc_ManResubStart( nCutMax, ABC_RS_DIV1_MAX ); + if ( nLevelsOdc > 0 ) + pManOdc = Abc_NtkDontCareAlloc( nCutMax, nLevelsOdc, fVerbose, fVeryVerbose ); + + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Abc_NtkStartReverseLevels( pNtk, 0 ); + + if ( Abc_NtkLatchNum(pNtk) ) + Abc_NtkForEachLatch(pNtk, pNode, i) + pNode->pNext = pNode->pData; + + // resynthesize each node once + pManRes->nNodesBeg = Abc_NtkNodeNum(pNtk); + nNodes = Abc_NtkObjNumMax(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // skip the constant node +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // skip persistant nodes + if ( Abc_NodeIsPersistant(pNode) ) + continue; + // skip the nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > 1000 ) + continue; + // stop if all nodes have been tried once + if ( i >= nNodes ) + break; + + // compute a reconvergence-driven cut +clk = clock(); + vLeaves = Abc_NodeFindCut( pManCut, pNode, 0 ); +// vLeaves = Abc_CutFactorLarge( pNode, nCutMax ); +pManRes->timeCut += clock() - clk; +/* + if ( fVerbose && vLeaves ) + printf( "Node %6d : Leaves = %3d. Volume = %3d.\n", pNode->Id, Vec_PtrSize(vLeaves), Abc_CutVolumeCheck(pNode, vLeaves) ); + if ( vLeaves == NULL ) + continue; +*/ + // get the don't-cares + if ( pManOdc ) + { +clk = clock(); + Abc_NtkDontCareClear( pManOdc ); + Abc_NtkDontCareCompute( pManOdc, pNode, vLeaves, pManRes->pCareSet ); +pManRes->timeTruth += clock() - clk; + } + + // evaluate this cut +clk = clock(); + pFForm = Abc_ManResubEval( pManRes, pNode, vLeaves, nStepsMax, fUpdateLevel, fVerbose ); +// Vec_PtrFree( vLeaves ); +// Abc_ManResubCleanup( pManRes ); +pManRes->timeRes += clock() - clk; + if ( pFForm == NULL ) + continue; + pManRes->nTotalGain += pManRes->nLastGain; +/* + if ( pManRes->nLeaves == 4 && pManRes->nMffc == 2 && pManRes->nLastGain == 1 ) + { + printf( "%6d : L = %2d. V = %2d. Mffc = %2d. Divs = %3d. Up = %3d. Un = %3d. B = %3d.\n", + pNode->Id, pManRes->nLeaves, Abc_CutVolumeCheck(pNode, vLeaves), pManRes->nMffc, pManRes->nDivs, + pManRes->vDivs1UP->nSize, pManRes->vDivs1UN->nSize, pManRes->vDivs1B->nSize ); + Abc_ManResubPrintDivs( pManRes, pNode, vLeaves ); + } +*/ + // acceptable replacement found, update the graph +clk = clock(); + Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRes->nLastGain ); +pManRes->timeNtk += clock() - clk; + Dec_GraphFree( pFForm ); + } + Extra_ProgressBarStop( pProgress ); +pManRes->timeTotal = clock() - clkStart; + pManRes->nNodesEnd = Abc_NtkNodeNum(pNtk); + + // print statistics + if ( fVerbose ) + Abc_ManResubPrint( pManRes ); + + // delete the managers + Abc_ManResubStop( pManRes ); + Abc_NtkManCutStop( pManCut ); + if ( pManOdc ) Abc_NtkDontCareFree( pManOdc ); + + // clean the data field + Abc_NtkForEachObj( pNtk, pNode, i ) + pNode->pData = NULL; + + if ( Abc_NtkLatchNum(pNtk) ) + Abc_NtkForEachLatch(pNtk, pNode, i) + pNode->pData = pNode->pNext, pNode->pNext = NULL; + + // put the nodes into the DFS order and reassign their IDs + Abc_NtkReassignIds( pNtk ); +// Abc_AigCheckFaninOrder( pNtk->pManFunc ); + // fix the levels + if ( fUpdateLevel ) + Abc_NtkStopReverseLevels( pNtk ); + else + Abc_NtkLevel( pNtk ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkRefactor: The network check has failed.\n" ); + return 0; + } +s_ResubTime = clock() - clkStart; + return 1; +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ManRes_t * Abc_ManResubStart( int nLeavesMax, int nDivsMax ) +{ + Abc_ManRes_t * p; + unsigned * pData; + int i, k; + assert( sizeof(unsigned) == 4 ); + p = ALLOC( Abc_ManRes_t, 1 ); + memset( p, 0, sizeof(Abc_ManRes_t) ); + p->nLeavesMax = nLeavesMax; + p->nDivsMax = nDivsMax; + p->vDivs = Vec_PtrAlloc( p->nDivsMax ); + // allocate simulation info + p->nBits = (1 << p->nLeavesMax); + p->nWords = (p->nBits <= 32)? 1 : (p->nBits / 32); + p->pInfo = ALLOC( unsigned, p->nWords * (p->nDivsMax + 1) ); + memset( p->pInfo, 0, sizeof(unsigned) * p->nWords * p->nLeavesMax ); + p->vSims = Vec_PtrAlloc( p->nDivsMax ); + for ( i = 0; i < p->nDivsMax; i++ ) + Vec_PtrPush( p->vSims, p->pInfo + i * p->nWords ); + // assign the care set + p->pCareSet = p->pInfo + p->nDivsMax * p->nWords; + Abc_InfoFill( p->pCareSet, p->nWords ); + // set elementary truth tables + for ( k = 0; k < p->nLeavesMax; k++ ) + { + pData = p->vSims->pArray[k]; + for ( i = 0; i < p->nBits; i++ ) + if ( i & (1 << k) ) + pData[i>>5] |= (1 << (i&31)); + } + // create the remaining divisors + p->vDivs1UP = Vec_PtrAlloc( p->nDivsMax ); + p->vDivs1UN = Vec_PtrAlloc( p->nDivsMax ); + p->vDivs1B = Vec_PtrAlloc( p->nDivsMax ); + p->vDivs2UP0 = Vec_PtrAlloc( p->nDivsMax ); + p->vDivs2UP1 = Vec_PtrAlloc( p->nDivsMax ); + p->vDivs2UN0 = Vec_PtrAlloc( p->nDivsMax ); + p->vDivs2UN1 = Vec_PtrAlloc( p->nDivsMax ); + p->vTemp = Vec_PtrAlloc( p->nDivsMax ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubStop( Abc_ManRes_t * p ) +{ + Vec_PtrFree( p->vDivs ); + Vec_PtrFree( p->vSims ); + Vec_PtrFree( p->vDivs1UP ); + Vec_PtrFree( p->vDivs1UN ); + Vec_PtrFree( p->vDivs1B ); + Vec_PtrFree( p->vDivs2UP0 ); + Vec_PtrFree( p->vDivs2UP1 ); + Vec_PtrFree( p->vDivs2UN0 ); + Vec_PtrFree( p->vDivs2UN1 ); + Vec_PtrFree( p->vTemp ); + free( p->pInfo ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubPrint( Abc_ManRes_t * p ) +{ + printf( "Used constants = %6d. ", p->nUsedNodeC ); PRT( "Cuts ", p->timeCut ); + printf( "Used replacements = %6d. ", p->nUsedNode0 ); PRT( "Resub ", p->timeRes ); + printf( "Used single ORs = %6d. ", p->nUsedNode1Or ); PRT( " Div ", p->timeDiv ); + printf( "Used single ANDs = %6d. ", p->nUsedNode1And ); PRT( " Mffc ", p->timeMffc ); + printf( "Used double ORs = %6d. ", p->nUsedNode2Or ); PRT( " Sim ", p->timeSim ); + printf( "Used double ANDs = %6d. ", p->nUsedNode2And ); PRT( " 1 ", p->timeRes1 ); + printf( "Used OR-AND = %6d. ", p->nUsedNode2OrAnd ); PRT( " D ", p->timeResD ); + printf( "Used AND-OR = %6d. ", p->nUsedNode2AndOr ); PRT( " 2 ", p->timeRes2 ); + printf( "Used OR-2ANDs = %6d. ", p->nUsedNode3OrAnd ); PRT( "Truth ", p->timeTruth ); //PRT( " 3 ", p->timeRes3 ); + printf( "Used AND-2ORs = %6d. ", p->nUsedNode3AndOr ); PRT( "AIG ", p->timeNtk ); + printf( "TOTAL = %6d. ", p->nUsedNodeC + + p->nUsedNode0 + + p->nUsedNode1Or + + p->nUsedNode1And + + p->nUsedNode2Or + + p->nUsedNode2And + + p->nUsedNode2OrAnd + + p->nUsedNode2AndOr + + p->nUsedNode3OrAnd + + p->nUsedNode3AndOr + ); PRT( "TOTAL ", p->timeTotal ); + printf( "Total leaves = %8d.\n", p->nTotalLeaves ); + printf( "Total divisors = %8d.\n", p->nTotalDivs ); +// printf( "Total gain = %8d.\n", p->nTotalGain ); + printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubCollectDivs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vInternal ) +{ + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return; + Abc_NodeSetTravIdCurrent(pNode); + // collect the fanins + Abc_ManResubCollectDivs_rec( Abc_ObjFanin0(pNode), vInternal ); + Abc_ManResubCollectDivs_rec( Abc_ObjFanin1(pNode), vInternal ); + // collect the internal node + if ( pNode->fMarkA == 0 ) + Vec_PtrPush( vInternal, pNode ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required ) +{ + Abc_Obj_t * pNode, * pFanout; + int i, k, Limit, Counter; + + Vec_PtrClear( p->vDivs1UP ); + Vec_PtrClear( p->vDivs1UN ); + Vec_PtrClear( p->vDivs1B ); + + // add the leaves of the cuts to the divisors + Vec_PtrClear( p->vDivs ); + Abc_NtkIncrementTravId( pRoot->pNtk ); + Vec_PtrForEachEntry( vLeaves, pNode, i ) + { + Vec_PtrPush( p->vDivs, pNode ); + Abc_NodeSetTravIdCurrent( pNode ); + } + + // mark nodes in the MFFC + Vec_PtrForEachEntry( p->vTemp, pNode, i ) + pNode->fMarkA = 1; + // collect the cone (without MFFC) + Abc_ManResubCollectDivs_rec( pRoot, p->vDivs ); + // unmark the current MFFC + Vec_PtrForEachEntry( p->vTemp, pNode, i ) + pNode->fMarkA = 0; + + // check if the number of divisors is not exceeded + if ( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp) >= Vec_PtrSize(p->vSims) - p->nLeavesMax ) + return 0; + + // get the number of divisors to collect + Limit = Vec_PtrSize(p->vSims) - p->nLeavesMax - (Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp)); + + // explore the fanouts, which are not in the MFFC + Counter = 0; + Vec_PtrForEachEntry( p->vDivs, pNode, i ) + { + if ( Abc_ObjFanoutNum(pNode) > 100 ) + { +// printf( "%d ", Abc_ObjFanoutNum(pNode) ); + continue; + } + // if the fanout has both fanins in the set, add it + Abc_ObjForEachFanout( pNode, pFanout, k ) + { + if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsCo(pFanout) || (int)pFanout->Level > Required ) + continue; + if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) ) + { + if ( Abc_ObjFanin0(pFanout) == pRoot || Abc_ObjFanin1(pFanout) == pRoot ) + continue; + Vec_PtrPush( p->vDivs, pFanout ); + Abc_NodeSetTravIdCurrent( pFanout ); + // quit computing divisors if there is too many of them + if ( ++Counter == Limit ) + goto Quits; + } + } + } + +Quits : + // get the number of divisors + p->nDivs = Vec_PtrSize(p->vDivs); + + // add the nodes in the MFFC + Vec_PtrForEachEntry( p->vTemp, pNode, i ) + Vec_PtrPush( p->vDivs, pNode ); + assert( pRoot == Vec_PtrEntryLast(p->vDivs) ); + + assert( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) <= Vec_PtrSize(p->vSims) - p->nLeavesMax ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ) +{ + Abc_Obj_t * pFanin, * pNode; + int i, k; + // print the nodes + Vec_PtrForEachEntry( p->vDivs, pNode, i ) + { + if ( i < Vec_PtrSize(vLeaves) ) + { + printf( "%6d : %c\n", pNode->Id, 'a'+i ); + continue; + } + printf( "%6d : %2d = ", pNode->Id, i ); + // find the first fanin + Vec_PtrForEachEntry( p->vDivs, pFanin, k ) + if ( Abc_ObjFanin0(pNode) == pFanin ) + break; + if ( k < Vec_PtrSize(vLeaves) ) + printf( "%c", 'a' + k ); + else + printf( "%d", k ); + printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" ); + // find the second fanin + Vec_PtrForEachEntry( p->vDivs, pFanin, k ) + if ( Abc_ObjFanin1(pNode) == pFanin ) + break; + if ( k < Vec_PtrSize(vLeaves) ) + printf( "%c", 'a' + k ); + else + printf( "%d", k ); + printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" ); + if ( pNode == pRoot ) + printf( " root" ); + printf( "\n" ); + } + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Performs simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords ) +{ + Abc_Obj_t * pObj; + unsigned * puData0, * puData1, * puData; + int i, k; + assert( Vec_PtrSize(vDivs) - nLeaves <= Vec_PtrSize(vSims) - nLeavesMax ); + // simulate + Vec_PtrForEachEntry( vDivs, pObj, i ) + { + if ( i < nLeaves ) + { // initialize the leaf + pObj->pData = Vec_PtrEntry( vSims, i ); + continue; + } + // set storage for the node's simulation info + pObj->pData = Vec_PtrEntry( vSims, i - nLeaves + nLeavesMax ); + // get pointer to the simulation info + puData = pObj->pData; + puData0 = Abc_ObjFanin0(pObj)->pData; + puData1 = Abc_ObjFanin1(pObj)->pData; + // simulate + if ( Abc_ObjFaninC0(pObj) && Abc_ObjFaninC1(pObj) ) + for ( k = 0; k < nWords; k++ ) + puData[k] = ~puData0[k] & ~puData1[k]; + else if ( Abc_ObjFaninC0(pObj) ) + for ( k = 0; k < nWords; k++ ) + puData[k] = ~puData0[k] & puData1[k]; + else if ( Abc_ObjFaninC1(pObj) ) + for ( k = 0; k < nWords; k++ ) + puData[k] = puData0[k] & ~puData1[k]; + else + for ( k = 0; k < nWords; k++ ) + puData[k] = puData0[k] & puData1[k]; + } + // normalize + Vec_PtrForEachEntry( vDivs, pObj, i ) + { + puData = pObj->pData; + pObj->fPhase = (puData[0] & 1); + if ( pObj->fPhase ) + for ( k = 0; k < nWords; k++ ) + puData[k] = ~puData[k]; + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubQuit0( Abc_Obj_t * pRoot, Abc_Obj_t * pObj ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eRoot; + pGraph = Dec_GraphCreate( 1 ); + Dec_GraphNode( pGraph, 0 )->pFunc = pObj; + eRoot = Dec_EdgeCreate( 0, pObj->fPhase ); + Dec_GraphSetRoot( pGraph, eRoot ); + if ( pRoot->fPhase ) + Dec_GraphComplement( pGraph ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubQuit1( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, int fOrGate ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eRoot, eNode0, eNode1; + assert( pObj0 != pObj1 ); + assert( !Abc_ObjIsComplement(pObj0) ); + assert( !Abc_ObjIsComplement(pObj1) ); + pGraph = Dec_GraphCreate( 2 ); + Dec_GraphNode( pGraph, 0 )->pFunc = pObj0; + Dec_GraphNode( pGraph, 1 )->pFunc = pObj1; + eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase ); + eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase ); + if ( fOrGate ) + eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + else + eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); + Dec_GraphSetRoot( pGraph, eRoot ); + if ( pRoot->fPhase ) + Dec_GraphComplement( pGraph ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubQuit21( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eRoot, eNode0, eNode1, eNode2; + assert( pObj0 != pObj1 ); + assert( !Abc_ObjIsComplement(pObj0) ); + assert( !Abc_ObjIsComplement(pObj1) ); + assert( !Abc_ObjIsComplement(pObj2) ); + pGraph = Dec_GraphCreate( 3 ); + Dec_GraphNode( pGraph, 0 )->pFunc = pObj0; + Dec_GraphNode( pGraph, 1 )->pFunc = pObj1; + Dec_GraphNode( pGraph, 2 )->pFunc = pObj2; + eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase ); + eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase ); + eNode2 = Dec_EdgeCreate( 2, pObj2->fPhase ); + if ( fOrGate ) + { + eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + eRoot = Dec_GraphAddNodeOr( pGraph, eNode2, eRoot ); + } + else + { + eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); + eRoot = Dec_GraphAddNodeAnd( pGraph, eNode2, eRoot ); + } + Dec_GraphSetRoot( pGraph, eRoot ); + if ( pRoot->fPhase ) + Dec_GraphComplement( pGraph ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubQuit2( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eRoot, ePrev, eNode0, eNode1, eNode2; + assert( pObj0 != pObj1 ); + assert( pObj0 != pObj2 ); + assert( pObj1 != pObj2 ); + assert( !Abc_ObjIsComplement(pObj0) ); + pGraph = Dec_GraphCreate( 3 ); + Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0); + Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1); + Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2); + eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ); + if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) ) + { + eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ); + eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ); + ePrev = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 ); + } + else + { + eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) ); + eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) ); + ePrev = Dec_GraphAddNodeAnd( pGraph, eNode1, eNode2 ); + } + if ( fOrGate ) + eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, ePrev ); + else + eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, ePrev ); + Dec_GraphSetRoot( pGraph, eRoot ); + if ( pRoot->fPhase ) + Dec_GraphComplement( pGraph ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubQuit3( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, Abc_Obj_t * pObj3, int fOrGate ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eRoot, ePrev0, ePrev1, eNode0, eNode1, eNode2, eNode3; + assert( pObj0 != pObj1 ); + assert( pObj2 != pObj3 ); + pGraph = Dec_GraphCreate( 4 ); + Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0); + Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1); + Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2); + Dec_GraphNode( pGraph, 3 )->pFunc = Abc_ObjRegular(pObj3); + if ( Abc_ObjIsComplement(pObj0) && Abc_ObjIsComplement(pObj1) ) + { + eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ); + eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ); + ePrev0 = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) ) + { + eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ); + eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ); + ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 ); + } + else + { + eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) ); + eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) ); + ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 ); + } + } + else + { + eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ^ Abc_ObjIsComplement(pObj0) ); + eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) ); + ePrev0 = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); + if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) ) + { + eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ); + eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ); + ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 ); + } + else + { + eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) ); + eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) ); + ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 ); + } + } + if ( fOrGate ) + eRoot = Dec_GraphAddNodeOr( pGraph, ePrev0, ePrev1 ); + else + eRoot = Dec_GraphAddNodeAnd( pGraph, ePrev0, ePrev1 ); + Dec_GraphSetRoot( pGraph, eRoot ); + if ( pRoot->fPhase ) + Dec_GraphComplement( pGraph ); + return pGraph; +} + + + + +/**Function************************************************************* + + Synopsis [Derives single-node unate/binate divisors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required ) +{ + Abc_Obj_t * pObj; + unsigned * puData, * puDataR; + int i, w; + Vec_PtrClear( p->vDivs1UP ); + Vec_PtrClear( p->vDivs1UN ); + Vec_PtrClear( p->vDivs1B ); + puDataR = p->pRoot->pData; + Vec_PtrForEachEntryStop( p->vDivs, pObj, i, p->nDivs ) + { + if ( (int)pObj->Level > Required - 1 ) + continue; + + puData = pObj->pData; + // check positive containment + for ( w = 0; w < p->nWords; w++ ) +// if ( puData[w] & ~puDataR[w] ) + if ( puData[w] & ~puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs1UP, pObj ); + continue; + } + // check negative containment + for ( w = 0; w < p->nWords; w++ ) +// if ( ~puData[w] & puDataR[w] ) + if ( ~puData[w] & puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs1UN, pObj ); + continue; + } + // add the node to binates + Vec_PtrPush( p->vDivs1B, pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Derives double-node unate/binate divisors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required ) +{ + Abc_Obj_t * pObj0, * pObj1; + unsigned * puData0, * puData1, * puDataR; + int i, k, w; + Vec_PtrClear( p->vDivs2UP0 ); + Vec_PtrClear( p->vDivs2UP1 ); + Vec_PtrClear( p->vDivs2UN0 ); + Vec_PtrClear( p->vDivs2UN1 ); + puDataR = p->pRoot->pData; + Vec_PtrForEachEntry( p->vDivs1B, pObj0, i ) + { + if ( (int)pObj0->Level > Required - 2 ) + continue; + + puData0 = pObj0->pData; + Vec_PtrForEachEntryStart( p->vDivs1B, pObj1, k, i + 1 ) + { + if ( (int)pObj1->Level > Required - 2 ) + continue; + + puData1 = pObj1->pData; + + if ( Vec_PtrSize(p->vDivs2UP0) < ABC_RS_DIV2_MAX ) + { + // get positive unate divisors + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & puData1[w]) & ~puDataR[w] ) + if ( (puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UP0, pObj0 ); + Vec_PtrPush( p->vDivs2UP1, pObj1 ); + } + for ( w = 0; w < p->nWords; w++ ) +// if ( (~puData0[w] & puData1[w]) & ~puDataR[w] ) + if ( (~puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) ); + Vec_PtrPush( p->vDivs2UP1, pObj1 ); + } + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] ) + if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UP0, pObj0 ); + Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) ); + } + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | puData1[w]) & ~puDataR[w] ) + if ( (puData0[w] | puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) ); + Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) ); + } + } + + if ( Vec_PtrSize(p->vDivs2UN0) < ABC_RS_DIV2_MAX ) + { + // get negative unate divisors + for ( w = 0; w < p->nWords; w++ ) +// if ( ~(puData0[w] & puData1[w]) & puDataR[w] ) + if ( ~(puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UN0, pObj0 ); + Vec_PtrPush( p->vDivs2UN1, pObj1 ); + } + for ( w = 0; w < p->nWords; w++ ) +// if ( ~(~puData0[w] & puData1[w]) & puDataR[w] ) + if ( ~(~puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) ); + Vec_PtrPush( p->vDivs2UN1, pObj1 ); + } + for ( w = 0; w < p->nWords; w++ ) +// if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] ) + if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UN0, pObj0 ); + Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) ); + } + for ( w = 0; w < p->nWords; w++ ) +// if ( ~(puData0[w] | puData1[w]) & puDataR[w] ) + if ( ~(puData0[w] | puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) ); + Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) ); + } + } + } + } +// printf( "%d %d ", Vec_PtrSize(p->vDivs2UP0), Vec_PtrSize(p->vDivs2UN0) ); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p ) +{ + Dec_Graph_t * pGraph; + unsigned * upData; + int w; + upData = p->pRoot->pData; + for ( w = 0; w < p->nWords; w++ ) +// if ( upData[w] ) + if ( upData[w] & p->pCareSet[w] ) // care set + break; + if ( w != p->nWords ) + return NULL; + // get constant node graph + if ( p->pRoot->fPhase ) + pGraph = Dec_GraphCreateConst1(); + else + pGraph = Dec_GraphCreateConst0(); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p ) +{ + Abc_Obj_t * pObj; + unsigned * puData, * puDataR; + int i, w; + puDataR = p->pRoot->pData; + Vec_PtrForEachEntryStop( p->vDivs, pObj, i, p->nDivs ) + { + puData = pObj->pData; + for ( w = 0; w < p->nWords; w++ ) +// if ( puData[w] != puDataR[w] ) + if ( (puData[w] ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + return Abc_ManResubQuit0( p->pRoot, pObj ); + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required ) +{ + Abc_Obj_t * pObj0, * pObj1; + unsigned * puData0, * puData1, * puDataR; + int i, k, w; + puDataR = p->pRoot->pData; + // check positive unate divisors + Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i ) + { + puData0 = pObj0->pData; + Vec_PtrForEachEntryStart( p->vDivs1UP, pObj1, k, i + 1 ) + { + puData1 = pObj1->pData; + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | puData1[w]) != puDataR[w] ) + if ( ((puData0[w] | puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + p->nUsedNode1Or++; + return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 1 ); + } + } + } + // check negative unate divisors + Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i ) + { + puData0 = pObj0->pData; + Vec_PtrForEachEntryStart( p->vDivs1UN, pObj1, k, i + 1 ) + { + puData1 = pObj1->pData; + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & puData1[w]) != puDataR[w] ) + if ( ((puData0[w] & puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + p->nUsedNode1And++; + return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 0 ); + } + } + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required ) +{ + Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObjMax, * pObjMin0, * pObjMin1; + unsigned * puData0, * puData1, * puData2, * puDataR; + int i, k, j, w, LevelMax; + puDataR = p->pRoot->pData; + // check positive unate divisors + Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i ) + { + puData0 = pObj0->pData; + Vec_PtrForEachEntryStart( p->vDivs1UP, pObj1, k, i + 1 ) + { + puData1 = pObj1->pData; + Vec_PtrForEachEntryStart( p->vDivs1UP, pObj2, j, k + 1 ) + { + puData2 = pObj2->pData; + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | puData1[w] | puData2[w]) != puDataR[w] ) + if ( ((puData0[w] | puData1[w] | puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + LevelMax = ABC_MAX( pObj0->Level, ABC_MAX(pObj1->Level, pObj2->Level) ); + assert( LevelMax <= Required - 1 ); + + pObjMax = NULL; + if ( (int)pObj0->Level == LevelMax ) + pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2; + if ( (int)pObj1->Level == LevelMax ) + { + if ( pObjMax ) continue; + pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2; + } + if ( (int)pObj2->Level == LevelMax ) + { + if ( pObjMax ) continue; + pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1; + } + + p->nUsedNode2Or++; + return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 1 ); + } + } + } + } + // check negative unate divisors + Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i ) + { + puData0 = pObj0->pData; + Vec_PtrForEachEntryStart( p->vDivs1UN, pObj1, k, i + 1 ) + { + puData1 = pObj1->pData; + Vec_PtrForEachEntryStart( p->vDivs1UN, pObj2, j, k + 1 ) + { + puData2 = pObj2->pData; + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & puData1[w] & puData2[w]) != puDataR[w] ) + if ( ((puData0[w] & puData1[w] & puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + LevelMax = ABC_MAX( pObj0->Level, ABC_MAX(pObj1->Level, pObj2->Level) ); + assert( LevelMax <= Required - 1 ); + + pObjMax = NULL; + if ( (int)pObj0->Level == LevelMax ) + pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2; + if ( (int)pObj1->Level == LevelMax ) + { + if ( pObjMax ) continue; + pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2; + } + if ( (int)pObj2->Level == LevelMax ) + { + if ( pObjMax ) continue; + pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1; + } + + p->nUsedNode2And++; + return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 0 ); + } + } + } + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required ) +{ + Abc_Obj_t * pObj0, * pObj1, * pObj2; + unsigned * puData0, * puData1, * puData2, * puDataR; + int i, k, w; + puDataR = p->pRoot->pData; + // check positive unate divisors + Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i ) + { + puData0 = pObj0->pData; + Vec_PtrForEachEntry( p->vDivs2UP0, pObj1, k ) + { + pObj2 = Vec_PtrEntry( p->vDivs2UP1, k ); + + puData1 = Abc_ObjRegular(pObj1)->pData; + puData2 = Abc_ObjRegular(pObj2)->pData; + if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) ) + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | (puData1[w] | puData2[w])) != puDataR[w] ) + if ( ((puData0[w] | (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + else if ( Abc_ObjIsComplement(pObj1) ) + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | (~puData1[w] & puData2[w])) != puDataR[w] ) + if ( ((puData0[w] | (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + else if ( Abc_ObjIsComplement(pObj2) ) + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | (puData1[w] & ~puData2[w])) != puDataR[w] ) + if ( ((puData0[w] | (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + else + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | (puData1[w] & puData2[w])) != puDataR[w] ) + if ( ((puData0[w] | (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + if ( w == p->nWords ) + { + p->nUsedNode2OrAnd++; + return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 1 ); + } + } + } + // check negative unate divisors + Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i ) + { + puData0 = pObj0->pData; + Vec_PtrForEachEntry( p->vDivs2UN0, pObj1, k ) + { + pObj2 = Vec_PtrEntry( p->vDivs2UN1, k ); + + puData1 = Abc_ObjRegular(pObj1)->pData; + puData2 = Abc_ObjRegular(pObj2)->pData; + if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) ) + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & (puData1[w] | puData2[w])) != puDataR[w] ) + if ( ((puData0[w] & (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + else if ( Abc_ObjIsComplement(pObj1) ) + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & (~puData1[w] & puData2[w])) != puDataR[w] ) + if ( ((puData0[w] & (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + else if ( Abc_ObjIsComplement(pObj2) ) + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & (puData1[w] & ~puData2[w])) != puDataR[w] ) + if ( ((puData0[w] & (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + else + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & (puData1[w] & puData2[w])) != puDataR[w] ) + if ( ((puData0[w] & (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + if ( w == p->nWords ) + { + p->nUsedNode2AndOr++; + return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 0 ); + } + } + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required ) +{ + Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObj3; + unsigned * puData0, * puData1, * puData2, * puData3, * puDataR; + int i, k, w, Flag; + puDataR = p->pRoot->pData; + // check positive unate divisors + Vec_PtrForEachEntry( p->vDivs2UP0, pObj0, i ) + { + pObj1 = Vec_PtrEntry( p->vDivs2UP1, i ); + puData0 = Abc_ObjRegular(pObj0)->pData; + puData1 = Abc_ObjRegular(pObj1)->pData; + Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2); + + Vec_PtrForEachEntryStart( p->vDivs2UP0, pObj2, k, i + 1 ) + { + pObj3 = Vec_PtrEntry( p->vDivs2UP1, k ); + puData2 = Abc_ObjRegular(pObj2)->pData; + puData3 = Abc_ObjRegular(pObj3)->pData; + + Flag = (Flag & 12) | (Abc_ObjIsComplement(pObj2) << 1) | Abc_ObjIsComplement(pObj3); + assert( Flag < 16 ); + switch( Flag ) + { + case 0: // 0000 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 1: // 0001 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 2: // 0010 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 3: // 0011 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + + case 4: // 0100 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 5: // 0101 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 6: // 0110 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 7: // 0111 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + + case 8: // 1000 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 9: // 1001 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) + if ( (((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 10: // 1010 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 11: // 1011 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) + if ( (((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + + case 12: // 1100 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 13: // 1101 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) + if ( (((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) + break; + break; + case 14: // 1110 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) + break; + break; + case 15: // 1111 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) + if ( (((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) + break; + break; + + } + if ( w == p->nWords ) + { + p->nUsedNode3OrAnd++; + return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 1 ); + } + } + } +/* + // check negative unate divisors + Vec_PtrForEachEntry( p->vDivs2UN0, pObj0, i ) + { + pObj1 = Vec_PtrEntry( p->vDivs2UN1, i ); + puData0 = Abc_ObjRegular(pObj0)->pData; + puData1 = Abc_ObjRegular(pObj1)->pData; + Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2); + + Vec_PtrForEachEntryStart( p->vDivs2UN0, pObj2, k, i + 1 ) + { + pObj3 = Vec_PtrEntry( p->vDivs2UN1, k ); + puData2 = Abc_ObjRegular(pObj2)->pData; + puData3 = Abc_ObjRegular(pObj3)->pData; + + Flag = (Flag & 12) | (Abc_ObjIsComplement(pObj2) << 1) | Abc_ObjIsComplement(pObj3); + assert( Flag < 16 ); + switch( Flag ) + { + case 0: // 0000 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 1: // 0001 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) + break; + break; + case 2: // 0010 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 3: // 0011 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) + break; + break; + + case 4: // 0100 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 5: // 0101 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) + break; + break; + case 6: // 0110 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & ~puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 7: // 0111 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & ~puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) + break; + break; + + case 8: // 1000 + for ( w = 0; w < p->nWords; w++ ) + if ( ((~puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 9: // 1001 + for ( w = 0; w < p->nWords; w++ ) + if ( ((~puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) + break; + break; + case 10: // 1010 + for ( w = 0; w < p->nWords; w++ ) + if ( ((~puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 11: // 1011 + for ( w = 0; w < p->nWords; w++ ) + if ( ((~puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) + break; + break; + + case 12: // 1100 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] | puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 13: // 1101 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] | puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) + break; + break; + case 14: // 1110 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] | puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 15: // 1111 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] | puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) + break; + break; + + } + if ( w == p->nWords ) + { + p->nUsedNode3AndOr++; + return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 0 ); + } + } + } +*/ + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubCleanup( Abc_ManRes_t * p ) +{ + Abc_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( p->vDivs, pObj, i ) + pObj->pData = NULL; + Vec_PtrClear( p->vDivs ); + p->pRoot = NULL; +} + +/**Function************************************************************* + + Synopsis [Evaluates resubstution of one cut.] + + Description [Returns the graph to add if any.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, bool fUpdateLevel, bool fVerbose ) +{ + extern int Abc_NodeMffsInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside ); + Dec_Graph_t * pGraph; + int Required; + int clk; + + Required = fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY; + + assert( nSteps >= 0 ); + assert( nSteps <= 3 ); + p->pRoot = pRoot; + p->nLeaves = Vec_PtrSize(vLeaves); + p->nLastGain = -1; + + // collect the MFFC +clk = clock(); + p->nMffc = Abc_NodeMffsInside( pRoot, vLeaves, p->vTemp ); +p->timeMffc += clock() - clk; + assert( p->nMffc > 0 ); + + // collect the divisor nodes +clk = clock(); + if ( !Abc_ManResubCollectDivs( p, pRoot, vLeaves, Required ) ) + return NULL; + p->timeDiv += clock() - clk; + + p->nTotalDivs += p->nDivs; + p->nTotalLeaves += p->nLeaves; + + // simulate the nodes +clk = clock(); + Abc_ManResubSimulate( p->vDivs, p->nLeaves, p->vSims, p->nLeavesMax, p->nWords ); +p->timeSim += clock() - clk; + +clk = clock(); + // consider constants + if ( pGraph = Abc_ManResubQuit( p ) ) + { + p->nUsedNodeC++; + p->nLastGain = p->nMffc; + return pGraph; + } + + // consider equal nodes + if ( pGraph = Abc_ManResubDivs0( p ) ) + { +p->timeRes1 += clock() - clk; + p->nUsedNode0++; + p->nLastGain = p->nMffc; + return pGraph; + } + if ( nSteps == 0 || p->nMffc == 1 ) + { +p->timeRes1 += clock() - clk; + return NULL; + } + + // get the one level divisors + Abc_ManResubDivsS( p, Required ); + + // consider one node + if ( pGraph = Abc_ManResubDivs1( p, Required ) ) + { +p->timeRes1 += clock() - clk; + p->nLastGain = p->nMffc - 1; + return pGraph; + } +p->timeRes1 += clock() - clk; + if ( nSteps == 1 || p->nMffc == 2 ) + return NULL; + +clk = clock(); + // consider triples + if ( pGraph = Abc_ManResubDivs12( p, Required ) ) + { +p->timeRes2 += clock() - clk; + p->nLastGain = p->nMffc - 2; + return pGraph; + } +p->timeRes2 += clock() - clk; + + // get the two level divisors +clk = clock(); + Abc_ManResubDivsD( p, Required ); +p->timeResD += clock() - clk; + + // consider two nodes +clk = clock(); + if ( pGraph = Abc_ManResubDivs2( p, Required ) ) + { +p->timeRes2 += clock() - clk; + p->nLastGain = p->nMffc - 2; + return pGraph; + } +p->timeRes2 += clock() - clk; + if ( nSteps == 2 || p->nMffc == 3 ) + return NULL; + + // consider two nodes +clk = clock(); + if ( pGraph = Abc_ManResubDivs3( p, Required ) ) + { +p->timeRes3 += clock() - clk; + p->nLastGain = p->nMffc - 3; + return pGraph; + } +p->timeRes3 += clock() - clk; + if ( nSteps == 3 || p->nLeavesMax == 4 ) + return NULL; + return NULL; +} + + + + +/**Function************************************************************* + + Synopsis [Computes the volume and checks if the cut is feasible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CutVolumeCheck_rec( Abc_Obj_t * pObj ) +{ + // quit if the node is visited (or if it is a leaf) + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 0; + Abc_NodeSetTravIdCurrent(pObj); + // report the error + if ( Abc_ObjIsCi(pObj) ) + printf( "Abc_CutVolumeCheck() ERROR: The set of nodes is not a cut!\n" ); + // count the number of nodes in the leaves + return 1 + Abc_CutVolumeCheck_rec( Abc_ObjFanin0(pObj) ) + + Abc_CutVolumeCheck_rec( Abc_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Computes the volume and checks if the cut is feasible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ) +{ + Abc_Obj_t * pObj; + int i; + // mark the leaves + Abc_NtkIncrementTravId( pNode->pNtk ); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + // traverse the nodes starting from the given one and count them + return Abc_CutVolumeCheck_rec( pNode ); +} + +/**Function************************************************************* + + Synopsis [Computes the factor cut of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_CutFactor_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ) +{ + if ( pObj->fMarkA ) + return; + if ( Abc_ObjIsCi(pObj) || (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) ) + { + Vec_PtrPush( vLeaves, pObj ); + pObj->fMarkA = 1; + return; + } + Abc_CutFactor_rec( Abc_ObjFanin0(pObj), vLeaves ); + Abc_CutFactor_rec( Abc_ObjFanin1(pObj), vLeaves ); +} + +/**Function************************************************************* + + Synopsis [Computes the factor cut of the node.] + + Description [Factor-cut is the cut at a node in terms of factor-nodes. + Factor-nodes are roots of the node trees (MUXes/EXORs are counted as single nodes). + Factor-cut is unique for the given node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_CutFactor( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vLeaves; + Abc_Obj_t * pObj; + int i; + assert( !Abc_ObjIsCi(pNode) ); + vLeaves = Vec_PtrAlloc( 10 ); + Abc_CutFactor_rec( Abc_ObjFanin0(pNode), vLeaves ); + Abc_CutFactor_rec( Abc_ObjFanin1(pNode), vLeaves ); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->fMarkA = 0; + return vLeaves; +} + +/**Function************************************************************* + + Synopsis [Cut computation.] + + Description [This cut computation works as follows: + It starts with the factor cut at the node. If the factor-cut is large, quit. + It supports the set of leaves of the cut under construction and labels all nodes + in the cut under construction, including the leaves. + It computes the factor-cuts of the leaves and checks if it is easible to add any of them. + If it is, it randomly chooses one feasible and continues.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax ) +{ + Vec_Ptr_t * vLeaves, * vFactors, * vFact, * vNext; + Vec_Int_t * vFeasible; + Abc_Obj_t * pLeaf, * pTemp; + int i, k, Counter, RandLeaf; + int BestCut, BestShare; + assert( Abc_ObjIsNode(pNode) ); + // get one factor-cut + vLeaves = Abc_CutFactor( pNode ); + if ( Vec_PtrSize(vLeaves) > nLeavesMax ) + { + Vec_PtrFree(vLeaves); + return NULL; + } + if ( Vec_PtrSize(vLeaves) == nLeavesMax ) + return vLeaves; + // initialize the factor cuts for the leaves + vFactors = Vec_PtrAlloc( nLeavesMax ); + Abc_NtkIncrementTravId( pNode->pNtk ); + Vec_PtrForEachEntry( vLeaves, pLeaf, i ) + { + Abc_NodeSetTravIdCurrent( pLeaf ); + if ( Abc_ObjIsCi(pLeaf) ) + Vec_PtrPush( vFactors, NULL ); + else + Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) ); + } + // construct larger factor cuts + vFeasible = Vec_IntAlloc( nLeavesMax ); + while ( 1 ) + { + BestCut = -1; + // find the next feasible cut to add + Vec_IntClear( vFeasible ); + Vec_PtrForEachEntry( vFactors, vFact, i ) + { + if ( vFact == NULL ) + continue; + // count the number of unmarked leaves of this factor cut + Counter = 0; + Vec_PtrForEachEntry( vFact, pTemp, k ) + Counter += !Abc_NodeIsTravIdCurrent(pTemp); + // if the number of new leaves is smaller than the diff, it is feasible + if ( Counter <= nLeavesMax - Vec_PtrSize(vLeaves) + 1 ) + { + Vec_IntPush( vFeasible, i ); + if ( BestCut == -1 || BestShare < Vec_PtrSize(vFact) - Counter ) + BestCut = i, BestShare = Vec_PtrSize(vFact) - Counter; + } + } + // quit if there is no feasible factor cuts + if ( Vec_IntSize(vFeasible) == 0 ) + break; + // randomly choose one leaf and get its factor cut +// RandLeaf = Vec_IntEntry( vFeasible, rand() % Vec_IntSize(vFeasible) ); + // choose the cut that has most sharing with the other cuts + RandLeaf = BestCut; + + pLeaf = Vec_PtrEntry( vLeaves, RandLeaf ); + vNext = Vec_PtrEntry( vFactors, RandLeaf ); + // unmark this leaf + Abc_NodeSetTravIdPrevious( pLeaf ); + // remove this cut from the leaves and factor cuts + for ( i = RandLeaf; i < Vec_PtrSize(vLeaves)-1; i++ ) + { + Vec_PtrWriteEntry( vLeaves, i, Vec_PtrEntry(vLeaves, i+1) ); + Vec_PtrWriteEntry( vFactors, i, Vec_PtrEntry(vFactors,i+1) ); + } + Vec_PtrShrink( vLeaves, Vec_PtrSize(vLeaves) -1 ); + Vec_PtrShrink( vFactors, Vec_PtrSize(vFactors)-1 ); + // add new leaves, compute their factor cuts + Vec_PtrForEachEntry( vNext, pLeaf, i ) + { + if ( Abc_NodeIsTravIdCurrent(pLeaf) ) + continue; + Abc_NodeSetTravIdCurrent( pLeaf ); + Vec_PtrPush( vLeaves, pLeaf ); + if ( Abc_ObjIsCi(pLeaf) ) + Vec_PtrPush( vFactors, NULL ); + else + Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) ); + } + Vec_PtrFree( vNext ); + assert( Vec_PtrSize(vLeaves) <= nLeavesMax ); + if ( Vec_PtrSize(vLeaves) == nLeavesMax ) + break; + } + + // remove temporary storage + Vec_PtrForEachEntry( vFactors, vFact, i ) + if ( vFact ) Vec_PtrFree( vFact ); + Vec_PtrFree( vFactors ); + Vec_IntFree( vFeasible ); + return vLeaves; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcRewrite.c b/abc70930/src/base/abci/abcRewrite.c new file mode 100644 index 00000000..b615f47e --- /dev/null +++ b/abc70930/src/base/abci/abcRewrite.c @@ -0,0 +1,414 @@ +/**CFile**************************************************************** + + FileName [abcRewrite.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Technology-independent resynthesis of the AIG based on DAG aware rewriting.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRewrite.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "rwr.h" +#include "dec.h" + +/* + The ideas realized in this package are inspired by the paper: + Per Bjesse, Arne Boralv, "DAG-aware circuit compression for + formal verification", Proc. ICCAD 2004, pp. 42-49. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk ); +static void Abc_NodePrintCuts( Abc_Obj_t * pNode ); +static void Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ); + +extern void Abc_PlaceBegin( Abc_Ntk_t * pNtk ); +extern void Abc_PlaceEnd( Abc_Ntk_t * pNtk ); +extern void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs incremental rewriting of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable ) +{ + ProgressBar * pProgress; + Cut_Man_t * pManCut; + Rwr_Man_t * pManRwr; + Abc_Obj_t * pNode; + Vec_Ptr_t * vAddedCells = NULL, * vUpdatedNets = NULL; + Dec_Graph_t * pGraph; + int i, nNodes, nGain, fCompl; + int clk, clkStart = clock(); + + assert( Abc_NtkIsStrash(pNtk) ); + // cleanup the AIG + Abc_AigCleanup(pNtk->pManFunc); +/* + { + Vec_Vec_t * vParts; + vParts = Abc_NtkPartitionSmart( pNtk, 50, 1 ); + Vec_VecFree( vParts ); + } +*/ + + // start placement package +// if ( fPlaceEnable ) +// { +// Abc_PlaceBegin( pNtk ); +// vAddedCells = Abc_AigUpdateStart( pNtk->pManFunc, &vUpdatedNets ); +// } + + // start the rewriting manager + pManRwr = Rwr_ManStart( 0 ); + if ( pManRwr == NULL ) + return 0; + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Abc_NtkStartReverseLevels( pNtk, 0 ); + // start the cut manager +clk = clock(); + pManCut = Abc_NtkStartCutManForRewrite( pNtk ); +Rwr_ManAddTimeCuts( pManRwr, clock() - clk ); + pNtk->pManCut = pManCut; + + if ( fVeryVerbose ) + Rwr_ScoresClean( pManRwr ); + + // resynthesize each node once + pManRwr->nNodesBeg = Abc_NtkNodeNum(pNtk); + nNodes = Abc_NtkObjNumMax(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // stop if all nodes have been tried once + if ( i >= nNodes ) + break; + // skip persistant nodes + if ( Abc_NodeIsPersistant(pNode) ) + continue; + // skip the nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > 1000 ) + continue; + + // for each cut, try to resynthesize it + nGain = Rwr_NodeRewrite( pManRwr, pManCut, pNode, fUpdateLevel, fUseZeros, fPlaceEnable ); + if ( !(nGain > 0 || nGain == 0 && fUseZeros) ) + continue; + // if we end up here, a rewriting step is accepted + + // get hold of the new subgraph to be added to the AIG + pGraph = Rwr_ManReadDecs(pManRwr); + fCompl = Rwr_ManReadCompl(pManRwr); + + // reset the array of the changed nodes + if ( fPlaceEnable ) + Abc_AigUpdateReset( pNtk->pManFunc ); + + // complement the FF if needed + if ( fCompl ) Dec_GraphComplement( pGraph ); +clk = clock(); + Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, nGain ); +Rwr_ManAddTimeUpdate( pManRwr, clock() - clk ); + if ( fCompl ) Dec_GraphComplement( pGraph ); + + // use the array of changed nodes to update placement +// if ( fPlaceEnable ) +// Abc_PlaceUpdate( vAddedCells, vUpdatedNets ); + } + Extra_ProgressBarStop( pProgress ); +Rwr_ManAddTimeTotal( pManRwr, clock() - clkStart ); + // print stats + pManRwr->nNodesEnd = Abc_NtkNodeNum(pNtk); + if ( fVerbose ) + Rwr_ManPrintStats( pManRwr ); +// Rwr_ManPrintStatsFile( pManRwr ); + if ( fVeryVerbose ) + Rwr_ScoresReport( pManRwr ); + // delete the managers + Rwr_ManStop( pManRwr ); + Cut_ManStop( pManCut ); + pNtk->pManCut = NULL; + + // start placement package +// if ( fPlaceEnable ) +// { +// Abc_PlaceEnd( pNtk ); +// Abc_AigUpdateStop( pNtk->pManFunc ); +// } + + // put the nodes into the DFS order and reassign their IDs + { +// int clk = clock(); + Abc_NtkReassignIds( pNtk ); +// PRT( "time", clock() - clk ); + } +// Abc_AigCheckFaninOrder( pNtk->pManFunc ); + // fix the levels + if ( fUpdateLevel ) + Abc_NtkStopReverseLevels( pNtk ); + else + Abc_NtkLevel( pNtk ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkRewrite: The network check has failed.\n" ); + return 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Starts the cut manager for rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk ) +{ + static Cut_Params_t Params, * pParams = &Params; + Cut_Man_t * pManCut; + Abc_Obj_t * pObj; + int i; + // start the cut manager + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = 4; // the max cut size ("k" of the k-feasible cuts) + pParams->nKeepMax = 250; // the max number of cuts kept at a node + pParams->fTruth = 1; // compute truth tables + pParams->fFilter = 1; // filter dominated cuts + pParams->fSeq = 0; // compute sequential cuts + pParams->fDrop = 0; // drop cuts on the fly + pParams->fVerbose = 0; // the verbosiness flag + pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); + pManCut = Cut_ManStart( pParams ); + if ( pParams->fDrop ) + Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); + // set cuts for PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_NodeSetTriv( pManCut, pObj->Id ); + return pManCut; +} + +/**Function************************************************************* + + Synopsis [Prints the cuts at the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodePrintCuts( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vCuts; + Cut_Cut_t * pCut; + int k; + + printf( "\nNode %s\n", Abc_ObjName(pNode) ); + vCuts = (Vec_Ptr_t *)pNode->pCopy; + Vec_PtrForEachEntry( vCuts, pCut, k ) + { + Extra_PrintBinary( stdout, (unsigned *)&pCut->uSign, 16 ); + printf( " " ); + Cut_CutPrint( pCut, 0 ); + printf( "\n" ); + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManRewritePrintDivs( Vec_Ptr_t * vDivs, int nLeaves ) +{ + Abc_Obj_t * pFanin, * pNode, * pRoot; + int i, k; + pRoot = Vec_PtrEntryLast(vDivs); + // print the nodes + Vec_PtrForEachEntry( vDivs, pNode, i ) + { + if ( i < nLeaves ) + { + printf( "%6d : %c\n", pNode->Id, 'a'+i ); + continue; + } + printf( "%6d : %2d = ", pNode->Id, i ); + // find the first fanin + Vec_PtrForEachEntry( vDivs, pFanin, k ) + if ( Abc_ObjFanin0(pNode) == pFanin ) + break; + if ( k < nLeaves ) + printf( "%c", 'a' + k ); + else + printf( "%d", k ); + printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" ); + // find the second fanin + Vec_PtrForEachEntry( vDivs, pFanin, k ) + if ( Abc_ObjFanin1(pNode) == pFanin ) + break; + if ( k < nLeaves ) + printf( "%c", 'a' + k ); + else + printf( "%d", k ); + printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" ); + if ( pNode == pRoot ) + printf( " root" ); + printf( "\n" ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManShowCutCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vDivs ) +{ + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return; + Abc_NodeSetTravIdCurrent(pNode); + Abc_ManShowCutCone_rec( Abc_ObjFanin0(pNode), vDivs ); + Abc_ManShowCutCone_rec( Abc_ObjFanin1(pNode), vDivs ); + Vec_PtrPush( vDivs, pNode ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + Abc_Obj_t * pObj; + Vec_Ptr_t * vDivs; + int i; + vDivs = Vec_PtrAlloc( 100 ); + Abc_NtkIncrementTravId( pNtk ); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + { + Abc_NodeSetTravIdCurrent( Abc_ObjRegular(pObj) ); + Vec_PtrPush( vDivs, Abc_ObjRegular(pObj) ); + } + Abc_ManShowCutCone_rec( pNode, vDivs ); + Abc_ManRewritePrintDivs( vDivs, Vec_PtrSize(vLeaves) ); + Vec_PtrFree( vDivs ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RwrExpWithCut_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, int fUseA ) +{ + if ( Vec_PtrFind(vLeaves, pNode) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pNode)) >= 0 ) + { + if ( fUseA ) + Abc_ObjRegular(pNode)->fMarkA = 1; + else + Abc_ObjRegular(pNode)->fMarkB = 1; + return; + } + assert( Abc_ObjIsNode(pNode) ); + Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, fUseA ); + Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, fUseA ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RwrExpWithCut( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ) +{ + Abc_Obj_t * pObj; + int i, CountA, CountB; + Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, 1 ); + Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, 0 ); + CountA = CountB = 0; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + { + CountA += Abc_ObjRegular(pObj)->fMarkA; + CountB += Abc_ObjRegular(pObj)->fMarkB; + Abc_ObjRegular(pObj)->fMarkA = 0; + Abc_ObjRegular(pObj)->fMarkB = 0; + } + printf( "(%d,%d:%d) ", CountA, CountB, CountA+CountB-Vec_PtrSize(vLeaves) ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcRr.c b/abc70930/src/base/abci/abcRr.c new file mode 100644 index 00000000..92adc718 --- /dev/null +++ b/abc70930/src/base/abci/abcRr.c @@ -0,0 +1,999 @@ +/**CFile**************************************************************** + + FileName [abcRr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Redundancy removal.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fraig.h" +#include "sim.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Abc_RRMan_t_ Abc_RRMan_t; +struct Abc_RRMan_t_ +{ + // the parameters + Abc_Ntk_t * pNtk; // the network + int nFaninLevels; // the number of fanin levels + int nFanoutLevels; // the number of fanout levels + // the node/fanin/fanout + Abc_Obj_t * pNode; // the node + Abc_Obj_t * pFanin; // the fanin + Abc_Obj_t * pFanout; // the fanout + // the intermediate cones + Vec_Ptr_t * vFaninLeaves; // the leaves of the fanin cone + Vec_Ptr_t * vFanoutRoots; // the roots of the fanout cone + // the window + Vec_Ptr_t * vLeaves; // the leaves of the window + Vec_Ptr_t * vCone; // the internal nodes of the window + Vec_Ptr_t * vRoots; // the roots of the window + Abc_Ntk_t * pWnd; // the window derived for the edge + // the miter + Abc_Ntk_t * pMiter; // the miter derived from the window + Prove_Params_t * pParams; // the miter proving parameters + // statistical variables + int nNodesOld; // the old number of nodes + int nLevelsOld; // the old number of levels + int nEdgesTried; // the number of nodes tried + int nEdgesRemoved; // the number of nodes proved + int timeWindow; // the time to construct the window + int timeMiter; // the time to construct the miter + int timeProve; // the time to prove the miter + int timeUpdate; // the network update time + int timeTotal; // the total runtime +}; + +static Abc_RRMan_t * Abc_RRManStart(); +static void Abc_RRManStop( Abc_RRMan_t * p ); +static void Abc_RRManPrintStats( Abc_RRMan_t * p ); +static void Abc_RRManClean( Abc_RRMan_t * p ); +static int Abc_NtkRRProve( Abc_RRMan_t * p ); +static int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout ); +static int Abc_NtkRRWindow( Abc_RRMan_t * p ); + +static int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit ); +static int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ); +static int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ); +static void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit ); +static Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots ); + +static void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk ); +static void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Removes stuck-at redundancies.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose ) +{ + ProgressBar * pProgress; + Abc_RRMan_t * p; + Abc_Obj_t * pNode, * pFanin, * pFanout; + int i, k, m, nNodes, RetValue, clk, clkTotal = clock(); + // start the manager + p = Abc_RRManStart( nFaninLevels, nFanoutLevels ); + p->pNtk = pNtk; + p->nFaninLevels = nFaninLevels; + p->nFanoutLevels = nFanoutLevels; + p->nNodesOld = Abc_NtkNodeNum(pNtk); + p->nLevelsOld = Abc_AigLevel(pNtk); + // remember latch values +// Abc_NtkForEachLatch( pNtk, pNode, i ) +// pNode->pNext = pNode->pData; + // go through the nodes + Abc_NtkCleanCopy(pNtk); + nNodes = Abc_NtkObjNumMax(pNtk); + Abc_NtkRRSimulateStart(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // stop if all nodes have been tried once + if ( i >= nNodes ) + break; + // skip the constant node +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // skip persistant nodes + if ( Abc_NodeIsPersistant(pNode) ) + continue; + // skip the nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > 1000 ) + continue; + // construct the window + if ( !fUseFanouts ) + { + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + // skip the nodes with only one fanout (tree nodes) + if ( Abc_ObjFanoutNum(pFanin) == 1 ) + continue; +/* + if ( pFanin->Id == 228 && pNode->Id == 2649 ) + { + int k = 0; + } +*/ + p->nEdgesTried++; + Abc_RRManClean( p ); + p->pNode = pNode; + p->pFanin = pFanin; + p->pFanout = NULL; + + clk = clock(); + RetValue = Abc_NtkRRWindow( p ); + p->timeWindow += clock() - clk; + if ( !RetValue ) + continue; +/* + if ( pFanin->Id == 228 && pNode->Id == 2649 ) + { + Abc_NtkShowAig( p->pWnd, 0 ); + } +*/ + clk = clock(); + RetValue = Abc_NtkRRProve( p ); + p->timeMiter += clock() - clk; + if ( !RetValue ) + continue; +//printf( "%d -> %d (%d)\n", pFanin->Id, pNode->Id, k ); + + clk = clock(); + Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout ); + p->timeUpdate += clock() - clk; + + p->nEdgesRemoved++; + break; + } + continue; + } + // use the fanouts + Abc_ObjForEachFanin( pNode, pFanin, k ) + Abc_ObjForEachFanout( pNode, pFanout, m ) + { + // skip the nodes with only one fanout (tree nodes) +// if ( Abc_ObjFanoutNum(pFanin) == 1 && Abc_ObjFanoutNum(pNode) == 1 ) +// continue; + + p->nEdgesTried++; + Abc_RRManClean( p ); + p->pNode = pNode; + p->pFanin = pFanin; + p->pFanout = pFanout; + + clk = clock(); + RetValue = Abc_NtkRRWindow( p ); + p->timeWindow += clock() - clk; + if ( !RetValue ) + continue; + + clk = clock(); + RetValue = Abc_NtkRRProve( p ); + p->timeMiter += clock() - clk; + if ( !RetValue ) + continue; + + clk = clock(); + Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout ); + p->timeUpdate += clock() - clk; + + p->nEdgesRemoved++; + break; + } + } + Abc_NtkRRSimulateStop(pNtk); + Extra_ProgressBarStop( pProgress ); + p->timeTotal = clock() - clkTotal; + if ( fVerbose ) + Abc_RRManPrintStats( p ); + Abc_RRManStop( p ); + // restore latch values +// Abc_NtkForEachLatch( pNtk, pNode, i ) +// pNode->pData = pNode->pNext, pNode->pNext = NULL; + // put the nodes into the DFS order and reassign their IDs + Abc_NtkReassignIds( pNtk ); + Abc_NtkLevel( pNtk ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkRR: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Start the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_RRMan_t * Abc_RRManStart() +{ + Abc_RRMan_t * p; + p = ALLOC( Abc_RRMan_t, 1 ); + memset( p, 0, sizeof(Abc_RRMan_t) ); + p->vFaninLeaves = Vec_PtrAlloc( 100 ); // the leaves of the fanin cone + p->vFanoutRoots = Vec_PtrAlloc( 100 ); // the roots of the fanout cone + p->vLeaves = Vec_PtrAlloc( 100 ); // the leaves of the window + p->vCone = Vec_PtrAlloc( 100 ); // the internal nodes of the window + p->vRoots = Vec_PtrAlloc( 100 ); // the roots of the window + p->pParams = ALLOC( Prove_Params_t, 1 ); + memset( p->pParams, 0, sizeof(Prove_Params_t) ); + Prove_ParamsSetDefault( p->pParams ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stop the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RRManStop( Abc_RRMan_t * p ) +{ + Abc_RRManClean( p ); + Vec_PtrFree( p->vFaninLeaves ); + Vec_PtrFree( p->vFanoutRoots ); + Vec_PtrFree( p->vLeaves ); + Vec_PtrFree( p->vCone ); + Vec_PtrFree( p->vRoots ); + free( p->pParams ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Stop the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RRManPrintStats( Abc_RRMan_t * p ) +{ + double Ratio = 100.0*(p->nNodesOld - Abc_NtkNodeNum(p->pNtk))/p->nNodesOld; + printf( "Redundancy removal statistics:\n" ); + printf( "Edges tried = %6d.\n", p->nEdgesTried ); + printf( "Edges removed = %6d. (%5.2f %%)\n", p->nEdgesRemoved, 100.0*p->nEdgesRemoved/p->nEdgesTried ); + printf( "Node gain = %6d. (%5.2f %%)\n", p->nNodesOld - Abc_NtkNodeNum(p->pNtk), Ratio ); + printf( "Level gain = %6d.\n", p->nLevelsOld - Abc_AigLevel(p->pNtk) ); + PRT( "Windowing ", p->timeWindow ); + PRT( "Miter ", p->timeMiter ); + PRT( " Construct ", p->timeMiter - p->timeProve ); + PRT( " Prove ", p->timeProve ); + PRT( "Update ", p->timeUpdate ); + PRT( "TOTAL ", p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Clean the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RRManClean( Abc_RRMan_t * p ) +{ + p->pNode = NULL; + p->pFanin = NULL; + p->pFanout = NULL; + Vec_PtrClear( p->vFaninLeaves ); + Vec_PtrClear( p->vFanoutRoots ); + Vec_PtrClear( p->vLeaves ); + Vec_PtrClear( p->vCone ); + Vec_PtrClear( p->vRoots ); + if ( p->pWnd ) Abc_NtkDelete( p->pWnd ); + if ( p->pMiter ) Abc_NtkDelete( p->pMiter ); + p->pWnd = NULL; + p->pMiter = NULL; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the miter is constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRProve( Abc_RRMan_t * p ) +{ + Abc_Ntk_t * pWndCopy; + int RetValue, clk; +// Abc_NtkShowAig( p->pWnd, 0 ); + pWndCopy = Abc_NtkDup( p->pWnd ); + Abc_NtkRRUpdate( pWndCopy, p->pNode->pCopy->pCopy, p->pFanin->pCopy->pCopy, p->pFanout? p->pFanout->pCopy->pCopy : NULL ); + if ( !Abc_NtkIsDfsOrdered(pWndCopy) ) + Abc_NtkReassignIds(pWndCopy); + p->pMiter = Abc_NtkMiter( p->pWnd, pWndCopy, 1, 0 ); + Abc_NtkDelete( pWndCopy ); +clk = clock(); + RetValue = Abc_NtkMiterProve( &p->pMiter, p->pParams ); +p->timeProve += clock() - clk; + if ( RetValue == 1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Updates the network after redundancy removal.] + + Description [This procedure assumes that non-control value of the fanin + was proved redundant. It is okay to concentrate on non-control values + because the control values can be seen as redundancy of the fanout edge.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout ) +{ + Abc_Obj_t * pNodeNew, * pFanoutNew; + assert( pFanout == NULL ); + assert( !Abc_ObjIsComplement(pNode) ); + assert( !Abc_ObjIsComplement(pFanin) ); + assert( !Abc_ObjIsComplement(pFanout) ); + // find the node after redundancy removal + if ( pFanin == Abc_ObjFanin0(pNode) ) + pNodeNew = Abc_ObjChild1(pNode); + else if ( pFanin == Abc_ObjFanin1(pNode) ) + pNodeNew = Abc_ObjChild0(pNode); + else assert( 0 ); + // replace + if ( pFanout == NULL ) + { + Abc_AigReplace( pNtk->pManFunc, pNode, pNodeNew, 1 ); + return 1; + } + // find the fanout after redundancy removal + if ( pNode == Abc_ObjFanin0(pFanout) ) + pFanoutNew = Abc_AigAnd( pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC0(pFanout)), Abc_ObjChild1(pFanout) ); + else if ( pNode == Abc_ObjFanin1(pFanout) ) + pFanoutNew = Abc_AigAnd( pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC1(pFanout)), Abc_ObjChild0(pFanout) ); + else assert( 0 ); + // replace + Abc_AigReplace( pNtk->pManFunc, pFanout, pFanoutNew, 1 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Constructs window for checking RR.] + + Description [If the window (p->pWnd) with the given scope (p->nFaninLevels, + p->nFanoutLevels) cannot be constructed, returns 0. Otherwise, returns 1. + The levels are measured from the fanin node (pFanin) and the fanout node + (pEdgeFanout), respectively.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRWindow( Abc_RRMan_t * p ) +{ + Abc_Obj_t * pObj, * pEdgeFanin, * pEdgeFanout; + int i, LevelMin, LevelMax, RetValue; + + // get the edge + pEdgeFanout = p->pFanout? p->pFanout : p->pNode; + pEdgeFanin = p->pFanout? p->pNode : p->pFanin; + // get the minimum and maximum levels of the window + LevelMin = ABC_MAX( 0, ((int)p->pFanin->Level) - p->nFaninLevels ); + LevelMax = (int)pEdgeFanout->Level + p->nFanoutLevels; + + // start the TFI leaves with the fanin + Abc_NtkIncrementTravId( p->pNtk ); + Abc_NodeSetTravIdCurrent( p->pFanin ); + Vec_PtrPush( p->vFaninLeaves, p->pFanin ); + // mark the TFI cone and collect the leaves down to the given level + while ( Abc_NtkRRTfi_int(p->vFaninLeaves, LevelMin) ); + + // mark the leaves with the new TravId + Abc_NtkIncrementTravId( p->pNtk ); + Vec_PtrForEachEntry( p->vFaninLeaves, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + // traverse the TFO cone of the leaves (while skipping the edge) + // (a) mark the nodes in the cone using the current TravId + // (b) collect the nodes that have external fanouts into p->vFanoutRoots + while ( Abc_NtkRRTfo_int(p->vFaninLeaves, p->vFanoutRoots, LevelMax, pEdgeFanin, pEdgeFanout) ); + + // mark the fanout roots + Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i ) + pObj->fMarkA = 1; + // collect roots reachable from the fanout (p->vRoots) + RetValue = Abc_NtkRRTfo_rec( pEdgeFanout, p->vRoots, LevelMax + 1 ); + // unmark the fanout roots + Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i ) + pObj->fMarkA = 0; + + // return if the window is infeasible + if ( RetValue == 0 ) + return 0; + + // collect the DFS-ordered new cone (p->vCone) and new leaves (p->vLeaves) + // using the previous marks coming from the TFO cone + Abc_NtkIncrementTravId( p->pNtk ); + Vec_PtrForEachEntry( p->vRoots, pObj, i ) + Abc_NtkRRTfi_rec( pObj, p->vLeaves, p->vCone, LevelMin ); + + // create a new network + p->pWnd = Abc_NtkWindow( p->pNtk, p->vLeaves, p->vCone, p->vRoots ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Marks the nodes in the TFI and collects their leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit ) +{ + Abc_Obj_t * pObj, * pNext; + int i, k, LevelMax, nSize; + assert( LevelLimit >= 0 ); + // find the maximum level of leaves + LevelMax = 0; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + if ( LevelMax < (int)pObj->Level ) + LevelMax = pObj->Level; + // if the nodes are all PIs, LevelMax == 0 + if ( LevelMax <= LevelLimit ) + return 0; + // expand the nodes with the minimum level + nSize = Vec_PtrSize(vLeaves); + Vec_PtrForEachEntryStop( vLeaves, pObj, i, nSize ) + { + if ( LevelMax != (int)pObj->Level ) + continue; + Abc_ObjForEachFanin( pObj, pNext, k ) + { + if ( Abc_NodeIsTravIdCurrent(pNext) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + Vec_PtrPush( vLeaves, pNext ); + } + } + // remove old nodes (cannot remove a PI) + k = 0; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + { + if ( LevelMax == (int)pObj->Level ) + continue; + Vec_PtrWriteEntry( vLeaves, k++, pObj ); + } + Vec_PtrShrink( vLeaves, k ); + if ( Vec_PtrSize(vLeaves) > 2000 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Marks the nodes in the TFO and collects their roots.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ) +{ + Abc_Obj_t * pObj, * pNext; + int i, k, LevelMin, nSize, fObjIsRoot; + // find the minimum level of leaves + LevelMin = ABC_INFINITY; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + if ( LevelMin > (int)pObj->Level ) + LevelMin = pObj->Level; + // if the minimum level exceed the limit, we are done + if ( LevelMin > LevelLimit ) + return 0; + // expand the nodes with the minimum level + nSize = Vec_PtrSize(vLeaves); + Vec_PtrForEachEntryStop( vLeaves, pObj, i, nSize ) + { + if ( LevelMin != (int)pObj->Level ) + continue; + fObjIsRoot = 0; + Abc_ObjForEachFanout( pObj, pNext, k ) + { + // check if the fanout is outside of the cone + if ( Abc_ObjIsCo(pNext) || pNext->Level > (unsigned)LevelLimit ) + { + fObjIsRoot = 1; + continue; + } + // skip the edge under check + if ( pObj == pEdgeFanin && pNext == pEdgeFanout ) + continue; + // skip the visited fanouts + if ( Abc_NodeIsTravIdCurrent(pNext) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + Vec_PtrPush( vLeaves, pNext ); + } + if ( fObjIsRoot ) + Vec_PtrPush( vRoots, pObj ); + } + // remove old nodes + k = 0; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + { + if ( LevelMin == (int)pObj->Level ) + continue; + Vec_PtrWriteEntry( vLeaves, k++, pObj ); + } + Vec_PtrShrink( vLeaves, k ); + if ( Vec_PtrSize(vLeaves) > 2000 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Collects the roots in the TFO of the node.] + + Description [Note that this procedure can be improved by + marking and skipping the visited nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ) +{ + Abc_Obj_t * pFanout; + int i; + // if we encountered a node outside of the TFO cone of the fanins, quit + if ( Abc_ObjIsCo(pNode) || pNode->Level > (unsigned)LevelLimit ) + return 0; + // if we encountered a node on the boundary, add it to the roots + if ( pNode->fMarkA ) + { + Vec_PtrPushUnique( vRoots, pNode ); + return 1; + } + // mark the node with the current TravId (needed to have all internal nodes marked) + Abc_NodeSetTravIdCurrent( pNode ); + // traverse the fanouts + Abc_ObjForEachFanout( pNode, pFanout, i ) + if ( !Abc_NtkRRTfo_rec( pFanout, vRoots, LevelLimit ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Collects the leaves and cone of the roots.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit ) +{ + Abc_Obj_t * pFanin; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return; + // add node to leaves if it is not in TFI cone of the leaves (marked before) or below the limit + if ( !Abc_NodeIsTravIdPrevious(pNode) || (int)pNode->Level <= LevelLimit ) + { + Abc_NodeSetTravIdCurrent( pNode ); + Vec_PtrPush( vLeaves, pNode ); + return; + } + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // call for the node's fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NtkRRTfi_rec( pFanin, vLeaves, vCone, LevelLimit ); + // add the node to the cone in topological order + Vec_PtrPush( vCone, pNode ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj; + int fCheck = 1; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( "temp" ); + // map the constant nodes + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + // create and map the PIs + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + // copy the AND gates + Vec_PtrForEachEntry( vCone, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // compare the number of nodes before and after + if ( Vec_PtrSize(vCone) != Abc_NtkNodeNum(pNtkNew) ) + printf( "Warning: Structural hashing during windowing reduced %d nodes (this is a bug).\n", + Vec_PtrSize(vCone) - Abc_NtkNodeNum(pNtkNew) ); + // create the POs + Vec_PtrForEachEntry( vRoots, pObj, i ) + { + assert( !Abc_ObjIsComplement(pObj->pCopy) ); + Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObj->pCopy ); + } + // add the PI/PO names + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_NtkAddDummyPoNames( pNtkNew ); + Abc_NtkAddDummyAssertNames( pNtkNew ); + // check + if ( fCheck && !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkWindow: The network check has failed.\n" ); + return NULL; + } + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Starts simulation to detect non-redundant edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + unsigned uData, uData0, uData1; + int i; + Abc_AigConst1(pNtk)->pData = (void *)~((unsigned)0); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pData = (void *)SIM_RANDOM_UNSIGNED; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) continue; + uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; + uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData; + uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0; + uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1; + assert( pObj->pData == NULL ); + pObj->pData = (void *)uData; + } +} + +/**Function************************************************************* + + Synopsis [Stops simulation to detect non-redundant edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pData = NULL; +} + + + + + + + +static void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes ); +static void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField ); +static void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField ); + +/**Function************************************************************* + + Synopsis [Simulation to detect non-redundant edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Abc_NtkRRSimulate( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes, * vField; + Vec_Str_t * vTargets; + Abc_Obj_t * pObj; + unsigned uData, uData0, uData1; + int PrevCi, Phase, i, k; + + // start the candidates + vTargets = Vec_StrStart( Abc_NtkObjNumMax(pNtk) + 1 ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + Phase = ((Abc_ObjFanoutNum(Abc_ObjFanin1(pObj)) > 1) << 1); + Phase |= (Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) > 1); + Vec_StrWriteEntry( vTargets, pObj->Id, (char)Phase ); + } + + // simulate patters and store them in copy + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)~((unsigned)0); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)SIM_RANDOM_UNSIGNED; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) continue; + uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; + uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData; + uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0; + uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1; + pObj->pCopy = (Abc_Obj_t *)uData; + } + // store the result in data + Abc_NtkForEachCo( pNtk, pObj, i ) + { + uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; + if ( Abc_ObjFaninC0(pObj) ) + pObj->pData = (void *)~uData0; + else + pObj->pData = (void *)uData0; + } + + // refine the candidates + for ( PrevCi = 0; PrevCi < Abc_NtkCiNum(pNtk); PrevCi = i ) + { + vNodes = Vec_PtrAlloc( 10 ); + Abc_NtkIncrementTravId( pNtk ); + for ( i = PrevCi; i < Abc_NtkCiNum(pNtk); i++ ) + { + Sim_TraverseNodes_rec( Abc_NtkCi(pNtk, i), vTargets, vNodes ); + if ( Vec_PtrSize(vNodes) > 128 ) + break; + } + // collect the marked nodes in the topological order + vField = Vec_PtrAlloc( 10 ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pObj, k ) + Sim_CollectNodes_rec( pObj, vField ); + + // simulate these nodes + Sim_SimulateCollected( vTargets, vNodes, vField ); + // prepare for the next loop + Vec_PtrFree( vNodes ); + } + + // clean + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pData = NULL; + return vTargets; +} + +/**Function************************************************************* + + Synopsis [Collects nodes starting from the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + char Entry; + int k; + if ( Abc_NodeIsTravIdCurrent(pRoot) ) + return; + Abc_NodeSetTravIdCurrent( pRoot ); + // save the reached targets + Entry = Vec_StrEntry(vTargets, pRoot->Id); + if ( Entry & 1 ) + Vec_PtrPush( vNodes, Abc_ObjNot(pRoot) ); + if ( Entry & 2 ) + Vec_PtrPush( vNodes, pRoot ); + // explore the fanouts + Abc_ObjForEachFanout( pRoot, pFanout, k ) + Sim_TraverseNodes_rec( pFanout, vTargets, vNodes ); +} + +/**Function************************************************************* + + Synopsis [Collects nodes starting from the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField ) +{ + Abc_Obj_t * pFanin; + int i; + if ( Abc_NodeIsTravIdCurrent(pRoot) ) + return; + if ( !Abc_NodeIsTravIdPrevious(pRoot) ) + return; + Abc_NodeSetTravIdCurrent( pRoot ); + Abc_ObjForEachFanin( pRoot, pFanin, i ) + Sim_CollectNodes_rec( pFanin, vField ); + if ( !Abc_ObjIsCo(pRoot) ) + pRoot->pData = (void *)Vec_PtrSize(vField); + Vec_PtrPush( vField, pRoot ); +} + +/**Function************************************************************* + + Synopsis [Simulate the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField ) +{ + Abc_Obj_t * pObj, * pFanin0, * pFanin1, * pDisproved; + Vec_Ptr_t * vSims; + unsigned * pUnsigned, * pUnsignedF; + int i, k, Phase, fCompl; + // get simulation info + vSims = Sim_UtilInfoAlloc( Vec_PtrSize(vField), Vec_PtrSize(vNodes), 0 ); + // simulate the nodes + Vec_PtrForEachEntry( vField, pObj, i ) + { + if ( Abc_ObjIsCi(pObj) ) + { + pUnsigned = Vec_PtrEntry( vSims, i ); + for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) + pUnsigned[k] = (unsigned)pObj->pCopy; + continue; + } + if ( Abc_ObjIsCo(pObj) ) + { + pUnsigned = Vec_PtrEntry( vSims, i ); + pUnsignedF = Vec_PtrEntry( vSims, (int)Abc_ObjFanin0(pObj)->pData ); + if ( Abc_ObjFaninC0(pObj) ) + for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) + pUnsigned[k] = ~pUnsignedF[k]; + else + for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) + pUnsigned[k] = pUnsignedF[k]; + // update targets + for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) + { + if ( pUnsigned[k] == (unsigned)pObj->pData ) + continue; + pDisproved = Vec_PtrEntry( vNodes, k ); + fCompl = Abc_ObjIsComplement(pDisproved); + pDisproved = Abc_ObjRegular(pDisproved); + Phase = Vec_StrEntry( vTargets, pDisproved->Id ); + if ( fCompl ) + Phase = (Phase & 2); + else + Phase = (Phase & 1); + Vec_StrWriteEntry( vTargets, pDisproved->Id, (char)Phase ); + } + continue; + } + // simulate the node + pFanin0 = Abc_ObjFanin0(pObj); + pFanin1 = Abc_ObjFanin1(pObj); + } +} + + + +/* + { + unsigned uData; + if ( pFanin == Abc_ObjFanin0(pNode) ) + { + uData = (unsigned)Abc_ObjFanin1(pNode)->pData; + uData = Abc_ObjFaninC1(pNode)? ~uData : uData; + } + else if ( pFanin == Abc_ObjFanin1(pNode) ) + { + uData = (unsigned)Abc_ObjFanin0(pNode)->pData; + uData = Abc_ObjFaninC0(pNode)? ~uData : uData; + } + uData ^= (unsigned)pNode->pData; +// Extra_PrintBinary( stdout, &uData, 32 ); printf( "\n" ); + if ( Extra_WordCountOnes(uData) > 8 ) + continue; + } +*/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcSat.c b/abc70930/src/base/abci/abcSat.c new file mode 100644 index 00000000..58614584 --- /dev/null +++ b/abc70930/src/base/abci/abcSat.c @@ -0,0 +1,884 @@ +/**CFile**************************************************************** + + FileName [abcSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to solve the miter using the internal SAT sat_solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "satSolver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes ); +extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); +static nMuxes; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Attempts to solve the miter using an internal SAT sat_solver.] + + Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose, sint64 * pNumConfs, sint64 * pNumInspects ) +{ + sat_solver * pSat; + lbool status; + int RetValue, clk; + + if ( pNumConfs ) + *pNumConfs = 0; + if ( pNumInspects ) + *pNumInspects = 0; + + assert( Abc_NtkLatchNum(pNtk) == 0 ); + +// if ( Abc_NtkPoNum(pNtk) > 1 ) +// fprintf( stdout, "Warning: The miter has %d outputs. SAT will try to prove all of them.\n", Abc_NtkPoNum(pNtk) ); + + // load clauses into the sat_solver + clk = clock(); + pSat = Abc_NtkMiterSatCreate( pNtk, 0 ); + if ( pSat == NULL ) + return 1; +//printf( "%d \n", pSat->clauses.size ); +//sat_solver_delete( pSat ); +//return 1; + +// printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); +// PRT( "Time", clock() - clk ); + + // simplify the problem + clk = clock(); + status = sat_solver_simplify(pSat); +// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); +// PRT( "Time", clock() - clk ); + if ( status == 0 ) + { + sat_solver_delete( pSat ); +// printf( "The problem is UNSATISFIABLE after simplification.\n" ); + return 1; + } + + // solve the miter + clk = clock(); + if ( fVerbose ) + pSat->verbosity = 1; + status = sat_solver_solve( pSat, NULL, NULL, (sint64)nConfLimit, (sint64)nInsLimit, (sint64)0, (sint64)0 ); + if ( status == l_Undef ) + { +// printf( "The problem timed out.\n" ); + RetValue = -1; + } + else if ( status == l_True ) + { +// printf( "The problem is SATISFIABLE.\n" ); + RetValue = 0; + } + else if ( status == l_False ) + { +// printf( "The problem is UNSATISFIABLE.\n" ); + RetValue = 1; + } + else + assert( 0 ); +// PRT( "SAT sat_solver time", clock() - clk ); +// printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts ); + + // if the problem is SAT, get the counterexample + if ( status == l_True ) + { +// Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk ); + Vec_Int_t * vCiIds = Abc_NtkGetCiSatVarNums( pNtk ); + pNtk->pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); + Vec_IntFree( vCiIds ); + } + // free the sat_solver + if ( fVerbose ) + Sat_SolverPrintStats( stdout, pSat ); + + if ( pNumConfs ) + *pNumConfs = (int)pSat->stats.conflicts; + if ( pNumInspects ) + *pNumInspects = (int)pSat->stats.inspects; + +sat_solver_store_write( pSat, "trace.cnf" ); +sat_solver_store_free( pSat ); + + sat_solver_delete( pSat ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Returns the array of CI IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vCiIds; + Abc_Obj_t * pObj; + int i; + vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Vec_IntPush( vCiIds, (int)pObj->pCopy ); + return vCiIds; +} + + + +/**Function************************************************************* + + Synopsis [Adds trivial clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkClauseTriv( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ) +{ +//printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses ); + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) ); +// Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) ); + return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); +} + +/**Function************************************************************* + + Synopsis [Adds trivial clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkClauseTop( sat_solver * pSat, Vec_Ptr_t * vNodes, Vec_Int_t * vVars ) +{ + Abc_Obj_t * pNode; + int i; +//printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses ); + vVars->nSize = 0; + Vec_PtrForEachEntry( vNodes, pNode, i ) + Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) ); +// Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) ); + return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); +} + +/**Function************************************************************* + + Synopsis [Adds trivial clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkClauseAnd( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, Vec_Int_t * vVars ) +{ + int fComp1, Var, Var1, i; +//printf( "Adding AND %d. (%d) %d\n", pNode->Id, vSuper->nSize+1, (int)pSat->sat_solver_stats.clauses ); + + assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_ObjIsNode( pNode ) ); + +// nVars = sat_solver_nvars(pSat); + Var = (int)pNode->pCopy; +// Var = pNode->Id; + +// assert( Var < nVars ); + for ( i = 0; i < vSuper->nSize; i++ ) + { + // get the predecessor nodes + // get the complemented attributes of the nodes + fComp1 = Abc_ObjIsComplement(vSuper->pArray[i]); + // determine the variable numbers + Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->pCopy; +// Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id; + + // check that the variables are in the SAT manager +// assert( Var1 < nVars ); + + // suppose the AND-gate is A * B = C + // add !A => !C or A + !C + // fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 ); + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(Var1, fComp1) ); + Vec_IntPush( vVars, toLitCond(Var, 1 ) ); + if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) + return 0; + } + + // add A & B => C or !A + !B + C +// fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 ); + vVars->nSize = 0; + for ( i = 0; i < vSuper->nSize; i++ ) + { + // get the predecessor nodes + // get the complemented attributes of the nodes + fComp1 = Abc_ObjIsComplement(vSuper->pArray[i]); + // determine the variable numbers + Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->pCopy; +// Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id; + // add this variable to the array + Vec_IntPush( vVars, toLitCond(Var1, !fComp1) ); + } + Vec_IntPush( vVars, toLitCond(Var, 0) ); + return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); +} + +/**Function************************************************************* + + Synopsis [Adds trivial clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkClauseMux( sat_solver * pSat, Abc_Obj_t * pNode, Abc_Obj_t * pNodeC, Abc_Obj_t * pNodeT, Abc_Obj_t * pNodeE, Vec_Int_t * vVars ) +{ + int VarF, VarI, VarT, VarE, fCompT, fCompE; +//printf( "Adding mux %d. %d\n", pNode->Id, (int)pSat->sat_solver_stats.clauses ); + + assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_NodeIsMuxType( pNode ) ); + // get the variable numbers + VarF = (int)pNode->pCopy; + VarI = (int)pNodeC->pCopy; + VarT = (int)Abc_ObjRegular(pNodeT)->pCopy; + VarE = (int)Abc_ObjRegular(pNodeE)->pCopy; +// VarF = (int)pNode->Id; +// VarI = (int)pNodeC->Id; +// VarT = (int)Abc_ObjRegular(pNodeT)->Id; +// VarE = (int)Abc_ObjRegular(pNodeE)->Id; + + // get the complementation flags + fCompT = Abc_ObjIsComplement(pNodeT); + fCompE = Abc_ObjIsComplement(pNodeE); + + // f = ITE(i, t, e) + // i' + t' + f + // i' + t + f' + // i + e' + f + // i + e + f' + // create four clauses + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(VarI, 1) ); + Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) ); + Vec_IntPush( vVars, toLitCond(VarF, 0) ); + if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) + return 0; + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(VarI, 1) ); + Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) ); + Vec_IntPush( vVars, toLitCond(VarF, 1) ); + if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) + return 0; + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(VarI, 0) ); + Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) ); + Vec_IntPush( vVars, toLitCond(VarF, 0) ); + if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) + return 0; + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(VarI, 0) ); + Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) ); + Vec_IntPush( vVars, toLitCond(VarF, 1) ); + if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) + return 0; + + if ( VarT == VarE ) + { +// assert( fCompT == !fCompE ); + return 1; + } + + // two additional clauses + // t' & e' -> f' t + e + f' + // t & e -> f t' + e' + f + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) ); + Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) ); + Vec_IntPush( vVars, toLitCond(VarF, 1) ); + if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) + return 0; + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) ); + Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) ); + Vec_IntPush( vVars, toLitCond(VarF, 0) ); + return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCollectSupergate_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst, int fStopAtMux ) +{ + int RetValue1, RetValue2, i; + // check if the node is visited + if ( Abc_ObjRegular(pNode)->fMarkB ) + { + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pNode ) + return 1; + // check if the node is present in the opposite polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == Abc_ObjNot(pNode) ) + return -1; + assert( 0 ); + return 0; + } + // if the new node is complemented or a PI, another gate begins + if ( !fFirst ) + if ( Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || Abc_ObjFanoutNum(pNode) > 1 || fStopAtMux && Abc_NodeIsMuxType(pNode) ) + { + Vec_PtrPush( vSuper, pNode ); + Abc_ObjRegular(pNode)->fMarkB = 1; + return 0; + } + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + // go through the branches + RetValue1 = Abc_NtkCollectSupergate_rec( Abc_ObjChild0(pNode), vSuper, 0, fStopAtMux ); + RetValue2 = Abc_NtkCollectSupergate_rec( Abc_ObjChild1(pNode), vSuper, 0, fStopAtMux ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCollectSupergate( Abc_Obj_t * pNode, int fStopAtMux, Vec_Ptr_t * vNodes ) +{ + int RetValue, i; + assert( !Abc_ObjIsComplement(pNode) ); + // collect the nodes in the implication supergate + Vec_PtrClear( vNodes ); + RetValue = Abc_NtkCollectSupergate_rec( pNode, vNodes, 1, fStopAtMux ); + assert( vNodes->nSize > 1 ); + // unmark the visited nodes + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vNodes->nSize = 0; +} + + +/**Function************************************************************* + + Synopsis [Computes the factor of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkNodeFactor( Abc_Obj_t * pObj, int nLevelMax ) +{ +// nLevelMax = ((nLevelMax)/2)*3; + assert( (int)pObj->Level <= nLevelMax ); +// return (int)(100000000.0 * pow(0.999, nLevelMax - pObj->Level)); + return (int)(100000000.0 * (1 + 0.01 * pObj->Level)); +// return (int)(100000000.0 / ((nLevelMax)/2)*3 - pObj->Level); +} + +/**Function************************************************************* + + Synopsis [Sets up the SAT sat_solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMiterSatCreateInt( sat_solver * pSat, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pFanin, * pNodeC, * pNodeT, * pNodeE; + Vec_Ptr_t * vNodes, * vSuper; + Vec_Int_t * vVars; + int i, k, fUseMuxes = 1; + int clk1 = clock(); +// int fOrderCiVarsFirst = 0; + int nLevelsMax = Abc_AigLevel(pNtk); + int RetValue = 0; + + assert( Abc_NtkIsStrash(pNtk) ); + + // clean the CI node pointers + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = NULL; + + // start the data structures + vNodes = Vec_PtrAlloc( 1000 ); // the nodes corresponding to vars in the sat_solver + vSuper = Vec_PtrAlloc( 100 ); // the nodes belonging to the given implication supergate + vVars = Vec_IntAlloc( 100 ); // the temporary array for variables in the clause + + // add the clause for the constant node + pNode = Abc_AigConst1(pNtk); + pNode->fMarkA = 1; + pNode->pCopy = (Abc_Obj_t *)vNodes->nSize; + Vec_PtrPush( vNodes, pNode ); + Abc_NtkClauseTriv( pSat, pNode, vVars ); +/* + // add the PI variables first + Abc_NtkForEachCi( pNtk, pNode, i ) + { + pNode->fMarkA = 1; + pNode->pCopy = (Abc_Obj_t *)vNodes->nSize; + Vec_PtrPush( vNodes, pNode ); + } +*/ + // collect the nodes that need clauses and top-level assignments + Vec_PtrClear( vSuper ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + // get the fanin + pFanin = Abc_ObjFanin0(pNode); + // create the node's variable + if ( pFanin->fMarkA == 0 ) + { + pFanin->fMarkA = 1; + pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize; + Vec_PtrPush( vNodes, pFanin ); + } + // add the trivial clause + Vec_PtrPush( vSuper, Abc_ObjChild0(pNode) ); + } + if ( !Abc_NtkClauseTop( pSat, vSuper, vVars ) ) + goto Quits; + + + // add the clauses + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + assert( !Abc_ObjIsComplement(pNode) ); + if ( !Abc_AigNodeIsAnd(pNode) ) + continue; +//printf( "%d ", pNode->Id ); + + // add the clauses + if ( fUseMuxes && Abc_NodeIsMuxType(pNode) ) + { + nMuxes++; + + pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE ); + Vec_PtrClear( vSuper ); + Vec_PtrPush( vSuper, pNodeC ); + Vec_PtrPush( vSuper, pNodeT ); + Vec_PtrPush( vSuper, pNodeE ); + // add the fanin nodes to explore + Vec_PtrForEachEntry( vSuper, pFanin, k ) + { + pFanin = Abc_ObjRegular(pFanin); + if ( pFanin->fMarkA == 0 ) + { + pFanin->fMarkA = 1; + pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize; + Vec_PtrPush( vNodes, pFanin ); + } + } + // add the clauses + if ( !Abc_NtkClauseMux( pSat, pNode, pNodeC, pNodeT, pNodeE, vVars ) ) + goto Quits; + } + else + { + // get the supergate + Abc_NtkCollectSupergate( pNode, fUseMuxes, vSuper ); + // add the fanin nodes to explore + Vec_PtrForEachEntry( vSuper, pFanin, k ) + { + pFanin = Abc_ObjRegular(pFanin); + if ( pFanin->fMarkA == 0 ) + { + pFanin->fMarkA = 1; + pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize; + Vec_PtrPush( vNodes, pFanin ); + } + } + // add the clauses + if ( vSuper->nSize == 0 ) + { + if ( !Abc_NtkClauseTriv( pSat, Abc_ObjNot(pNode), vVars ) ) +// if ( !Abc_NtkClauseTriv( pSat, pNode, vVars ) ) + goto Quits; + } + else + { + if ( !Abc_NtkClauseAnd( pSat, pNode, vSuper, vVars ) ) + goto Quits; + } + } + } +/* + // set preferred variables + if ( fOrderCiVarsFirst ) + { + int * pPrefVars = ALLOC( int, Abc_NtkCiNum(pNtk) ); + int nVars = 0; + Abc_NtkForEachCi( pNtk, pNode, i ) + { + if ( pNode->fMarkA == 0 ) + continue; + pPrefVars[nVars++] = (int)pNode->pCopy; + } + nVars = ABC_MIN( nVars, 10 ); + ASat_SolverSetPrefVars( pSat, pPrefVars, nVars ); + } +*/ + RetValue = 1; +Quits : + // delete + Vec_IntFree( vVars ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vSuper ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Sets up the SAT sat_solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes ) +{ + sat_solver * pSat; + Abc_Obj_t * pNode; + int RetValue, i, clk = clock(); + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsBddLogic(pNtk) ); + if ( Abc_NtkIsBddLogic(pNtk) ) + return Abc_NtkMiterSatCreateLogic(pNtk, fAllPrimes); + + nMuxes = 0; + pSat = sat_solver_new(); +//sat_solver_store_alloc( pSat ); + RetValue = Abc_NtkMiterSatCreateInt( pSat, pNtk ); +sat_solver_store_mark_roots( pSat ); + + Abc_NtkForEachObj( pNtk, pNode, i ) + pNode->fMarkA = 0; +// ASat_SolverWriteDimacs( pSat, "temp_sat.cnf", NULL, NULL, 1 ); + if ( RetValue == 0 ) + { + sat_solver_delete(pSat); + return NULL; + } +// printf( "Ands = %6d. Muxes = %6d (%5.2f %%). ", Abc_NtkNodeNum(pNtk), nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) ); +// PRT( "Creating sat_solver", clock() - clk ); + return pSat; +} + + + + +/**Function************************************************************* + + Synopsis [Adds clauses for the internal node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeAddClauses( sat_solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars ) +{ + Abc_Obj_t * pFanin; + int i, c, nFanins; + int RetValue; + char * pCube; + + nFanins = Abc_ObjFaninNum( pNode ); + assert( nFanins == Abc_SopGetVarNum( pSop0 ) ); + +// if ( nFanins == 0 ) + if ( Cudd_Regular(pNode->pData) == Cudd_ReadOne(pNode->pNtk->pManFunc) ) + { + vVars->nSize = 0; +// if ( Abc_SopIsConst1(pSop1) ) + if ( !Cudd_IsComplement(pNode->pData) ) + Vec_IntPush( vVars, toLit(pNode->Id) ); + else + Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + return 1; + } + + // add clauses for the negative phase + for ( c = 0; ; c++ ) + { + // get the cube + pCube = pSop0 + c * (nFanins + 3); + if ( *pCube == 0 ) + break; + // add the clause + vVars->nSize = 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pCube[i] == '0' ) + Vec_IntPush( vVars, toLit(pFanin->Id) ); + else if ( pCube[i] == '1' ) + Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); + } + Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + } + + // add clauses for the positive phase + for ( c = 0; ; c++ ) + { + // get the cube + pCube = pSop1 + c * (nFanins + 3); + if ( *pCube == 0 ) + break; + // add the clause + vVars->nSize = 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pCube[i] == '0' ) + Vec_IntPush( vVars, toLit(pFanin->Id) ); + else if ( pCube[i] == '1' ) + Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); + } + Vec_IntPush( vVars, toLit(pNode->Id) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds clauses for the PO node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeAddClausesTop( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ) +{ + Abc_Obj_t * pFanin; + int RetValue; + + pFanin = Abc_ObjFanin0(pNode); + if ( Abc_ObjFaninC0(pNode) ) + { + vVars->nSize = 0; + Vec_IntPush( vVars, toLit(pFanin->Id) ); + Vec_IntPush( vVars, toLit(pNode->Id) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + + vVars->nSize = 0; + Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); + Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + } + else + { + vVars->nSize = 0; + Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); + Vec_IntPush( vVars, toLit(pNode->Id) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + + vVars->nSize = 0; + Vec_IntPush( vVars, toLit(pFanin->Id) ); + Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + } + + vVars->nSize = 0; + Vec_IntPush( vVars, toLit(pNode->Id) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Sets up the SAT sat_solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes ) +{ + sat_solver * pSat; + Extra_MmFlex_t * pMmFlex; + Abc_Obj_t * pNode; + Vec_Str_t * vCube; + Vec_Int_t * vVars; + char * pSop0, * pSop1; + int i; + + assert( Abc_NtkIsBddLogic(pNtk) ); + + // transfer the IDs to the copy field + Abc_NtkForEachPi( pNtk, pNode, i ) + pNode->pCopy = (void *)pNode->Id; + + // start the data structures + pSat = sat_solver_new(); +sat_solver_store_alloc( pSat ); + pMmFlex = Extra_MmFlexStart(); + vCube = Vec_StrAlloc( 100 ); + vVars = Vec_IntAlloc( 100 ); + + // add clauses for each internal nodes + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // derive SOPs for both phases of the node + Abc_NodeBddToCnf( pNode, pMmFlex, vCube, fAllPrimes, &pSop0, &pSop1 ); + // add the clauses to the sat_solver + if ( !Abc_NodeAddClauses( pSat, pSop0, pSop1, pNode, vVars ) ) + { + sat_solver_delete( pSat ); + pSat = NULL; + goto finish; + } + } + // add clauses for each PO + Abc_NtkForEachPo( pNtk, pNode, i ) + { + if ( !Abc_NodeAddClausesTop( pSat, pNode, vVars ) ) + { + sat_solver_delete( pSat ); + pSat = NULL; + goto finish; + } + } +sat_solver_store_mark_roots( pSat ); + +finish: + // delete + Vec_StrFree( vCube ); + Vec_IntFree( vVars ); + Extra_MmFlexStop( pMmFlex ); + return pSat; +} + + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcStrash.c b/abc70930/src/base/abci/abcStrash.c new file mode 100644 index 00000000..c77f8dea --- /dev/null +++ b/abc70930/src/base/abci/abcStrash.c @@ -0,0 +1,478 @@ +/**CFile**************************************************************** + + FileName [abcStrash.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Strashing of the current network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "extra.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reapplies structural hashing to the AIG.] + + Description [Because of the structural hashing, this procedure should not + change the number of nodes. It is useful to detect the bugs in the original AIG.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup ) +{ + extern int timeRetime; + Abc_Ntk_t * pNtkAig; + Abc_Obj_t * pObj; + int i, nNodes;//, RetValue; + assert( Abc_NtkIsStrash(pNtk) ); +//timeRetime = clock(); + // print warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" ); + // start the new network (constants and CIs of the old network will point to the their counterparts in the new network) + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // restrash the nodes (assuming a topological order of the old network) + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // finalize the network + Abc_NtkFinalize( pNtk, pNtkAig ); + // print warning about self-feed latches +// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) +// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); + // perform cleanup if requested + if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) + printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkStrash: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } +//timeRetime = clock() - timeRetime; +// if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) ) +// printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue ); + return pNtkAig; + +} + +/**Function************************************************************* + + Synopsis [Reapplies structural hashing to the AIG.] + + Description [Because of the structural hashing, this procedure should not + change the number of nodes. It is useful to detect the bugs in the original AIG.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, bool fCleanup ) +{ + extern int timeRetime; + Abc_Ntk_t * pNtkAig; + Abc_Obj_t * pObj; + int i, nNodes;//, RetValue; + assert( Abc_NtkIsStrash(pNtk) ); +//timeRetime = clock(); + // print warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" ); + // start the new network (constants and CIs of the old network will point to the their counterparts in the new network) + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // complement the 1-values registers + Abc_NtkForEachLatch( pNtk, pObj, i ) + if ( Abc_LatchIsInit1(pObj) ) + Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy); + // restrash the nodes (assuming a topological order of the old network) + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // finalize the network + Abc_NtkFinalize( pNtk, pNtkAig ); + // complement the 1-valued registers + Abc_NtkForEachLatch( pNtkAig, pObj, i ) + if ( Abc_LatchIsInit1(pObj) ) + Abc_ObjXorFaninC( Abc_ObjFanin0(pObj), 0 ); + // set all constant-0 values + Abc_NtkForEachLatch( pNtkAig, pObj, i ) + Abc_LatchSetInit0( pObj ); + + // print warning about self-feed latches +// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) +// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); + // perform cleanup if requested + if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) + printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkStrash: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } +//timeRetime = clock() - timeRetime; +// if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) ) +// printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue ); + return pNtkAig; + +} + +/**Function************************************************************* + + Synopsis [Transforms logic network into structurally hashed AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord ) +{ + Abc_Ntk_t * pNtkAig; + int nNodes; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + // consider the special case when the network is already structurally hashed + if ( Abc_NtkIsStrash(pNtk) ) + return Abc_NtkRestrash( pNtk, fCleanup ); + // convert the node representation in the logic network to the AIG form + if ( !Abc_NtkToAig(pNtk) ) + { + printf( "Converting to AIGs has failed.\n" ); + return NULL; + } + // perform strashing +// Abc_NtkCleanCopy( pNtk ); + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes, fRecord ); + Abc_NtkFinalize( pNtk, pNtkAig ); + // print warning about self-feed latches +// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) +// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); + // perform cleanup if requested + nNodes = fCleanup? Abc_AigCleanup(pNtkAig->pManFunc) : 0; +// if ( nNodes ) +// printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkStrash: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Appends the second network to the first.] + + Description [Modifies the first network by adding the logic of the second. + Performs structural hashing while appending the networks. Does not change + the second network. Returns 0 if the appending failed, 1 otherise.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos ) +{ + Abc_Obj_t * pObj; + char * pName; + int i, nNewCis; + // the first network should be an AIG + assert( Abc_NtkIsStrash(pNtk1) ); + assert( Abc_NtkIsLogic(pNtk2) || Abc_NtkIsStrash(pNtk2) ); + if ( Abc_NtkIsLogic(pNtk2) && !Abc_NtkToAig(pNtk2) ) + { + printf( "Converting to AIGs has failed.\n" ); + return 0; + } + // check that the networks have the same PIs + // reorder PIs of pNtk2 according to pNtk1 + if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1, 1 ) ) + printf( "Abc_NtkAppend(): The union of the network PIs is computed (warning).\n" ); + // perform strashing + nNewCis = 0; + Abc_NtkCleanCopy( pNtk2 ); + if ( Abc_NtkIsStrash(pNtk2) ) + Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtk1); + Abc_NtkForEachCi( pNtk2, pObj, i ) + { + pName = Abc_ObjName(pObj); + pObj->pCopy = Abc_NtkFindCi(pNtk1, Abc_ObjName(pObj)); + if ( pObj->pCopy == NULL ) + { + pObj->pCopy = Abc_NtkDupObj(pNtk1, pObj, 1); + nNewCis++; + } + } + if ( nNewCis ) + printf( "Warning: Procedure Abc_NtkAppend() added %d new CIs.\n", nNewCis ); + // add pNtk2 to pNtk1 while strashing + if ( Abc_NtkIsLogic(pNtk2) ) + Abc_NtkStrashPerform( pNtk2, pNtk1, 1, 0 ); + else + Abc_NtkForEachNode( pNtk2, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtk1->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // add the COs of the second network + if ( fAddPos ) + { + Abc_NtkForEachPo( pNtk2, pObj, i ) + { + Abc_NtkDupObj( pNtk1, pObj, 0 ); + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj->pCopy), NULL ); + } + } + else + { + Abc_Obj_t * pObjOld, * pDriverOld, * pDriverNew; + int fCompl, iNodeId; + // OR the choices + Abc_NtkForEachCo( pNtk2, pObj, i ) + { + iNodeId = Nm_ManFindIdByNameTwoTypes( pNtk1->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI ); + assert( iNodeId >= 0 ); + pObjOld = Abc_NtkObj( pNtk1, iNodeId ); + // derive the new driver + pDriverOld = Abc_ObjChild0( pObjOld ); + pDriverNew = Abc_ObjChild0Copy( pObj ); + pDriverNew = Abc_AigOr( pNtk1->pManFunc, pDriverOld, pDriverNew ); + if ( Abc_ObjRegular(pDriverOld) == Abc_ObjRegular(pDriverNew) ) + continue; + // replace the old driver by the new driver + fCompl = Abc_ObjRegular(pDriverOld)->fPhase ^ Abc_ObjRegular(pDriverNew)->fPhase; + Abc_ObjPatchFanin( pObjOld, Abc_ObjRegular(pDriverOld), Abc_ObjNotCond(Abc_ObjRegular(pDriverNew), fCompl) ); + } + } + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtk1 ) ) + { + printf( "Abc_NtkAppend: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Prepares the network for strashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNodeOld; + int i, clk = clock(); + assert( Abc_NtkIsLogic(pNtkOld) ); + assert( Abc_NtkIsStrash(pNtkNew) ); +// vNodes = Abc_NtkDfs( pNtkOld, fAllNodes ); + vNodes = Abc_NtkDfsIter( pNtkOld, fAllNodes ); +//printf( "Nodes = %d. ", Vec_PtrSize(vNodes) ); +//PRT( "Time", clock() - clk ); + pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNodeOld, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNodeOld->pCopy = Abc_NodeStrash( pNtkNew, pNodeOld, fRecord ); + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Transfers the AIG from one manager into another.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Abc_NodeStrash_rec( pMan, Hop_ObjFanin0(pObj) ); + Abc_NodeStrash_rec( pMan, Hop_ObjFanin1(pObj) ); + pObj->pData = Abc_AigAnd( pMan, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node.] + + Description [Assume the network is in the AIG form] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, int fRecord ) +{ + Hop_Man_t * pMan; + Hop_Obj_t * pRoot; + Abc_Obj_t * pFanin; + int i; + assert( Abc_ObjIsNode(pNodeOld) ); + assert( Abc_NtkHasAig(pNodeOld->pNtk) && !Abc_NtkIsStrash(pNodeOld->pNtk) ); + // get the local AIG manager and the local root node + pMan = pNodeOld->pNtk->pManFunc; + pRoot = pNodeOld->pData; + // check the constant case + if ( Abc_NodeIsConst(pNodeOld) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) ) + return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Hop_IsComplement(pRoot) ); + // perform special case-strashing using the record of AIG subgraphs + if ( fRecord && Abc_NtkRecIsRunning() && Abc_ObjFaninNum(pNodeOld) > 2 && Abc_ObjFaninNum(pNodeOld) <= Abc_NtkRecVarNum() ) + { + extern Vec_Int_t * Abc_NtkRecMemory(); + extern int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars ); + int nVars = Abc_NtkRecVarNum(); + Vec_Int_t * vMemory = Abc_NtkRecMemory(); + unsigned * pTruth = Abc_ConvertAigToTruth( pMan, Hop_Regular(pRoot), nVars, vMemory, 0 ); + assert( Extra_TruthSupportSize(pTruth, nVars) == Abc_ObjFaninNum(pNodeOld) ); // should be swept + if ( Hop_IsComplement(pRoot) ) + Extra_TruthNot( pTruth, pTruth, nVars ); + if ( Abc_NtkRecStrashNode( pNtkNew, pNodeOld, pTruth, nVars ) ) + return pNodeOld->pCopy; + } + // set elementary variables + Abc_ObjForEachFanin( pNodeOld, pFanin, i ) + Hop_IthVar(pMan, i)->pData = pFanin->pCopy; + // strash the AIG of this node + Abc_NodeStrash_rec( pNtkNew->pManFunc, Hop_Regular(pRoot) ); + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + // return the final node + return Abc_ObjNotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + + + + + + + +/**Function************************************************************* + + Synopsis [Copies the topmost levels of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int LevelCut ) +{ + assert( !Abc_ObjIsComplement(pNode) ); + if ( pNode->pCopy ) + return pNode->pCopy; + if ( pNode->Level <= (unsigned)LevelCut ) + return pNode->pCopy = Abc_NtkCreatePi( pNtkNew ); + Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(pNode), LevelCut ); + Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin1(pNode), LevelCut ); + return pNode->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); +} + +/**Function************************************************************* + + Synopsis [Copies the topmost levels of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjNew, * pPoNew; + int LevelCut; + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkCoNum(pNtk) == 1 ); + // get the cutoff level + LevelCut = ABC_MAX( 0, Abc_AigLevel(pNtk) - nLevels ); + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + // create PIs below the cut and nodes above the cut + Abc_NtkCleanCopy( pNtk ); + pObjNew = Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(Abc_NtkPo(pNtk, 0)), LevelCut ); + pObjNew = Abc_ObjNotCond( pObjNew, Abc_ObjFaninC0(Abc_NtkPo(pNtk, 0)) ); + // add the PO node and name + pPoNew = Abc_NtkCreatePo(pNtkNew); + Abc_ObjAddFanin( pPoNew, pObjNew ); + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_ObjAssignName( pPoNew, Abc_ObjName(Abc_NtkPo(pNtk, 0)), NULL ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkTopmost: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcSweep.c b/abc70930/src/base/abci/abcSweep.c new file mode 100644 index 00000000..1ae8745b --- /dev/null +++ b/abc70930/src/base/abci/abcSweep.c @@ -0,0 +1,948 @@ +/**CFile**************************************************************** + + FileName [abcDsd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Technology dependent sweep.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fraig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); +static stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose ); +static void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, bool fVerbose ); +static void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ); +static void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ); +static int Abc_NodeDroppingCost( Abc_Obj_t * pNode ); + +static int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ); +static void Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose ); +static void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, bool fConst0 ); +static void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sweping functionally equivalence nodes.] + + Description [Removes gates with equivalent functionality. Works for + both technology-independent and mapped networks. If the flag is set, + allows adding inverters at the gate outputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ) +{ + Fraig_Params_t Params; + Abc_Ntk_t * pNtkAig; + Fraig_Man_t * pMan; + stmm_table * tEquiv; + Abc_Obj_t * pObj; + int i, fUseTrick; + + assert( !Abc_NtkIsStrash(pNtk) ); + + // save gate assignments + fUseTrick = 0; + if ( Abc_NtkIsMappedLogic(pNtk) ) + { + fUseTrick = 1; + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pNext = pObj->pData; + } + // derive the AIG + pNtkAig = Abc_NtkStrash( pNtk, 0, 1, 0 ); + // reconstruct gate assignments + if ( fUseTrick ) + { + extern void * Abc_FrameReadLibGen(); + Hop_ManStop( pNtk->pManFunc ); + pNtk->pManFunc = Abc_FrameReadLibGen(); + pNtk->ntkFunc = ABC_FUNC_MAP; + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pData = pObj->pNext, pObj->pNext = NULL; + } + + // perform fraiging of the AIG + Fraig_ParamsSetDefault( &Params ); + pMan = Abc_NtkToFraig( pNtkAig, &Params, 0, 0 ); + // cannot use EXDC with FRAIG because it can create classes of equivalent FRAIG nodes + // with representative nodes that do not correspond to the nodes with the current network + + // update FRAIG using EXDC + if ( fExdc ) + { + if ( pNtk->pExdc == NULL ) + printf( "Warning: Networks has no EXDC.\n" ); + else + Abc_NtkFraigSweepUsingExdc( pMan, pNtk ); + } + // assign levels to the nodes of the network + Abc_NtkLevel( pNtk ); + + // collect the classes of equivalent nets + tEquiv = Abc_NtkFraigEquiv( pNtk, fUseInv, fVerbose, fVeryVerbose ); + + // transform the network into the equivalent one + Abc_NtkFraigTransform( pNtk, tEquiv, fUseInv, fVerbose ); + stmm_free_table( tEquiv ); + + // free the manager + Fraig_ManFree( pMan ); + Abc_NtkDelete( pNtkAig ); + + // cleanup the dangling nodes + if ( Abc_NtkHasMapping(pNtk) ) + Abc_NtkCleanup( pNtk, fVerbose ); + else + Abc_NtkSweep( pNtk, fVerbose ); + + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkFraigSweep: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Sweep the network using EXDC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + Fraig_Node_t * gNodeExdc, * gNode, * gNodeRes; + Abc_Obj_t * pNode, * pNodeAig; + int i; + extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkExdc ); + + assert( pNtk->pExdc ); + // derive FRAIG node representing don't-cares in the EXDC network + gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc ); + // update the node pointers + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip the constant input nodes + if ( Abc_ObjFaninNum(pNode) == 0 ) + continue; + // get the strashed node + pNodeAig = pNode->pCopy; + // skip the dangling nodes + if ( pNodeAig == NULL ) + continue; + // get the FRAIG node + gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, Abc_ObjIsComplement(pNodeAig) ); + // perform ANDing with EXDC + gNodeRes = Fraig_NodeAnd( pMan, gNode, Fraig_Not(gNodeExdc) ); + // write the node back + Abc_ObjRegular(pNodeAig)->pCopy = (Abc_Obj_t *)Fraig_NotCond( gNodeRes, Abc_ObjIsComplement(pNodeAig) ); + } +} + +/**Function************************************************************* + + Synopsis [Collects equivalence classses of node in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose ) +{ + Abc_Obj_t * pList, * pNode, * pNodeAig; + Fraig_Node_t * gNode; + Abc_Obj_t ** ppSlot; + stmm_table * tStrash2Net; + stmm_table * tResult; + stmm_generator * gen; + int c, Counter; + + // create mapping of strashed nodes into the corresponding network nodes + tStrash2Net = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); + Abc_NtkForEachNode( pNtk, pNode, c ) + { + // skip the constant input nodes + if ( Abc_ObjFaninNum(pNode) == 0 ) + continue; + // get the strashed node + pNodeAig = pNode->pCopy; + // skip the dangling nodes + if ( pNodeAig == NULL ) + continue; + // skip the nodes that fanout into COs + if ( Abc_NodeFindCoFanout(pNode) ) + continue; + // get the FRAIG node + gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, Abc_ObjIsComplement(pNodeAig) ); + if ( !stmm_find_or_add( tStrash2Net, (char *)Fraig_Regular(gNode), (char ***)&ppSlot ) ) + *ppSlot = NULL; + // add the node to the list + pNode->pNext = *ppSlot; + *ppSlot = pNode; + // mark the node if it is complemented + pNode->fPhase = Fraig_IsComplement(gNode); + } + + // print the classes + c = 0; + Counter = 0; + tResult = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); + stmm_foreach_item( tStrash2Net, gen, (char **)&gNode, (char **)&pList ) + { + // skip the trival classes + if ( pList == NULL || pList->pNext == NULL ) + continue; + // add the non-trival class + stmm_insert( tResult, (char *)pList, NULL ); + // count nodes in the non-trival classes + for ( pNode = pList; pNode; pNode = pNode->pNext ) + Counter++; + + if ( fVeryVerbose ) + { + printf( "Class %2d : {", c ); + for ( pNode = pList; pNode; pNode = pNode->pNext ) + { + pNode->pCopy = NULL; + printf( " %s", Abc_ObjName(pNode) ); + printf( "(%c)", pNode->fPhase? '-' : '+' ); + printf( "(%d)", pNode->Level ); + } + printf( " }\n" ); + c++; + } + } + if ( fVerbose || fVeryVerbose ) + { + printf( "Sweeping stats for network \"%s\":\n", pNtk->pName ); + printf( "Internal nodes = %d. Different functions (up to compl) = %d.\n", Abc_NtkNodeNum(pNtk), stmm_count(tStrash2Net) ); + printf( "Non-trivial classes = %d. Nodes in non-trivial classes = %d.\n", stmm_count(tResult), Counter ); + } + stmm_free_table( tStrash2Net ); + return tResult; +} + + +/**Function************************************************************* + + Synopsis [Transforms the network using the equivalence relation on nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, bool fVerbose ) +{ + stmm_generator * gen; + Abc_Obj_t * pList; + if ( stmm_count(tEquiv) == 0 ) + return; + // merge nodes in the classes + if ( Abc_NtkHasMapping( pNtk ) ) + { + Abc_NtkDelayTrace( pNtk ); + stmm_foreach_item( tEquiv, gen, (char **)&pList, NULL ) + Abc_NtkFraigMergeClassMapped( pNtk, pList, fUseInv, fVerbose ); + } + else + { + stmm_foreach_item( tEquiv, gen, (char **)&pList, NULL ) + Abc_NtkFraigMergeClass( pNtk, pList, fUseInv, fVerbose ); + } +} + + +/**Function************************************************************* + + Synopsis [Transforms the list of one-phase equivalent nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ) +{ + Abc_Obj_t * pListDir, * pListInv; + Abc_Obj_t * pNodeMin, * pNode, * pNext; + float Arrival1, Arrival2; + + assert( pChain ); + assert( pChain->pNext ); + + // divide the nodes into two parts: + // those that need the invertor and those that don't need + pListDir = pListInv = NULL; + for ( pNode = pChain, pNext = pChain->pNext; + pNode; + pNode = pNext, pNext = pNode? pNode->pNext : NULL ) + { + // check to which class the node belongs + if ( pNode->fPhase == 1 ) + { + pNode->pNext = pListDir; + pListDir = pNode; + } + else + { + pNode->pNext = pListInv; + pListInv = pNode; + } + } + + // find the node with the smallest number of logic levels + pNodeMin = pListDir; + for ( pNode = pListDir; pNode; pNode = pNode->pNext ) + { + Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst; + Arrival2 = Abc_NodeReadArrival(pNode )->Worst; +// assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 ); +// assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 ); + if ( Arrival1 > Arrival2 || + Arrival1 == Arrival2 && pNodeMin->Level > pNode->Level || + Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level && + Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) ) + pNodeMin = pNode; + } + + // move the fanouts of the direct nodes + for ( pNode = pListDir; pNode; pNode = pNode->pNext ) + if ( pNode != pNodeMin ) + Abc_ObjTransferFanout( pNode, pNodeMin ); + + // find the node with the smallest number of logic levels + pNodeMin = pListInv; + for ( pNode = pListInv; pNode; pNode = pNode->pNext ) + { + Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst; + Arrival2 = Abc_NodeReadArrival(pNode )->Worst; +// assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 ); +// assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 ); + if ( Arrival1 > Arrival2 || + Arrival1 == Arrival2 && pNodeMin->Level > pNode->Level || + Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level && + Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) ) + pNodeMin = pNode; + } + + // move the fanouts of the direct nodes + for ( pNode = pListInv; pNode; pNode = pNode->pNext ) + if ( pNode != pNodeMin ) + Abc_ObjTransferFanout( pNode, pNodeMin ); +} + +/**Function************************************************************* + + Synopsis [Process one equivalence class of nodes.] + + Description [This function does not remove the nodes. It only switches + around the connections.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ) +{ + Abc_Obj_t * pListDir, * pListInv; + Abc_Obj_t * pNodeMin, * pNodeMinInv; + Abc_Obj_t * pNode, * pNext; + + assert( pChain ); + assert( pChain->pNext ); + + // find the node with the smallest number of logic levels + pNodeMin = pChain; + for ( pNode = pChain->pNext; pNode; pNode = pNode->pNext ) + if ( pNodeMin->Level > pNode->Level || + ( pNodeMin->Level == pNode->Level && + Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) ) ) + pNodeMin = pNode; + + // divide the nodes into two parts: + // those that need the invertor and those that don't need + pListDir = pListInv = NULL; + for ( pNode = pChain, pNext = pChain->pNext; + pNode; + pNode = pNext, pNext = pNode? pNode->pNext : NULL ) + { + if ( pNode == pNodeMin ) + continue; + // check to which class the node belongs + if ( pNodeMin->fPhase == pNode->fPhase ) + { + pNode->pNext = pListDir; + pListDir = pNode; + } + else + { + pNode->pNext = pListInv; + pListInv = pNode; + } + } + + // move the fanouts of the direct nodes + for ( pNode = pListDir; pNode; pNode = pNode->pNext ) + Abc_ObjTransferFanout( pNode, pNodeMin ); + + // skip if there are no inverted nodes + if ( pListInv == NULL ) + return; + + // add the invertor + pNodeMinInv = Abc_NtkCreateNodeInv( pNtk, pNodeMin ); + + // move the fanouts of the inverted nodes + for ( pNode = pListInv; pNode; pNode = pNode->pNext ) + Abc_ObjTransferFanout( pNode, pNodeMinInv ); +} + + +/**Function************************************************************* + + Synopsis [Returns the number of literals saved if this node becomes useless.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeDroppingCost( Abc_Obj_t * pNode ) +{ + return 1; +} + + + + + +/**Function************************************************************* + + Synopsis [Removes dangling nodes.] + + Description [Returns the number of nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + int Counter; + assert( Abc_NtkIsLogic(pNtk) ); + // mark the nodes reachable from the POs + vNodes = Abc_NtkDfs( pNtk, 0 ); + Counter = Abc_NtkReduceNodes( pNtk, vNodes ); + if ( fVerbose ) + printf( "Cleanup removed %d dangling nodes.\n", Counter ); + Vec_PtrFree( vNodes ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Preserves the nodes collected in the array.] + + Description [Returns the number of nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pNode; + int i, Counter; + assert( Abc_NtkIsLogic(pNtk) ); + // mark the nodes reachable from the POs + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkA = 1; + // remove the non-marked nodes + Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( pNode->fMarkA == 0 ) + { + Abc_NtkDeleteObj( pNode ); + Counter++; + } + // unmark the remaining nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkA = 0; + // check + if ( !Abc_NtkCheck( pNtk ) ) + printf( "Abc_NtkCleanup: The network check has failed.\n" ); + return Counter; +} + + + + +/**Function************************************************************* + + Synopsis [Tranditional sweep of the network.] + + Description [Propagates constant and single-input node, removes dangling nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pFanout, * pDriver; + int i, nNodesOld; + assert( Abc_NtkIsLogic(pNtk) ); + // convert network to BDD representation + if ( !Abc_NtkToBdd(pNtk) ) + { + fprintf( stdout, "Converting to BDD has failed.\n" ); + return 1; + } + // perform cleanup + nNodesOld = Abc_NtkNodeNum(pNtk); + Abc_NtkCleanup( pNtk, 0 ); + // prepare nodes for sweeping + Abc_NtkRemoveDupFanins(pNtk); + Abc_NtkMinimumBase(pNtk); + // collect sweepable nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( Abc_ObjFaninNum(pNode) < 2 ) + Vec_PtrPush( vNodes, pNode ); + // sweep the nodes + while ( Vec_PtrSize(vNodes) > 0 ) + { + // get any sweepable node + pNode = Vec_PtrPop(vNodes); + if ( !Abc_ObjIsNode(pNode) ) + continue; + // get any non-CO fanout of this node + pFanout = Abc_NodeFindNonCoFanout(pNode); + if ( pFanout == NULL ) + continue; + assert( Abc_ObjIsNode(pFanout) ); + // transform the function of the fanout + if ( Abc_ObjFaninNum(pNode) == 0 ) + Abc_NodeConstantInput( pFanout, pNode, Abc_NodeIsConst0(pNode) ); + else + { + assert( Abc_ObjFaninNum(pNode) == 1 ); + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_NodeIsInv(pNode) ) + Abc_NodeComplementInput( pFanout, pNode ); + Abc_ObjPatchFanin( pFanout, pNode, pDriver ); + } + Abc_NodeRemoveDupFanins( pFanout ); + Abc_NodeMinimumBase( pFanout ); + // check if the fanout should be added + if ( Abc_ObjFaninNum(pFanout) < 2 ) + Vec_PtrPush( vNodes, pFanout ); + // check if the node has other fanouts + if ( Abc_ObjFanoutNum(pNode) > 0 ) + Vec_PtrPush( vNodes, pNode ); + else + Abc_NtkDeleteObj_rec( pNode, 1 ); + } + Vec_PtrFree( vNodes ); + // sweep a node into its CO fanout if all of this is true: + // (a) this node is a single-input node + // (b) the driver of the node has only one fanout (this node) + // (c) the driver is a node + Abc_NtkForEachCo( pNtk, pFanout, i ) + { + pNode = Abc_ObjFanin0(pFanout); + if ( Abc_ObjFaninNum(pNode) != 1 ) + continue; + pDriver = Abc_ObjFanin0(pNode); + if ( !(Abc_ObjFanoutNum(pDriver) == 1 && Abc_ObjIsNode(pDriver)) ) + continue; + // trasform this CO + if ( Abc_NodeIsInv(pNode) ) + pDriver->pData = Cudd_Not(pDriver->pData); + Abc_ObjPatchFanin( pFanout, pNode, pDriver ); + } + // perform cleanup + Abc_NtkCleanup( pNtk, 0 ); + // report + if ( fVerbose ) + printf( "Sweep removed %d nodes.\n", nNodesOld - Abc_NtkNodeNum(pNtk) ); + return nNodesOld - Abc_NtkNodeNum(pNtk); +} + + +/**Function************************************************************* + + Synopsis [Replaces the local function by its cofactor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, bool fConst0 ) +{ + DdManager * dd = pNode->pNtk->pManFunc; + DdNode * bVar, * bTemp; + int iFanin; + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 ) + { + printf( "Node %s should be among", Abc_ObjName(pFanin) ); + printf( " the fanins of node %s...\n", Abc_ObjName(pNode) ); + return; + } + bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iFanin), fConst0 ); + pNode->pData = Cudd_Cofactor( dd, bTemp = pNode->pData, bVar ); Cudd_Ref( pNode->pData ); + Cudd_RecursiveDeref( dd, bTemp ); +} + +/**Function************************************************************* + + Synopsis [Changes the polarity of one fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) +{ + DdManager * dd = pNode->pNtk->pManFunc; + DdNode * bVar, * bCof0, * bCof1; + int iFanin; + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 ) + { + printf( "Node %s should be among", Abc_ObjName(pFanin) ); + printf( " the fanins of node %s...\n", Abc_ObjName(pNode) ); + return; + } + bVar = Cudd_bddIthVar( dd, iFanin ); + bCof0 = Cudd_Cofactor( dd, pNode->pData, Cudd_Not(bVar) ); Cudd_Ref( bCof0 ); + bCof1 = Cudd_Cofactor( dd, pNode->pData, bVar ); Cudd_Ref( bCof1 ); + Cudd_RecursiveDeref( dd, pNode->pData ); + pNode->pData = Cudd_bddIte( dd, bVar, bCof0, bCof1 ); Cudd_Ref( pNode->pData ); + Cudd_RecursiveDeref( dd, bCof0 ); + Cudd_RecursiveDeref( dd, bCof1 ); +} + + + +/**Function************************************************************* + + Synopsis [Removes all objects whose trav ID is not current.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRemoveNonCurrentObjects( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int Counter, i; + int fVerbose = 0; + + // report on the nodes to be deleted + if ( fVerbose ) + { + printf( "These nodes will be deleted: \n" ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent( pObj ) ) + { + printf( " " ); + Abc_ObjPrint( stdout, pObj ); + } + } + + // delete the nodes + Counter = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent( pObj ) ) + { + Abc_NtkDeleteObj( pObj ); + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Check if the fanin of this latch is a constant.] + + Description [Returns 0/1 if constant; -1 if not a constant.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSetTravId_rec( Abc_Obj_t * pObj ) +{ + Abc_NodeSetTravIdCurrent(pObj); + if ( Abc_ObjFaninNum(pObj) == 0 ) + return; + assert( Abc_ObjFaninNum(pObj) == 1 ); + Abc_NtkSetTravId_rec( Abc_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Check if the fanin of this latch is a constant.] + + Description [Returns 0/1 if constant; -1 if not a constant.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckConstant_rec( Abc_Obj_t * pObj ) +{ + if ( Abc_ObjFaninNum(pObj) == 0 ) + { + if ( !Abc_ObjIsNode(pObj) ) + return -1; + if ( Abc_NodeIsConst0(pObj) ) + return 0; + if ( Abc_NodeIsConst1(pObj) ) + return 1; + assert( 0 ); + return -1; + } + if ( Abc_ObjIsLatch(pObj) || Abc_ObjFaninNum(pObj) > 1 ) + return -1; + if ( !Abc_ObjIsNode(pObj) || Abc_NodeIsBuf(pObj) ) + return Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) ); + if ( Abc_NodeIsInv(pObj) ) + { + int RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) ); + if ( RetValue == 0 ) + return 1; + if ( RetValue == 1 ) + return 0; + return RetValue; + } + assert( 0 ); + return -1; +} + +/**Function************************************************************* + + Synopsis [Removes redundant latches.] + + Description [The redundant latches are of two types: + - Latches fed by a constant which matches the init value of the latch. + - Latches fed by a constant which does not match the init value of the latch + can be all replaced by one latch.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLatchSweep( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pFanin, * pLatch, * pLatchPivot = NULL; + int Counter, RetValue, i; + Counter = 0; + // go through the latches + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + // check if the latch has constant input + RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pLatch) ); + if ( RetValue == -1 ) + continue; + // found a latch with constant fanin + if ( (RetValue == 1 && Abc_LatchIsInit0(pLatch)) || + (RetValue == 0 && Abc_LatchIsInit1(pLatch)) ) + { + // fanin constant differs from the latch init value + if ( pLatchPivot == NULL ) + { + pLatchPivot = pLatch; + continue; + } + if ( Abc_LatchInit(pLatch) != Abc_LatchInit(pLatchPivot) ) // add inverter + pFanin = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanout0(pLatchPivot) ); + else + pFanin = Abc_ObjFanout0(pLatchPivot); + } + else + pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); + // replace latch + Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pFanin ); + // delete the extra nodes + Abc_NtkDeleteObj_rec( Abc_ObjFanout0(pLatch), 0 ); + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Replaces autonumnous logic by free inputs.] + + Description [Assumes that non-autonomous logic is marked with + the current ID.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkReplaceAutonomousLogic( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pFanin; + Vec_Ptr_t * vNodes; + int i, k, Counter; + // collect the nodes that feed into the reachable logic + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachObj( pNtk, pNode, i ) + { + // skip non-visited fanins + if ( !Abc_NodeIsTravIdCurrent(pNode) ) + continue; + // look for non-visited fanins + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + // skip visited fanins + if ( Abc_NodeIsTravIdCurrent(pFanin) ) + continue; + // skip constants and latches fed by constants + if ( Abc_NtkCheckConstant_rec(pFanin) != -1 || + (Abc_ObjIsBo(pFanin) && Abc_NtkCheckConstant_rec(Abc_ObjFanin0(Abc_ObjFanin0(pFanin))) != -1) ) + { + Abc_NtkSetTravId_rec( pFanin ); + continue; + } + assert( !Abc_ObjIsLatch(pFanin) ); + Vec_PtrPush( vNodes, pFanin ); + } + } + Vec_PtrUniqify( vNodes, Abc_ObjPointerCompare ); + // replace these nodes by the PIs + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + pFanin = Abc_NtkCreatePi(pNtk); + Abc_ObjAssignName( pFanin, Abc_ObjName(pFanin), NULL ); + Abc_NodeSetTravIdCurrent( pFanin ); + Abc_ObjTransferFanout( pNode, pFanin ); + } + Counter = Vec_PtrSize(vNodes); + Vec_PtrFree( vNodes ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Sequential cleanup.] + + Description [Performs three tasks: + - Removes logic that does not feed into POs. + - Removes latches driven by constant values equal to the initial state. + - Replaces the autonomous components by additional PI variables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + int Counter; + assert( Abc_NtkIsLogic(pNtk) ); + // mark the nodes reachable from the POs + vNodes = Abc_NtkDfsSeq( pNtk ); + Vec_PtrFree( vNodes ); + // remove the non-marked nodes + Counter = Abc_NodeRemoveNonCurrentObjects( pNtk ); + if ( fVerbose ) + printf( "Cleanup removed %4d dangling objects.\n", Counter ); + // check if some of the latches can be removed + if ( fLatchSweep ) + { + Counter = Abc_NtkLatchSweep( pNtk ); + if ( fVerbose ) + printf( "Cleanup removed %4d redundant latches.\n", Counter ); + } + // detect the autonomous components + if ( fAutoSweep ) + { + vNodes = Abc_NtkDfsSeqReverse( pNtk ); + Vec_PtrFree( vNodes ); + // replace them by PIs + Counter = Abc_NtkReplaceAutonomousLogic( pNtk ); + if ( fVerbose ) + printf( "Cleanup added %4d additional PIs.\n", Counter ); + // remove the non-marked nodes + Counter = Abc_NodeRemoveNonCurrentObjects( pNtk ); + if ( fVerbose ) + printf( "Cleanup removed %4d autonomous objects.\n", Counter ); + } + // check + if ( !Abc_NtkCheck( pNtk ) ) + printf( "Abc_NtkCleanupSeq: The network check has failed.\n" ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcSymm.c b/abc70930/src/base/abci/abcSymm.c new file mode 100644 index 00000000..0f76065c --- /dev/null +++ b/abc70930/src/base/abci/abcSymm.c @@ -0,0 +1,229 @@ +/**CFile**************************************************************** + + FileName [abcSymm.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Computation of two-variable symmetries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcSymm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose ); +static void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose ); +static void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose ); +static void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [The top level procedure to compute symmetries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose ) +{ + if ( fUseBdds || fNaive ) + Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fReorder, fVerbose ); + else + Abc_NtkSymmetriesUsingSandS( pNtk, fVerbose ); +} + +/**Function************************************************************* + + Synopsis [Symmetry computation using simulation and SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose ) +{ + extern int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose ); + int nSymms = Sim_ComputeTwoVarSymms( pNtk, fVerbose ); + printf( "The total number of symmetries is %d.\n", nSymms ); +} + +/**Function************************************************************* + + Synopsis [Symmetry computation using BDDs (both naive and smart).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose ) +{ + DdManager * dd; + int clk, clkBdd, clkSym; + int fGarbCollect = 1; + + // compute the global functions +clk = clock(); + dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, fReorder, fVerbose ); + printf( "Shared BDD size = %d nodes.\n", Abc_NtkSizeOfGlobalBdds(pNtk) ); + Cudd_AutodynDisable( dd ); + if ( !fGarbCollect ) + Cudd_DisableGarbageCollection( dd ); + Cudd_zddVarsFromBddVars( dd, 2 ); +clkBdd = clock() - clk; + // create the collapsed network +clk = clock(); + Ntk_NetworkSymmsBdd( dd, pNtk, fNaive, fVerbose ); +clkSym = clock() - clk; + // undo the global functions + Abc_NtkFreeGlobalBdds( pNtk, 1 ); +printf( "Statistics of BDD-based symmetry detection:\n" ); +printf( "Algorithm = %s. Reordering = %s. Garbage collection = %s.\n", + fNaive? "naive" : "fast", fReorder? "yes" : "no", fGarbCollect? "yes" : "no" ); +PRT( "Constructing BDDs", clkBdd ); +PRT( "Computing symms ", clkSym ); +PRT( "TOTAL ", clkBdd + clkSym ); +} + +/**Function************************************************************* + + Synopsis [Symmetry computation using BDDs (both naive and smart).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose ) +{ + Extra_SymmInfo_t * pSymms; + Abc_Obj_t * pNode; + DdNode * bFunc; + int nSymms = 0; + int nSupps = 0; + int i; + + // compute symmetry info for each PO + Abc_NtkForEachCo( pNtk, pNode, i ) + { +// bFunc = pNtk->vFuncsGlob->pArray[i]; + bFunc = Abc_ObjGlobalBdd( pNode ); + nSupps += Cudd_SupportSize( dd, bFunc ); + if ( Cudd_IsConstant(bFunc) ) + continue; + if ( fNaive ) + pSymms = Extra_SymmPairsComputeNaive( dd, bFunc ); + else + pSymms = Extra_SymmPairsCompute( dd, bFunc ); + nSymms += pSymms->nSymms; + if ( fVerbose ) + { + printf( "Output %6s (%d): ", Abc_ObjName(pNode), pSymms->nSymms ); + Ntk_NetworkSymmsPrint( pNtk, pSymms ); + } +//Extra_SymmPairsPrint( pSymms ); + Extra_SymmPairsDissolve( pSymms ); + } + printf( "Total number of vars in functional supports = %8d.\n", nSupps ); + printf( "Total number of two-variable symmetries = %8d.\n", nSymms ); +} + +/**Function************************************************************* + + Synopsis [Printing symmetry groups from the symmetry data structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms ) +{ + char ** pInputNames; + int * pVarTaken; + int i, k, nVars, nSize, fStart; + + // get variable names + nVars = Abc_NtkCiNum(pNtk); + pInputNames = Abc_NtkCollectCioNames( pNtk, 0 ); + + // alloc the array of marks + pVarTaken = ALLOC( int, nVars ); + memset( pVarTaken, 0, sizeof(int) * nVars ); + + // print the groups + fStart = 1; + nSize = pSymms->nVars; + for ( i = 0; i < nSize; i++ ) + { + // skip the variable already considered + if ( pVarTaken[i] ) + continue; + // find all the vars symmetric with this one + for ( k = 0; k < nSize; k++ ) + { + if ( k == i ) + continue; + if ( pSymms->pSymms[i][k] == 0 ) + continue; + // vars i and k are symmetric + assert( pVarTaken[k] == 0 ); + // there is a new symmetry pair + if ( fStart == 1 ) + { // start a new symmetry class + fStart = 0; + printf( " { %s", pInputNames[ pSymms->pVars[i] ] ); + // mark the var as taken + pVarTaken[i] = 1; + } + printf( " %s", pInputNames[ pSymms->pVars[k] ] ); + // mark the var as taken + pVarTaken[k] = 1; + } + if ( fStart == 0 ) + { + printf( " }" ); + fStart = 1; + } + } + printf( "\n" ); + + free( pInputNames ); + free( pVarTaken ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcTiming.c b/abc70930/src/base/abci/abcTiming.c new file mode 100644 index 00000000..967e4617 --- /dev/null +++ b/abc70930/src/base/abci/abcTiming.c @@ -0,0 +1,905 @@ +/**CFile**************************************************************** + + FileName [abcTiming.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Computation of timing info for mapped circuits.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcTiming.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Abc_ManTime_t_ +{ + Abc_Time_t tArrDef; + Abc_Time_t tReqDef; + Vec_Ptr_t * vArrs; + Vec_Ptr_t * vReqs; +}; + +// static functions +static Abc_ManTime_t * Abc_ManTimeStart(); +static void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive ); +void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk ); + +void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode ); + +// accessing the arrival and required times of a node +static inline Abc_Time_t * Abc_NodeArrival( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vArrs->pArray[pNode->Id]; } +static inline Abc_Time_t * Abc_NodeRequired( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vReqs->pArray[pNode->Id]; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the arrival time of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode ) +{ + assert( pNode->pNtk->pManTime ); + return Abc_NodeArrival(pNode); +} + +/**Function************************************************************* + + Synopsis [Reads the arrival time of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode ) +{ + assert( pNode->pNtk->pManTime ); + return Abc_NodeRequired(pNode); +} + +/**Function************************************************************* + + Synopsis [Reads the arrival time of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk ) +{ + assert( pNtk->pManTime ); + return &pNtk->pManTime->tArrDef; +} + +/**Function************************************************************* + + Synopsis [Reads the arrival time of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk ) +{ + assert( pNtk->pManTime ); + return &pNtk->pManTime->tReqDef; +} + +/**Function************************************************************* + + Synopsis [Sets the default arrival time for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall ) +{ + if ( Rise == 0.0 && Fall == 0.0 ) + return; + if ( pNtk->pManTime == NULL ) + pNtk->pManTime = Abc_ManTimeStart(); + pNtk->pManTime->tArrDef.Rise = Rise; + pNtk->pManTime->tArrDef.Fall = Fall; + pNtk->pManTime->tArrDef.Worst = ABC_MAX( Rise, Fall ); +} + +/**Function************************************************************* + + Synopsis [Sets the default arrival time for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall ) +{ + if ( Rise == 0.0 && Fall == 0.0 ) + return; + if ( pNtk->pManTime == NULL ) + pNtk->pManTime = Abc_ManTimeStart(); + pNtk->pManTime->tReqDef.Rise = Rise; + pNtk->pManTime->tReqDef.Rise = Fall; + pNtk->pManTime->tReqDef.Worst = ABC_MAX( Rise, Fall ); +} + +/**Function************************************************************* + + Synopsis [Sets the arrival time for an object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ) +{ + Vec_Ptr_t * vTimes; + Abc_Time_t * pTime; + if ( pNtk->pManTime == NULL ) + pNtk->pManTime = Abc_ManTimeStart(); + if ( pNtk->pManTime->tArrDef.Rise == Rise && pNtk->pManTime->tArrDef.Fall == Fall ) + return; + Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 ); + // set the arrival time + vTimes = pNtk->pManTime->vArrs; + pTime = vTimes->pArray[ObjId]; + pTime->Rise = Rise; + pTime->Fall = Rise; + pTime->Worst = ABC_MAX( Rise, Fall ); +} + +/**Function************************************************************* + + Synopsis [Sets the arrival time for an object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ) +{ + Vec_Ptr_t * vTimes; + Abc_Time_t * pTime; + if ( pNtk->pManTime == NULL ) + pNtk->pManTime = Abc_ManTimeStart(); + if ( pNtk->pManTime->tReqDef.Rise == Rise && pNtk->pManTime->tReqDef.Fall == Fall ) + return; + Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 ); + // set the required time + vTimes = pNtk->pManTime->vReqs; + pTime = vTimes->pArray[ObjId]; + pTime->Rise = Rise; + pTime->Fall = Rise; + pTime->Worst = ABC_MAX( Rise, Fall ); +} + +/**Function************************************************************* + + Synopsis [Finalizes the timing manager after setting arr/req times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + Abc_Time_t ** ppTimes, * pTime; + int i; + if ( pNtk->pManTime == NULL ) + return; + Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 ); + // set the default timing + ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; + Abc_NtkForEachPi( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + if ( pTime->Worst != -ABC_INFINITY ) + continue; + *pTime = pNtk->pManTime->tArrDef; + } + // set the default timing + ppTimes = (Abc_Time_t **)pNtk->pManTime->vReqs->pArray; + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + if ( pTime->Worst != -ABC_INFINITY ) + continue; + *pTime = pNtk->pManTime->tReqDef; + } + // set the 0 arrival times for latch outputs and constant nodes + ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; + Abc_NtkForEachLatchOutput( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + pTime->Fall = pTime->Rise = pTime->Worst = 0.0; + } +} + +/**Function************************************************************* + + Synopsis [Prepares the timing manager for delay trace.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + Abc_Time_t ** ppTimes, * pTime; + int i; + // if there is no timing manager, allocate and initialize + if ( pNtk->pManTime == NULL ) + { + pNtk->pManTime = Abc_ManTimeStart(); + Abc_NtkTimeInitialize( pNtk ); + return; + } + // if timing manager is given, expand it if necessary + Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 ); + // clean arrivals except for PIs + ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY; + } + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY; + } + // clean required except for POs +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ManTime_t * Abc_ManTimeStart() +{ + Abc_ManTime_t * p; + p = ALLOC( Abc_ManTime_t, 1 ); + memset( p, 0, sizeof(Abc_ManTime_t) ); + p->vArrs = Vec_PtrAlloc( 0 ); + p->vReqs = Vec_PtrAlloc( 0 ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManTimeStop( Abc_ManTime_t * p ) +{ + if ( p->vArrs->nSize > 0 ) + { + free( p->vArrs->pArray[0] ); + Vec_PtrFree( p->vArrs ); + } + if ( p->vReqs->nSize > 0 ) + { + free( p->vReqs->pArray[0] ); + Vec_PtrFree( p->vReqs ); + } + free( p ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the timing manager with the PI/PO timing info.] + + Description [The PIs/POs of the new network should be allocated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj; + Abc_Time_t ** ppTimesOld, ** ppTimesNew; + int i; + if ( pNtkOld->pManTime == NULL ) + return; + assert( Abc_NtkPiNum(pNtkOld) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtkOld) == Abc_NtkPoNum(pNtkNew) ); + assert( Abc_NtkLatchNum(pNtkOld) == Abc_NtkLatchNum(pNtkNew) ); + // create the new timing manager + pNtkNew->pManTime = Abc_ManTimeStart(); + Abc_ManTimeExpand( pNtkNew->pManTime, Abc_NtkObjNumMax(pNtkNew), 0 ); + // set the default timing + pNtkNew->pManTime->tArrDef = pNtkOld->pManTime->tArrDef; + pNtkNew->pManTime->tReqDef = pNtkOld->pManTime->tReqDef; + // set the CI timing + ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vArrs->pArray; + ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vArrs->pArray; + Abc_NtkForEachCi( pNtkOld, pObj, i ) + *ppTimesNew[ Abc_NtkCi(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ]; + // set the CO timing + ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vReqs->pArray; + ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vReqs->pArray; + Abc_NtkForEachCo( pNtkOld, pObj, i ) + *ppTimesNew[ Abc_NtkCo(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ]; +} + +/**Function************************************************************* + + Synopsis [Expends the storage for timing information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive ) +{ + Vec_Ptr_t * vTimes; + Abc_Time_t * ppTimes, * ppTimesOld, * pTime; + int nSizeOld, nSizeNew, i; + + nSizeOld = p->vArrs->nSize; + if ( nSizeOld >= nSize ) + return; + nSizeNew = fProgressive? 2 * nSize : nSize; + if ( nSizeNew < 100 ) + nSizeNew = 100; + + vTimes = p->vArrs; + Vec_PtrGrow( vTimes, nSizeNew ); + vTimes->nSize = nSizeNew; + ppTimesOld = ( nSizeOld == 0 )? NULL : vTimes->pArray[0]; + ppTimes = REALLOC( Abc_Time_t, ppTimesOld, nSizeNew ); + for ( i = 0; i < nSizeNew; i++ ) + vTimes->pArray[i] = ppTimes + i; + for ( i = nSizeOld; i < nSizeNew; i++ ) + { + pTime = vTimes->pArray[i]; + pTime->Rise = -ABC_INFINITY; + pTime->Fall = -ABC_INFINITY; + pTime->Worst = -ABC_INFINITY; + } + + vTimes = p->vReqs; + Vec_PtrGrow( vTimes, nSizeNew ); + vTimes->nSize = nSizeNew; + ppTimesOld = ( nSizeOld == 0 )? NULL : vTimes->pArray[0]; + ppTimes = REALLOC( Abc_Time_t, ppTimesOld, nSizeNew ); + for ( i = 0; i < nSizeNew; i++ ) + vTimes->pArray[i] = ppTimes + i; + for ( i = nSizeOld; i < nSizeNew; i++ ) + { + pTime = vTimes->pArray[i]; + pTime->Rise = -ABC_INFINITY; + pTime->Fall = -ABC_INFINITY; + pTime->Worst = -ABC_INFINITY; + } +} + + + + + + +/**Function************************************************************* + + Synopsis [Sets the CI node levels according to the arrival info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtkOld ) +{ + Abc_Obj_t * pNodeOld, * pNodeNew; + float tAndDelay; + int i; + if ( pNtkOld->pManTime == NULL ) + return; + if ( Mio_LibraryReadNand2(Abc_FrameReadLibGen()) == NULL ) + return; + tAndDelay = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen()); + Abc_NtkForEachPi( pNtkOld, pNodeOld, i ) + { + pNodeNew = pNodeOld->pCopy; + pNodeNew->Level = (int)(Abc_NodeArrival(pNodeOld)->Worst / tAndDelay); + } +} + +/**Function************************************************************* + + Synopsis [Sets the CI node levels according to the arrival info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk ) +{ + Abc_Time_t * p; + Abc_Obj_t * pNode; + int i; + p = ALLOC( Abc_Time_t, Abc_NtkCiNum(pNtk) ); + memset( p, 0, sizeof(Abc_Time_t) * Abc_NtkCiNum(pNtk) ); + if ( pNtk->pManTime == NULL ) + return p; + // set the PI arrival times + Abc_NtkForEachPi( pNtk, pNode, i ) + p[i] = *Abc_NodeArrival(pNode); + return p; +} + + +/**Function************************************************************* + + Synopsis [Sets the CI node levels according to the arrival info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk ) +{ + float * p; + Abc_Obj_t * pNode; + int i; + p = ALLOC( float, Abc_NtkCiNum(pNtk) ); + memset( p, 0, sizeof(float) * Abc_NtkCiNum(pNtk) ); + if ( pNtk->pManTime == NULL ) + return p; + // set the PI arrival times + Abc_NtkForEachPi( pNtk, pNode, i ) + p[i] = Abc_NodeArrival(pNode)->Worst; + return p; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pDriver; + Vec_Ptr_t * vNodes; + Abc_Time_t * pTime; + float tArrivalMax; + int i; + + assert( Abc_NtkIsMappedLogic(pNtk) ); + + Abc_NtkTimePrepare( pNtk ); + vNodes = Abc_NtkDfs( pNtk, 1 ); + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_NodeDelayTraceArrival( vNodes->pArray[i] ); + Vec_PtrFree( vNodes ); + + // get the latest arrival times + tArrivalMax = -ABC_INFINITY; + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pDriver = Abc_ObjFanin0(pNode); + pTime = Abc_NodeArrival(pDriver); + if ( tArrivalMax < pTime->Worst ) + tArrivalMax = pTime->Worst; + } + return tArrivalMax; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + Abc_Time_t * pTimeIn, * pTimeOut; + float tDelayBlockRise, tDelayBlockFall; + Mio_PinPhase_t PinPhase; + Mio_Pin_t * pPin; + int i; + + // start the arrival time of the node + pTimeOut = Abc_NodeArrival(pNode); + pTimeOut->Rise = pTimeOut->Fall = -ABC_INFINITY; + // go through the pins of the gate + pPin = Mio_GateReadPins(pNode->pData); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + pTimeIn = Abc_NodeArrival(pFanin); + // get the interesting parameters of this pin + PinPhase = Mio_PinReadPhase(pPin); + tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); + tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin ); + // compute the arrival times of the positive phase + if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present + { + if ( pTimeOut->Rise < pTimeIn->Rise + tDelayBlockRise ) + pTimeOut->Rise = pTimeIn->Rise + tDelayBlockRise; + if ( pTimeOut->Fall < pTimeIn->Fall + tDelayBlockFall ) + pTimeOut->Fall = pTimeIn->Fall + tDelayBlockFall; + } + if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present + { + if ( pTimeOut->Rise < pTimeIn->Fall + tDelayBlockRise ) + pTimeOut->Rise = pTimeIn->Fall + tDelayBlockRise; + if ( pTimeOut->Fall < pTimeIn->Rise + tDelayBlockFall ) + pTimeOut->Fall = pTimeIn->Rise + tDelayBlockFall; + } + pPin = Mio_PinReadNext(pPin); + } + pTimeOut->Worst = ABC_MAX( pTimeOut->Rise, pTimeOut->Fall ); +} + + + + +/**Function************************************************************* + + Synopsis [Computes the level of the node using its fanin levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjLevelNew( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i, Level = 0; + Abc_ObjForEachFanin( pObj, pFanin, i ) + Level = ABC_MAX( Level, Abc_ObjLevel(pFanin) ); + return Level + 1; +} + +/**Function************************************************************* + + Synopsis [Computes the reverse level of the node using its fanout levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i, LevelCur, Level = 0; + Abc_ObjForEachFanout( pObj, pFanout, i ) + { + LevelCur = Abc_ObjReverseLevel( pFanout ); + Level = ABC_MAX( Level, LevelCur ); + } + return Level + 1; +} + +/**Function************************************************************* + + Synopsis [Returns required level of the node.] + + Description [Converts the reverse levels of the node into its required + level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjRequiredLevel( Abc_Obj_t * pObj ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + assert( pNtk->vLevelsR ); + return pNtk->LevelMax + 1 - Abc_ObjReverseLevel(pObj); +} + +/**Function************************************************************* + + Synopsis [Returns the reverse level of the node.] + + Description [The reverse level is the level of the node in reverse + topological order, starting from the COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjReverseLevel( Abc_Obj_t * pObj ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + assert( pNtk->vLevelsR ); + Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 ); + return Vec_IntEntry(pNtk->vLevelsR, pObj->Id); +} + +/**Function************************************************************* + + Synopsis [Sets the reverse level of the node.] + + Description [The reverse level is the level of the node in reverse + topological order, starting from the COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + assert( pNtk->vLevelsR ); + Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 ); + Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, LevelR ); +} + +/**Function************************************************************* + + Synopsis [Prepares for the computation of required levels.] + + Description [This procedure should be called before the required times + are used. It starts internal data structures, which records the level + from the COs of the network nodes in reverse topologogical order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + // remember the maximum number of direct levels + pNtk->LevelMax = Abc_NtkLevel(pNtk) + nMaxLevelIncrease; + // start the reverse levels + pNtk->vLevelsR = Vec_IntAlloc( 0 ); + Vec_IntFill( pNtk->vLevelsR, 1 + Abc_NtkObjNumMax(pNtk), 0 ); + // compute levels in reverse topological order + vNodes = Abc_NtkDfsReverse( pNtk ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + Abc_ObjSetReverseLevel( pObj, Abc_ObjReverseLevelNew(pObj) ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Cleans the data structures used to compute required levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk ) +{ + assert( pNtk->vLevelsR ); + Vec_IntFree( pNtk->vLevelsR ); + pNtk->vLevelsR = NULL; + pNtk->LevelMax = 0; + +} + +/**Function************************************************************* + + Synopsis [Incrementally updates level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) +{ + Abc_Obj_t * pFanout, * pTemp; + int LevelOld, Lev, k, m; + // check if level has changed + LevelOld = Abc_ObjLevel(pObjNew); + if ( LevelOld == Abc_ObjLevelNew(pObjNew) ) + return; + // start the data structure for level update + // we cannot fail to visit a node when using this structure because the + // nodes are stored by their _old_ levels, which are assumed to be correct + Vec_VecClear( vLevels ); + Vec_VecPush( vLevels, LevelOld, pObjNew ); + pObjNew->fMarkA = 1; + // recursively update level + Vec_VecForEachEntryStart( vLevels, pTemp, Lev, k, LevelOld ) + { + pTemp->fMarkA = 0; + assert( Abc_ObjLevel(pTemp) == Lev ); + Abc_ObjSetLevel( pTemp, Abc_ObjLevelNew(pTemp) ); + // if the level did not change, no need to check the fanout levels + if ( Abc_ObjLevel(pTemp) == Lev ) + continue; + // schedule fanout for level update + Abc_ObjForEachFanout( pTemp, pFanout, m ) + { + if ( !Abc_ObjIsCo(pFanout) && !pFanout->fMarkA ) + { + assert( Abc_ObjLevel(pFanout) >= Lev ); + Vec_VecPush( vLevels, Abc_ObjLevel(pFanout), pFanout ); + pFanout->fMarkA = 1; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Incrementally updates level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) +{ + Abc_Obj_t * pFanin, * pTemp; + int LevelOld, LevFanin, Lev, k, m; + // check if level has changed + LevelOld = Abc_ObjReverseLevel(pObjNew); + if ( LevelOld == Abc_ObjReverseLevelNew(pObjNew) ) + return; + // start the data structure for level update + // we cannot fail to visit a node when using this structure because the + // nodes are stored by their _old_ levels, which are assumed to be correct + Vec_VecClear( vLevels ); + Vec_VecPush( vLevels, LevelOld, pObjNew ); + pObjNew->fMarkA = 1; + // recursively update level + Vec_VecForEachEntryStart( vLevels, pTemp, Lev, k, LevelOld ) + { + pTemp->fMarkA = 0; + LevelOld = Abc_ObjReverseLevel(pTemp); + assert( LevelOld == Lev ); + Abc_ObjSetReverseLevel( pTemp, Abc_ObjReverseLevelNew(pTemp) ); + // if the level did not change, no need to check the fanout levels + if ( Abc_ObjReverseLevel(pTemp) == Lev ) + continue; + // schedule fanins for level update + Abc_ObjForEachFanin( pTemp, pFanin, m ) + { + if ( !Abc_ObjIsCi(pFanin) && !pFanin->fMarkA ) + { + LevFanin = Abc_ObjReverseLevel( pFanin ); + assert( LevFanin >= Lev ); + Vec_VecPush( vLevels, LevFanin, pFanin ); + pFanin->fMarkA = 1; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Replaces the node and incrementally updates levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) +{ + // replace the old node by the new node + pObjNew->Level = pObj->Level; + Abc_ObjReplace( pObj, pObjNew ); + // update the level of the node + Abc_NtkUpdateLevel( pObjNew, vLevels ); + Abc_ObjSetReverseLevel( pObjNew, 0 ); + Abc_NtkUpdateReverseLevel( pObjNew, vLevels ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcUnate.c b/abc70930/src/base/abci/abcUnate.c new file mode 100644 index 00000000..20804d19 --- /dev/null +++ b/abc70930/src/base/abci/abcUnate.c @@ -0,0 +1,155 @@ +/**CFile**************************************************************** + + FileName [abcUnate.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcUnate.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose ); +static void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Detects unate variables of the multi-output function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose ) +{ + if ( fUseBdds || fUseNaive ) + Abc_NtkPrintUnateBdd( pNtk, fUseNaive, fVerbose ); + else + Abc_NtkPrintUnateSat( pNtk, fVerbose ); +} + +/**Function************************************************************* + + Synopsis [Detects unate variables using BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose ) +{ + Abc_Obj_t * pNode; + Extra_UnateInfo_t * p; + DdManager * dd; // the BDD manager used to hold shared BDDs +// DdNode ** pbGlobal; // temporary storage for global BDDs + int TotalSupps = 0; + int TotalUnate = 0; + int i, clk = clock(); + int clkBdd, clkUnate; + + // compute the global BDDs + dd = Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose); + if ( dd == NULL ) + return; +clkBdd = clock() - clk; + + // get information about the network +// dd = pNtk->pManGlob; +// dd = Abc_NtkGlobalBddMan( pNtk ); +// pbGlobal = (DdNode **)Vec_PtrArray( pNtk->vFuncsGlob ); + + // print the size of the BDDs + printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // perform naive BDD-based computation + if ( fUseNaive ) + { + Abc_NtkForEachCo( pNtk, pNode, i ) + { +// p = Extra_UnateComputeSlow( dd, pbGlobal[i] ); + p = Extra_UnateComputeSlow( dd, Abc_ObjGlobalBdd(pNode) ); + if ( fVerbose ) + Extra_UnateInfoPrint( p ); + TotalSupps += p->nVars; + TotalUnate += p->nUnate; + Extra_UnateInfoDissolve( p ); + } + } + // perform smart BDD-based computation + else + { + // create ZDD variables in the manager + Cudd_zddVarsFromBddVars( dd, 2 ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { +// p = Extra_UnateComputeFast( dd, pbGlobal[i] ); + p = Extra_UnateComputeFast( dd, Abc_ObjGlobalBdd(pNode) ); + if ( fVerbose ) + Extra_UnateInfoPrint( p ); + TotalSupps += p->nVars; + TotalUnate += p->nUnate; + Extra_UnateInfoDissolve( p ); + } + } +clkUnate = clock() - clk - clkBdd; + + // print stats + printf( "Ins/Outs = %4d/%4d. Total supp = %5d. Total unate = %5d.\n", + Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), TotalSupps, TotalUnate ); + PRT( "Glob BDDs", clkBdd ); + PRT( "Unateness", clkUnate ); + PRT( "Total ", clock() - clk ); + + // deref the PO functions +// Abc_NtkFreeGlobalBdds( pNtk ); + // stop the global BDD manager +// Extra_StopManager( pNtk->pManGlob ); +// pNtk->pManGlob = NULL; + Abc_NtkFreeGlobalBdds( pNtk, 1 ); +} + +/**Function************************************************************* + + Synopsis [Detects unate variables using SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose ) +{ +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcUnreach.c b/abc70930/src/base/abci/abcUnreach.c new file mode 100644 index 00000000..ea0a4cd2 --- /dev/null +++ b/abc70930/src/base/abci/abcUnreach.c @@ -0,0 +1,349 @@ +/**CFile**************************************************************** + + FileName [abcUnreach.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Computes unreachable states for small benchmarks.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcUnreach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ); +static DdNode * Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ); +static DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bRelation, DdNode * bInitial, bool fVerbose ); +static Abc_Ntk_t * Abc_NtkConstructExdc ( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Extracts sequential DCs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose ) +{ + int fReorder = 1; + DdManager * dd; + DdNode * bRelation, * bInitial, * bUnreach; + + // remove EXDC network if present + if ( pNtk->pExdc ) + { + Abc_NtkDelete( pNtk->pExdc ); + pNtk->pExdc = NULL; + } + + // compute the global BDDs of the latches + dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); + if ( dd == NULL ) + return 0; + if ( fVerbose ) + printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // create the transition relation (dereferenced global BDDs) + bRelation = Abc_NtkTransitionRelation( dd, pNtk, fVerbose ); Cudd_Ref( bRelation ); + // create the initial state and the variable map + bInitial = Abc_NtkInitStateAndVarMap( dd, pNtk, fVerbose ); Cudd_Ref( bInitial ); + // compute the unreachable states + bUnreach = Abc_NtkComputeUnreachable( dd, pNtk, bRelation, bInitial, fVerbose ); Cudd_Ref( bUnreach ); + Cudd_RecursiveDeref( dd, bRelation ); + Cudd_RecursiveDeref( dd, bInitial ); + + // reorder and disable reordering + if ( fReorder ) + { + if ( fVerbose ) + fprintf( stdout, "BDD nodes in the unreachable states before reordering %d.\n", Cudd_DagSize(bUnreach) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); + Cudd_AutodynDisable( dd ); + if ( fVerbose ) + fprintf( stdout, "BDD nodes in the unreachable states after reordering %d.\n", Cudd_DagSize(bUnreach) ); + } + + // allocate ZDD variables + Cudd_zddVarsFromBddVars( dd, 2 ); + // create the EXDC network representing the unreachable states + if ( pNtk->pExdc ) + Abc_NtkDelete( pNtk->pExdc ); + pNtk->pExdc = Abc_NtkConstructExdc( dd, pNtk, bUnreach ); + Cudd_RecursiveDeref( dd, bUnreach ); + Extra_StopManager( dd ); +// pNtk->pManGlob = NULL; + + // make sure that everything is okay + if ( pNtk->pExdc && !Abc_NtkCheck( pNtk->pExdc ) ) + { + printf( "Abc_NtkExtractSequentialDcs: The network check has failed.\n" ); + Abc_NtkDelete( pNtk->pExdc ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes the transition relation of the network.] + + Description [Assumes that the global BDDs are computed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ) +{ + DdNode * bRel, * bTemp, * bProd, * bVar, * bInputs; + Abc_Obj_t * pNode; + int fReorder = 1; + int i; + + // extand the BDD manager to represent NS variables + assert( dd->size == Abc_NtkCiNum(pNtk) ); + Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + Abc_NtkLatchNum(pNtk) - 1 ); + + // enable reordering + if ( fReorder ) + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + else + Cudd_AutodynDisable( dd ); + + // compute the transition relation + bRel = b1; Cudd_Ref( bRel ); + Abc_NtkForEachLatch( pNtk, pNode, i ) + { + bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i ); +// bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd ); + bProd = Cudd_bddXnor( dd, bVar, Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( bProd ); + bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + } + // free the global BDDs +// Abc_NtkFreeGlobalBdds( pNtk ); + Abc_NtkFreeGlobalBdds( pNtk, 0 ); + + // quantify the PI variables + bInputs = Extra_bddComputeRangeCube( dd, 0, Abc_NtkPiNum(pNtk) ); Cudd_Ref( bInputs ); + bRel = Cudd_bddExistAbstract( dd, bTemp = bRel, bInputs ); Cudd_Ref( bRel ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bInputs ); + + // reorder and disable reordering + if ( fReorder ) + { + if ( fVerbose ) + fprintf( stdout, "BDD nodes in the transition relation before reordering %d.\n", Cudd_DagSize(bRel) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + Cudd_AutodynDisable( dd ); + if ( fVerbose ) + fprintf( stdout, "BDD nodes in the transition relation after reordering %d.\n", Cudd_DagSize(bRel) ); + } + Cudd_Deref( bRel ); + return bRel; +} + +/**Function************************************************************* + + Synopsis [Computes the initial state and sets up the variable map.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ) +{ + DdNode ** pbVarsX, ** pbVarsY; + DdNode * bTemp, * bProd, * bVar; + Abc_Obj_t * pLatch; + int i; + + // set the variable mapping for Cudd_bddVarMap() + pbVarsX = ALLOC( DdNode *, dd->size ); + pbVarsY = ALLOC( DdNode *, dd->size ); + bProd = b1; Cudd_Ref( bProd ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + pbVarsX[i] = dd->vars[ Abc_NtkPiNum(pNtk) + i ]; + pbVarsY[i] = dd->vars[ Abc_NtkCiNum(pNtk) + i ]; + // get the initial value of the latch + bVar = Cudd_NotCond( pbVarsX[i], !Abc_LatchIsInit1(pLatch) ); + bProd = Cudd_bddAnd( dd, bTemp = bProd, bVar ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Abc_NtkLatchNum(pNtk) ); + FREE( pbVarsX ); + FREE( pbVarsY ); + + Cudd_Deref( bProd ); + return bProd; +} + +/**Function************************************************************* + + Synopsis [Computes the set of unreachable states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bTrans, DdNode * bInitial, bool fVerbose ) +{ + DdNode * bRelation, * bReached, * bCubeCs; + DdNode * bCurrent, * bNext, * bTemp; + int nIters, nMints; + + // perform reachability analisys + bCurrent = bInitial; Cudd_Ref( bCurrent ); + bReached = bInitial; Cudd_Ref( bReached ); + bRelation = bTrans; Cudd_Ref( bRelation ); + bCubeCs = Extra_bddComputeRangeCube( dd, Abc_NtkPiNum(pNtk), Abc_NtkCiNum(pNtk) ); Cudd_Ref( bCubeCs ); + for ( nIters = 1; ; nIters++ ) + { + // compute the next states + bNext = Cudd_bddAndAbstract( dd, bRelation, bCurrent, bCubeCs ); Cudd_Ref( bNext ); + Cudd_RecursiveDeref( dd, bCurrent ); + // remap these states into the current state vars + bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext ); + Cudd_RecursiveDeref( dd, bTemp ); + // check if there are any new states + if ( Cudd_bddLeq( dd, bNext, bReached ) ) + break; + // get the new states + bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); + // minimize the new states with the reached states +// bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( dd, bTemp ); + // add to the reached states + bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bNext ); + // minimize the transition relation +// bRelation = Cudd_bddConstrain( dd, bTemp = bRelation, Cudd_Not(bReached) ); Cudd_Ref( bRelation ); +// Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_RecursiveDeref( dd, bRelation ); + Cudd_RecursiveDeref( dd, bCubeCs ); + Cudd_RecursiveDeref( dd, bNext ); + // report the stats + if ( fVerbose ) + { + nMints = (int)Cudd_CountMinterm(dd, bReached, Abc_NtkLatchNum(pNtk) ); + fprintf( stdout, "Reachability analysis completed in %d iterations.\n", nIters ); + fprintf( stdout, "The number of minterms in the reachable state set = %d. (%6.2f %%)\n", nMints, 100.0*nMints/(1<<Abc_NtkLatchNum(pNtk)) ); + } +//PRB( dd, bReached ); + Cudd_Deref( bReached ); + return Cudd_Not( bReached ); +} + +/**Function************************************************************* + + Synopsis [Creates the EXDC network.] + + Description [The set of unreachable states depends on CS variables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkConstructExdc( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pNodeNew; + int * pPermute; + int i; + + // start the new network + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 ); + pNtkNew->pName = Extra_UtilStrsav( "exdc" ); + pNtkNew->pSpec = NULL; + + // create PIs corresponding to LOs + Abc_NtkForEachLatchOutput( pNtk, pNode, i ) + Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pNode), NULL ); + // cannot ADD POs here because pLatch->pCopy point to the PIs + + // create a new node + pNodeNew = Abc_NtkCreateNode(pNtkNew); + // add the fanins corresponding to latch outputs + Abc_NtkForEachLatchOutput( pNtk, pNode, i ) + Abc_ObjAddFanin( pNodeNew, pNode->pCopy ); + + // create the logic function + pPermute = ALLOC( int, dd->size ); + for ( i = 0; i < dd->size; i++ ) + pPermute[i] = -1; + Abc_NtkForEachLatch( pNtk, pNode, i ) + pPermute[Abc_NtkPiNum(pNtk) + i] = i; + // remap the functions + pNodeNew->pData = Extra_TransferPermute( dd, pNtkNew->pManFunc, bUnreach, pPermute ); Cudd_Ref( pNodeNew->pData ); + free( pPermute ); + Abc_NodeMinimumBase( pNodeNew ); + + // for each CO, create PO (skip POs equal to CIs because of name conflict) + Abc_NtkForEachPo( pNtk, pNode, i ) + if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) + Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL ); + Abc_NtkForEachLatchInput( pNtk, pNode, i ) + Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL ); + + // link to the POs of the network + Abc_NtkForEachPo( pNtk, pNode, i ) + if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + Abc_NtkForEachLatchInput( pNtk, pNode, i ) + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + + // remove the extra nodes + Abc_AigCleanup( pNtkNew->pManFunc ); + + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + + // transform the network to the SOP representation + if ( !Abc_NtkBddToSop( pNtkNew, 0 ) ) + { + printf( "Abc_NtkConstructExdc(): Converting to SOPs has failed.\n" ); + return NULL; + } + return pNtkNew; +// return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcVerify.c b/abc70930/src/base/abci/abcVerify.c new file mode 100644 index 00000000..9c9bbcfd --- /dev/null +++ b/abc70930/src/base/abci/abcVerify.c @@ -0,0 +1,1018 @@ +/**CFile**************************************************************** + + FileName [abcVerify.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Combinational and sequential verification for two networks.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcVerify.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fraig.h" +#include "sim.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel ); +extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Verifies combinational equivalence by brute-force SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ) +{ + extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); + Abc_Ntk_t * pMiter; + Abc_Ntk_t * pCnf; + int RetValue; + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0 ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); + Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pMiter ); + printf( "Networks are equivalent after structural hashing.\n" ); + return; + } + + // convert the miter into a CNF + pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 ); + Abc_NtkDelete( pMiter ); + if ( pCnf == NULL ) + { + printf( "Renoding for CNF has failed.\n" ); + return; + } + + // solve the CNF using the SAT solver + RetValue = Abc_NtkMiterSat( pCnf, (sint64)nConfLimit, (sint64)nInsLimit, 0, NULL, NULL ); + if ( RetValue == -1 ) + printf( "Networks are undecided (SAT solver timed out).\n" ); + else if ( RetValue == 0 ) + printf( "Networks are NOT EQUIVALENT after SAT.\n" ); + else + printf( "Networks are equivalent after SAT.\n" ); + if ( pCnf->pModel ) + Abc_NtkVerifyReportError( pNtk1, pNtk2, pCnf->pModel ); + FREE( pCnf->pModel ); + Abc_NtkDelete( pCnf ); +} + + +/**Function************************************************************* + + Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ) +{ + Prove_Params_t Params, * pParams = &Params; +// Fraig_Params_t Params; +// Fraig_Man_t * pMan; + Abc_Ntk_t * pMiter; + int RetValue; + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0 ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); + Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return; + } + if ( RetValue == 1 ) + { + printf( "Networks are equivalent after structural hashing.\n" ); + Abc_NtkDelete( pMiter ); + return; + } +/* + // convert the miter into a FRAIG + Fraig_ParamsSetDefault( &Params ); + Params.fVerbose = fVerbose; + Params.nSeconds = nSeconds; +// Params.fFuncRed = 0; +// Params.nPatsRand = 0; +// Params.nPatsDyna = 0; + pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 ); + Fraig_ManProveMiter( pMan ); + + // analyze the result + RetValue = Fraig_ManCheckMiter( pMan ); + // report the result + if ( RetValue == -1 ) + printf( "Networks are undecided (SAT solver timed out on the final miter).\n" ); + else if ( RetValue == 1 ) + printf( "Networks are equivalent after fraiging.\n" ); + else if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after fraiging.\n" ); + Abc_NtkVerifyReportError( pNtk1, pNtk2, Fraig_ManReadModel(pMan) ); + } + else assert( 0 ); + // delete the fraig manager + Fraig_ManFree( pMan ); + // delete the miter + Abc_NtkDelete( pMiter ); +*/ + // solve the CNF using the SAT solver + Prove_ParamsSetDefault( pParams ); + pParams->nItersMax = 5; +// RetValue = Abc_NtkMiterProve( &pMiter, pParams ); +// pParams->fVerbose = 1; + RetValue = Abc_NtkIvyProve( &pMiter, pParams ); + if ( RetValue == -1 ) + printf( "Networks are undecided (resource limits is reached).\n" ); + else if ( RetValue == 0 ) + { + int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiter, pMiter->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); + else + printf( "Networks are NOT EQUIVALENT.\n" ); + free( pSimInfo ); + } + else + printf( "Networks are equivalent.\n" ); + if ( pMiter->pModel ) + Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); + Abc_NtkDelete( pMiter ); +} + +/**Function************************************************************* + + Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose ) +{ + extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); + extern void * Abc_FrameGetGlobalFrame(); + + Prove_Params_t Params, * pParams = &Params; + Abc_Ntk_t * pMiter, * pMiterPart; + Abc_Obj_t * pObj; + int i, RetValue, Status, nOutputs; + + // solve the CNF using the SAT solver + Prove_ParamsSetDefault( pParams ); + pParams->nItersMax = 5; + // pParams->fVerbose = 1; + + assert( nPartSize > 0 ); + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, nPartSize ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); + Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return; + } + if ( RetValue == 1 ) + { + printf( "Networks are equivalent after structural hashing.\n" ); + Abc_NtkDelete( pMiter ); + return; + } + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); + + // solve the problem iteratively for each output of the miter + Status = 1; + nOutputs = 0; + Abc_NtkForEachPo( pMiter, pObj, i ) + { + if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pMiter) ) + { + if ( Abc_ObjFaninC0(pObj) ) // complemented -> const 0 + RetValue = 1; + else + RetValue = 0; + pMiterPart = NULL; + } + else + { + // get the cone of this output + pMiterPart = Abc_NtkCreateCone( pMiter, Abc_ObjFanin0(pObj), Abc_ObjName(pObj), 0 ); + if ( Abc_ObjFaninC0(pObj) ) + Abc_ObjXorFaninC( Abc_NtkPo(pMiterPart,0), 0 ); + // solve the cone + // RetValue = Abc_NtkMiterProve( &pMiterPart, pParams ); + RetValue = Abc_NtkIvyProve( &pMiterPart, pParams ); + } + + if ( RetValue == -1 ) + { + printf( "Networks are undecided (resource limits is reached).\r" ); + Status = -1; + } + else if ( RetValue == 0 ) + { + int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); + else + printf( "Networks are NOT EQUIVALENT. \n" ); + free( pSimInfo ); + Status = 0; + break; + } + else + { + printf( "Finished part %5d (out of %5d)\r", i+1, Abc_NtkPoNum(pMiter) ); + nOutputs += nPartSize; + } +// if ( pMiter->pModel ) +// Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); + if ( pMiterPart ) + Abc_NtkDelete( pMiterPart ); + } + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); + + if ( Status == 1 ) + printf( "Networks are equivalent. \n" ); + else if ( Status == -1 ) + printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) ); + Abc_NtkDelete( pMiter ); +} + +/**Function************************************************************* + + Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ) +{ + extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ); + extern Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nPartSizeLimit, int fVerbose ); + extern void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOnePtr ); + extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); + extern void * Abc_FrameGetGlobalFrame(); + + Vec_Ptr_t * vParts, * vOnePtr; + Vec_Int_t * vOne; + Prove_Params_t Params, * pParams = &Params; + Abc_Ntk_t * pMiter, * pMiterPart; + int i, RetValue, Status, nOutputs; + + // solve the CNF using the SAT solver + Prove_ParamsSetDefault( pParams ); + pParams->nItersMax = 5; + // pParams->fVerbose = 1; + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 1 ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); + Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return; + } + if ( RetValue == 1 ) + { + printf( "Networks are equivalent after structural hashing.\n" ); + Abc_NtkDelete( pMiter ); + return; + } + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); + + // partition the outputs + vParts = Abc_NtkPartitionSmart( pMiter, 300, 0 ); + + // fraig each partition + Status = 1; + nOutputs = 0; + vOnePtr = Vec_PtrAlloc( 1000 ); + Vec_PtrForEachEntry( vParts, vOne, i ) + { + // get this part of the miter + Abc_NtkConvertCos( pMiter, vOne, vOnePtr ); + pMiterPart = Abc_NtkCreateConeArray( pMiter, vOnePtr, 0 ); + Abc_NtkCombinePos( pMiterPart, 0 ); + // check the miter for being constant + RetValue = Abc_NtkMiterIsConstant( pMiterPart ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after partitioning.\n" ); + Abc_NtkDelete( pMiterPart ); + break; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pMiterPart ); + continue; + } + printf( "Verifying part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", + i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pMiterPart), Abc_NtkPoNum(pMiterPart), + Abc_NtkNodeNum(pMiterPart), Abc_AigLevel(pMiterPart) ); + // solve the problem + RetValue = Abc_NtkIvyProve( &pMiterPart, pParams ); + if ( RetValue == -1 ) + { + printf( "Networks are undecided (resource limits is reached).\r" ); + Status = -1; + } + else if ( RetValue == 0 ) + { + int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); + else + printf( "Networks are NOT EQUIVALENT. \n" ); + free( pSimInfo ); + Status = 0; + Abc_NtkDelete( pMiterPart ); + break; + } + else + { +// printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) ); + nOutputs += Vec_IntSize(vOne); + } + Abc_NtkDelete( pMiterPart ); + } + printf( " \r" ); + Vec_VecFree( (Vec_Vec_t *)vParts ); + Vec_PtrFree( vOnePtr ); + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); + + if ( Status == 1 ) + printf( "Networks are equivalent. \n" ); + else if ( Status == -1 ) + printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) ); + Abc_NtkDelete( pMiter ); +} + +/**Function************************************************************* + + Synopsis [Verifies sequential equivalence by brute-force SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames ) +{ + extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); + Abc_Ntk_t * pMiter; + Abc_Ntk_t * pFrames; + Abc_Ntk_t * pCnf; + int RetValue; + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + Abc_NtkDelete( pMiter ); + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + return; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pMiter ); + printf( "Networks are equivalent after structural hashing.\n" ); + return; + } + + // create the timeframes + pFrames = Abc_NtkFrames( pMiter, nFrames, 1 ); + Abc_NtkDelete( pMiter ); + if ( pFrames == NULL ) + { + printf( "Frames computation has failed.\n" ); + return; + } + RetValue = Abc_NtkMiterIsConstant( pFrames ); + if ( RetValue == 0 ) + { + Abc_NtkDelete( pFrames ); + printf( "Networks are NOT EQUIVALENT after framing.\n" ); + return; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pFrames ); + printf( "Networks are equivalent after framing.\n" ); + return; + } + + // convert the miter into a CNF + pCnf = Abc_NtkMulti( pFrames, 0, 100, 1, 0, 0, 0 ); + Abc_NtkDelete( pFrames ); + if ( pCnf == NULL ) + { + printf( "Renoding for CNF has failed.\n" ); + return; + } + + // solve the CNF using the SAT solver + RetValue = Abc_NtkMiterSat( pCnf, (sint64)nConfLimit, (sint64)nInsLimit, 0, NULL, NULL ); + if ( RetValue == -1 ) + printf( "Networks are undecided (SAT solver timed out).\n" ); + else if ( RetValue == 0 ) + printf( "Networks are NOT EQUIVALENT after SAT.\n" ); + else + printf( "Networks are equivalent after SAT.\n" ); + Abc_NtkDelete( pCnf ); +} + +/**Function************************************************************* + + Synopsis [Verifies combinational equivalence by fraiging followed by SAT] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ) +{ + Fraig_Params_t Params; + Fraig_Man_t * pMan; + Abc_Ntk_t * pMiter; + Abc_Ntk_t * pFrames; + int RetValue; + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return 0; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames ); + Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return 0; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pMiter ); + printf( "Networks are equivalent after structural hashing.\n" ); + return 1; + } + + // create the timeframes + pFrames = Abc_NtkFrames( pMiter, nFrames, 1 ); + Abc_NtkDelete( pMiter ); + if ( pFrames == NULL ) + { + printf( "Frames computation has failed.\n" ); + return 0; + } + RetValue = Abc_NtkMiterIsConstant( pFrames ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after framing.\n" ); + // report the error + pFrames->pModel = Abc_NtkVerifyGetCleanModel( pFrames, 1 ); +// Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pFrames->pModel, nFrames ); + FREE( pFrames->pModel ); + Abc_NtkDelete( pFrames ); + return 0; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pFrames ); + printf( "Networks are equivalent after framing.\n" ); + return 1; + } + + // convert the miter into a FRAIG + Fraig_ParamsSetDefault( &Params ); + Params.fVerbose = fVerbose; + Params.nSeconds = nSeconds; +// Params.fFuncRed = 0; +// Params.nPatsRand = 0; +// Params.nPatsDyna = 0; + pMan = Abc_NtkToFraig( pFrames, &Params, 0, 0 ); + Fraig_ManProveMiter( pMan ); + + // analyze the result + RetValue = Fraig_ManCheckMiter( pMan ); + // report the result + if ( RetValue == -1 ) + printf( "Networks are undecided (SAT solver timed out on the final miter).\n" ); + else if ( RetValue == 1 ) + printf( "Networks are equivalent after fraiging.\n" ); + else if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after fraiging.\n" ); +// Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, Fraig_ManReadModel(pMan), nFrames ); + } + else assert( 0 ); + // delete the fraig manager + Fraig_ManFree( pMan ); + // delete the miter + Abc_NtkDelete( pFrames ); + return RetValue == 1; +} + +/**Function************************************************************* + + Synopsis [Returns a dummy pattern full of zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames ) +{ + int * pModel = ALLOC( int, Abc_NtkCiNum(pNtk) * nFrames ); + memset( pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) * nFrames ); + return pModel; +} + +/**Function************************************************************* + + Synopsis [Returns the PO values under the given input pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel ) +{ + Abc_Obj_t * pNode; + int * pValues, Value0, Value1, i; + int fStrashed = 0; + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtk = Abc_NtkStrash(pNtk, 0, 0, 0); + fStrashed = 1; + } +/* + printf( "Counter example: " ); + Abc_NtkForEachCi( pNtk, pNode, i ) + printf( " %d", pModel[i] ); + printf( "\n" ); +*/ + // increment the trav ID + Abc_NtkIncrementTravId( pNtk ); + // set the CI values + Abc_AigConst1(pNtk)->pCopy = (void *)1; + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = (void *)pModel[i]; + // simulate in the topological order + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Value0 = ((int)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode); + Value1 = ((int)Abc_ObjFanin1(pNode)->pCopy) ^ Abc_ObjFaninC1(pNode); + pNode->pCopy = (void *)(Value0 & Value1); + } + // fill the output values + pValues = ALLOC( int, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + pValues[i] = ((int)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode); + if ( fStrashed ) + Abc_NtkDelete( pNtk ); + return pValues; +} + + +/**Function************************************************************* + + Synopsis [Reports mismatch between the two networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int * pValues1, * pValues2; + int nErrors, nPrinted, i, iNode = -1; + + assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) ); + assert( Abc_NtkCoNum(pNtk1) == Abc_NtkCoNum(pNtk2) ); + // get the CO values under this model + pValues1 = Abc_NtkVerifySimulatePattern( pNtk1, pModel ); + pValues2 = Abc_NtkVerifySimulatePattern( pNtk2, pModel ); + // count the mismatches + nErrors = 0; + for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ ) + nErrors += (int)( pValues1[i] != pValues2[i] ); + printf( "Verification failed for at least %d outputs: ", nErrors ); + // print the first 3 outputs + nPrinted = 0; + for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ ) + if ( pValues1[i] != pValues2[i] ) + { + if ( iNode == -1 ) + iNode = i; + printf( " %s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) ); + if ( ++nPrinted == 3 ) + break; + } + if ( nPrinted != nErrors ) + printf( " ..." ); + printf( "\n" ); + // report mismatch for the first output + if ( iNode >= 0 ) + { + printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n", + Abc_ObjName(Abc_NtkCo(pNtk1,iNode)), pValues1[iNode], pValues2[iNode] ); + printf( "Input pattern: " ); + // collect PIs in the cone + pNode = Abc_NtkCo(pNtk1,iNode); + vNodes = Abc_NtkNodeSupport( pNtk1, &pNode, 1 ); + // set the PI numbers + Abc_NtkForEachCi( pNtk1, pNode, i ) + pNode->pCopy = (void*)i; + // print the model + pNode = Vec_PtrEntry( vNodes, 0 ); + if ( Abc_ObjIsCi(pNode) ) + { + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + assert( Abc_ObjIsCi(pNode) ); + printf( " %s=%d", Abc_ObjName(pNode), pModel[(int)pNode->pCopy] ); + } + } + printf( "\n" ); + Vec_PtrFree( vNodes ); + } + free( pValues1 ); + free( pValues2 ); +} + + +/**Function************************************************************* + + Synopsis [Computes the COs in the support of the PO in the given frame.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkGetSeqPoSupp( Abc_Ntk_t * pNtk, int iFrame, int iNumPo ) +{ + Abc_Ntk_t * pFrames; + Abc_Obj_t * pObj, * pNodePo; + Vec_Ptr_t * vSupp; + int i, k; + // get the timeframes of the network + pFrames = Abc_NtkFrames( pNtk, iFrame + 1, 0 ); +//Abc_NtkShowAig( pFrames ); + + // get the PO of the timeframes + pNodePo = Abc_NtkPo( pFrames, iFrame * Abc_NtkPoNum(pNtk) + iNumPo ); + // set the support + vSupp = Abc_NtkNodeSupport( pFrames, &pNodePo, 1 ); + // mark the support of the frames + Abc_NtkForEachCi( pFrames, pObj, i ) + pObj->pCopy = NULL; + Vec_PtrForEachEntry( vSupp, pObj, i ) + pObj->pCopy = (void *)1; + // mark the support of the network if the support of the timeframes is marked + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = NULL; + Abc_NtkForEachLatch( pNtk, pObj, i ) + if ( Abc_NtkBox(pFrames, i)->pCopy ) + pObj->pCopy = (void *)1; + Abc_NtkForEachPi( pNtk, pObj, i ) + for ( k = 0; k <= iFrame; k++ ) + if ( Abc_NtkPi(pFrames, k*Abc_NtkPiNum(pNtk) + i)->pCopy ) + pObj->pCopy = (void *)1; + // free stuff + Vec_PtrFree( vSupp ); + Abc_NtkDelete( pFrames ); +} + +/**Function************************************************************* + + Synopsis [Reports mismatch between the two sequential networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ) +{ + Vec_Ptr_t * vInfo1, * vInfo2; + Abc_Obj_t * pObj, * pObjError, * pObj1, * pObj2; + int ValueError1, ValueError2; + unsigned * pPats1, * pPats2; + int i, o, k, nErrors, iFrameError, iNodePo, nPrinted; + int fRemove1 = 0, fRemove2 = 0; + + if ( !Abc_NtkIsStrash(pNtk1) ) + fRemove1 = 1, pNtk1 = Abc_NtkStrash( pNtk1, 0, 0, 0 ); + if ( !Abc_NtkIsStrash(pNtk2) ) + fRemove2 = 1, pNtk2 = Abc_NtkStrash( pNtk2, 0, 0, 0 ); + + // simulate sequential circuits + vInfo1 = Sim_SimulateSeqModel( pNtk1, nFrames, pModel ); + vInfo2 = Sim_SimulateSeqModel( pNtk2, nFrames, pModel ); + + // look for a discrepancy in the PO values + nErrors = 0; + pObjError = NULL; + for ( i = 0; i < nFrames; i++ ) + { + if ( pObjError ) + break; + Abc_NtkForEachPo( pNtk1, pObj1, o ) + { + pObj2 = Abc_NtkPo( pNtk2, o ); + pPats1 = Sim_SimInfoGet(vInfo1, pObj1); + pPats2 = Sim_SimInfoGet(vInfo2, pObj2); + if ( pPats1[i] == pPats2[i] ) + continue; + nErrors++; + if ( pObjError == NULL ) + { + pObjError = pObj1; + iFrameError = i; + iNodePo = o; + ValueError1 = (pPats1[i] > 0); + ValueError2 = (pPats2[i] > 0); + } + } + } + + if ( pObjError == NULL ) + { + printf( "No output mismatches detected.\n" ); + Sim_UtilInfoFree( vInfo1 ); + Sim_UtilInfoFree( vInfo2 ); + if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); + if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); + return; + } + + printf( "Verification failed for at least %d output%s of frame %d: ", nErrors, (nErrors>1? "s":""), iFrameError+1 ); + // print the first 3 outputs + nPrinted = 0; + Abc_NtkForEachPo( pNtk1, pObj1, o ) + { + pObj2 = Abc_NtkPo( pNtk2, o ); + pPats1 = Sim_SimInfoGet(vInfo1, pObj1); + pPats2 = Sim_SimInfoGet(vInfo2, pObj2); + if ( pPats1[iFrameError] == pPats2[iFrameError] ) + continue; + printf( " %s", Abc_ObjName(pObj1) ); + if ( ++nPrinted == 3 ) + break; + } + if ( nPrinted != nErrors ) + printf( " ..." ); + printf( "\n" ); + + // mark CIs of the networks in the cone of influence of this output + Abc_NtkGetSeqPoSupp( pNtk1, iFrameError, iNodePo ); + Abc_NtkGetSeqPoSupp( pNtk2, iFrameError, iNodePo ); + + // report mismatch for the first output + printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n", + Abc_ObjName(pObjError), ValueError1, ValueError2 ); + + printf( "The cone of influence of output %s in Network1:\n", Abc_ObjName(pObjError) ); + printf( "PIs: " ); + Abc_NtkForEachPi( pNtk1, pObj, i ) + if ( pObj->pCopy ) + printf( "%s ", Abc_ObjName(pObj) ); + printf( "\n" ); + printf( "Latches: " ); + Abc_NtkForEachLatch( pNtk1, pObj, i ) + if ( pObj->pCopy ) + printf( "%s ", Abc_ObjName(pObj) ); + printf( "\n" ); + + printf( "The cone of influence of output %s in Network2:\n", Abc_ObjName(pObjError) ); + printf( "PIs: " ); + Abc_NtkForEachPi( pNtk2, pObj, i ) + if ( pObj->pCopy ) + printf( "%s ", Abc_ObjName(pObj) ); + printf( "\n" ); + printf( "Latches: " ); + Abc_NtkForEachLatch( pNtk2, pObj, i ) + if ( pObj->pCopy ) + printf( "%s ", Abc_ObjName(pObj) ); + printf( "\n" ); + + // print the patterns + for ( i = 0; i <= iFrameError; i++ ) + { + printf( "Frame %d: ", i+1 ); + + printf( "PI(1):" ); + Abc_NtkForEachPi( pNtk1, pObj, k ) + if ( pObj->pCopy ) + printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 ); + printf( " " ); + printf( "L(1):" ); + Abc_NtkForEachLatch( pNtk1, pObj, k ) + if ( pObj->pCopy ) + printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 ); + printf( " " ); + printf( "%s(1):", Abc_ObjName(pObjError) ); + printf( "%d", Sim_SimInfoGet(vInfo1, pObjError)[i] > 0 ); + + printf( " " ); + + printf( "PI(2):" ); + Abc_NtkForEachPi( pNtk2, pObj, k ) + if ( pObj->pCopy ) + printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 ); + printf( " " ); + printf( "L(2):" ); + Abc_NtkForEachLatch( pNtk2, pObj, k ) + if ( pObj->pCopy ) + printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 ); + printf( " " ); + printf( "%s(2):", Abc_ObjName(pObjError) ); + printf( "%d", Sim_SimInfoGet(vInfo2, pObjError)[i] > 0 ); + + printf( "\n" ); + } + Abc_NtkForEachCi( pNtk1, pObj, i ) + pObj->pCopy = NULL; + Abc_NtkForEachCi( pNtk2, pObj, i ) + pObj->pCopy = NULL; + + Sim_UtilInfoFree( vInfo1 ); + Sim_UtilInfoFree( vInfo2 ); + if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); + if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); +} + +/**Function************************************************************* + + Synopsis [Simulates buggy miter emailed by Mike.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSimulteBuggyMiter( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + int * pModel1, * pModel2, * pResult1, * pResult2; + char * vPiValues1 = "01001011100000000011010110101000000"; + char * vPiValues2 = "11001101011101011111110100100010001"; + + assert( strlen(vPiValues1) == (unsigned)Abc_NtkPiNum(pNtk) ); + assert( 1 == Abc_NtkPoNum(pNtk) ); + + pModel1 = ALLOC( int, Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pObj, i ) + pModel1[i] = vPiValues1[i] - '0'; + Abc_NtkForEachLatch( pNtk, pObj, i ) + pModel1[Abc_NtkPiNum(pNtk)+i] = ((int)pObj->pData) - 1; + + pResult1 = Abc_NtkVerifySimulatePattern( pNtk, pModel1 ); + printf( "Value = %d\n", pResult1[0] ); + + pModel2 = ALLOC( int, Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pObj, i ) + pModel2[i] = vPiValues2[i] - '0'; + Abc_NtkForEachLatch( pNtk, pObj, i ) + pModel2[Abc_NtkPiNum(pNtk)+i] = pResult1[Abc_NtkPoNum(pNtk)+i]; + + pResult2 = Abc_NtkVerifySimulatePattern( pNtk, pModel2 ); + printf( "Value = %d\n", pResult2[0] ); + + free( pModel1 ); + free( pModel2 ); + free( pResult1 ); + free( pResult2 ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcXsim.c b/abc70930/src/base/abci/abcXsim.c new file mode 100644 index 00000000..5d9e4634 --- /dev/null +++ b/abc70930/src/base/abci/abcXsim.c @@ -0,0 +1,227 @@ +/**CFile**************************************************************** + + FileName [abcXsim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Using X-valued simulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcXsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define XVS0 ABC_INIT_ZERO +#define XVS1 ABC_INIT_ONE +#define XVSX ABC_INIT_DC + +static inline void Abc_ObjSetXsim( Abc_Obj_t * pObj, int Value ) { pObj->pCopy = (void *)Value; } +static inline int Abc_ObjGetXsim( Abc_Obj_t * pObj ) { return (int)pObj->pCopy; } +static inline int Abc_XsimInv( int Value ) +{ + if ( Value == XVS0 ) + return XVS1; + if ( Value == XVS1 ) + return XVS0; + assert( Value == XVSX ); + return XVSX; +} +static inline int Abc_XsimAnd( int Value0, int Value1 ) +{ + if ( Value0 == XVS0 || Value1 == XVS0 ) + return XVS0; + if ( Value0 == XVSX || Value1 == XVSX ) + return XVSX; + assert( Value0 == XVS1 && Value1 == XVS1 ); + return XVS1; +} +static inline int Abc_XsimRand2() +{ + return (rand() & 1) ? XVS1 : XVS0; +} +static inline int Abc_XsimRand3() +{ + int RetValue; + do { + RetValue = rand() & 3; + } while ( RetValue == 0 ); + return RetValue; +} +static inline int Abc_ObjGetXsimFanin0( Abc_Obj_t * pObj ) +{ + int RetValue; + RetValue = Abc_ObjGetXsim(Abc_ObjFanin0(pObj)); + return Abc_ObjFaninC0(pObj)? Abc_XsimInv(RetValue) : RetValue; +} +static inline int Abc_ObjGetXsimFanin1( Abc_Obj_t * pObj ) +{ + int RetValue; + RetValue = Abc_ObjGetXsim(Abc_ObjFanin1(pObj)); + return Abc_ObjFaninC1(pObj)? Abc_XsimInv(RetValue) : RetValue; +} +static inline void Abc_XsimPrint( FILE * pFile, int Value ) +{ + if ( Value == XVS0 ) + { + fprintf( pFile, "0" ); + return; + } + if ( Value == XVS1 ) + { + fprintf( pFile, "1" ); + return; + } + assert( Value == XVSX ); + fprintf( pFile, "x" ); +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs X-valued simulation of the sequential network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose ) +{ + Abc_Obj_t * pObj; + int i, f; + assert( Abc_NtkIsStrash(pNtk) ); + srand( 0x12341234 ); + // start simulation + Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 ); + if ( fXInputs ) + { + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, XVSX ); + } + else + { + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); + } + if ( fXState ) + { + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjSetXsim( Abc_ObjFanout0(pObj), XVSX ); + } + else + { + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) ); + } + // simulate and print the result + fprintf( stdout, "Frame : Inputs : Latches : Outputs\n" ); + for ( f = 0; f < nFrames; f++ ) + { + Abc_AigForEachAnd( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) ); + // print out + fprintf( stdout, "%2d : ", f ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); + fprintf( stdout, " : " ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { +// if ( Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) != XVSX ) +// printf( " %s=", Abc_ObjName(pObj) ); + Abc_XsimPrint( stdout, Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) ); + } + fprintf( stdout, " : " ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); + if ( Abc_NtkAssertNum(pNtk) ) + { + fprintf( stdout, " : " ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); + } + fprintf( stdout, "\n" ); + // assign input values + if ( fXInputs ) + { + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, XVSX ); + } + else + { + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); + } + // transfer the latch values + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) ); + } +} + +/**Function************************************************************* + + Synopsis [Cycles the circuit to create a new initial state.] + + Description [Simulates the circuit with random input for the given + number of timeframes to get a better initial state.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ) +{ + Abc_Obj_t * pObj; + int i, f; + assert( Abc_NtkIsStrash(pNtk) ); + srand( 0x12341234 ); + // initialize the values + Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchIsInit1(pObj)? XVS1 : XVS0 ); + // simulate for the given number of timeframes + for ( f = 0; f < nFrames; f++ ) + { + Abc_AigForEachAnd( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) ); + // assign input values + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); + // transfer the latch values + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) ); + } + // set the final values + Abc_NtkForEachLatch( pNtk, pObj, i ) + pObj->pData = (void *)Abc_ObjGetXsim(Abc_ObjFanout0(pObj)); +} + +/////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abc_.c b/abc70930/src/base/abci/abc_.c new file mode 100644 index 00000000..75ec88c3 --- /dev/null +++ b/abc70930/src/base/abci/abc_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [abc_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/module.make b/abc70930/src/base/abci/module.make new file mode 100644 index 00000000..4558119e --- /dev/null +++ b/abc70930/src/base/abci/module.make @@ -0,0 +1,54 @@ +SRC += src/base/abci/abc.c \ + src/base/abci/abcAttach.c \ + src/base/abci/abcAuto.c \ + src/base/abci/abcBalance.c \ + src/base/abci/abcBmc.c \ + src/base/abci/abcCas.c \ + src/base/abci/abcClpBdd.c \ + src/base/abci/abcClpSop.c \ + src/base/abci/abcCut.c \ + src/base/abci/abcDar.c \ + src/base/abci/abcDebug.c \ + src/base/abci/abcDress.c \ + src/base/abci/abcDsd.c \ + src/base/abci/abcEspresso.c \ + src/base/abci/abcExtract.c \ + src/base/abci/abcFpga.c \ + src/base/abci/abcFpgaFast.c \ + src/base/abci/abcFraig.c \ + src/base/abci/abcFxu.c \ + src/base/abci/abcGen.c \ + src/base/abci/abcHaig.c \ + src/base/abci/abcIf.c \ + src/base/abci/abcIvy.c \ + src/base/abci/abcLut.c \ + src/base/abci/abcMap.c \ + src/base/abci/abcMini.c \ + src/base/abci/abcMiter.c \ + src/base/abci/abcMulti.c \ + src/base/abci/abcNtbdd.c \ + src/base/abci/abcOdc.c \ + src/base/abci/abcOrder.c \ + src/base/abci/abcPart.c \ + src/base/abci/abcPrint.c \ + src/base/abci/abcProve.c \ + src/base/abci/abcQbf.c \ + src/base/abci/abcQuant.c \ + src/base/abci/abcRec.c \ + src/base/abci/abcReconv.c \ + src/base/abci/abcRefactor.c \ + src/base/abci/abcRenode.c \ + src/base/abci/abcReorder.c \ + src/base/abci/abcRestruct.c \ + src/base/abci/abcResub.c \ + src/base/abci/abcRewrite.c \ + src/base/abci/abcRr.c \ + src/base/abci/abcSat.c \ + src/base/abci/abcStrash.c \ + src/base/abci/abcSweep.c \ + src/base/abci/abcSymm.c \ + src/base/abci/abcTiming.c \ + src/base/abci/abcUnate.c \ + src/base/abci/abcUnreach.c \ + src/base/abci/abcVerify.c \ + src/base/abci/abcXsim.c diff --git a/abc70930/src/base/cmd/cmd.c b/abc70930/src/base/cmd/cmd.c new file mode 100644 index 00000000..2dc03d5c --- /dev/null +++ b/abc70930/src/base/cmd/cmd.c @@ -0,0 +1,1674 @@ +/**CFile**************************************************************** + + FileName [cmd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Command file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifdef WIN32 +#include <process.h> +#endif + +#include "mainInt.h" +#include "cmdInt.h" +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int CmdCommandTime ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandEcho ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandQuit ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandWhich ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandHistory ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandAlias ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandUnalias ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandHelp ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandSource ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandSetVariable ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandUnsetVariable ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandUndo ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandRecall ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandEmpty ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#ifdef WIN32 +static int CmdCommandLs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#endif +static int CmdCommandSis ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandMvsis ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandCapo ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function******************************************************************** + + Synopsis [Initializes the command package.] + + SideEffects [Commands are added to the command table.] + + SeeAlso [Cmd_End] + +******************************************************************************/ +void Cmd_Init( Abc_Frame_t * pAbc ) +{ + pAbc->tCommands = st_init_table(strcmp, st_strhash); + pAbc->tAliases = st_init_table(strcmp, st_strhash); + pAbc->tFlags = st_init_table(strcmp, st_strhash); + pAbc->aHistory = Vec_PtrAlloc( 100 ); + + Cmd_CommandAdd( pAbc, "Basic", "time", CmdCommandTime, 0); + Cmd_CommandAdd( pAbc, "Basic", "echo", CmdCommandEcho, 0); + Cmd_CommandAdd( pAbc, "Basic", "quit", CmdCommandQuit, 0); + Cmd_CommandAdd( pAbc, "Basic", "history", CmdCommandHistory, 0); + Cmd_CommandAdd( pAbc, "Basic", "alias", CmdCommandAlias, 0); + Cmd_CommandAdd( pAbc, "Basic", "unalias", CmdCommandUnalias, 0); + Cmd_CommandAdd( pAbc, "Basic", "help", CmdCommandHelp, 0); + Cmd_CommandAdd( pAbc, "Basic", "source", CmdCommandSource, 0); + Cmd_CommandAdd( pAbc, "Basic", "set", CmdCommandSetVariable, 0); + Cmd_CommandAdd( pAbc, "Basic", "unset", CmdCommandUnsetVariable, 0); + Cmd_CommandAdd( pAbc, "Basic", "undo", CmdCommandUndo, 0); + Cmd_CommandAdd( pAbc, "Basic", "recall", CmdCommandRecall, 0); + Cmd_CommandAdd( pAbc, "Basic", "empty", CmdCommandEmpty, 0); +#ifdef WIN32 + Cmd_CommandAdd( pAbc, "Basic", "ls", CmdCommandLs, 0 ); +#endif + + Cmd_CommandAdd( pAbc, "Various", "sis", CmdCommandSis, 1); + Cmd_CommandAdd( pAbc, "Various", "mvsis", CmdCommandMvsis, 1); + Cmd_CommandAdd( pAbc, "Various", "capo", CmdCommandCapo, 0); +} + +/**Function******************************************************************** + + Synopsis [Ends the command package.] + + Description [Ends the command package. Tables are freed.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Cmd_End( Abc_Frame_t * pAbc ) +{ + st_generator * gen; + char * pKey, * pValue; + int i; + +// st_free_table( pAbc->tCommands, (void (*)()) 0, CmdCommandFree ); +// st_free_table( pAbc->tAliases, (void (*)()) 0, CmdCommandAliasFree ); +// st_free_table( pAbc->tFlags, free, free ); + + st_foreach_item( pAbc->tCommands, gen, (char **)&pKey, (char **)&pValue ) + CmdCommandFree( (Abc_Command *)pValue ); + st_free_table( pAbc->tCommands ); + + st_foreach_item( pAbc->tAliases, gen, (char **)&pKey, (char **)&pValue ) + CmdCommandAliasFree( (Abc_Alias *)pValue ); + st_free_table( pAbc->tAliases ); + + st_foreach_item( pAbc->tFlags, gen, (char **)&pKey, (char **)&pValue ) + free( pKey ), free( pValue ); + st_free_table( pAbc->tFlags ); + + for ( i = 0; i < pAbc->aHistory->nSize; i++ ) + free( pAbc->aHistory->pArray[i] ); + Vec_PtrFree( pAbc->aHistory ); +} + + + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind ) + { + goto usage; + } + + pAbc->TimeTotal += pAbc->TimeCommand; + fprintf( pAbc->Out, "elapse: %3.2f seconds, total: %3.2f seconds\n", + (float)pAbc->TimeCommand / CLOCKS_PER_SEC, (float)pAbc->TimeTotal / CLOCKS_PER_SEC ); +/* + { + FILE * pTable; + pTable = fopen( "runtimes.txt", "a+" ); + fprintf( pTable, "%4.2f\n", (float)pAbc->TimeCommand / CLOCKS_PER_SEC ); + fclose( pTable ); + } +*/ + pAbc->TimeCommand = 0; + return 0; + + usage: + fprintf( pAbc->Err, "usage: time [-h]\n" ); + fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandEcho( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int i; + int c; + int n = 1; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "hn" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + n = 0; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + for ( i = globalUtilOptind; i < argc; i++ ) + fprintf( pAbc->Out, "%s ", argv[i] ); + if ( n ) + fprintf( pAbc->Out, "\n" ); + else + fflush ( pAbc->Out ); + return 0; + + usage: + fprintf( pAbc->Err, "usage: echo [-h] string \n" ); + fprintf( pAbc->Err, " -n \t\tsuppress newline at the end\n" ); + fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); + return ( 1 ); +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandQuit( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "hs" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + break; + case 's': + return -2; + break; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind ) + goto usage; + return -1; + + usage: + fprintf( pAbc->Err, "usage: quit [-h] [-s]\n" ); + fprintf( pAbc->Err, " -h print the command usage\n" ); + fprintf( pAbc->Err, + " -s frees all the memory before quitting\n" ); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandWhich( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + return 0; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int i, c, num, size; + + num = 20; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default : + goto usage; + } + } + if ( argc > 2 ) + goto usage; + + // get the number of commands to print + if ( argc == globalUtilOptind + 1 ) + num = atoi(argv[globalUtilOptind]); + // print the commands + size = pAbc->aHistory->nSize; + num = ( num < size ) ? num : size; + for ( i = size - num; i < size; i++ ) + fprintf( pAbc->Out, "%s", pAbc->aHistory->pArray[i] ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: history [-h] <num>\n" ); + fprintf( pAbc->Err, " prints the latest command entered on the command line\n" ); + fprintf( pAbc->Err, " -h : print the command usage\n" ); + fprintf( pAbc->Err, "num : print the last num commands\n" ); + return ( 1 ); +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandAlias( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char *key, *value; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + + if ( argc == 1 ) + { + CmdPrintTable( pAbc->tAliases, 1 ); + return 0; + + } + else if ( argc == 2 ) + { + if ( st_lookup( pAbc->tAliases, argv[1], &value ) ) + CmdCommandAliasPrint( pAbc, ( Abc_Alias * ) value ); + return 0; + } + + // delete any existing alias + key = argv[1]; + if ( st_delete( pAbc->tAliases, &key, &value ) ) + CmdCommandAliasFree( ( Abc_Alias * ) value ); + CmdCommandAliasAdd( pAbc, argv[1], argc - 2, argv + 2 ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: alias [-h] [command [string]]\n" ); + fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); + return ( 1 ); +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandUnalias( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int i; + char *key, *value; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + if ( argc < 2 ) + { + goto usage; + } + + for ( i = 1; i < argc; i++ ) + { + key = argv[i]; + if ( st_delete( pAbc->tAliases, &key, &value ) ) + { + CmdCommandAliasFree( ( Abc_Alias * ) value ); + } + } + return 0; + + usage: + fprintf( pAbc->Err, "usage: unalias [-h] alias_names\n" ); + fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandHelp( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + bool fPrintAll; + int c; + + fPrintAll = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + case 'v': + fPrintAll ^= 1; + break; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind ) + goto usage; + + CmdCommandPrint( pAbc, fPrintAll ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: help [-a] [-h]\n" ); + fprintf( pAbc->Err, " prints the list of available commands by group\n" ); + fprintf( pAbc->Err, " -a toggle printing hidden commands [default = %s]\n", fPrintAll? "yes": "no" ); + fprintf( pAbc->Err, " -h print the command usage\n" ); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int c, echo, prompt, silent, interactive, quit_count, lp_count; + int status = 0; /* initialize so that lint doesn't complain */ + int lp_file_index, did_subst; + char *prompt_string, *real_filename, line[MAX_STR], *command; + FILE *fp; + + interactive = silent = prompt = echo = 0; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ipsxh" ) ) != EOF ) + { + switch ( c ) + { + case 'i': /* a hack to distinguish EOF from stdin */ + interactive = 1; + break; + case 'p': + prompt ^= 1; + break; + case 's': + silent ^= 1; + break; + case 'x': + echo ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + /* added to avoid core-dumping when no script file is specified */ + if ( argc == globalUtilOptind ) + { + goto usage; + } + + lp_file_index = globalUtilOptind; + lp_count = 0; + + /* + * FIX (Tom, 5/7/95): I'm not sure what the purpose of this outer do loop + * is. In particular, lp_file_index is never modified in the loop, so it + * looks it would just read the same file over again. Also, SIS had + * lp_count initialized to -1, and hence, any file sourced by SIS (if -l or + * -t options on "source" were used in SIS) would actually be executed + * twice. + */ + do + { + lp_count++; /* increment the loop counter */ + + fp = CmdFileOpen( pAbc, argv[lp_file_index], "r", &real_filename, silent ); + if ( fp == NULL ) + { + FREE( real_filename ); + return !silent; /* error return if not silent */ + } + + quit_count = 0; + do + { + if ( prompt ) + { + prompt_string = Cmd_FlagReadByName( pAbc, "prompt" ); + if ( prompt_string == NULL ) + prompt_string = "abc> "; + + } + else + { + prompt_string = NULL; + } + + /* clear errors -- e.g., EOF reached from stdin */ + clearerr( fp ); + + /* read another command line */ +// if (CmdFgetsFilec(line, MAX_STR, fp, prompt_string) == NULL) { +// Abc_UtilsPrintPrompt(prompt_string); +// fflush(stdout); + if ( fgets( line, MAX_STR, fp ) == NULL ) + { + if ( interactive ) + { + if ( quit_count++ < 5 ) + { + fprintf( pAbc->Err, "\nUse \"quit\" to leave ABC.\n" ); + continue; + } + status = -1; /* fake a 'quit' */ + } + else + { + status = 0; /* successful end of 'source' ; loop? */ + } + break; + } + quit_count = 0; + + if ( echo ) + { + fprintf( pAbc->Out, "abc - > %s", line ); + } + command = CmdHistorySubstitution( pAbc, line, &did_subst ); + if ( command == NULL ) + { + status = 1; + break; + } + if ( did_subst ) + { + if ( interactive ) + { + fprintf( pAbc->Out, "%s\n", command ); + } + } + if ( command != line ) + { + ( void ) strcpy( line, command ); + } + if ( interactive && *line != '\0' ) + { + Cmd_HistoryAddCommand( pAbc, Extra_UtilStrsav(line) ); + if ( pAbc->Hst != NULL ) + { + fprintf( pAbc->Hst, "%s\n", line ); + ( void ) fflush( pAbc->Hst ); + } + } + + status = Cmd_CommandExecute( pAbc, line ); + } + while ( status == 0 ); + + if ( fp != stdin ) + { + if ( status > 0 ) + { + fprintf( pAbc->Err, + "** cmd error: aborting 'source %s'\n", + real_filename ); + } + ( void ) fclose( fp ); + } + FREE( real_filename ); + + } + while ( ( status == 0 ) && ( lp_count <= 0 ) ); + + return status; + + usage: + fprintf( pAbc->Err, "usage: source [-psxh] <file_name>\n" ); + fprintf( pAbc->Err, "\t-p supply prompt before reading each line [default = %s]\n", prompt? "yes": "no" ); + fprintf( pAbc->Err, "\t-s silently ignore nonexistant file [default = %s]\n", silent? "yes": "no" ); + fprintf( pAbc->Err, "\t-x echo each line as it is executed [default = %s]\n", echo? "yes": "no" ); + fprintf( pAbc->Err, "\t-h print the command usage\n" ); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char *flag_value, *key, *value; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == 0 || argc > 3 ) + { + goto usage; + } + else if ( argc == 1 ) + { + CmdPrintTable( pAbc->tFlags, 0 ); + return 0; + } + else + { + key = argv[1]; + if ( st_delete( pAbc->tFlags, &key, &value ) ) + { + FREE( key ); + FREE( value ); + } + + flag_value = argc == 2 ? Extra_UtilStrsav( "" ) : Extra_UtilStrsav( argv[2] ); +// flag_value = argc == 2 ? NULL : Extra_UtilStrsav(argv[2]); + st_insert( pAbc->tFlags, Extra_UtilStrsav(argv[1]), flag_value ); + + if ( strcmp( argv[1], "abcout" ) == 0 ) + { + if ( pAbc->Out != stdout ) + fclose( pAbc->Out ); + if ( strcmp( flag_value, "" ) == 0 ) + flag_value = "-"; + pAbc->Out = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); + if ( pAbc->Out == NULL ) + pAbc->Out = stdout; +#if HAVE_SETVBUF + setvbuf( pAbc->Out, ( char * ) NULL, _IOLBF, 0 ); +#endif + } + if ( strcmp( argv[1], "abcerr" ) == 0 ) + { + if ( pAbc->Err != stderr ) + fclose( pAbc->Err ); + if ( strcmp( flag_value, "" ) == 0 ) + flag_value = "-"; + pAbc->Err = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); + if ( pAbc->Err == NULL ) + pAbc->Err = stderr; +#if HAVE_SETVBUF + setvbuf( pAbc->Err, ( char * ) NULL, _IOLBF, 0 ); +#endif + } + if ( strcmp( argv[1], "history" ) == 0 ) + { + if ( pAbc->Hst != NULL ) + fclose( pAbc->Hst ); + if ( strcmp( flag_value, "" ) == 0 ) + pAbc->Hst = NULL; + else + { + pAbc->Hst = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); + if ( pAbc->Hst == NULL ) + pAbc->Hst = NULL; + } + } + return 0; + } + + usage: + fprintf( pAbc->Err, "usage: set [-h] <name> <value>\n" ); + fprintf( pAbc->Err, "\t sets the value of parameter <name>\n" ); + fprintf( pAbc->Err, "\t-h : print the command usage\n" ); + return 1; + +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandUnsetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int i; + char *key, *value; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + if ( argc < 2 ) + { + goto usage; + } + + for ( i = 1; i < argc; i++ ) + { + key = argv[i]; + if ( st_delete( pAbc->tFlags, &key, &value ) ) + { + FREE( key ); + FREE( value ); + } + } + return 0; + + + usage: + fprintf( pAbc->Err, "usage: unset [-h] <name> \n" ); + fprintf( pAbc->Err, "\t removes the value of parameter <name>\n" ); + fprintf( pAbc->Err, "\t-h : print the command usage\n" ); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + // if there are no arguments on the command line + // set the current network to be the network from the previous step + if ( argc == 1 ) + return CmdCommandRecall( pAbc, argc, argv ); + + fprintf( pAbc->Err, "usage: undo\n" ); + fprintf( pAbc->Err, " sets the current network to be the previously saved network\n" ); + return 1; + +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandRecall( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNtk; + int iStep, iStepFound; + int nNetsToSave, c; + char * pValue; + int iStepStart, iStepStop; + + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + // get the number of networks to save + pValue = Cmd_FlagReadByName( pAbc, "savesteps" ); + // if the value of steps to save is not set, assume 1-level undo + if ( pValue == NULL ) + nNetsToSave = 1; + else + nNetsToSave = atoi(pValue); + + // if there are no arguments on the command line + // set the current network to be the network from the previous step + if ( argc == 1 ) + { + // get the previously saved network + pNtk = Abc_NtkBackup(pAbc->pNtkCur); + if ( pNtk == NULL ) + fprintf( pAbc->Out, "There is no previously saved network.\n" ); + else // set the current network to be the copy of the previous one + Abc_FrameSetCurrentNetwork( pAbc, Abc_NtkDup(pNtk) ); + return 0; + } + if ( argc == 2 ) // the second argument is the number of the step to return to + { + // read the number of the step to return to + iStep = atoi(argv[1]); + // check whether it is reasonable + if ( iStep >= pAbc->nSteps ) + { + iStepStart = pAbc->nSteps - nNetsToSave; + if ( iStepStart <= 0 ) + iStepStart = 1; + iStepStop = pAbc->nSteps; + if ( iStepStop <= 0 ) + iStepStop = 1; + if ( iStepStart == iStepStop ) + fprintf( pAbc->Out, "Can only recall step %d.\n", iStepStop ); + else + fprintf( pAbc->Out, "Can only recall steps %d-%d.\n", iStepStart, iStepStop ); + } + else if ( iStep < 0 ) + fprintf( pAbc->Out, "Cannot recall step %d.\n", iStep ); + else if ( iStep == 0 ) + Abc_FrameDeleteAllNetworks( pAbc ); + else + { + // scroll backward through the list of networks + // to determine if such a network exist + iStepFound = 0; + for ( pNtk = pAbc->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk) ) + if ( (iStepFound = Abc_NtkStep(pNtk)) == iStep ) + break; + if ( pNtk == NULL ) + { + iStepStart = iStepFound; + if ( iStepStart <= 0 ) + iStepStart = 1; + iStepStop = pAbc->nSteps; + if ( iStepStop <= 0 ) + iStepStop = 1; + if ( iStepStart == iStepStop ) + fprintf( pAbc->Out, "Can only recall step %d.\n", iStepStop ); + else + fprintf( pAbc->Out, "Can only recall steps %d-%d.\n", iStepStart, iStepStop ); + } + else + Abc_FrameSetCurrentNetwork( pAbc, Abc_NtkDup(pNtk) ); + } + return 0; + } + +usage: + + fprintf( pAbc->Err, "usage: recall -h <num>\n" ); + fprintf( pAbc->Err, " set the current network to be one of the previous networks\n" ); + fprintf( pAbc->Err, "<num> : level to return to [default = previous]\n" ); + fprintf( pAbc->Err, " -h : print the command usage\n"); + return 1; +} + + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandEmpty( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int c; + + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + Abc_FrameDeleteAllNetworks( pAbc ); + Abc_FrameRestart( pAbc ); + return 0; +usage: + + fprintf( pAbc->Err, "usage: empty [-h]\n" ); + fprintf( pAbc->Err, " removes all the currently stored networks\n" ); + fprintf( pAbc->Err, " -h : print the command usage\n"); + return 1; +} + + +#if 0 + +/**Function******************************************************************** + + Synopsis [Donald's version.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNtkTemp; + int id, c; + + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + break; + default: + goto usage; + } + } + if (globalUtilOptind <= argc) { + pNtkTemp = pAbc->pNtk; + pAbc->pNtk = pAbc->pNtkSaved; + pAbc->pNtkSaved = pNtkTemp; + } + id = atoi(argv[globalUtilOptind]); + pNtkTemp = Cmd_HistoryGetSnapshot(pAbc, id); + if (!pNtkTemp) + fprintf( pAbc->Err, "Snapshot %d does not exist\n", id); + else + pAbc->pNtk = Abc_NtkDup(pNtkTemp, Abc_NtkMan(pNtkTemp)); + + return 0; +usage: + fprintf( pAbc->Err, "usage: undo\n" ); + fprintf( pAbc->Err, " swaps the current network and the backup network\n" ); + return 1; +} + +#endif + + +#ifdef WIN32 +/**Function************************************************************* + + Synopsis [Command to print the contents of the current directory (Windows).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +#include <io.h> + +// these structures are defined in <io.h> but are for some reason invisible +typedef unsigned long _fsize_t; // Could be 64 bits for Win32 + +struct _finddata_t { + unsigned attrib; + time_t time_create; // -1 for FAT file systems + time_t time_access; // -1 for FAT file systems + time_t time_write; + _fsize_t size; + char name[260]; +}; + +extern long _findfirst( char *filespec, struct _finddata_t *fileinfo ); +extern int _findnext( long handle, struct _finddata_t *fileinfo ); +extern int _findclose( long handle ); + +int CmdCommandLs( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + struct _finddata_t c_file; + long hFile; + int fLong = 0; + int fOnlyBLIF = 0; + char Buffer[25]; + int Counter = 0; + int fPrintedNewLine; + char c; + + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "lb") ) != EOF ) + { + switch (c) + { + case 'l': + fLong = 1; + break; + case 'b': + fOnlyBLIF = 1; + break; + default: + goto usage; + } + } + + // find first .mv file in current directory + if( (hFile = _findfirst( ((fOnlyBLIF)? "*.mv": "*.*"), &c_file )) == -1L ) + { + if ( fOnlyBLIF ) + fprintf( pAbc->Out, "No *.mv files in the current directory.\n" ); + else + fprintf( pAbc->Out, "No files in the current directory.\n" ); + } + else + { + if ( fLong ) + { + fprintf( pAbc->Out, " File Date Size | File Date Size \n" ); + fprintf( pAbc->Out, " ----------------------------------------------------------------------------- \n" ); + do + { + strcpy( Buffer, ctime( &(c_file.time_write) ) ); + Buffer[16] = 0; + fprintf( pAbc->Out, " %-17s %.24s%7ld", c_file.name, Buffer+4, c_file.size ); + if ( ++Counter % 2 == 0 ) + { + fprintf( pAbc->Out, "\n" ); + fPrintedNewLine = 1; + } + else + { + fprintf( pAbc->Out, " |" ); + fPrintedNewLine = 0; + } + } + while( _findnext( hFile, &c_file ) == 0 ); + } + else + { + do + { + fprintf( pAbc->Out, " %-18s", c_file.name ); + if ( ++Counter % 4 == 0 ) + { + fprintf( pAbc->Out, "\n" ); + fPrintedNewLine = 1; + } + else + { + fprintf( pAbc->Out, " " ); + fPrintedNewLine = 0; + } + } + while( _findnext( hFile, &c_file ) == 0 ); + } + if ( !fPrintedNewLine ) + fprintf( pAbc->Out, "\n" ); + _findclose( hFile ); + } + return 0; + +usage: + fprintf( pAbc->Err, "Usage: ls [-l] [-b]\n" ); + fprintf( pAbc->Err, " print the file names in the current directory\n" ); + fprintf( pAbc->Err, " -l : print in the long format [default = short]\n" ); + fprintf( pAbc->Err, " -b : print only .mv files [default = all]\n" ); + return 1; +} +#endif + + + +#ifdef WIN32 +#define unlink _unlink +#endif + +/**Function******************************************************************** + + Synopsis [Calls SIS internally.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pFile; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkNew, * pNetlist; + char * pNameWin = "sis.exe"; + char * pNameUnix = "sis"; + char Command[1000], Buffer[100]; + char * pSisName; + int i; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + goto usage; + } + + if ( strcmp( argv[0], "sis" ) != 0 ) + { + fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] ); + goto usage; + } + + if ( argc == 1 ) + goto usage; + if ( strcmp( argv[1], "-h" ) == 0 ) + goto usage; + if ( strcmp( argv[1], "-?" ) == 0 ) + goto usage; + + // get the names from the resource file + if ( Cmd_FlagReadByName(pAbc, "siswin") ) + pNameWin = Cmd_FlagReadByName(pAbc, "siswin"); + if ( Cmd_FlagReadByName(pAbc, "sisunix") ) + pNameUnix = Cmd_FlagReadByName(pAbc, "sisunix"); + + // check if SIS is available + if ( (pFile = fopen( pNameWin, "r" )) ) + pSisName = pNameWin; + else if ( (pFile = fopen( pNameUnix, "r" )) ) + pSisName = pNameUnix; + else if ( pFile == NULL ) + { + fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pNameWin, pNameUnix ); + goto usage; + } + fclose( pFile ); + + if ( Abc_NtkIsMappedLogic(pNtk) ) + { + Abc_NtkMapToSop(pNtk); + printf( "The current network is unmapped before calling SIS.\n" ); + } + + // write out the current network + if ( Abc_NtkIsLogic(pNtk) ) + Abc_NtkToSop(pNtk, 0); + pNetlist = Abc_NtkToNetlist(pNtk); + if ( pNetlist == NULL ) + { + fprintf( pErr, "Cannot produce the intermediate network.\n" ); + goto usage; + } + Io_WriteBlif( pNetlist, "_sis_in.blif", 1 ); + Abc_NtkDelete( pNetlist ); + + // create the file for sis + sprintf( Command, "%s -x -c ", pSisName ); + strcat ( Command, "\"" ); + strcat ( Command, "read_blif _sis_in.blif" ); + strcat ( Command, "; " ); + for ( i = 1; i < argc; i++ ) + { + sprintf( Buffer, " %s", argv[i] ); + strcat( Command, Buffer ); + } + strcat( Command, "; " ); + strcat( Command, "write_blif _sis_out.blif" ); + strcat( Command, "\"" ); + + // call SIS + if ( system( Command ) ) + { + fprintf( pErr, "The following command has returned non-zero exit status:\n" ); + fprintf( pErr, "\"%s\"\n", Command ); + unlink( "_sis_in.blif" ); + goto usage; + } + + // read in the SIS output + if ( (pFile = fopen( "_sis_out.blif", "r" )) == NULL ) + { + fprintf( pErr, "Cannot open SIS output file \"%s\".\n", "_sis_out.blif" ); + unlink( "_sis_in.blif" ); + goto usage; + } + fclose( pFile ); + + // set the new network + pNtkNew = Io_Read( "_sis_out.blif", IO_FILE_BLIF, 1 ); + // set the original spec of the new network + if ( pNtk->pSpec ) + { + FREE( pNtkNew->pSpec ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); + + // remove temporary networks + unlink( "_sis_in.blif" ); + unlink( "_sis_out.blif" ); + return 0; + +usage: + fprintf( pErr, "\n" ); + fprintf( pErr, "Usage: sis [-h] <com>\n"); + fprintf( pErr, " invokes SIS command for the current ABC network\n" ); + fprintf( pErr, " (the executable of SIS should be in the same directory)\n" ); + fprintf( pErr, " -h : print the command usage\n" ); + fprintf( pErr, " <com> : a SIS command (or a semicolon-separated list of commands in quotes)\n" ); + fprintf( pErr, " Example 1: sis eliminate 0\n" ); + fprintf( pErr, " Example 2: sis \"ps; rd; fx; ps\"\n" ); + fprintf( pErr, " Example 3: sis source script.rugged\n" ); + return 1; // error exit +} + + +/**Function******************************************************************** + + Synopsis [Calls SIS internally.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pFile; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkNew, * pNetlist; + char Command[1000], Buffer[100]; + char * pNameWin = "mvsis.exe"; + char * pNameUnix = "mvsis"; + char * pMvsisName; + int i; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + goto usage; + } + + if ( strcmp( argv[0], "mvsis" ) != 0 ) + { + fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] ); + goto usage; + } + + if ( argc == 1 ) + goto usage; + if ( strcmp( argv[1], "-h" ) == 0 ) + goto usage; + if ( strcmp( argv[1], "-?" ) == 0 ) + goto usage; + + // get the names from the resource file + if ( Cmd_FlagReadByName(pAbc, "mvsiswin") ) + pNameWin = Cmd_FlagReadByName(pAbc, "mvsiswin"); + if ( Cmd_FlagReadByName(pAbc, "mvsisunix") ) + pNameUnix = Cmd_FlagReadByName(pAbc, "mvsisunix"); + + // check if MVSIS is available + if ( (pFile = fopen( pNameWin, "r" )) ) + pMvsisName = pNameWin; + else if ( (pFile = fopen( pNameUnix, "r" )) ) + pMvsisName = pNameUnix; + else if ( pFile == NULL ) + { + fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pNameWin, pNameUnix ); + goto usage; + } + fclose( pFile ); + + if ( Abc_NtkIsMappedLogic(pNtk) ) + { + Abc_NtkMapToSop(pNtk); + printf( "The current network is unmapped before calling MVSIS.\n" ); + } + + // write out the current network + if ( Abc_NtkIsLogic(pNtk) ) + Abc_NtkToSop(pNtk, 0); + pNetlist = Abc_NtkToNetlist(pNtk); + if ( pNetlist == NULL ) + { + fprintf( pErr, "Cannot produce the intermediate network.\n" ); + goto usage; + } + Io_WriteBlif( pNetlist, "_mvsis_in.blif", 1 ); + Abc_NtkDelete( pNetlist ); + + // create the file for MVSIS + sprintf( Command, "%s -x -c ", pMvsisName ); + strcat ( Command, "\"" ); + strcat ( Command, "read_blif _mvsis_in.blif" ); + strcat ( Command, "; " ); + for ( i = 1; i < argc; i++ ) + { + sprintf( Buffer, " %s", argv[i] ); + strcat( Command, Buffer ); + } + strcat( Command, "; " ); + strcat( Command, "write_blif _mvsis_out.blif" ); + strcat( Command, "\"" ); + + // call MVSIS + if ( system( Command ) ) + { + fprintf( pErr, "The following command has returned non-zero exit status:\n" ); + fprintf( pErr, "\"%s\"\n", Command ); + unlink( "_mvsis_in.blif" ); + goto usage; + } + + // read in the MVSIS output + if ( (pFile = fopen( "_mvsis_out.blif", "r" )) == NULL ) + { + fprintf( pErr, "Cannot open MVSIS output file \"%s\".\n", "_mvsis_out.blif" ); + unlink( "_mvsis_in.blif" ); + goto usage; + } + fclose( pFile ); + + // set the new network + pNtkNew = Io_Read( "_mvsis_out.blif", IO_FILE_BLIF, 1 ); + // set the original spec of the new network + if ( pNtk->pSpec ) + { + FREE( pNtkNew->pSpec ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); + + // remove temporary networks + unlink( "_mvsis_in.blif" ); + unlink( "_mvsis_out.blif" ); + return 0; + +usage: + fprintf( pErr, "\n" ); + fprintf( pErr, "Usage: mvsis [-h] <com>\n"); + fprintf( pErr, " invokes MVSIS command for the current ABC network\n" ); + fprintf( pErr, " (the executable of MVSIS should be in the same directory)\n" ); + fprintf( pErr, " -h : print the command usage\n" ); + fprintf( pErr, " <com> : a MVSIS command (or a semicolon-separated list of commands in quotes)\n" ); + fprintf( pErr, " Example 1: mvsis fraig_sweep\n" ); + fprintf( pErr, " Example 2: mvsis \"ps; fxu; ps\"\n" ); + fprintf( pErr, " Example 3: mvsis source mvsis.rugged\n" ); + return 1; // error exit +} + + +/**Function******************************************************************** + + Synopsis [Calls Capo internally.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandCapo( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pFile; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNetlist; + char Command[1000], Buffer[100]; + char * pProgNameCapoWin = "capo.exe"; + char * pProgNameCapoUnix = "capo"; + char * pProgNameGnuplotWin = "wgnuplot.exe"; + char * pProgNameGnuplotUnix = "gnuplot"; + char * pProgNameCapo; + char * pProgNameGnuplot; + char * pPlotFileName; + int i; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + goto usage; + } + + if ( strcmp( argv[0], "capo" ) != 0 ) + { + fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] ); + goto usage; + } + + if ( argc > 1 ) + { + if ( strcmp( argv[1], "-h" ) == 0 ) + goto usage; + if ( strcmp( argv[1], "-?" ) == 0 ) + goto usage; + } + + // get the names from the resource file + if ( Cmd_FlagReadByName(pAbc, "capowin") ) + pProgNameCapoWin = Cmd_FlagReadByName(pAbc, "capowin"); + if ( Cmd_FlagReadByName(pAbc, "capounix") ) + pProgNameCapoUnix = Cmd_FlagReadByName(pAbc, "capounix"); + + // check if capo is available + if ( (pFile = fopen( pProgNameCapoWin, "r" )) ) + pProgNameCapo = pProgNameCapoWin; + else if ( (pFile = fopen( pProgNameCapoUnix, "r" )) ) + pProgNameCapo = pProgNameCapoUnix; + else if ( pFile == NULL ) + { + fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameCapoWin, pProgNameCapoUnix ); + goto usage; + } + fclose( pFile ); + + if ( Abc_NtkIsMappedLogic(pNtk) ) + { + Abc_NtkMapToSop(pNtk); + printf( "The current network is unmapped before calling Capo.\n" ); + } + + // write out the current network + if ( Abc_NtkIsLogic(pNtk) ) + Abc_NtkToSop(pNtk, 0); + pNetlist = Abc_NtkToNetlist(pNtk); + if ( pNetlist == NULL ) + { + fprintf( pErr, "Cannot produce the intermediate network.\n" ); + goto usage; + } + Io_WriteBlif( pNetlist, "_capo_in.blif", 1 ); + Abc_NtkDelete( pNetlist ); + + // create the file for Capo + sprintf( Command, "%s -f _capo_in.blif -log out.txt ", pProgNameCapo ); + pPlotFileName = NULL; + for ( i = 1; i < argc; i++ ) + { + sprintf( Buffer, " %s", argv[i] ); + strcat( Command, Buffer ); + if ( !strcmp( argv[i], "-plot" ) ) + pPlotFileName = argv[i+1]; + } + + // call Capo + if ( system( Command ) ) + { + fprintf( pErr, "The following command has returned non-zero exit status:\n" ); + fprintf( pErr, "\"%s\"\n", Command ); + unlink( "_capo_in.blif" ); + goto usage; + } + // remove temporary networks + unlink( "_capo_in.blif" ); + if ( pPlotFileName == NULL ) + return 0; + + // get the file name + sprintf( Buffer, "%s.plt", pPlotFileName ); + pPlotFileName = Buffer; + + // read in the Capo plotting output + if ( (pFile = fopen( pPlotFileName, "r" )) == NULL ) + { + fprintf( pErr, "Cannot open the plot file \"%s\".\n\n", pPlotFileName ); + goto usage; + } + fclose( pFile ); + + // get the names from the plotting software + if ( Cmd_FlagReadByName(pAbc, "gnuplotwin") ) + pProgNameGnuplotWin = Cmd_FlagReadByName(pAbc, "gnuplotwin"); + if ( Cmd_FlagReadByName(pAbc, "gnuplotunix") ) + pProgNameGnuplotUnix = Cmd_FlagReadByName(pAbc, "gnuplotunix"); + + // check if Gnuplot is available + if ( (pFile = fopen( pProgNameGnuplotWin, "r" )) ) + pProgNameGnuplot = pProgNameGnuplotWin; + else if ( (pFile = fopen( pProgNameGnuplotUnix, "r" )) ) + pProgNameGnuplot = pProgNameGnuplotUnix; + else if ( pFile == NULL ) + { + fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameGnuplotWin, pProgNameGnuplotUnix ); + goto usage; + } + fclose( pFile ); + + // spawn the viewer +#ifdef WIN32 + if ( _spawnl( _P_NOWAIT, pProgNameGnuplot, pProgNameGnuplot, pPlotFileName, NULL ) == -1 ) + { + fprintf( stdout, "Cannot find \"%s\".\n", pProgNameGnuplot ); + goto usage; + } +#else + { + sprintf( Command, "%s %s ", pProgNameGnuplot, pPlotFileName ); + if ( system( Command ) == -1 ) + { + fprintf( stdout, "Cannot execute \"%s\".\n", Command ); + goto usage; + } + } +#endif + + // remove temporary networks +// unlink( pPlotFileName ); + return 0; + +usage: + fprintf( pErr, "\n" ); + fprintf( pErr, "Usage: capo [-h] <com>\n"); + fprintf( pErr, " peforms placement of the current network using Capo\n" ); + fprintf( pErr, " a Capo binary should be present in the same directory\n" ); + fprintf( pErr, " (if plotting, the Gnuplot binary should also be present)\n" ); + fprintf( pErr, " -h : print the command usage\n" ); + fprintf( pErr, " <com> : a Capo command\n" ); + fprintf( pErr, " Example 1: capo\n" ); + fprintf( pErr, " (performs placement with default options)\n" ); + fprintf( pErr, " Example 2: capo -AR <aspec_ratio> -WS <whitespace_percentage> -save\n" ); + fprintf( pErr, " (specifies the aspect ratio [default = 1.0] and\n" ); + fprintf( pErr, " the whitespace percentage [0%%; 100%%) [default = 15%%])\n" ); + fprintf( pErr, " Example 3: capo -plot <base_fileName>\n" ); + fprintf( pErr, " (produces <base_fileName.plt> and visualize it using Gnuplot)\n" ); + fprintf( pErr, " Example 4: capo -help\n" ); + fprintf( pErr, " (prints the default usage message of the Capo binary)\n" ); + fprintf( pErr, " Please refer to the Capo webpage for additional information:\n" ); + fprintf( pErr, " http://vlsicad.eecs.umich.edu/BK/PDtools/\n" ); + return 1; // error exit +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/cmd/cmd.h b/abc70930/src/base/cmd/cmd.h new file mode 100644 index 00000000..030b77e8 --- /dev/null +++ b/abc70930/src/base/cmd/cmd.h @@ -0,0 +1,73 @@ +/**CFile**************************************************************** + + FileName [cmd.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [External declarations of the command package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CMD_H__ +#define __CMD_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct MvCommand Abc_Command; // one command +typedef struct MvAlias Abc_Alias; // one alias + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cmd.c ===========================================================*/ +extern void Cmd_Init(); +extern void Cmd_End(); +/*=== cmdApi.c ========================================================*/ +extern void Cmd_CommandAdd( Abc_Frame_t * pAbc, char * sGroup, char * sName, void * pFunc, int fChanges ); +extern int Cmd_CommandExecute( Abc_Frame_t * pAbc, char * sCommand ); +/*=== cmdFlag.c ========================================================*/ +extern char * Cmd_FlagReadByName( Abc_Frame_t * pAbc, char * flag ); +extern void Cmd_FlagDeleteByName( Abc_Frame_t * pAbc, char * key ); +extern void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, char * key, char * value ); +/*=== cmdHist.c ========================================================*/ +extern void Cmd_HistoryAddCommand( Abc_Frame_t * pAbc, char * command ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/base/cmd/cmdAlias.c b/abc70930/src/base/cmd/cmdAlias.c new file mode 100644 index 00000000..0ec3feea --- /dev/null +++ b/abc70930/src/base/cmd/cmdAlias.c @@ -0,0 +1,120 @@ +/**CFile**************************************************************** + + FileName [cmdAlias.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures dealing with aliases in the command package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmdAlias.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cmdInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** argv ) +{ + Abc_Alias * pAlias; + int fStatus, i; + + pAlias = ALLOC(Abc_Alias, 1); + pAlias->sName = Extra_UtilStrsav(sName); + pAlias->argc = argc; + pAlias->argv = ALLOC(char *, pAlias->argc); + for(i = 0; i < argc; i++) + pAlias->argv[i] = Extra_UtilStrsav(argv[i]); + fStatus = st_insert( pAbc->tAliases, pAlias->sName, (char *) pAlias ); + assert(!fStatus); +} + +/**Function******************************************************************** + + Synopsis [required] + + Description [optional] + + SideEffects [required] + + SeeAlso [optional] + +******************************************************************************/ +void CmdCommandAliasPrint( Abc_Frame_t * pAbc, Abc_Alias * pAlias ) +{ + int i; + fprintf(pAbc->Out, "%-15s", pAlias->sName); + for(i = 0; i < pAlias->argc; i++) + fprintf( pAbc->Out, " %s", pAlias->argv[i] ); + fprintf( pAbc->Out, "\n" ); +} + +/**Function******************************************************************** + + Synopsis [required] + + Description [optional] + + SideEffects [required] + + SeeAlso [optional] + +******************************************************************************/ +char * CmdCommandAliasLookup( Abc_Frame_t * pAbc, char * sCommand ) +{ + Abc_Alias * pAlias; + char * value; + if (!st_lookup( pAbc->tAliases, sCommand, &value)) + return sCommand; + pAlias = (Abc_Alias *) value; + return pAlias->argv[0]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CmdCommandAliasFree( Abc_Alias * pAlias ) +{ + CmdFreeArgv( pAlias->argc, pAlias->argv ); + FREE(pAlias->sName); + FREE(pAlias); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/cmd/cmdApi.c b/abc70930/src/base/cmd/cmdApi.c new file mode 100644 index 00000000..7167e22b --- /dev/null +++ b/abc70930/src/base/cmd/cmdApi.c @@ -0,0 +1,104 @@ +/**CFile**************************************************************** + + FileName [cmdApi.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [External procedures of the command package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmdApi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" +#include "cmdInt.h" +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cmd_CommandAdd( Abc_Frame_t * pAbc, char * sGroup, char * sName, void * pFunc, int fChanges ) +{ + char * key, * value; + Abc_Command * pCommand; + int fStatus; + + key = sName; + if ( st_delete( pAbc->tCommands, &key, &value ) ) + { + // delete existing definition for this command + fprintf( pAbc->Err, "Cmd warning: redefining '%s'\n", sName ); + CmdCommandFree( (Abc_Command *)value ); + } + + // create the new command + pCommand = ALLOC( Abc_Command, 1 ); + pCommand->sName = Extra_UtilStrsav( sName ); + pCommand->sGroup = Extra_UtilStrsav( sGroup ); + pCommand->pFunc = pFunc; + pCommand->fChange = fChanges; + fStatus = st_insert( pAbc->tCommands, sName, (char *)pCommand ); + assert( !fStatus ); // the command should not be in the table +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cmd_CommandExecute( Abc_Frame_t * pAbc, char * sCommand ) +{ + int fStatus = 0, argc, loop; + char * sCommandNext, **argv; + + if ( !pAbc->fAutoexac ) + Cmd_HistoryAddCommand(pAbc, sCommand); + sCommandNext = sCommand; + do + { + sCommandNext = CmdSplitLine( pAbc, sCommandNext, &argc, &argv ); + loop = 0; + fStatus = CmdApplyAlias( pAbc, &argc, &argv, &loop ); + if ( fStatus == 0 ) + fStatus = CmdCommandDispatch( pAbc, argc, argv ); + CmdFreeArgv( argc, argv ); + } + while ( fStatus == 0 && *sCommandNext != '\0' ); + return fStatus; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/cmd/cmdFlag.c b/abc70930/src/base/cmd/cmdFlag.c new file mode 100644 index 00000000..993f2a49 --- /dev/null +++ b/abc70930/src/base/cmd/cmdFlag.c @@ -0,0 +1,104 @@ +/**CFile**************************************************************** + + FileName [cmdFlag.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures working with flags.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmdFlag.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function******************************************************************** + + Synopsis [Looks up value of flag in table of named values.] + + Description [The command parser maintains a table of named values. These + are manipulated using the 'set' and 'unset' commands. The value of the + named flag is returned, or NULL is returned if the flag has not been set.] + + SideEffects [] + +******************************************************************************/ +char * Cmd_FlagReadByName( Abc_Frame_t * pAbc, char * flag ) +{ + char * value; + if ( st_lookup(pAbc->tFlags, flag, &value) ) + return value; + return NULL; +} + + +/**Function******************************************************************** + + Synopsis [Updates a set value by calling instead of set command.] + + Description [Updates a set value by calling instead of set command.] + + SideEffects [] + +******************************************************************************/ +void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, char * key, char * value ) +{ + char * oldValue, * newValue; + if ( !key ) + return; + if ( value ) + newValue = Extra_UtilStrsav(value); + else + newValue = Extra_UtilStrsav(""); +// newValue = NULL; + if ( st_delete(pAbc->tFlags, &key, &oldValue) ) + FREE(oldValue); + st_insert( pAbc->tFlags, key, newValue ); +} + + +/**Function******************************************************************** + + Synopsis [Deletes a set value by calling instead of unset command.] + + Description [Deletes a set value by calling instead of unset command.] + + SideEffects [] + +******************************************************************************/ +void Cmd_FlagDeleteByName( Abc_Frame_t * pAbc, char * key ) +{ + char *value; + if ( !key ) + return; + if ( st_delete( pAbc->tFlags, &key, &value ) ) + { + FREE(key); + FREE(value); + } +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/cmd/cmdHist.c b/abc70930/src/base/cmd/cmdHist.c new file mode 100644 index 00000000..fae9382d --- /dev/null +++ b/abc70930/src/base/cmd/cmdHist.c @@ -0,0 +1,55 @@ +/**CFile**************************************************************** + + FileName [cmdHist.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures working with history.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmdHist.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" +#include "cmd.h" +#include "cmdInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cmd_HistoryAddCommand( Abc_Frame_t * p, char * command ) +{ + static char Buffer[MAX_STR]; + strcpy( Buffer, command ); + if ( command[strlen(command)-1] != '\n' ) + strcat( Buffer, "\n" ); + Vec_PtrPush( p->aHistory, Extra_UtilStrsav(Buffer) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/base/cmd/cmdInt.h b/abc70930/src/base/cmd/cmdInt.h new file mode 100644 index 00000000..c082bd94 --- /dev/null +++ b/abc70930/src/base/cmd/cmdInt.h @@ -0,0 +1,83 @@ +/**CFile**************************************************************** + + FileName [cmdInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Internal declarations of the command package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmdInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CMD_INT_H__ +#define __CMD_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "mainInt.h" +#include "cmd.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +struct MvCommand +{ + char * sName; // the command name + char * sGroup; // the group name + void * pFunc; // the function to execute the command + int fChange; // set to 1 to mark that the network is changed +}; + +struct MvAlias +{ + char * sName; // the alias name + int argc; // the number of alias parts + char ** argv; // the alias parts +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cmdAlias.c =============-========================================*/ +extern void CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** argv ); +extern void CmdCommandAliasPrint( Abc_Frame_t * pAbc, Abc_Alias * pAlias ); +extern char * CmdCommandAliasLookup( Abc_Frame_t * pAbc, char * sCommand ); +extern void CmdCommandAliasFree( Abc_Alias * p ); +/*=== cmdUtils.c =======================================================*/ +extern int CmdCommandDispatch( Abc_Frame_t * pAbc, int argc, char ** argv ); +extern char * CmdSplitLine( Abc_Frame_t * pAbc, char * sCommand, int * argc, char *** argv ); +extern int CmdApplyAlias( Abc_Frame_t * pAbc, int * argc, char *** argv, int * loop ); +extern char * CmdHistorySubstitution( Abc_Frame_t * pAbc, char * line, int * changed ); +extern FILE * CmdFileOpen( Abc_Frame_t * pAbc, char * sFileName, char * sMode, char ** pFileNameReal, int silent ); +extern void CmdFreeArgv( int argc, char ** argv ); +extern void CmdCommandFree( Abc_Command * pCommand ); +extern void CmdCommandPrint( Abc_Frame_t * pAbc, bool fPrintAll ); +extern void CmdPrintTable( st_table * tTable, int fAliases ); + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif + diff --git a/abc70930/src/base/cmd/cmdUtils.c b/abc70930/src/base/cmd/cmdUtils.c new file mode 100644 index 00000000..47e54bb3 --- /dev/null +++ b/abc70930/src/base/cmd/cmdUtils.c @@ -0,0 +1,649 @@ +/**CFile**************************************************************** + + FileName [cmdUtils.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Various utilities of the command package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmdUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" +#include "abc.h" +#include "cmdInt.h" +#include <ctype.h> // proper declaration of isspace + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int CmdCommandPrintCompare( Abc_Command ** ppC1, Abc_Command ** ppC2 ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int cmdCheckShellEscape( Abc_Frame_t * pAbc, int argc, char ** argv) +{ + if (argv[0][0] == '!') + { + const int size = 4096; + int i; + char buffer[4096]; + strncpy (buffer, &argv[0][1], size); + for (i = 1; i < argc; ++i) + { + strncat (buffer, " ", size); + strncat (buffer, argv[i], size); + } + if (buffer[0] == 0) + strncpy (buffer, "/bin/sh", size); + system (buffer); + + // NOTE: Since we reconstruct the cmdline by concatenating + // the parts, we lose information. So a command like + // `!ls "file name"` will be sent to the system as + // `ls file name` which is a BUG + + return 1; + } + else + { + return 0; + } +} + +/**Function************************************************************* + + Synopsis [Executes one command.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CmdCommandDispatch( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNetCopy; + int (*pFunc) ( Abc_Frame_t *, int, char ** ); + Abc_Command * pCommand; + char * value; + int fError; + int clk; + + if ( argc == 0 ) + return 0; + + if ( cmdCheckShellEscape( pAbc, argc, argv ) == 1 ) + return 0; + + // get the command + if ( !st_lookup( pAbc->tCommands, argv[0], (char **)&pCommand ) ) + { // the command is not in the table + fprintf( pAbc->Err, "** cmd error: unknown command '%s'\n", argv[0] ); + return 1; + } + + // get the backup network if the command is going to change the network + if ( pCommand->fChange ) + { + if ( pAbc->pNtkCur && Abc_FrameIsFlagEnabled( "backup" ) ) + { + pNetCopy = Abc_NtkDup( pAbc->pNtkCur ); + Abc_FrameSetCurrentNetwork( pAbc, pNetCopy ); + // swap the current network and the backup network + // to prevent the effect of resetting the short names + Abc_FrameSwapCurrentAndBackup( pAbc ); + } + } + + // execute the command + clk = Extra_CpuTime(); + pFunc = (int (*)(Abc_Frame_t *, int, char **))pCommand->pFunc; + fError = (*pFunc)( pAbc, argc, argv ); + pAbc->TimeCommand += (Extra_CpuTime() - clk); + + // automatic execution of arbitrary command after each command + // usually this is a passive command ... + if ( fError == 0 && !pAbc->fAutoexac ) + { + if ( st_lookup( pAbc->tFlags, "autoexec", &value ) ) + { + pAbc->fAutoexac = 1; + fError = Cmd_CommandExecute( pAbc, value ); + pAbc->fAutoexac = 0; + } + } + return fError; +} + +/**Function************************************************************* + + Synopsis [Splits the command line string into individual commands.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * CmdSplitLine( Abc_Frame_t * pAbc, char *sCommand, int *argc, char ***argv ) +{ + char *p, *start, c; + int i, j; + char *new_arg; + Vec_Ptr_t * vArgs; + int single_quote, double_quote; + + vArgs = Vec_PtrAlloc( 10 ); + + p = sCommand; + for ( ;; ) + { + // skip leading white space + while ( isspace( ( int ) *p ) ) + { + p++; + } + + // skip until end of this token + single_quote = double_quote = 0; + for ( start = p; ( c = *p ) != '\0'; p++ ) + { + if ( c == ';' || c == '#' || isspace( ( int ) c ) ) + { + if ( !single_quote && !double_quote ) + { + break; + } + } + if ( c == '\'' ) + { + single_quote = !single_quote; + } + if ( c == '"' ) + { + double_quote = !double_quote; + } + } + if ( single_quote || double_quote ) + { + ( void ) fprintf( pAbc->Err, "** cmd warning: ignoring unbalanced quote ...\n" ); + } + if ( start == p ) + break; + + new_arg = ALLOC( char, p - start + 1 ); + j = 0; + for ( i = 0; i < p - start; i++ ) + { + c = start[i]; + if ( ( c != '\'' ) && ( c != '\"' ) ) + { + new_arg[j++] = isspace( ( int ) c ) ? ' ' : start[i]; + } + } + new_arg[j] = '\0'; + Vec_PtrPush( vArgs, new_arg ); + } + + *argc = vArgs->nSize; + *argv = (char **)Vec_PtrReleaseArray( vArgs ); + Vec_PtrFree( vArgs ); + if ( *p == ';' ) + { + p++; + } + else if ( *p == '#' ) + { + for ( ; *p != 0; p++ ); // skip to end of line + } + return p; +} + +/**Function************************************************************* + + Synopsis [Replaces parts of the command line string by aliases if given.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop ) +{ + int i, argc, stopit, added, offset, did_subst, subst, fError, newc, j; + char *arg, **argv, **newv; + Abc_Alias *alias; + + argc = *argcp; + argv = *argvp; + stopit = 0; + for ( ; *loop < 200; ( *loop )++ ) + { + if ( argc == 0 ) + return 0; + if ( stopit != 0 || st_lookup( pAbc->tAliases, argv[0], (char **) &alias ) == 0 ) + { + return 0; + } + if ( strcmp( argv[0], alias->argv[0] ) == 0 ) + { + stopit = 1; + } + FREE( argv[0] ); + added = alias->argc - 1; + + /* shift all the arguments to the right */ + if ( added != 0 ) + { + argv = REALLOC( char *, argv, argc + added ); + for ( i = argc - 1; i >= 1; i-- ) + { + argv[i + added] = argv[i]; + } + for ( i = 1; i <= added; i++ ) + { + argv[i] = NULL; + } + argc += added; + } + subst = 0; + for ( i = 0, offset = 0; i < alias->argc; i++, offset++ ) + { + arg = CmdHistorySubstitution( pAbc, alias->argv[i], &did_subst ); + if ( arg == NULL ) + { + *argcp = argc; + *argvp = argv; + return ( 1 ); + } + if ( did_subst != 0 ) + { + subst = 1; + } + fError = 0; + do + { + arg = CmdSplitLine( pAbc, arg, &newc, &newv ); + /* + * If there's a complete `;' terminated command in `arg', + * when split_line() returns arg[0] != '\0'. + */ + if ( arg[0] == '\0' ) + { /* just a bunch of words */ + break; + } + fError = CmdApplyAlias( pAbc, &newc, &newv, loop ); + if ( fError == 0 ) + { + fError = CmdCommandDispatch( pAbc, newc, newv ); + } + CmdFreeArgv( newc, newv ); + } + while ( fError == 0 ); + if ( fError != 0 ) + { + *argcp = argc; + *argvp = argv; + return ( 1 ); + } + added = newc - 1; + if ( added != 0 ) + { + argv = REALLOC( char *, argv, argc + added ); + for ( j = argc - 1; j > offset; j-- ) + { + argv[j + added] = argv[j]; + } + argc += added; + } + for ( j = 0; j <= added; j++ ) + { + argv[j + offset] = newv[j]; + } + FREE( newv ); + offset += added; + } + if ( subst == 1 ) + { + for ( i = offset; i < argc; i++ ) + { + FREE( argv[i] ); + } + argc = offset; + } + *argcp = argc; + *argvp = argv; + } + + fprintf( pAbc->Err, "** cmd warning: alias loop\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs history substitution (now, disabled).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * CmdHistorySubstitution( Abc_Frame_t * pAbc, char *line, int *changed ) +{ + // as of today, no history substitution + *changed = 0; + return line; +} + +/**Function************************************************************* + + Synopsis [Opens the file with path (now, disabled).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +FILE * CmdFileOpen( Abc_Frame_t * pAbc, char *sFileName, char *sMode, char **pFileNameReal, int silent ) +{ + char * sRealName, * sPathUsr, * sPathLib, * sPathAll; + FILE * pFile; + + if (strcmp(sFileName, "-") == 0) { + if (strcmp(sMode, "w") == 0) { + sRealName = Extra_UtilStrsav( "stdout" ); + pFile = stdout; + } + else { + sRealName = Extra_UtilStrsav( "stdin" ); + pFile = stdin; + } + } + else { + sRealName = NULL; + if (strcmp(sMode, "r") == 0) { + + /* combine both pathes if exist */ + sPathUsr = Cmd_FlagReadByName(pAbc,"open_path"); + sPathLib = Cmd_FlagReadByName(pAbc,"lib_path"); + + if ( sPathUsr == NULL && sPathLib == NULL ) { + sPathAll = NULL; + } + else if ( sPathUsr == NULL ) { + sPathAll = Extra_UtilStrsav( sPathLib ); + } + else if ( sPathLib == NULL ) { + sPathAll = Extra_UtilStrsav( sPathUsr ); + } + else { + sPathAll = ALLOC( char, strlen(sPathLib)+strlen(sPathUsr)+5 ); + sprintf( sPathAll, "%s:%s",sPathUsr, sPathLib ); + } + if ( sPathAll != NULL ) { + sRealName = Extra_UtilFileSearch(sFileName, sPathAll, "r"); + FREE( sPathAll ); + } + } + if (sRealName == NULL) { + sRealName = Extra_UtilTildeExpand(sFileName); + } + if ((pFile = fopen(sRealName, sMode)) == NULL) { + if (! silent) { + perror(sRealName); + } + } + } + if ( pFileNameReal ) + *pFileNameReal = sRealName; + else + FREE(sRealName); + + return pFile; +} + +/**Function************************************************************* + + Synopsis [Frees the previously allocated argv array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CmdFreeArgv( int argc, char **argv ) +{ + int i; + for ( i = 0; i < argc; i++ ) + FREE( argv[i] ); + FREE( argv ); +} + +/**Function************************************************************* + + Synopsis [Frees the previously allocated command.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CmdCommandFree( Abc_Command * pCommand ) +{ + free( pCommand->sGroup ); + free( pCommand->sName ); + free( pCommand ); +} + + +/**Function************************************************************* + + Synopsis [Prints commands alphabetically by group.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CmdCommandPrint( Abc_Frame_t * pAbc, bool fPrintAll ) +{ + char *key, *value; + st_generator * gen; + Abc_Command ** ppCommands; + Abc_Command * pCommands; + int nCommands, i; + char * sGroupCur; + int LenghtMax, nColumns, iCom = 0; + + // put all commands into one array + nCommands = st_count( pAbc->tCommands ); + ppCommands = ALLOC( Abc_Command *, nCommands ); + i = 0; + st_foreach_item( pAbc->tCommands, gen, &key, &value ) + { + pCommands = (Abc_Command *)value; + if ( fPrintAll || pCommands->sName[0] != '_' ) + ppCommands[i++] = pCommands; + } + nCommands = i; + + // sort command by group and then by name, alphabetically + qsort( (void *)ppCommands, nCommands, sizeof(Abc_Command *), + (int (*)(const void *, const void *)) CmdCommandPrintCompare ); + assert( CmdCommandPrintCompare( ppCommands, ppCommands + nCommands - 1 ) <= 0 ); + + // get the longest command name + LenghtMax = 0; + for ( i = 0; i < nCommands; i++ ) + if ( LenghtMax < (int)strlen(ppCommands[i]->sName) ) + LenghtMax = (int)strlen(ppCommands[i]->sName); + // get the number of columns + nColumns = 79 / (LenghtMax + 2); + + // print the starting message + fprintf( pAbc->Out, " Welcome to ABC!" ); + + // print the command by group + sGroupCur = NULL; + for ( i = 0; i < nCommands; i++ ) + if ( sGroupCur && strcmp( sGroupCur, ppCommands[i]->sGroup ) == 0 ) + { // this command belongs to the same group as the previous one + if ( iCom++ % nColumns == 0 ) + fprintf( pAbc->Out, "\n" ); + // print this command + fprintf( pAbc->Out, " %-*s", LenghtMax, ppCommands[i]->sName ); + } + else + { // this command starts the new group of commands + // start the new group + fprintf( pAbc->Out, "\n" ); + fprintf( pAbc->Out, "\n" ); + fprintf( pAbc->Out, "%s commands:\n", ppCommands[i]->sGroup ); + // print this command + fprintf( pAbc->Out, " %-*s", LenghtMax, ppCommands[i]->sName ); + // remember current command group + sGroupCur = ppCommands[i]->sGroup; + // reset the command counter + iCom = 1; + } + fprintf( pAbc->Out, "\n" ); + FREE( ppCommands ); +} + +/**Function************************************************************* + + Synopsis [Comparision function used for sorting commands.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CmdCommandPrintCompare( Abc_Command ** ppC1, Abc_Command ** ppC2 ) +{ + Abc_Command * pC1 = *ppC1; + Abc_Command * pC2 = *ppC2; + int RetValue; + + RetValue = strcmp( pC1->sGroup, pC2->sGroup ); + if ( RetValue < 0 ) + return -1; + if ( RetValue > 0 ) + return 1; + // the command belong to the same group + + // put commands with "_" at the end of the list + if ( pC1->sName[0] != '_' && pC2->sName[0] == '_' ) + return -1; + if ( pC1->sName[0] == '_' && pC2->sName[0] != '_' ) + return 1; + + RetValue = strcmp( pC1->sName, pC2->sName ); + if ( RetValue < 0 ) + return -1; + if ( RetValue > 0 ) + return 1; + // should not be two indentical commands + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Comparision function used for sorting commands.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CmdNamePrintCompare( char ** ppC1, char ** ppC2 ) +{ + return strcmp( *ppC1, *ppC2 ); +} + +/**Function************************************************************* + + Synopsis [Comparision function used for sorting commands.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CmdPrintTable( st_table * tTable, int fAliases ) +{ + st_generator * gen; + char ** ppNames; + char * key, * value; + int nNames, i; + + // collect keys in the array + ppNames = ALLOC( char *, st_count(tTable) ); + nNames = 0; + st_foreach_item( tTable, gen, &key, &value ) + ppNames[nNames++] = key; + + // sort array by name + qsort( (void *)ppNames, nNames, sizeof(char *), + (int (*)(const void *, const void *))CmdNamePrintCompare ); + + // print in this order + for ( i = 0; i < nNames; i++ ) + { + st_lookup( tTable, ppNames[i], &value ); + if ( fAliases ) + CmdCommandAliasPrint( Abc_FrameGetGlobalFrame(), (Abc_Alias *)value ); + else + fprintf( stdout, "%-15s %-15s\n", ppNames[i], value ); + } + free( ppNames ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/base/cmd/module.make b/abc70930/src/base/cmd/module.make new file mode 100644 index 00000000..1eca3f65 --- /dev/null +++ b/abc70930/src/base/cmd/module.make @@ -0,0 +1,6 @@ +SRC += src/base/cmd/cmd.c \ + src/base/cmd/cmdAlias.c \ + src/base/cmd/cmdApi.c \ + src/base/cmd/cmdFlag.c \ + src/base/cmd/cmdHist.c \ + src/base/cmd/cmdUtils.c diff --git a/abc70930/src/base/io/io.c b/abc70930/src/base/io/io.c new file mode 100644 index 00000000..7a5e4a5d --- /dev/null +++ b/abc70930/src/base/io/io.c @@ -0,0 +1,1954 @@ +/**CFile**************************************************************** + + FileName [io.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Command file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: io.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "mainInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int IoCommandRead ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadAiger ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadBaf ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadBench ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadDsd ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadEdif ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadInit ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadPla ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadTruth ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadVerilog ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadVer ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadVerLib ( Abc_Frame_t * pAbc, int argc, char **argv ); + +static int IoCommandWrite ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteHie ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteAiger ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteBaf ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteBench ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteCnf ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteDot ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteGml ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteList ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWritePla ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteVerLib ( Abc_Frame_t * pAbc, int argc, char **argv ); + +extern int glo_fMapped; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_Init( Abc_Frame_t * pAbc ) +{ + Cmd_CommandAdd( pAbc, "I/O", "read", IoCommandRead, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_aiger", IoCommandReadAiger, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_baf", IoCommandReadBaf, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_blif", IoCommandReadBlif, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_blif_mv", IoCommandReadBlifMv, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_bench", IoCommandReadBench, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_dsd", IoCommandReadDsd, 1 ); +// Cmd_CommandAdd( pAbc, "I/O", "read_edif", IoCommandReadEdif, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_eqn", IoCommandReadEqn, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_init", IoCommandReadInit, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_pla", IoCommandReadPla, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_truth", IoCommandReadTruth, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_verilog", IoCommandReadVerilog, 1 ); +// Cmd_CommandAdd( pAbc, "I/O", "read_ver", IoCommandReadVer, 1 ); +// Cmd_CommandAdd( pAbc, "I/O", "read_verlib", IoCommandReadVerLib, 0 ); + + Cmd_CommandAdd( pAbc, "I/O", "write", IoCommandWrite, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_hie", IoCommandWriteHie, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_aiger", IoCommandWriteAiger, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_baf", IoCommandWriteBaf, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_blif", IoCommandWriteBlif, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_blif_mv", IoCommandWriteBlifMv, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_bench", IoCommandWriteBench, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_cellnet", IoCommandWriteCellNet, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_counter", IoCommandWriteCounter, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_cnf", IoCommandWriteCnf, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_dot", IoCommandWriteDot, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_eqn", IoCommandWriteEqn, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_gml", IoCommandWriteGml, 0 ); +// Cmd_CommandAdd( pAbc, "I/O", "write_list", IoCommandWriteList, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_pla", IoCommandWritePla, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_verilog", IoCommandWriteVerilog, 0 ); +// Cmd_CommandAdd( pAbc, "I/O", "write_verlib", IoCommandWriteVerLib, 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_End() +{ +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + glo_fMapped = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "mch" ) ) != EOF ) + { + switch ( c ) + { + case 'm': + glo_fMapped ^= 1; + break; + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, Io_ReadFileType(pFileName), fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read [-mch] <file>\n" ); + fprintf( pAbc->Err, "\t replaces the current network by the network read from <file>\n" ); + fprintf( pAbc->Err, "\t by calling the parser that matches the extension of <file>\n" ); + fprintf( pAbc->Err, "\t (to read a hierarchical design, use \"read_hie\")\n" ); + fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadAiger( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_AIGER, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_aiger [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in the AIGER format (http://fmv.jku.at/aiger)\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadBaf( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_BAF, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_baf [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in Binary Aig Format (BAF)\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fReadAsAig; + int fCheck; + int c; + extern Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck ); + + fCheck = 1; + fReadAsAig = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ach" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fReadAsAig ^= 1; + break; + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + if ( fReadAsAig ) + pNtk = Io_ReadBlifAsAig( pFileName, fCheck ); + else +// pNtk = Io_Read( pFileName, IO_FILE_BLIF, fCheck ); + { + Abc_Ntk_t * pTemp; + pNtk = Io_ReadBlif( pFileName, fCheck ); + pNtk = Abc_NtkToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + } + + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_blif [-ach] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in binary BLIF format\n" ); + fprintf( pAbc->Err, "\t-a : toggle creating AIG while reading the file [default = %s]\n", fReadAsAig? "yes":"no" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadBlifMv( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_BLIFMV, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_blif_mv [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in BLIF-MV format\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_BENCH, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_bench [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in BENCH format\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pString; + int fCheck; + int c; + extern Abc_Ntk_t * Io_ReadDsd( char * pFormula ); + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pString = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_ReadDsd( pString ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_dsd [-h] <formula>\n" ); + fprintf( pAbc->Err, "\t parses a formula representing DSD of a function\n" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tformula : the formula representing disjoint-support decomposition (DSD)\n" ); + fprintf( pAbc->Err, "\t Example of a formula: !(a*(b+CA(!d,e*f,c))*79B3(g,h,i,k))\n" ); + fprintf( pAbc->Err, "\t where \'!\' is an INV, \'*\' is an AND, \'+\' is an XOR, \n" ); + fprintf( pAbc->Err, "\t CA and 79B3 are hexadecimal representations of truth tables\n" ); + fprintf( pAbc->Err, "\t (in this case CA=11001010 is truth table of MUX(Data0,Data1,Ctrl))\n" ); + fprintf( pAbc->Err, "\t The lower chars (a,b,c,etc) are reserved for elementary variables.\n" ); + fprintf( pAbc->Err, "\t The upper chars (A,B,C,etc) are reserved for hexadecimal digits.\n" ); + fprintf( pAbc->Err, "\t No spaces are allowed in formulas. In parantheses, LSB goes first.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_EDIF, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_edif [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in EDIF (works only for ISCAS benchmarks)\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_EQN, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_eqn [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in equation format\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadInit( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + extern void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Abc_NtkDup( pNtk ); + Io_ReadBenchInit( pNtk, pFileName ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_init [-h] <file>\n" ); + fprintf( pAbc->Err, "\t reads initial state of the network in BENCH format\n" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_PLA, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_pla [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in PLA\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadTruth( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pSopCover; + int fHex; + int c; + + fHex = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "xh" ) ) != EOF ) + { + switch ( c ) + { + case 'x': + fHex ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // convert truth table to SOP + if ( fHex ) + pSopCover = Abc_SopFromTruthHex(argv[globalUtilOptind]); + else + pSopCover = Abc_SopFromTruthBin(argv[globalUtilOptind]); + if ( pSopCover == NULL ) + { + fprintf( pAbc->Err, "Reading truth table has failed.\n" ); + return 1; + } + + pNtk = Abc_NtkCreateWithNode( pSopCover ); + free( pSopCover ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Deriving the network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_truth [-xh] <truth>\n" ); + fprintf( pAbc->Err, "\t creates network with node having given truth table\n" ); + fprintf( pAbc->Err, "\t-x : toggles between bin and hex representation [default = %s]\n", fHex? "hex":"bin" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\ttruth : truth table with most signficant bit first (e.g. 1000 for AND(a,b))\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + glo_fMapped = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "mch" ) ) != EOF ) + { + switch ( c ) + { + case 'm': + glo_fMapped ^= 1; + break; + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_VERILOG, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_verilog [-mch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in Verilog (IWLS 2002/2005 subset)\n" ); + fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadVer( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkNew; + Abc_Lib_t * pDesign; + char * pFileName; + FILE * pFile; + int fCheck; + int c; + extern Abc_Ntk_t * Abc_LibDeriveAig( Abc_Ntk_t * pNtk, Abc_Lib_t * pLib ); + extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); + + printf( "Stand-alone structural Verilog reader is available as command \"read_verilog\".\n" ); + return 0; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + pFileName = argv[globalUtilOptind]; + if ( (pFile = fopen( pFileName, "r" )) == NULL ) + { + fprintf( pAbc->Err, "Cannot open input file \"%s\". ", pFileName ); + if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) ) + fprintf( pAbc->Err, "Did you mean \"%s\"?", pFileName ); + fprintf( pAbc->Err, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pDesign = Ver_ParseFile( pFileName, Abc_FrameReadLibVer(), fCheck, 1 ); + if ( pDesign == NULL ) + { + fprintf( pAbc->Err, "Reading network from the verilog file has failed.\n" ); + return 1; + } + + // derive root design + pNtk = Abc_LibDeriveRoot( pDesign ); + Abc_LibFree( pDesign, NULL ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Deriving root module has failed.\n" ); + return 1; + } + + // derive the AIG network from this design + pNtkNew = Abc_LibDeriveAig( pNtk, Abc_FrameReadLibVer() ); + Abc_NtkDelete( pNtk ); + if ( pNtkNew == NULL ) + { + fprintf( pAbc->Err, "Converting root module to AIG has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_ver [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read a network in structural verilog (using current library)\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadVerLib( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Lib_t * pLibrary; + char * pFileName; + FILE * pFile; + int fCheck; + int c; + extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + pFileName = argv[globalUtilOptind]; + if ( (pFile = fopen( pFileName, "r" )) == NULL ) + { + fprintf( pAbc->Err, "Cannot open input file \"%s\". ", pFileName ); + if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) ) + fprintf( pAbc->Err, "Did you mean \"%s\"?", pFileName ); + fprintf( pAbc->Err, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pLibrary = Ver_ParseFile( pFileName, NULL, fCheck, 0 ); + if ( pLibrary == NULL ) + { + fprintf( pAbc->Err, "Reading library from the verilog file has failed.\n" ); + return 1; + } + printf( "The library contains %d gates.\n", st_count(pLibrary->tModules) ); + // free old library + if ( Abc_FrameReadLibVer() ) + Abc_LibFree( Abc_FrameReadLibVer(), NULL ); + // read new library + Abc_FrameSetLibVer( pLibrary ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_verlib [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read a gate library in structural verilog\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWrite( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write [-h] <file>\n" ); + fprintf( pAbc->Err, "\t writes the current network into <file> by calling\n" ); + fprintf( pAbc->Err, "\t the writer that matches the extension of <file>\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteHie( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pBaseName, * pFileName; + int c; + + glo_fMapped = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF ) + { + switch ( c ) + { + case 'm': + glo_fMapped ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 2 ) + goto usage; + // get the output file name + pBaseName = argv[globalUtilOptind]; + pFileName = argv[globalUtilOptind+1]; + // call the corresponding file writer +// Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) ); + Io_WriteHie( pAbc->pNtkCur, pBaseName, pFileName ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_hie [-h] <orig> <file>\n" ); + fprintf( pAbc->Err, "\t writes the current network into <file> by calling\n" ); + fprintf( pAbc->Err, "\t the hierarchical writer that matches the extension of <file>\n" ); + fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog for <orig> [default = %s]\n", glo_fMapped? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\torig : the name of the original file with the hierarchical design\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteAiger( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int fWriteSymbols; + int c; + + fWriteSymbols = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fWriteSymbols ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + if ( fWriteSymbols ) + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_AIGER ); + else + { + if ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) + { + fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" ); + return 1; + } + Io_WriteAiger( pAbc->pNtkCur, pFileName, 0 ); + } + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_aiger [-sh] <file>\n" ); + fprintf( pAbc->Err, "\t write the network in the AIGER format (http://fmv.jku.at/aiger)\n" ); + fprintf( pAbc->Err, "\t-s : toggle saving I/O names [default = %s]\n", fWriteSymbols? "yes" : "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .aig)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteBaf( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BAF ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_baf [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the network into a BLIF file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .baf)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIF ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_blif [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the network into a BLIF file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .blif)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteBlifMv( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIFMV ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_blif_mv [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the network into a BLIF-MV file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .mv)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int fUseLuts; + int c; + + fUseLuts = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLuts ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + if ( !fUseLuts ) + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BENCH ); + else + { + Abc_Ntk_t * pNtkTemp; + pNtkTemp = Abc_NtkToNetlist( pAbc->pNtkCur ); + Abc_NtkToAig( pNtkTemp ); + Io_WriteBenchLut( pNtkTemp, pFileName ); + Abc_NtkDelete( pNtkTemp ); + } + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_bench [-lh] <file>\n" ); + fprintf( pAbc->Err, "\t write the network in BENCH format\n" ); + fprintf( pAbc->Err, "\t-l : toggle using LUTs in the output [default = %s]\n", fUseLuts? "yes" : "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .bench)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + extern void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName ); + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + pNtk = pAbc->pNtkCur; + if ( pNtk == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pAbc->Out, "The network should be a logic network (if it an AIG, use command \"logic\")\n" ); + return 0; + } + Io_WriteCellNet( pNtk, pFileName ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_cellnet [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the network is the cellnet format\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + int fAllPrimes; + int fNewAlgo; + extern Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName ); + + fNewAlgo = 1; + fAllPrimes = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nph" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fNewAlgo ^= 1; + break; + case 'p': + fAllPrimes ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // check if the feature will be used + if ( Abc_NtkIsStrash(pAbc->pNtkCur) && fAllPrimes ) + { + fAllPrimes = 0; + printf( "Warning: Selected option to write all primes has no effect when deriving CNF from AIG.\n" ); + } + // call the corresponding file writer + if ( fNewAlgo ) + Abc_NtkDarToCnf( pAbc->pNtkCur, pFileName ); + else if ( fAllPrimes ) + Io_WriteCnf( pAbc->pNtkCur, pFileName, 1 ); + else + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_CNF ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_cnf [-nph] <file>\n" ); + fprintf( pAbc->Err, "\t write the miter cone into a CNF file\n" ); + fprintf( pAbc->Err, "\t-n : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes" : "no" ); + fprintf( pAbc->Err, "\t-p : toggle using all primes to enhance implicativity [default = %s]\n", fAllPrimes? "yes" : "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_DOT ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_dot [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the current network into a DOT file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + int fNames; + + fNames = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fNames ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + pNtk = pAbc->pNtkCur; + if ( pNtk == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + // get the input file name + pFileName = argv[globalUtilOptind]; + + if ( pNtk->pModel == NULL ) + { + fprintf( pAbc->Out, "Counter-example is not available.\n" ); + return 0; + } + + // write the counter-example into the file + { + Abc_Obj_t * pObj; + FILE * pFile = fopen( pFileName, "w" ); + int i; + if ( pFile == NULL ) + { + fprintf( stdout, "IoCommandWriteCounter(): Cannot open the output file \"%s\".\n", pFileName ); + return 1; + } + if ( fNames ) + { + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "%s=%c ", Abc_ObjName(pObj), '0'+(pNtk->pModel[i]==1) ); + } + else + { + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "%c", '0'+(pNtk->pModel[i]==1) ); + } + fprintf( pFile, "\n" ); + fclose( pFile ); + } + + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_counter [-nh] <file>\n" ); + fprintf( pAbc->Err, "\t writes the counter-example derived by \"prove\" or \"sat\"\n" ); + fprintf( pAbc->Err, "\t the file contains values for each PI in the natural order\n" ); + fprintf( pAbc->Err, "\t-n : write input names into the file [default = %s]\n", fNames? "yes": "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_EQN ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_eqn [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the current network in the equation format\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_GML ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_gml [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write network using graph representation formal GML\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteList( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int fUseHost; + int c; + + printf( "This command currently does not work.\n" ); + return 0; + + fUseHost = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fUseHost ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } +/* + if ( !Abc_NtkIsSeq(pAbc->pNtkCur) ) + { + fprintf( stdout, "IoCommandWriteList(): Can write adjacency list for sequential AIGs only.\n" ); + return 0; + } +*/ + // get the input file name + pFileName = argv[globalUtilOptind]; + // write the file + Io_WriteList( pAbc->pNtkCur, pFileName, fUseHost ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_list [-nh] <file>\n" ); + fprintf( pAbc->Err, "\t write network using graph representation formal GML\n" ); + fprintf( pAbc->Err, "\t-n : toggle writing host node [default = %s]\n", fUseHost? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_PLA ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_pla [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the collapsed network into a PLA file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_VERILOG ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_verilog [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the current network in Verilog format\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteVerLib( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Lib_t * pLibrary; + char * pFileName; + int c; + extern void Io_WriteVerilogLibrary( Abc_Lib_t * pLibrary, char * pFileName ); + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // derive the netlist + pLibrary = Abc_FrameReadLibVer(); + if ( pLibrary == NULL ) + { + fprintf( pAbc->Out, "Verilog library is not specified.\n" ); + return 0; + } +// Io_WriteVerilogLibrary( pLibrary, pFileName ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_verlib [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the current verilog library\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/io.h b/abc70930/src/base/io/io.h new file mode 100644 index 00000000..45762b77 --- /dev/null +++ b/abc70930/src/base/io/io.h @@ -0,0 +1,146 @@ +/**CFile**************************************************************** + + FileName [io.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: io.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __IO_H__ +#define __IO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// network functionality +typedef enum { + IO_FILE_NONE = 0, + IO_FILE_AIGER, + IO_FILE_BAF, + IO_FILE_BLIF, + IO_FILE_BLIFMV, + IO_FILE_BENCH, + IO_FILE_CNF, + IO_FILE_DOT, + IO_FILE_EDIF, + IO_FILE_EQN, + IO_FILE_GML, + IO_FILE_LIST, + IO_FILE_PLA, + IO_FILE_VERILOG, + IO_FILE_UNKNOWN +} Io_FileType_t; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IO_WRITE_LINE_LENGTH 78 // the output line length + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== abcReadAiger.c ==========================================================*/ +extern Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ); +/*=== abcReadBaf.c ============================================================*/ +extern Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck ); +/*=== abcReadBlif.c ===========================================================*/ +extern Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ); +/*=== abcReadBlifMv.c =========================================================*/ +extern Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck ); +/*=== abcReadBench.c ==========================================================*/ +extern Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck ); +/*=== abcReadEdif.c ===========================================================*/ +extern Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck ); +/*=== abcReadEqn.c ============================================================*/ +extern Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck ); +/*=== abcReadPla.c ============================================================*/ +extern Abc_Ntk_t * Io_ReadPla( char * pFileName, int fCheck ); +/*=== abcReadVerilog.c ========================================================*/ +extern Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck ); +/*=== abcWriteAiger.c =========================================================*/ +extern void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols ); +/*=== abcWriteBaf.c ===========================================================*/ +extern void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWriteBlif.c ==========================================================*/ +extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); +extern void Io_WriteBlif( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); +extern void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ); +/*=== abcWriteBlifMv.c ==========================================================*/ +extern void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcWriteBench.c =========================================================*/ +extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); +extern int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcWriteCnf.c ===========================================================*/ +extern int Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName, int fAllPrimes ); +/*=== abcWriteDot.c ===========================================================*/ +extern void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName ); +extern void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); +extern void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); +/*=== abcWriteEqn.c ===========================================================*/ +extern void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWriteGml.c ===========================================================*/ +extern void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWriteList.c ==========================================================*/ +extern void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ); +/*=== abcWritePla.c ===========================================================*/ +extern int Io_WritePla( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcWriteVerilog.c =======================================================*/ +extern void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcUtil.c ===============================================================*/ +extern Io_FileType_t Io_ReadFileType( char * pFileName ); +extern Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck ); +extern Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck ); +extern void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType ); +extern void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName ); +extern Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Io_ReadCreateAssert( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ); +extern Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv ); +extern Abc_Obj_t * Io_ReadCreateResetMux( Abc_Ntk_t * pNtk, char * pResetLO, char * pDataLI, int fBlifMv ); +extern Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs ); +extern Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, bool fConst1 ); +extern Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ); +extern Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ); +extern FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose ); + + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/base/io/ioInt.h b/abc70930/src/base/io/ioInt.h new file mode 100644 index 00000000..3daf3c75 --- /dev/null +++ b/abc70930/src/base/io/ioInt.h @@ -0,0 +1,49 @@ +/**CFile**************************************************************** + + FileName [ioInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __IO_INT_H__ +#define __IO_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/base/io/ioReadAiger.c b/abc70930/src/base/io/ioReadAiger.c new file mode 100644 index 00000000..d3c4c878 --- /dev/null +++ b/abc70930/src/base/io/ioReadAiger.c @@ -0,0 +1,310 @@ +/**CFile**************************************************************** + + FileName [ioReadAiger.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read binary AIGER format developed by + Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 16, 2006.] + + Revision [$Id: ioReadAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +unsigned Io_ReadAigerDecode( char ** ppPos ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ) +{ + ProgressBar * pProgress; + FILE * pFile; + Vec_Ptr_t * vNodes, * vTerms; + Abc_Obj_t * pObj, * pNode0, * pNode1; + Abc_Ntk_t * pNtkNew; + int nTotal, nInputs, nOutputs, nLatches, nAnds, nFileSize, iTerm, nDigits, i; + char * pContents, * pDrivers, * pSymbols, * pCur, * pName, * pType; + unsigned uLit0, uLit1, uLit; + + // read the file into the buffer + nFileSize = Extra_FileSize( pFileName ); + pFile = fopen( pFileName, "rb" ); + pContents = ALLOC( char, nFileSize ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + + // check if the input file format is correct + if ( strncmp(pContents, "aig", 3) != 0 ) + { + fprintf( stdout, "Wrong input file format.\n" ); + return NULL; + } + + // allocate the empty AIG + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pName = Extra_FileNameGeneric( pFileName ); + pNtkNew->pName = Extra_UtilStrsav( pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pFileName ); + free( pName ); + + + // read the file type + pCur = pContents; while ( *pCur++ != ' ' ); + // read the number of objects + nTotal = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of inputs + nInputs = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of latches + nLatches = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of outputs + nOutputs = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of nodes + nAnds = atoi( pCur ); while ( *pCur++ != '\n' ); + // check the parameters + if ( nTotal != nInputs + nLatches + nAnds ) + { + fprintf( stdout, "The paramters are wrong.\n" ); + return NULL; + } + + // prepare the array of nodes + vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); + Vec_PtrPush( vNodes, Abc_ObjNot( Abc_AigConst1(pNtkNew) ) ); + + // create the PIs + for ( i = 0; i < nInputs; i++ ) + { + pObj = Abc_NtkCreatePi(pNtkNew); + Vec_PtrPush( vNodes, pObj ); + } + // create the POs + for ( i = 0; i < nOutputs; i++ ) + { + pObj = Abc_NtkCreatePo(pNtkNew); + } + // create the latches + nDigits = Extra_Base10Log( nLatches ); + for ( i = 0; i < nLatches; i++ ) + { + pObj = Abc_NtkCreateLatch(pNtkNew); + Abc_LatchSetInit0( pObj ); + pNode0 = Abc_NtkCreateBi(pNtkNew); + pNode1 = Abc_NtkCreateBo(pNtkNew); + Abc_ObjAddFanin( pObj, pNode0 ); + Abc_ObjAddFanin( pNode1, pObj ); + Vec_PtrPush( vNodes, pNode1 ); + // assign names to latch and its input +// Abc_ObjAssignName( pObj, Abc_ObjNameDummy("_L", i, nDigits), NULL ); +// printf( "Creating latch %s with input %d and output %d.\n", Abc_ObjName(pObj), pNode0->Id, pNode1->Id ); + } + + // remember the beginning of latch/PO literals + pDrivers = pCur; + + // scroll to the beginning of the binary data + for ( i = 0; i < nLatches + nOutputs; ) + if ( *pCur++ == '\n' ) + i++; + + // create the AND gates + pProgress = Extra_ProgressBarStart( stdout, nAnds ); + for ( i = 0; i < nAnds; i++ ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + uLit = ((i + 1 + nInputs + nLatches) << 1); + uLit1 = uLit - Io_ReadAigerDecode( &pCur ); + uLit0 = uLit1 - Io_ReadAigerDecode( &pCur ); +// assert( uLit1 > uLit0 ); + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); + pNode1 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); + assert( Vec_PtrSize(vNodes) == i + 1 + nInputs + nLatches ); + Vec_PtrPush( vNodes, Abc_AigAnd(pNtkNew->pManFunc, pNode0, pNode1) ); + } + Extra_ProgressBarStop( pProgress ); + + // remember the place where symbols begin + pSymbols = pCur; + + // read the latch driver literals + pCur = pDrivers; + Abc_NtkForEachLatchInput( pNtkNew, pObj, i ) + { + uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Abc_ObjAddFanin( pObj, pNode0 ); + +// printf( "Adding input %d to latch input %d.\n", pNode0->Id, pObj->Id ); + + } + // read the PO driver literals + Abc_NtkForEachPo( pNtkNew, pObj, i ) + { + uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Abc_ObjAddFanin( pObj, pNode0 ); + } + + // read the names if present + pCur = pSymbols; + if ( *pCur != 'c' ) + { + int Counter = 0; + while ( pCur < pContents + nFileSize && *pCur != 'c' ) + { + // get the terminal type + pType = pCur; + if ( *pCur == 'i' ) + vTerms = pNtkNew->vPis; + else if ( *pCur == 'l' ) + vTerms = pNtkNew->vBoxes; + else if ( *pCur == 'o' ) + vTerms = pNtkNew->vPos; + else + { + fprintf( stdout, "Wrong terminal type.\n" ); + return NULL; + } + // get the terminal number + iTerm = atoi( ++pCur ); while ( *pCur++ != ' ' ); + // get the node + if ( iTerm >= Vec_PtrSize(vTerms) ) + { + fprintf( stdout, "The number of terminal is out of bound.\n" ); + return NULL; + } + pObj = Vec_PtrEntry( vTerms, iTerm ); + if ( *pType == 'l' ) + pObj = Abc_ObjFanout0(pObj); + // assign the name + pName = pCur; while ( *pCur++ != '\n' ); + // assign this name + *(pCur-1) = 0; + Abc_ObjAssignName( pObj, pName, NULL ); + if ( *pType == 'l' ) + { + Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" ); + Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" ); + } + // mark the node as named + pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); + } + + // assign the remaining names + Abc_NtkForEachPi( pNtkNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); + Counter++; + } + Abc_NtkForEachLatchOutput( pNtkNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); + Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" ); + Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" ); + Counter++; + } + Abc_NtkForEachPo( pNtkNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); + Counter++; + } + if ( Counter ) + printf( "Io_ReadAiger(): Added %d default names for nameless I/O/register objects.\n", Counter ); + } + else + { +// printf( "Io_ReadAiger(): I/O/register names are not given. Generating short names.\n" ); + Abc_NtkShortNames( pNtkNew ); + } + + // read the name of the model if given + if ( *pCur == 'c' ) + { + if ( !strncmp( pCur + 2, ".model", 6 ) ) + { + char * pTemp; + for ( pTemp = pCur + 9; *pTemp && *pTemp != '\n'; pTemp++ ); + *pTemp = 0; + free( pNtkNew->pName ); + pNtkNew->pName = Extra_UtilStrsav( pCur + 9 ); + } + } + + + // skipping the comments + free( pContents ); + Vec_PtrFree( vNodes ); + + // remove the extra nodes + Abc_AigCleanup( pNtkNew->pManFunc ); + + // check the result + if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) ) + { + printf( "Io_ReadAiger: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Extracts one unsigned AIG edge from the input buffer.] + + Description [This procedure is a slightly modified version of Armin Biere's + procedure "unsigned decode (FILE * file)". ] + + SideEffects [Updates the current reading position.] + + SeeAlso [] + +***********************************************************************/ +unsigned Io_ReadAigerDecode( char ** ppPos ) +{ + unsigned x = 0, i = 0; + unsigned char ch; + +// while ((ch = getnoneofch (file)) & 0x80) + while ((ch = *(*ppPos)++) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + + return x | (ch << (7 * i)); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadBaf.c b/abc70930/src/base/io/ioReadBaf.c new file mode 100644 index 00000000..8dce54af --- /dev/null +++ b/abc70930/src/base/io/ioReadBaf.c @@ -0,0 +1,171 @@ +/**CFile**************************************************************** + + FileName [ioReadBaf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read AIG in the binary format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the AIG in the binary format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck ) +{ + ProgressBar * pProgress; + FILE * pFile; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pNode0, * pNode1; + Abc_Ntk_t * pNtkNew; + int nInputs, nOutputs, nLatches, nAnds, nFileSize, Num, i; + char * pContents, * pName, * pCur; + unsigned * pBufferNode; + + // read the file into the buffer + nFileSize = Extra_FileSize( pFileName ); + pFile = fopen( pFileName, "rb" ); + pContents = ALLOC( char, nFileSize ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + + // skip the comments (comment lines begin with '#' and end with '\n') + for ( pCur = pContents; *pCur == '#'; ) + while ( *pCur++ != '\n' ); + + // read the name + pName = pCur; while ( *pCur++ ); + // read the number of inputs + nInputs = atoi( pCur ); while ( *pCur++ ); + // read the number of outputs + nOutputs = atoi( pCur ); while ( *pCur++ ); + // read the number of latches + nLatches = atoi( pCur ); while ( *pCur++ ); + // read the number of nodes + nAnds = atoi( pCur ); while ( *pCur++ ); + + // allocate the empty AIG + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtkNew->pName = Extra_UtilStrsav( pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pFileName ); + + // prepare the array of nodes + vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); + Vec_PtrPush( vNodes, Abc_AigConst1(pNtkNew) ); + + // create the PIs + for ( i = 0; i < nInputs; i++ ) + { + pObj = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); + Vec_PtrPush( vNodes, pObj ); + } + // create the POs + for ( i = 0; i < nOutputs; i++ ) + { + pObj = Abc_NtkCreatePo(pNtkNew); + Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); + } + // create the latches + for ( i = 0; i < nLatches; i++ ) + { + pObj = Abc_NtkCreateLatch(pNtkNew); + Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); + + pNode0 = Abc_NtkCreateBi(pNtkNew); + Abc_ObjAssignName( pNode0, pCur, NULL ); while ( *pCur++ ); + + pNode1 = Abc_NtkCreateBo(pNtkNew); + Abc_ObjAssignName( pNode1, pCur, NULL ); while ( *pCur++ ); + Vec_PtrPush( vNodes, pNode1 ); + + Abc_ObjAddFanin( pObj, pNode0 ); + Abc_ObjAddFanin( pNode1, pObj ); + } + + // get the pointer to the beginning of the node array + pBufferNode = (int *)(pContents + (nFileSize - (2 * nAnds + nOutputs + nLatches) * sizeof(int)) ); + // make sure we are at the place where the nodes begin + if ( pBufferNode != (int *)pCur ) + { + free( pContents ); + Vec_PtrFree( vNodes ); + Abc_NtkDelete( pNtkNew ); + printf( "Warning: Internal reader error.\n" ); + return NULL; + } + + // create the AND gates + pProgress = Extra_ProgressBarStart( stdout, nAnds ); + for ( i = 0; i < nAnds; i++ ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, pBufferNode[2*i+0] >> 1), pBufferNode[2*i+0] & 1 ); + pNode1 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, pBufferNode[2*i+1] >> 1), pBufferNode[2*i+1] & 1 ); + Vec_PtrPush( vNodes, Abc_AigAnd(pNtkNew->pManFunc, pNode0, pNode1) ); + } + Extra_ProgressBarStop( pProgress ); + + // read the POs + Abc_NtkForEachCo( pNtkNew, pObj, i ) + { + Num = pBufferNode[2*nAnds+i]; + if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) + { + Abc_ObjSetData( Abc_ObjFanout0(pObj), (void *)(Num & 3) ); + Num >>= 2; + } + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, Num >> 1), Num & 1 ); + Abc_ObjAddFanin( pObj, pNode0 ); + } + free( pContents ); + Vec_PtrFree( vNodes ); + + // remove the extra nodes +// Abc_AigCleanup( pNtkNew->pManFunc ); + + // check the result + if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) ) + { + printf( "Io_ReadBaf: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; + +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadBench.c b/abc70930/src/base/io/ioReadBench.c new file mode 100644 index 00000000..007147bc --- /dev/null +++ b/abc70930/src/base/io/ioReadBench.c @@ -0,0 +1,360 @@ +/**CFile**************************************************************** + + FileName [ioReadBench.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read BENCH files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadBench.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from a BENCH file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck ) +{ + Extra_FileReader_t * p; + Abc_Ntk_t * pNtk; + + // start the file + p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t,()=" ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadBenchNetwork( p ); + Extra_FileReaderFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadBench: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vTokens; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode, * pNet; + Vec_Str_t * vString; + unsigned uTruth[8]; + char * pType, ** ppNames, * pString; + int iLine, nNames, nDigits, fLutsPresent = 0; + + // allocate the empty network + pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); + + // go through the lines of the file + vString = Vec_StrAlloc( 100 ); + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); + for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) + { + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); + + if ( vTokens->nSize == 1 ) + { + printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + + // get the type of the line + if ( strncmp( vTokens->pArray[0], "INPUT", 5 ) == 0 ) + Io_ReadCreatePi( pNtk, vTokens->pArray[1] ); + else if ( strncmp( vTokens->pArray[0], "OUTPUT", 5 ) == 0 ) + Io_ReadCreatePo( pNtk, vTokens->pArray[1] ); + else + { + // get the node name and the node type + pType = vTokens->pArray[1]; + if ( strncmp(pType, "DFF", 3) == 0 ) // works for both DFF and DFFRSE + { + pNode = Io_ReadCreateLatch( pNtk, vTokens->pArray[2], vTokens->pArray[0] ); +// Abc_LatchSetInit0( pNode ); + if ( pType[3] == '0' ) + Abc_LatchSetInit0( pNode ); + else if ( pType[3] == '1' ) + Abc_LatchSetInit1( pNode ); + else + Abc_LatchSetInitDc( pNode ); + } + else if ( strcmp(pType, "LUT") == 0 ) + { + fLutsPresent = 1; + ppNames = (char **)vTokens->pArray + 3; + nNames = vTokens->nSize - 3; + // check the number of inputs + if ( nNames > 8 ) + { + printf( "%s: Currently cannot read truth tables with more than 8 inputs (%d).\n", Extra_FileReaderGetFileName(p), nNames ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + // get the hex string + pString = vTokens->pArray[2]; + if ( strncmp( pString, "0x", 2 ) ) + { + printf( "%s: The LUT signature (%s) does not look like a hexadecimal beginning with \"0x\".\n", Extra_FileReaderGetFileName(p), pString ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + pString += 2; + // pad the string with zero's if needed + nDigits = (1 << nNames) / 4; + if ( nDigits == 0 ) + nDigits = 1; + if ( strlen(pString) < (unsigned)nDigits ) + { + Vec_StrFill( vString, nDigits - strlen(pString), '0' ); + Vec_StrPrintStr( vString, pString ); + Vec_StrPush( vString, 0 ); + pString = Vec_StrArray( vString ); + } + // read the hex number from the string + if ( !Extra_ReadHexadecimal( uTruth, pString, nNames ) ) + { + printf( "%s: Reading hexadecimal number (%s) has failed.\n", Extra_FileReaderGetFileName(p), pString ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + // check if the node is a constant node + if ( Extra_TruthIsConst0(uTruth, nNames) ) + { + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, 0 ); + Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 0\n" ) ); + } + else if ( Extra_TruthIsConst1(uTruth, nNames) ) + { + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, 0 ); + Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 1\n" ) ); + } + else + { + // create the node + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, nNames ); + assert( nNames > 0 ); + if ( nNames > 1 ) + Abc_ObjSetData( pNode, Abc_SopCreateFromTruth(pNtk->pManFunc, nNames, uTruth) ); + else if ( pString[0] == '2' ) + Abc_ObjSetData( pNode, Abc_SopCreateBuf(pNtk->pManFunc) ); + else if ( pString[0] == '1' ) + Abc_ObjSetData( pNode, Abc_SopCreateInv(pNtk->pManFunc) ); + else + { + printf( "%s: Reading truth table (%s) of single-input node has failed.\n", Extra_FileReaderGetFileName(p), pString ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + } + else + { + // create a new node and add it to the network + ppNames = (char **)vTokens->pArray + 2; + nNames = vTokens->nSize - 2; + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, nNames ); + // assign the cover + if ( strcmp(pType, "AND") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateAnd(pNtk->pManFunc, nNames, NULL) ); + else if ( strcmp(pType, "OR") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateOr(pNtk->pManFunc, nNames, NULL) ); + else if ( strcmp(pType, "NAND") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateNand(pNtk->pManFunc, nNames) ); + else if ( strcmp(pType, "NOR") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateNor(pNtk->pManFunc, nNames) ); + else if ( strcmp(pType, "XOR") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateXor(pNtk->pManFunc, nNames) ); + else if ( strcmp(pType, "NXOR") == 0 || strcmp(pType, "XNOR") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateNxor(pNtk->pManFunc, nNames) ); + else if ( strncmp(pType, "BUF", 3) == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateBuf(pNtk->pManFunc) ); + else if ( strcmp(pType, "NOT") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateInv(pNtk->pManFunc) ); + else if ( strncmp(pType, "MUX", 3) == 0 ) + Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, "1-0 1\n-11 1\n") ); + else if ( strncmp(pType, "gnd", 3) == 0 ) + Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 0\n" ) ); + else if ( strncmp(pType, "vdd", 3) == 0 ) + Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 1\n" ) ); + else + { + printf( "Io_ReadBenchNetwork(): Cannot determine gate type \"%s\" in line %d.\n", pType, Extra_FileReaderGetLineNumber(p, 0) ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + } + } + Extra_ProgressBarStop( pProgress ); + Vec_StrFree( vString ); + + // check if constant 0 is present + if ( (pNet = Abc_NtkFindNet( pNtk, "gnd" )) ) + { + if ( Abc_ObjFaninNum(pNet) == 0 ) + Io_ReadCreateConst( pNtk, "gnd", 0 ); + } + if ( (pNet = Abc_NtkFindNet( pNtk, "1" )) ) + { + if ( Abc_ObjFaninNum(pNet) == 0 ) + { + printf( "Io_ReadBenchNetwork(): Adding constant 0 fanin to non-driven net \"1\".\n" ); + Io_ReadCreateConst( pNtk, "1", 0 ); + } + } + // check if constant 1 is present + if ( (pNet = Abc_NtkFindNet( pNtk, "vdd" )) ) + { + if ( Abc_ObjFaninNum(pNet) == 0 ) + Io_ReadCreateConst( pNtk, "vdd", 1 ); + } + if ( (pNet = Abc_NtkFindNet( pNtk, "2" )) ) + { + if ( Abc_ObjFaninNum(pNet) == 0 ) + { + printf( "Io_ReadBenchNetwork(): Adding constant 1 fanin to non-driven net \"2\".\n" ); + Io_ReadCreateConst( pNtk, "2", 1 ); + } + } + + Abc_NtkFinalizeRead( pNtk ); + + // if LUTs are present, collapse the truth tables into cubes + if ( fLutsPresent ) + { + if ( !Abc_NtkToBdd(pNtk) ) + { + printf( "Io_ReadBenchNetwork(): Converting to BDD has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + if ( !Abc_NtkToSop(pNtk, 0) ) + { + printf( "Io_ReadBenchNetwork(): Converting to SOP has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + return pNtk; +} + + +/**Function************************************************************* + + Synopsis [Reads initial state in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName ) +{ + char pBuffer[1000]; + FILE * pFile; + char * pToken; + Abc_Obj_t * pObj; + int Num; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Io_ReadBenchInit(): Failed to open file \"%s\".\n", pFileName ); + return; + } + while ( fgets( pBuffer, 999, pFile ) ) + { + pToken = strtok( pBuffer, " \n\t\r" ); + // find the latch output + Num = Nm_ManFindIdByName( pNtk->pManName, pToken, ABC_OBJ_BO ); + if ( Num < 0 ) + { + printf( "Io_ReadBenchInit(): Cannot find register with output %s.\n", pToken ); + continue; + } + pObj = Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); + if ( !Abc_ObjIsLatch(pObj) ) + { + printf( "Io_ReadBenchInit(): The signal is not a register output %s.\n", pToken ); + continue; + } + // assign the new init state + pToken = strtok( NULL, " \n\t\r" ); + if ( pToken[0] == '0' ) + Abc_LatchSetInit0( pObj ); + else if ( pToken[0] == '1' ) + Abc_LatchSetInit1( pObj ); + else if ( pToken[0] == '2' ) + Abc_LatchSetInitDc( pObj ); + else + { + printf( "Io_ReadBenchInit(): The signal %s has unknown initial value (%s).\n", + Abc_ObjName(Abc_ObjFanout0(pObj)), pToken ); + continue; + } + } + fclose( pFile ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadBlif.c b/abc70930/src/base/io/ioReadBlif.c new file mode 100644 index 00000000..d0750178 --- /dev/null +++ b/abc70930/src/base/io/ioReadBlif.c @@ -0,0 +1,1105 @@ +/**CFile**************************************************************** + + FileName [ioReadBlif.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read BLIF files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Io_ReadBlif_t_ Io_ReadBlif_t; // all reading info +struct Io_ReadBlif_t_ +{ + // general info about file + char * pFileName; // the name of the file + Extra_FileReader_t * pReader; // the input file reader + // current processing info + Abc_Ntk_t * pNtkMaster; // the primary network + Abc_Ntk_t * pNtkCur; // the primary network + int LineCur; // the line currently parsed + // temporary storage for tokens + Vec_Ptr_t * vTokens; // the current tokens + Vec_Ptr_t * vNewTokens; // the temporary storage for the tokens + Vec_Str_t * vCubes; // the temporary storage for the tokens + // the error message + FILE * Output; // the output stream + char sError[1000]; // the error string generated during parsing + int fError; // set to 1 when error occurs +}; + +static Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ); +static void Io_ReadBlifFree( Io_ReadBlif_t * p ); +static void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ); +static Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ); +static char * Io_ReadBlifCleanName( char * pName ); + +static Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ); +static Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ); +static int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkAsserts( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ); +static int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the (hierarchical) network from the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ) +{ + Io_ReadBlif_t * p; + Abc_Ntk_t * pNtk; + + // start the file + p = Io_ReadBlifFile( pFileName ); + if ( p == NULL ) + return NULL; + + // read the hierarchical network + pNtk = Io_ReadBlifNetwork( p ); + if ( pNtk == NULL ) + { + Io_ReadBlifFree( p ); + return NULL; + } + pNtk->pSpec = Extra_UtilStrsav( pFileName ); + Abc_NtkTimeInitialize( pNtk ); + Io_ReadBlifFree( p ); + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadBlif: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Iteratively reads several networks in the hierarchical design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ) +{ + Abc_Ntk_t * pNtk, * pNtkMaster; + + // read the name of the master network + p->vTokens = Io_ReadBlifGetTokens(p); + if ( p->vTokens == NULL || strcmp( p->vTokens->pArray[0], ".model" ) ) + { + p->LineCur = 0; + sprintf( p->sError, "Wrong input file format." ); + Io_ReadBlifPrintErrorMessage( p ); + return NULL; + } + + // read networks (with EXDC) + pNtkMaster = NULL; + while ( p->vTokens ) + { + // read the network and its EXDC if present + pNtk = Io_ReadBlifNetworkOne( p ); + if ( pNtk == NULL ) + break; + if ( p->vTokens && strcmp(p->vTokens->pArray[0], ".exdc") == 0 ) + { + pNtk->pExdc = Io_ReadBlifNetworkOne( p ); + Abc_NtkFinalizeRead( pNtk->pExdc ); + if ( pNtk->pExdc == NULL ) + break; + } + // add this network as part of the hierarchy + if ( pNtkMaster == NULL ) // no master network so far + { + p->pNtkMaster = pNtkMaster = pNtk; + continue; + } +/* + // make sure hierarchy does not have the network with this name + if ( pNtkMaster->tName2Model && stmm_is_member( pNtkMaster->tName2Model, pNtk->pName ) ) + { + p->LineCur = 0; + sprintf( p->sError, "Model %s is multiply defined in the file.", pNtk->pName ); + Io_ReadBlifPrintErrorMessage( p ); + Abc_NtkDelete( pNtk ); + Abc_NtkDelete( pNtkMaster ); + pNtkMaster = NULL; + return NULL; + } + // add the network to the hierarchy + if ( pNtkMaster->tName2Model == NULL ) + pNtkMaster->tName2Model = stmm_init_table(strcmp, stmm_strhash); + stmm_insert( pNtkMaster->tName2Model, pNtk->pName, (char *)pNtk ); +*/ + } +/* + // if there is a hierarchy, connect the boxes + if ( pNtkMaster && pNtkMaster->tName2Model ) + { + if ( Io_ReadBlifNetworkConnectBoxes( p, pNtkMaster ) ) + { + Abc_NtkDelete( pNtkMaster ); + return NULL; + } + } + else +*/ + if ( !p->fError ) + Abc_NtkFinalizeRead( pNtkMaster ); + // return the master network + return pNtkMaster; +} + +/**Function************************************************************* + + Synopsis [Reads one (main or exdc) network from the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtk; + char * pDirective; + int iLine, fTokensReady, fStatus; + + // make sure the tokens are present + assert( p->vTokens != NULL ); + + // create the new network + p->pNtkCur = pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); + // read the model name + if ( strcmp( p->vTokens->pArray[0], ".model" ) == 0 ) + pNtk->pName = Extra_UtilStrsav( p->vTokens->pArray[1] ); + else if ( strcmp( p->vTokens->pArray[0], ".exdc" ) != 0 ) + { + printf( "%s: File parsing skipped after line %d (\"%s\").\n", p->pFileName, + Extra_FileReaderGetLineNumber(p->pReader, 0), p->vTokens->pArray[0] ); + Abc_NtkDelete(pNtk); + p->pNtkCur = NULL; + return NULL; + } + + // read the inputs/outputs + if ( p->pNtkMaster == NULL ) + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p->pReader) ); + fTokensReady = fStatus = 0; + for ( iLine = 0; fTokensReady || (p->vTokens = Io_ReadBlifGetTokens(p)); iLine++ ) + { + if ( p->pNtkMaster == NULL && iLine % 1000 == 0 ) + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p->pReader), NULL ); + + // consider different line types + fTokensReady = 0; + pDirective = p->vTokens->pArray[0]; + if ( !strcmp( pDirective, ".names" ) ) + { fStatus = Io_ReadBlifNetworkNames( p, &p->vTokens ); fTokensReady = 1; } + else if ( !strcmp( pDirective, ".gate" ) ) + fStatus = Io_ReadBlifNetworkGate( p, p->vTokens ); + else if ( !strcmp( pDirective, ".latch" ) ) + fStatus = Io_ReadBlifNetworkLatch( p, p->vTokens ); + else if ( !strcmp( pDirective, ".inputs" ) ) + fStatus = Io_ReadBlifNetworkInputs( p, p->vTokens ); + else if ( !strcmp( pDirective, ".outputs" ) ) + fStatus = Io_ReadBlifNetworkOutputs( p, p->vTokens ); + else if ( !strcmp( pDirective, ".asserts" ) ) + fStatus = Io_ReadBlifNetworkAsserts( p, p->vTokens ); + else if ( !strcmp( pDirective, ".input_arrival" ) ) + fStatus = Io_ReadBlifNetworkInputArrival( p, p->vTokens ); + else if ( !strcmp( pDirective, ".default_input_arrival" ) ) + fStatus = Io_ReadBlifNetworkDefaultInputArrival( p, p->vTokens ); +// else if ( !strcmp( pDirective, ".subckt" ) ) +// fStatus = Io_ReadBlifNetworkSubcircuit( p, p->vTokens ); + else if ( !strcmp( pDirective, ".exdc" ) ) + break; + else if ( !strcmp( pDirective, ".end" ) ) + { + p->vTokens = Io_ReadBlifGetTokens(p); + break; + } + else if ( !strcmp( pDirective, ".blackbox" ) ) + { + pNtk->ntkType = ABC_NTK_NETLIST; + pNtk->ntkFunc = ABC_FUNC_BLACKBOX; + Extra_MmFlexStop( pNtk->pManFunc ); + pNtk->pManFunc = NULL; + } + else + printf( "%s (line %d): Skipping directive \"%s\".\n", p->pFileName, + Extra_FileReaderGetLineNumber(p->pReader, 0), pDirective ); + if ( p->vTokens == NULL ) // some files do not have ".end" in the end + break; + if ( fStatus == 1 ) + { + Extra_ProgressBarStop( pProgress ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + if ( p->pNtkMaster == NULL ) + Extra_ProgressBarStop( pProgress ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + int i; + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreatePi( p->pNtkCur, vTokens->pArray[i] ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + int i; + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreatePo( p->pNtkCur, vTokens->pArray[i] ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkAsserts( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + int i; + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreateAssert( p->pNtkCur, vTokens->pArray[i] ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + Abc_Ntk_t * pNtk = p->pNtkCur; + Abc_Obj_t * pLatch; + int ResetValue; + if ( vTokens->nSize < 3 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .latch line does not have enough tokens." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // create the latch + pLatch = Io_ReadCreateLatch( pNtk, vTokens->pArray[1], vTokens->pArray[2] ); + // get the latch reset value + if ( vTokens->nSize == 3 ) + Abc_LatchSetInitDc( pLatch ); + else + { + ResetValue = atoi(vTokens->pArray[vTokens->nSize-1]); + if ( ResetValue != 0 && ResetValue != 1 && ResetValue != 2 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .latch line has an unknown reset value (%s).", vTokens->pArray[3] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + if ( ResetValue == 0 ) + Abc_LatchSetInit0( pLatch ); + else if ( ResetValue == 1 ) + Abc_LatchSetInit1( pLatch ); + else if ( ResetValue == 2 ) + Abc_LatchSetInitDc( pLatch ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ) +{ + Vec_Ptr_t * vTokens = *pvTokens; + Abc_Ntk_t * pNtk = p->pNtkCur; + Abc_Obj_t * pNode; + char * pToken, Char, ** ppNames; + int nFanins, nNames; + + // create a new node and add it to the network + if ( vTokens->nSize < 2 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .names line has less than two tokens." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // create the node + ppNames = (char **)vTokens->pArray + 1; + nNames = vTokens->nSize - 2; + pNode = Io_ReadCreateNode( pNtk, ppNames[nNames], ppNames, nNames ); + + // derive the functionality of the node + p->vCubes->nSize = 0; + nFanins = vTokens->nSize - 2; + if ( nFanins == 0 ) + { + while ( vTokens = Io_ReadBlifGetTokens(p) ) + { + pToken = vTokens->pArray[0]; + if ( pToken[0] == '.' ) + break; + // read the cube + if ( vTokens->nSize != 1 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The number of tokens in the constant cube is wrong." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // create the cube + Char = ((char *)vTokens->pArray[0])[0]; + Vec_StrPush( p->vCubes, ' ' ); + Vec_StrPush( p->vCubes, Char ); + Vec_StrPush( p->vCubes, '\n' ); + } + } + else + { + while ( vTokens = Io_ReadBlifGetTokens(p) ) + { + pToken = vTokens->pArray[0]; + if ( pToken[0] == '.' ) + break; + // read the cube + if ( vTokens->nSize != 2 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The number of tokens in the cube is wrong." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // create the cube + Vec_StrAppend( p->vCubes, vTokens->pArray[0] ); + // check the char + Char = ((char *)vTokens->pArray[1])[0]; + if ( Char != '0' && Char != '1' && Char != 'x' && Char != 'n' ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The output character in the constant cube is wrong." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + Vec_StrPush( p->vCubes, ' ' ); + Vec_StrPush( p->vCubes, Char ); + Vec_StrPush( p->vCubes, '\n' ); + } + } + // if there is nothing there + if ( p->vCubes->nSize == 0 ) + { + // create an empty cube + Vec_StrPush( p->vCubes, ' ' ); + Vec_StrPush( p->vCubes, '0' ); + Vec_StrPush( p->vCubes, '\n' ); + } + Vec_StrPush( p->vCubes, 0 ); + + // set the pointer to the functionality of the node + Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, p->vCubes->pArray) ); + + // check the size + if ( Abc_ObjFaninNum(pNode) != Abc_SopGetVarNum(Abc_ObjData(pNode)) ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The number of fanins (%d) of node %s is different from SOP size (%d).", + Abc_ObjFaninNum(pNode), Abc_ObjName(Abc_ObjFanout(pNode,0)), Abc_SopGetVarNum(Abc_ObjData(pNode)) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // return the last array of tokens + *pvTokens = vTokens; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + Mio_Library_t * pGenlib; + Mio_Gate_t * pGate; + Abc_Obj_t * pNode; + char ** ppNames; + int i, nNames; + + // check that the library is available + pGenlib = Abc_FrameReadLibGen(); + if ( pGenlib == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The current library is not available." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // create a new node and add it to the network + if ( vTokens->nSize < 2 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .gate line has less than two tokens." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // get the gate + pGate = Mio_LibraryReadGateByName( pGenlib, vTokens->pArray[1] ); + if ( pGate == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Cannot find gate \"%s\" in the library.", vTokens->pArray[1] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // if this is the first line with gate, update the network type + if ( Abc_NtkNodeNum(p->pNtkCur) == 0 ) + { + assert( p->pNtkCur->ntkFunc == ABC_FUNC_SOP ); + p->pNtkCur->ntkFunc = ABC_FUNC_MAP; + Extra_MmFlexStop( p->pNtkCur->pManFunc ); + p->pNtkCur->pManFunc = pGenlib; + } + + // remove the formal parameter names + for ( i = 2; i < vTokens->nSize; i++ ) + { + vTokens->pArray[i] = Io_ReadBlifCleanName( vTokens->pArray[i] ); + if ( vTokens->pArray[i] == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Invalid gate input assignment." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + } + + // create the node + ppNames = (char **)vTokens->pArray + 2; + nNames = vTokens->nSize - 3; + pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames ); + + // set the pointer to the functionality of the node + Abc_ObjSetData( pNode, pGate ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Creates a multi-input multi-output box in the hierarchical design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + Abc_Obj_t * pBox; + Vec_Ptr_t * vNames; + char * pName; + int i; + + // create a new node and add it to the network + if ( vTokens->nSize < 3 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .subcircuit line has less than three tokens." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // store the names of formal/actual inputs/outputs of the box + vNames = Vec_PtrAlloc( 10 ); + Vec_PtrForEachEntryStart( vTokens, pName, i, 1 ) +// Vec_PtrPush( vNames, Abc_NtkRegisterName(p->pNtkCur, pName) ); + Vec_PtrPush( vNames, Extra_UtilStrsav(pName) ); // memory leak!!! + + // create a new box and add it to the network + pBox = Abc_NtkCreateBlackbox( p->pNtkCur ); + // set the pointer to the node names + Abc_ObjSetData( pBox, vNames ); + // remember the line of the file + pBox->pCopy = (void *)Extra_FileReaderGetLineNumber(p->pReader, 0); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Io_ReadBlifCleanName( char * pName ) +{ + int i, Length; + Length = strlen(pName); + for ( i = 0; i < Length; i++ ) + if ( pName[i] == '=' ) + return pName + i + 1; + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + Abc_Obj_t * pNet; + char * pFoo1, * pFoo2; + double TimeRise, TimeFall; + + // make sure this is indeed the .inputs line + assert( strncmp( vTokens->pArray[0], ".input_arrival", 14 ) == 0 ); + if ( vTokens->nSize != 4 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Wrong number of arguments on .input_arrival line." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pNet = Abc_NtkFindNet( p->pNtkCur, vTokens->pArray[1] ); + if ( pNet == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Cannot find object corresponding to %s on .input_arrival line.", vTokens->pArray[1] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + TimeRise = strtod( vTokens->pArray[2], &pFoo1 ); + TimeFall = strtod( vTokens->pArray[3], &pFoo2 ); + if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .input_arrival line.", vTokens->pArray[2], vTokens->pArray[3] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // set the arrival time + Abc_NtkTimeSetArrival( p->pNtkCur, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + char * pFoo1, * pFoo2; + double TimeRise, TimeFall; + + // make sure this is indeed the .inputs line + assert( strncmp( vTokens->pArray[0], ".default_input_arrival", 23 ) == 0 ); + if ( vTokens->nSize != 3 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Wrong number of arguments on .default_input_arrival line." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + TimeRise = strtod( vTokens->pArray[1], &pFoo1 ); + TimeFall = strtod( vTokens->pArray[2], &pFoo2 ); + if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_input_arrival line.", vTokens->pArray[1], vTokens->pArray[2] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // set the arrival time + Abc_NtkTimeSetDefaultArrival( p->pNtkCur, (float)TimeRise, (float)TimeFall ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Prints the error message including the file name and line number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ) +{ + p->fError = 1; + if ( p->LineCur == 0 ) // the line number is not given + fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); + else // print the error message with the line number + fprintf( p->Output, "%s (line %d): %s\n", p->pFileName, p->LineCur, p->sError ); +} + +/**Function************************************************************* + + Synopsis [Gets the tokens taking into account the line breaks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ) +{ + Vec_Ptr_t * vTokens; + char * pLastToken; + int i; + + // get rid of the old tokens + if ( p->vNewTokens->nSize > 0 ) + { + for ( i = 0; i < p->vNewTokens->nSize; i++ ) + free( p->vNewTokens->pArray[i] ); + p->vNewTokens->nSize = 0; + } + + // get the new tokens + vTokens = Extra_FileReaderGetTokens(p->pReader); + if ( vTokens == NULL ) + return vTokens; + + // check if there is a transfer to another line + pLastToken = vTokens->pArray[vTokens->nSize - 1]; + if ( pLastToken[ strlen(pLastToken)-1 ] != '\\' ) + return vTokens; + + // remove the slash + pLastToken[ strlen(pLastToken)-1 ] = 0; + if ( pLastToken[0] == 0 ) + vTokens->nSize--; + // load them into the new array + for ( i = 0; i < vTokens->nSize; i++ ) + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); + + // load as long as there is the line break + while ( 1 ) + { + // get the new tokens + vTokens = Extra_FileReaderGetTokens(p->pReader); + if ( vTokens->nSize == 0 ) + return p->vNewTokens; + // check if there is a transfer to another line + pLastToken = vTokens->pArray[vTokens->nSize - 1]; + if ( pLastToken[ strlen(pLastToken)-1 ] == '\\' ) + { + // remove the slash + pLastToken[ strlen(pLastToken)-1 ] = 0; + if ( pLastToken[0] == 0 ) + vTokens->nSize--; + // load them into the new array + for ( i = 0; i < vTokens->nSize; i++ ) + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); + continue; + } + // otherwise, load them and break + for ( i = 0; i < vTokens->nSize; i++ ) + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); + break; + } + return p->vNewTokens; +} + +/**Function************************************************************* + + Synopsis [Starts the reading data structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ) +{ + Extra_FileReader_t * pReader; + Io_ReadBlif_t * p; + + // start the reader + pReader = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t" ); + + if ( pReader == NULL ) + return NULL; + + // start the reading data structure + p = ALLOC( Io_ReadBlif_t, 1 ); + memset( p, 0, sizeof(Io_ReadBlif_t) ); + p->pFileName = pFileName; + p->pReader = pReader; + p->Output = stdout; + p->vNewTokens = Vec_PtrAlloc( 100 ); + p->vCubes = Vec_StrAlloc( 100 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the data structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadBlifFree( Io_ReadBlif_t * p ) +{ + Extra_FileReaderFree( p->pReader ); + Vec_PtrFree( p->vNewTokens ); + Vec_StrFree( p->vCubes ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Connect one box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkConnectBoxesOneBox( Io_ReadBlif_t * p, Abc_Obj_t * pBox, stmm_table * tName2Model ) +{ + Vec_Ptr_t * pNames; + Abc_Ntk_t * pNtkModel; + Abc_Obj_t * pObj, * pNet; + char * pName, * pActual; + int i, Length, Start; + + // get the model for this box + pNames = pBox->pData; + if ( !stmm_lookup( tName2Model, Vec_PtrEntry(pNames, 0), (char **)&pNtkModel ) ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot find the model for subcircuit %s.", Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // create the fanins of the box + Abc_NtkForEachPi( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + if ( Abc_NtkPiNum(pNtkModel) == 0 ) + Start = 1; + else + { + Vec_PtrForEachEntryStart( pNames, pName, i, 1 ) + { + pActual = Io_ReadBlifCleanName(pName); + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + Length = pActual - pName - 1; + pName[Length] = 0; + // find the PI net with this name + pObj = Abc_NtkFindNet( pNtkModel, pName ); + if ( pObj == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot find formal input \"%s\" as an PI of model \"%s\".", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // get the PI + pObj = Abc_ObjFanin0(pObj); + // quit if this is not a PI net + if ( !Abc_ObjIsPi(pObj) ) + { + pName[Length] = '='; + Start = i; + break; + } + // remember the actual name in the net + if ( pObj->pCopy != NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal input \"%s\" is used more than once.", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pObj->pCopy = (void *)pActual; + // quit if we processed all PIs + if ( i == Abc_NtkPiNum(pNtkModel) ) + { + Start = i+1; + break; + } + } + } + // create the fanins of the box + Abc_NtkForEachPi( pNtkModel, pObj, i ) + { + pActual = (void *)pObj->pCopy; + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal input \"%s\" of model %s is not driven.", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); + Abc_ObjAddFanin( pBox, pNet ); + } + Abc_NtkForEachPi( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + + // create the fanouts of the box + Abc_NtkForEachPo( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + Vec_PtrForEachEntryStart( pNames, pName, i, Start ) + { + pActual = Io_ReadBlifCleanName(pName); + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + Length = pActual - pName - 1; + pName[Length] = 0; + // find the PO net with this name + pObj = Abc_NtkFindNet( pNtkModel, pName ); + if ( pObj == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot find formal output \"%s\" as an PO of model \"%s\".", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // get the PO + pObj = Abc_ObjFanout0(pObj); + if ( pObj->pCopy != NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal output \"%s\" is used more than once.", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pObj->pCopy = (void *)pActual; + } + // create the fanouts of the box + Abc_NtkForEachPo( pNtkModel, pObj, i ) + { + pActual = (void *)pObj->pCopy; + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal output \"%s\" of model %s is not driven.", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); + Abc_ObjAddFanin( pNet, pBox ); + } + Abc_NtkForEachPo( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + + // remove the array of names, assign the pointer to the model + Vec_PtrForEachEntry( pBox->pData, pName, i ) + free( pName ); + Vec_PtrFree( pBox->pData ); + pBox->pData = pNtkModel; + return 0; +} + +/**Function************************************************************* + + Synopsis [Connect the boxes in the hierarchy of networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkConnectBoxesOne( Io_ReadBlif_t * p, Abc_Ntk_t * pNtk, stmm_table * tName2Model ) +{ + Abc_Obj_t * pBox; + int i; + // go through the boxes + Abc_NtkForEachBlackbox( pNtk, pBox, i ) + if ( Io_ReadBlifNetworkConnectBoxesOneBox( p, pBox, tName2Model ) ) + return 1; + Abc_NtkFinalizeRead( pNtk ); + return 0; +} + +#if 0 + +/**Function************************************************************* + + Synopsis [Connect the boxes in the hierarchy of networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ) +{ + stmm_generator * gen; + Abc_Ntk_t * pNtk; + char * pName; + // connect the master network + if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtkMaster, pNtkMaster->tName2Model ) ) + return 1; + // connect other networks + stmm_foreach_item( pNtkMaster->tName2Model, gen, &pName, (char **)&pNtk ) + if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtk, pNtkMaster->tName2Model ) ) + return 1; + return 0; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadBlifAig.c b/abc70930/src/base/io/ioReadBlifAig.c new file mode 100644 index 00000000..c448bab6 --- /dev/null +++ b/abc70930/src/base/io/ioReadBlifAig.c @@ -0,0 +1,1013 @@ +/**CFile**************************************************************** + + FileName [ioReadBlifAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read BLIF file into AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 23, 2006.] + + Revision [$Id: ioReadBlifAig.c,v 1.00 2006/12/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "extra.h" +#include "vecPtr.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// latch initial values +typedef enum { + IO_BLIF_INIT_NONE = 0, // 0: unknown + IO_BLIF_INIT_ZERO, // 1: zero + IO_BLIF_INIT_ONE, // 2: one + IO_BLIF_INIT_DC // 3: don't-care +} Io_BlifInit_t; + +typedef struct Io_BlifObj_t_ Io_BlifObj_t; // parsing object +struct Io_BlifObj_t_ +{ + unsigned fPi : 1; // the object is a primary input + unsigned fPo : 1; // the object is a primary output + unsigned fLi : 1; // the object is a latch input + unsigned fLo : 1; // the object is a latch output + unsigned fDef : 1; // the object is defined as a table (node, PO, LI) + unsigned fLoop : 1; // flag for loop detection + unsigned Init : 2; // the latch initial state + unsigned Offset : 24; // temporary number + char * pName; // the name of this object + void * pEquiv; // the AIG node representing this line + Io_BlifObj_t * pNext; // the next obj in the hash table +}; + +typedef struct Io_BlifMan_t_ Io_BlifMan_t; // parsing manager +struct Io_BlifMan_t_ +{ + // general info about file + char * pFileName; // the name of the file + char * pBuffer; // the begining of the file buffer + Vec_Ptr_t * vLines; // the line beginnings + // temporary objects + Io_BlifObj_t * pObjects; // the storage for objects + int nObjects; // the number of objects allocated + int iObjNext; // the next free object + // file lines + char * pModel; // .model line + Vec_Ptr_t * vInputs; // .inputs lines + Vec_Ptr_t * vOutputs; // .outputs lines + Vec_Ptr_t * vLatches; // .latches lines + Vec_Ptr_t * vNames; // .names lines + // network objects + Vec_Ptr_t * vPis; // the PI structures + Vec_Ptr_t * vPos; // the PO structures + Vec_Ptr_t * vLis; // the LI structures + Vec_Ptr_t * vLos; // the LO structures + // mapping of names into objects + Io_BlifObj_t ** pTable; // the hash table + int nTableSize; // the hash table size + // current processing info + Abc_Ntk_t * pAig; // the network under construction + Vec_Ptr_t * vTokens; // the current tokens + char sError[512]; // the error string generated during parsing + // statistics + int nTablesRead; // the number of processed tables + int nTablesLeft; // the number of dangling tables +}; + +// static functions +static Io_BlifMan_t * Io_BlifAlloc(); +static void Io_BlifFree( Io_BlifMan_t * p ); +static char * Io_BlifLoadFile( char * pFileName ); +static void Io_BlifReadPreparse( Io_BlifMan_t * p ); +static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p ); +static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseConstruct( Io_BlifMan_t * p ); +static int Io_BlifCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from the BLIF file as an AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck ) +{ + FILE * pFile; + Io_BlifMan_t * p; + Abc_Ntk_t * pAig; + + // check that the file is available + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Io_Blif(): The file is unavailable (absent or open).\n" ); + return 0; + } + fclose( pFile ); + + // start the file reader + p = Io_BlifAlloc(); + p->pFileName = pFileName; + p->pBuffer = Io_BlifLoadFile( pFileName ); + if ( p->pBuffer == NULL ) + { + Io_BlifFree( p ); + return NULL; + } + // prepare the file for parsing + Io_BlifReadPreparse( p ); + // construct the network + pAig = Io_BlifParse( p ); + if ( p->sError[0] ) + fprintf( stdout, "%s\n", p->sError ); + if ( pAig == NULL ) + return NULL; + Io_BlifFree( p ); + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pAig ) ) + { + printf( "Io_Blif: The network check has failed.\n" ); + Abc_NtkDelete( pAig ); + return NULL; + } + return pAig; +} + +/**Function************************************************************* + + Synopsis [Allocates the BLIF parsing structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_BlifMan_t * Io_BlifAlloc() +{ + Io_BlifMan_t * p; + p = ALLOC( Io_BlifMan_t, 1 ); + memset( p, 0, sizeof(Io_BlifMan_t) ); + p->vLines = Vec_PtrAlloc( 512 ); + p->vInputs = Vec_PtrAlloc( 512 ); + p->vOutputs = Vec_PtrAlloc( 512 ); + p->vLatches = Vec_PtrAlloc( 512 ); + p->vNames = Vec_PtrAlloc( 512 ); + p->vTokens = Vec_PtrAlloc( 512 ); + p->vPis = Vec_PtrAlloc( 512 ); + p->vPos = Vec_PtrAlloc( 512 ); + p->vLis = Vec_PtrAlloc( 512 ); + p->vLos = Vec_PtrAlloc( 512 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the BLIF parsing structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_BlifFree( Io_BlifMan_t * p ) +{ + if ( p->pAig ) + Abc_NtkDelete( p->pAig ); + if ( p->pBuffer ) free( p->pBuffer ); + if ( p->pObjects ) free( p->pObjects ); + if ( p->pTable ) free( p->pTable ); + Vec_PtrFree( p->vLines ); + Vec_PtrFree( p->vInputs ); + Vec_PtrFree( p->vOutputs ); + Vec_PtrFree( p->vLatches ); + Vec_PtrFree( p->vNames ); + Vec_PtrFree( p->vTokens ); + Vec_PtrFree( p->vPis ); + Vec_PtrFree( p->vPos ); + Vec_PtrFree( p->vLis ); + Vec_PtrFree( p->vLos ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Hashing for character strings.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static unsigned Io_BlifHashString( char * pName, int TableSize ) +{ + static int s_Primes[10] = { + 1291, 1699, 2357, 4177, 5147, + 5647, 6343, 7103, 7873, 8147 + }; + unsigned i, Key = 0; + for ( i = 0; pName[i] != '\0'; i++ ) + Key ^= s_Primes[i%10]*pName[i]*pName[i]; + return Key % TableSize; +} + +/**Function************************************************************* + + Synopsis [Checks if the given name exists in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_BlifObj_t ** Io_BlifHashLookup( Io_BlifMan_t * p, char * pName ) +{ + Io_BlifObj_t ** ppEntry; + for ( ppEntry = p->pTable + Io_BlifHashString(pName, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext ) + if ( !strcmp((*ppEntry)->pName, pName) ) + return ppEntry; + return ppEntry; +} + +/**Function************************************************************* + + Synopsis [Finds or add the given name to the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_BlifObj_t * Io_BlifHashFindOrAdd( Io_BlifMan_t * p, char * pName ) +{ + Io_BlifObj_t ** ppEntry; + ppEntry = Io_BlifHashLookup( p, pName ); + if ( *ppEntry == NULL ) + { + assert( p->iObjNext < p->nObjects ); + *ppEntry = p->pObjects + p->iObjNext++; + (*ppEntry)->pName = pName; + } + return *ppEntry; +} + + +/**Function************************************************************* + + Synopsis [Collects the already split tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_BlifCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput ) +{ + char * pCur; + Vec_PtrClear( vTokens ); + for ( pCur = pInput; pCur < pOutput; pCur++ ) + { + if ( *pCur == 0 ) + continue; + Vec_PtrPush( vTokens, pCur ); + while ( *++pCur ); + } +} + +/**Function************************************************************* + + Synopsis [Splits the line into tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_BlifSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != Stop; pCur++ ) + if ( Io_BlifCharIsSpace(*pCur) ) + *pCur = 0; + // collect tokens + Io_BlifCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Returns the 1-based number of the line in which the token occurs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifGetLine( Io_BlifMan_t * p, char * pToken ) +{ + char * pLine; + int i; + Vec_PtrForEachEntry( p->vLines, pLine, i ) + if ( pToken < pLine ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Conservatively estimates the number of primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifEstimatePiNum( Io_BlifMan_t * p ) +{ + char * pCur; + int i, fSpaces; + int Counter = 0; + Vec_PtrForEachEntry( p->vInputs, pCur, i ) + for ( fSpaces = 0; *pCur; pCur++ ) + { + if ( Io_BlifCharIsSpace(*pCur) ) + { + if ( !fSpaces ) + Counter++; + fSpaces = 1; + } + else + fSpaces = 0; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Conservatively estimates the number of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifEstimateAndNum( Io_BlifMan_t * p ) +{ + Io_BlifObj_t * pObj; + char * pCur; + int i, CounterOne, Counter = 0; + for ( i = 0; i < p->iObjNext; i++ ) + { + pObj = p->pObjects + i; + if ( !pObj->fDef ) + continue; + CounterOne = 0; + for ( pCur = pObj->pName + strlen(pObj->pName); *pCur != '.'; pCur++ ) + if ( *pCur == '0' || *pCur == '1' ) + CounterOne++; + if ( CounterOne ) + Counter += CounterOne - 1; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Reads the file into a character buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_BlifLoadFile( char * pFileName ) +{ + FILE * pFile; + int nFileSize; + char * pContents; + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Io_BlifLoadFile(): The file is unavailable (absent or open).\n" ); + return NULL; + } + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + if ( nFileSize == 0 ) + { + printf( "Io_BlifLoadFile(): The file is empty.\n" ); + return NULL; + } + pContents = ALLOC( char, nFileSize + 10 ); + rewind( pFile ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + // finish off the file with the spare .end line + // some benchmarks suddenly break off without this line + strcpy( pContents + nFileSize, "\n.end\n" ); + return pContents; +} + +/**Function************************************************************* + + Synopsis [Prepares the parsing.] + + Description [Performs several preliminary operations: + - Cuts the file buffer into separate lines. + - Removes comments and line extenders. + - Sorts lines by directives. + - Estimates the number of objects. + - Allocates room for the objects. + - Allocates room for the hash table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_BlifReadPreparse( Io_BlifMan_t * p ) +{ + char * pCur, * pPrev; + int i, fComment = 0; + // parse the buffer into lines and remove comments + Vec_PtrPush( p->vLines, p->pBuffer ); + for ( pCur = p->pBuffer; *pCur; pCur++ ) + { + if ( *pCur == '\n' ) + { + *pCur = 0; + fComment = 0; + Vec_PtrPush( p->vLines, pCur + 1 ); + } + else if ( *pCur == '#' ) + fComment = 1; + // remove comments + if ( fComment ) + *pCur = 0; + } + + // unfold the line extensions and sort lines by directive + Vec_PtrForEachEntry( p->vLines, pCur, i ) + { + if ( *pCur == 0 ) + continue; + // find previous non-space character + for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- ) + if ( !Io_BlifCharIsSpace(*pPrev) ) + break; + // if it is the line extender, overwrite it with spaces + if ( *pPrev == '\\' ) + { + for ( ; *pPrev; pPrev++ ) + *pPrev = ' '; + *pPrev = ' '; + continue; + } + // skip spaces at the beginning of the line + while ( Io_BlifCharIsSpace(*pCur++) ); + // parse directives + if ( *(pCur-1) != '.' ) + continue; + if ( !strncmp(pCur, "names", 5) ) + Vec_PtrPush( p->vNames, pCur ); + else if ( !strncmp(pCur, "latch", 5) ) + Vec_PtrPush( p->vLatches, pCur ); + else if ( !strncmp(pCur, "inputs", 6) ) + Vec_PtrPush( p->vInputs, pCur ); + else if ( !strncmp(pCur, "outputs", 7) ) + Vec_PtrPush( p->vOutputs, pCur ); + else if ( !strncmp(pCur, "model", 5) ) + p->pModel = pCur; + else if ( !strncmp(pCur, "end", 3) || !strncmp(pCur, "exdc", 4) ) + break; + else + { + pCur--; + if ( pCur[strlen(pCur)-1] == '\r' ) + pCur[strlen(pCur)-1] = 0; + fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_BlifGetLine(p, pCur), pCur ); + } + } + + // count the number of objects + p->nObjects = Io_BlifEstimatePiNum(p) + Vec_PtrSize(p->vLatches) + Vec_PtrSize(p->vNames) + 512; + + // allocate memory for objects + p->pObjects = ALLOC( Io_BlifObj_t, p->nObjects ); + memset( p->pObjects, 0, p->nObjects * sizeof(Io_BlifObj_t) ); + + // allocate memory for the hash table + p->nTableSize = p->nObjects/2 + 1; + p->pTable = ALLOC( Io_BlifObj_t *, p->nTableSize ); + memset( p->pTable, 0, p->nTableSize * sizeof(Io_BlifObj_t *) ); +} + + +/**Function************************************************************* + + Synopsis [Reads the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p ) +{ + Abc_Ntk_t * pAig; + char * pLine; + int i; + // parse the model + if ( !Io_BlifParseModel( p, p->pModel ) ) + return NULL; + // parse the inputs + Vec_PtrForEachEntry( p->vInputs, pLine, i ) + if ( !Io_BlifParseInputs( p, pLine ) ) + return NULL; + // parse the outputs + Vec_PtrForEachEntry( p->vOutputs, pLine, i ) + if ( !Io_BlifParseOutputs( p, pLine ) ) + return NULL; + // parse the latches + Vec_PtrForEachEntry( p->vLatches, pLine, i ) + if ( !Io_BlifParseLatch( p, pLine ) ) + return NULL; + // parse the nodes + Vec_PtrForEachEntry( p->vNames, pLine, i ) + if ( !Io_BlifParseNames( p, pLine ) ) + return NULL; + // reconstruct the network from the parsed data + if ( !Io_BlifParseConstruct( p ) ) + return NULL; + // return the network + pAig = p->pAig; + p->pAig = NULL; + return pAig; +} + +/**Function************************************************************* + + Synopsis [Parses the model line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine ) +{ + char * pToken; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry( p->vTokens, 0 ); + assert( !strcmp(pToken, "model") ); + if ( Vec_PtrSize(p->vTokens) != 2 ) + { + sprintf( p->sError, "Line %d: Model line has %d entries while it should have 2.", Io_BlifGetLine(p, pToken), Vec_PtrSize(p->vTokens) ); + return 0; + } + p->pModel = Vec_PtrEntry( p->vTokens, 1 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the inputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine ) +{ + Io_BlifObj_t * pObj; + char * pToken; + int i; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(p->vTokens, 0); + assert( !strcmp(pToken, "inputs") ); + Vec_PtrForEachEntryStart( p->vTokens, pToken, i, 1 ) + { + pObj = Io_BlifHashFindOrAdd( p, pToken ); + if ( pObj->fPi ) + { + sprintf( p->sError, "Line %d: Primary input (%s) is defined more than once.", Io_BlifGetLine(p, pToken), pToken ); + return 0; + } + pObj->fPi = 1; + Vec_PtrPush( p->vPis, pObj ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the outputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine ) +{ + Io_BlifObj_t * pObj; + char * pToken; + int i; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(p->vTokens, 0); + assert( !strcmp(pToken, "outputs") ); + Vec_PtrForEachEntryStart( p->vTokens, pToken, i, 1 ) + { + pObj = Io_BlifHashFindOrAdd( p, pToken ); + if ( pObj->fPo ) + fprintf( stdout, "Line %d: Primary output (%s) is defined more than once (warning only).\n", Io_BlifGetLine(p, pToken), pToken ); + pObj->fPo = 1; + Vec_PtrPush( p->vPos, pObj ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the latches line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine ) +{ + Io_BlifObj_t * pObj; + char * pToken; + int Init; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(p->vTokens,0); + assert( !strcmp(pToken, "latch") ); + if ( Vec_PtrSize(p->vTokens) < 3 ) + { + sprintf( p->sError, "Line %d: Latch does not have input name and output name.", Io_BlifGetLine(p, pToken) ); + return 0; + } + // get initial value + if ( Vec_PtrSize(p->vTokens) > 3 ) + Init = atoi( Vec_PtrEntry(p->vTokens,3) ); + else + Init = 2; + if ( Init < 0 || Init > 2 ) + { + sprintf( p->sError, "Line %d: Initial state of the latch is incorrect (%s).", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,3) ); + return 0; + } + if ( Init == 0 ) + Init = IO_BLIF_INIT_ZERO; + else if ( Init == 1 ) + Init = IO_BLIF_INIT_ONE; + else // if ( Init == 2 ) + Init = IO_BLIF_INIT_DC; + // get latch input + pObj = Io_BlifHashFindOrAdd( p, Vec_PtrEntry(p->vTokens,1) ); + pObj->fLi = 1; + Vec_PtrPush( p->vLis, pObj ); + pObj->Init = Init; + // get latch output + pObj = Io_BlifHashFindOrAdd( p, Vec_PtrEntry(p->vTokens,2) ); + if ( pObj->fPi ) + { + sprintf( p->sError, "Line %d: Primary input (%s) is also defined latch output.", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,2) ); + return 0; + } + if ( pObj->fLo ) + { + sprintf( p->sError, "Line %d: Latch output (%s) is defined as the output of another latch.", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,2) ); + return 0; + } + pObj->fLo = 1; + Vec_PtrPush( p->vLos, pObj ); + pObj->Init = Init; + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the nodes line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine ) +{ + Io_BlifObj_t * pObj; + char * pName; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + assert( !strcmp(Vec_PtrEntry(p->vTokens,0), "names") ); + pName = Vec_PtrEntryLast( p->vTokens ); + pObj = Io_BlifHashFindOrAdd( p, pName ); + if ( pObj->fPi ) + { + sprintf( p->sError, "Line %d: Primary input (%s) has a table.", Io_BlifGetLine(p, pName), pName ); + return 0; + } + if ( pObj->fLo ) + { + sprintf( p->sError, "Line %d: Latch output (%s) has a table.", Io_BlifGetLine(p, pName), pName ); + return 0; + } + if ( pObj->fDef ) + { + sprintf( p->sError, "Line %d: Signal (%s) is defined more than once.", Io_BlifGetLine(p, pName), pName ); + return 0; + } + pObj->fDef = 1; + // remember offset to the first fanin name + pObj->pName = pName; + pObj->Offset = pObj->pName - (char *)Vec_PtrEntry(p->vTokens,1); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Constructs the AIG from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Obj_t * Io_BlifParseTable( Io_BlifMan_t * p, char * pTable, Vec_Ptr_t * vFanins ) +{ + char * pProduct, * pOutput; + Abc_Obj_t * pRes, * pCube; + int i, k, Polarity = -1; + + p->nTablesRead++; + // get the tokens + Io_BlifSplitIntoTokens( p->vTokens, pTable, '.' ); + if ( Vec_PtrSize(p->vTokens) == 0 ) + return Abc_ObjNot( Abc_AigConst1(p->pAig) ); + if ( Vec_PtrSize(p->vTokens) == 1 ) + { + pOutput = Vec_PtrEntry( p->vTokens, 0 ); + if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) + { + sprintf( p->sError, "Line %d: Constant table has wrong output value (%s).", Io_BlifGetLine(p, pOutput), pOutput ); + return NULL; + } + return Abc_ObjNotCond( Abc_AigConst1(p->pAig), pOutput[0] == '0' ); + } + pProduct = Vec_PtrEntry( p->vTokens, 0 ); + if ( Vec_PtrSize(p->vTokens) % 2 == 1 ) + { + sprintf( p->sError, "Line %d: Table has odd number of tokens (%d).", Io_BlifGetLine(p, pProduct), Vec_PtrSize(p->vTokens) ); + return NULL; + } + // parse the table + pRes = Abc_ObjNot( Abc_AigConst1(p->pAig) ); + for ( i = 0; i < Vec_PtrSize(p->vTokens)/2; i++ ) + { + pProduct = Vec_PtrEntry( p->vTokens, 2*i + 0 ); + pOutput = Vec_PtrEntry( p->vTokens, 2*i + 1 ); + if ( strlen(pProduct) != (unsigned)Vec_PtrSize(vFanins) ) + { + sprintf( p->sError, "Line %d: Cube (%s) has size different from the fanin count (%d).", Io_BlifGetLine(p, pProduct), pProduct, Vec_PtrSize(vFanins) ); + return NULL; + } + if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) + { + sprintf( p->sError, "Line %d: Output value (%s) is incorrect.", Io_BlifGetLine(p, pProduct), pOutput ); + return NULL; + } + if ( Polarity == -1 ) + Polarity = pOutput[0] - '0'; + else if ( Polarity != pOutput[0] - '0' ) + { + sprintf( p->sError, "Line %d: Output value (%s) differs from the value in the first line of the table (%d).", Io_BlifGetLine(p, pProduct), pOutput, Polarity ); + return NULL; + } + // parse one product product + pCube = Abc_AigConst1(p->pAig); + for ( k = 0; pProduct[k]; k++ ) + { + if ( pProduct[k] == '0' ) + pCube = Abc_AigAnd( p->pAig->pManFunc, pCube, Abc_ObjNot(Vec_PtrEntry(vFanins,k)) ); + else if ( pProduct[k] == '1' ) + pCube = Abc_AigAnd( p->pAig->pManFunc, pCube, Vec_PtrEntry(vFanins,k) ); + else if ( pProduct[k] != '-' ) + { + sprintf( p->sError, "Line %d: Product term (%s) contains character (%c).", Io_BlifGetLine(p, pProduct), pProduct, pProduct[k] ); + return NULL; + } + } + pRes = Abc_AigOr( p->pAig->pManFunc, pRes, pCube ); + } + pRes = Abc_ObjNotCond( pRes, Polarity == 0 ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Constructs the AIG from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Obj_t * Io_BlifParseConstruct_rec( Io_BlifMan_t * p, char * pName ) +{ + Vec_Ptr_t * vFanins; + Abc_Obj_t * pFaninAbc; + Io_BlifObj_t * pObjIo; + char * pNameFanin; + int i; + // get the IO object with this name + pObjIo = *Io_BlifHashLookup( p, pName ); + if ( pObjIo == NULL ) + { + sprintf( p->sError, "Line %d: Signal (%s) is not defined as a table.", Io_BlifGetLine(p, pName), pName ); + return NULL; + } + // loop detection + if ( pObjIo->fLoop ) + { + sprintf( p->sError, "Line %d: Signal (%s) appears twice on a combinational path.", Io_BlifGetLine(p, pName), pName ); + return NULL; + } + // check if the AIG is already constructed + if ( pObjIo->pEquiv ) + return pObjIo->pEquiv; + // mark this node on the path + pObjIo->fLoop = 1; + // construct the AIGs for the fanins + vFanins = Vec_PtrAlloc( 8 ); + Io_BlifCollectTokens( vFanins, pObjIo->pName - pObjIo->Offset, pObjIo->pName ); + Vec_PtrForEachEntry( vFanins, pNameFanin, i ) + { + pFaninAbc = Io_BlifParseConstruct_rec( p, pNameFanin ); + if ( pFaninAbc == NULL ) + { + Vec_PtrFree( vFanins ); + return NULL; + } + Vec_PtrWriteEntry( vFanins, i, pFaninAbc ); + } + // construct the node + pObjIo->pEquiv = Io_BlifParseTable( p, pObjIo->pName + strlen(pObjIo->pName), vFanins ); + Vec_PtrFree( vFanins ); + // unmark this node on the path + pObjIo->fLoop = 0; + // remember the new node + return pObjIo->pEquiv; +} + +/**Function************************************************************* + + Synopsis [Constructs the AIG from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseConstruct( Io_BlifMan_t * p ) +{ + Abc_Ntk_t * pAig; + Io_BlifObj_t * pObjIo, * pObjIoInput; + Abc_Obj_t * pObj, * pLatch; + int i; + // allocate the empty AIG + pAig = p->pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pAig->pName = Extra_UtilStrsav( p->pModel ); + pAig->pSpec = Extra_UtilStrsav( p->pFileName ); + // create PIs + Vec_PtrForEachEntry( p->vPis, pObjIo, i ) + { + pObj = Abc_NtkCreatePi( pAig ); + Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); + pObjIo->pEquiv = pObj; + } + // create POs + Vec_PtrForEachEntry( p->vPos, pObjIo, i ) + { + pObj = Abc_NtkCreatePo( pAig ); + Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); + } + // create latches + Vec_PtrForEachEntry( p->vLos, pObjIo, i ) + { + // add the latch input terminal + pObj = Abc_NtkCreateBi( pAig ); + pObjIoInput = Vec_PtrEntry( p->vLis, i ); + Abc_ObjAssignName( pObj, pObjIoInput->pName, NULL ); + + // add the latch box + pLatch = Abc_NtkCreateLatch( pAig ); + pLatch->pData = (void *)pObjIo->Init; + Abc_ObjAssignName( pLatch, pObjIo->pName, "L" ); + Abc_ObjAddFanin( pLatch, pObj ); + + // add the latch output terminal + pObj = Abc_NtkCreateBo( pAig ); + Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); + Abc_ObjAddFanin( pObj, pLatch ); + // set the value of the latch output +// pObjIo->pEquiv = Abc_ObjNotCond( pObj, pObjIo->Init ); + pObjIo->pEquiv = pObj; + } + // traverse the nodes from the POs + Vec_PtrForEachEntry( p->vPos, pObjIo, i ) + { + pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName ); + if ( pObj == NULL ) + return 0; + Abc_ObjAddFanin( Abc_NtkPo(p->pAig, i), pObj ); + } + // traverse the nodes from the latch inputs + Vec_PtrForEachEntry( p->vLis, pObjIo, i ) + { + pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName ); + if ( pObj == NULL ) + return 0; +// pObj = Abc_ObjNotCond( pObj, pObjIo->Init ); + Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(p->pAig, i)), pObj ); + } + p->nTablesLeft = Vec_PtrSize(p->vNames) - p->nTablesRead; + if ( p->nTablesLeft ) + printf( "The number of dangling tables = %d.\n", p->nTablesLeft ); + printf( "AND nodes = %6d. Estimate = %6d.\n", Abc_NtkNodeNum(p->pAig), Io_BlifEstimateAndNum(p) ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadBlifMv.c b/abc70930/src/base/io/ioReadBlifMv.c new file mode 100644 index 00000000..18578cbb --- /dev/null +++ b/abc70930/src/base/io/ioReadBlifMv.c @@ -0,0 +1,1696 @@ +/**CFile**************************************************************** + + FileName [ioReadBlifMv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read BLIF-MV file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 8, 2007.] + + Revision [$Id: ioReadBlifMv.c,v 1.00 2007/01/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "extra.h" +#include "vecPtr.h" +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IO_BLIFMV_MAXVALUES 256 + +typedef struct Io_MvVar_t_ Io_MvVar_t; // parsing var +typedef struct Io_MvMod_t_ Io_MvMod_t; // parsing model +typedef struct Io_MvMan_t_ Io_MvMan_t; // parsing manager + +struct Io_MvVar_t_ +{ + int nValues; // the number of values + char ** pNames; // the value names +}; + +struct Io_MvMod_t_ +{ + // file lines + char * pName; // .model line + Vec_Ptr_t * vInputs; // .inputs lines + Vec_Ptr_t * vOutputs; // .outputs lines + Vec_Ptr_t * vLatches; // .latch lines + Vec_Ptr_t * vResets; // .reset lines + Vec_Ptr_t * vNames; // .names lines + Vec_Ptr_t * vSubckts; // .subckt lines + Vec_Ptr_t * vMvs; // .mv lines + int fBlackBox; // indicates blackbox model + // the resulting network + Abc_Ntk_t * pNtk; + Abc_Obj_t * pResetLatch; + // the parent manager + Io_MvMan_t * pMan; +}; + +struct Io_MvMan_t_ +{ + // general info about file + int fBlifMv; // the file is BLIF-MV + int fUseReset; // the reset circuitry is added + char * pFileName; // the name of the file + char * pBuffer; // the contents of the file + Vec_Ptr_t * vLines; // the line beginnings + // the results of reading + Abc_Lib_t * pDesign; // the design under construction + int nNDnodes; // the counter of ND nodes + // intermediate storage for models + Vec_Ptr_t * vModels; // vector of models + Io_MvMod_t * pLatest; // the current model + // current processing info + Vec_Ptr_t * vTokens; // the current tokens + Vec_Ptr_t * vTokens2; // the current tokens + Vec_Str_t * vFunc; // the local function + // error reporting + char sError[512]; // the error string generated during parsing + // statistics + int nTablesRead; // the number of processed tables + int nTablesLeft; // the number of dangling tables +}; + +// static functions +static Io_MvMan_t * Io_MvAlloc(); +static void Io_MvFree( Io_MvMan_t * p ); +static Io_MvMod_t * Io_MvModAlloc(); +static void Io_MvModFree( Io_MvMod_t * p ); +static char * Io_MvLoadFile( char * pFileName ); +static void Io_MvReadPreparse( Io_MvMan_t * p ); +static void Io_MvReadInterfaces( Io_MvMan_t * p ); +static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p ); +static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset ); +static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens ); +static Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar ); + +static int Io_MvCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; } +static int Io_MvCharIsMvSymb( char s ) { return s == '(' || s == ')' || s == '{' || s == '}' || s == '-' || s == ',' || s == '!'; } + +extern void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from the BLIF or BLIF-MV file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck ) +{ + FILE * pFile; + Io_MvMan_t * p; + Abc_Ntk_t * pNtk; + Abc_Lib_t * pDesign; + char * pDesignName; + int RetValue, i; + + // check that the file is available + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Io_ReadBlifMv(): The file is unavailable (absent or open).\n" ); + return 0; + } + fclose( pFile ); + + // start the file reader + p = Io_MvAlloc(); + p->fBlifMv = fBlifMv; + p->fUseReset = 0; + p->pFileName = pFileName; + p->pBuffer = Io_MvLoadFile( pFileName ); + if ( p->pBuffer == NULL ) + { + Io_MvFree( p ); + return NULL; + } + // set the design name + pDesignName = Extra_FileNameGeneric( pFileName ); + p->pDesign = Abc_LibCreate( pDesignName ); + free( pDesignName ); + // free the HOP manager + Hop_ManStop( p->pDesign->pManFunc ); + p->pDesign->pManFunc = NULL; + // prepare the file for parsing + Io_MvReadPreparse( p ); + // parse interfaces of each network + Io_MvReadInterfaces( p ); + // construct the network + pDesign = Io_MvParse( p ); + if ( p->sError[0] ) + fprintf( stdout, "%s\n", p->sError ); + if ( pDesign == NULL ) + return NULL; + Io_MvFree( p ); +// pDesign should be linked to all models of the design + + // make sure that everything is okay with the network structure + if ( fCheck ) + { + Vec_PtrForEachEntry( pDesign->vModules, pNtk, i ) + { + if ( !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadBlifMv: The network check has failed for network %s.\n", pNtk->pName ); + Abc_LibFree( pDesign, NULL ); + return NULL; + } + } + } + +//Abc_LibPrint( pDesign ); + + // detect top-level model + RetValue = Abc_LibFindTopLevelModels( pDesign ); + pNtk = Vec_PtrEntry( pDesign->vTops, 0 ); + if ( RetValue > 1 ) + printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n", + Vec_PtrSize(pDesign->vTops), pNtk->pName ); + + // extract the master network + pNtk->pDesign = pDesign; + pDesign->pManFunc = NULL; + + // verify the design for cyclic dependence + assert( Vec_PtrSize(pDesign->vModules) > 0 ); + if ( Vec_PtrSize(pDesign->vModules) == 1 ) + { +// printf( "Warning: The design is not hierarchical.\n" ); + Abc_LibFree( pDesign, pNtk ); + pNtk->pDesign = NULL; + pNtk->pSpec = Extra_UtilStrsav( pFileName ); + } + else + Abc_NtkIsAcyclicHierarchy( pNtk ); + +//Io_WriteBlifMv( pNtk, "_temp_.mv" ); + if ( pNtk->pSpec == NULL ) + pNtk->pSpec = Extra_UtilStrsav( pFileName ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Allocates the BLIF parsing structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_MvMan_t * Io_MvAlloc() +{ + Io_MvMan_t * p; + p = ALLOC( Io_MvMan_t, 1 ); + memset( p, 0, sizeof(Io_MvMan_t) ); + p->vLines = Vec_PtrAlloc( 512 ); + p->vModels = Vec_PtrAlloc( 512 ); + p->vTokens = Vec_PtrAlloc( 512 ); + p->vTokens2 = Vec_PtrAlloc( 512 ); + p->vFunc = Vec_StrAlloc( 512 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the BLIF parsing structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvFree( Io_MvMan_t * p ) +{ + Io_MvMod_t * pMod; + int i; + if ( p->pDesign ) + Abc_LibFree( p->pDesign, NULL ); + if ( p->pBuffer ) + free( p->pBuffer ); + if ( p->vLines ) + Vec_PtrFree( p->vLines ); + if ( p->vModels ) + { + Vec_PtrForEachEntry( p->vModels, pMod, i ) + Io_MvModFree( pMod ); + Vec_PtrFree( p->vModels ); + } + Vec_PtrFree( p->vTokens ); + Vec_PtrFree( p->vTokens2 ); + Vec_StrFree( p->vFunc ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Allocates the BLIF parsing structure for one model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_MvMod_t * Io_MvModAlloc() +{ + Io_MvMod_t * p; + p = ALLOC( Io_MvMod_t, 1 ); + memset( p, 0, sizeof(Io_MvMod_t) ); + p->vInputs = Vec_PtrAlloc( 512 ); + p->vOutputs = Vec_PtrAlloc( 512 ); + p->vLatches = Vec_PtrAlloc( 512 ); + p->vResets = Vec_PtrAlloc( 512 ); + p->vNames = Vec_PtrAlloc( 512 ); + p->vSubckts = Vec_PtrAlloc( 512 ); + p->vMvs = Vec_PtrAlloc( 512 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Allocates the BLIF parsing structure for one model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvModFree( Io_MvMod_t * p ) +{ +// if ( p->pNtk ) +// Abc_NtkDelete( p->pNtk ); + Vec_PtrFree( p->vInputs ); + Vec_PtrFree( p->vOutputs ); + Vec_PtrFree( p->vLatches ); + Vec_PtrFree( p->vResets ); + Vec_PtrFree( p->vNames ); + Vec_PtrFree( p->vSubckts ); + Vec_PtrFree( p->vMvs ); + free( p ); +} + + + +/**Function************************************************************* + + Synopsis [Counts the number of given chars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvCountChars( char * pLine, char Char ) +{ + char * pCur; + int Counter = 0; + for ( pCur = pLine; *pCur; pCur++ ) + if ( *pCur == Char ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the place where the arrow is hiding.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_MvFindArrow( char * pLine ) +{ + char * pCur; + for ( pCur = pLine; *(pCur+1); pCur++ ) + if ( *pCur == '-' && *(pCur+1) == '>' ) + { + *pCur = ' '; + *(pCur+1) = ' '; + return pCur; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Collects the already split tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput ) +{ + char * pCur; + Vec_PtrClear( vTokens ); + for ( pCur = pInput; pCur < pOutput; pCur++ ) + { + if ( *pCur == 0 ) + continue; + Vec_PtrPush( vTokens, pCur ); + while ( *++pCur ); + } +} + +/**Function************************************************************* + + Synopsis [Splits the line into tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != Stop; pCur++ ) + if ( Io_MvCharIsSpace(*pCur) ) + *pCur = 0; + // collect tokens + Io_MvCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Splits the line into tokens when .default may be present.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvSplitIntoTokensMv( Vec_Ptr_t * vTokens, char * pLine ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != '.' || *(pCur+1) == 'd'; pCur++ ) + if ( Io_MvCharIsSpace(*pCur) ) + *pCur = 0; + // collect tokens + Io_MvCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Splits the line into tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != Stop; pCur++ ) + if ( Io_MvCharIsSpace(*pCur) || *pCur == Char ) + *pCur = 0; + // collect tokens + Io_MvCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Returns the 1-based number of the line in which the token occurs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvGetLine( Io_MvMan_t * p, char * pToken ) +{ + char * pLine; + int i; + Vec_PtrForEachEntry( p->vLines, pLine, i ) + if ( pToken < pLine ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Reads the file into a character buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_MvLoadFile( char * pFileName ) +{ + FILE * pFile; + int nFileSize; + char * pContents; + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Io_MvLoadFile(): The file is unavailable (absent or open).\n" ); + return NULL; + } + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + if ( nFileSize == 0 ) + { + printf( "Io_MvLoadFile(): The file is empty.\n" ); + return NULL; + } + pContents = ALLOC( char, nFileSize + 10 ); + rewind( pFile ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + // finish off the file with the spare .end line + // some benchmarks suddenly break off without this line + strcpy( pContents + nFileSize, "\n.end\n" ); + return pContents; +} + +/**Function************************************************************* + + Synopsis [Prepares the parsing.] + + Description [Performs several preliminary operations: + - Cuts the file buffer into separate lines. + - Removes comments and line extenders. + - Sorts lines by directives. + - Estimates the number of objects. + - Allocates room for the objects. + - Allocates room for the hash table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvReadPreparse( Io_MvMan_t * p ) +{ + char * pCur, * pPrev; + int i, fComment = 0; + // parse the buffer into lines and remove comments + Vec_PtrPush( p->vLines, p->pBuffer ); + for ( pCur = p->pBuffer; *pCur; pCur++ ) + { + if ( *pCur == '\n' ) + { + *pCur = 0; +// if ( *(pCur-1) == '\r' ) +// *(pCur-1) = 0; + fComment = 0; + Vec_PtrPush( p->vLines, pCur + 1 ); + } + else if ( *pCur == '#' ) + fComment = 1; + // remove comments + if ( fComment ) + *pCur = 0; + } + + // unfold the line extensions and sort lines by directive + Vec_PtrForEachEntry( p->vLines, pCur, i ) + { + if ( *pCur == 0 ) + continue; + // find previous non-space character + for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- ) + if ( !Io_MvCharIsSpace(*pPrev) ) + break; + // if it is the line extender, overwrite it with spaces + if ( *pPrev == '\\' ) + { + for ( ; *pPrev; pPrev++ ) + *pPrev = ' '; + *pPrev = ' '; + continue; + } + // skip spaces at the beginning of the line + while ( Io_MvCharIsSpace(*pCur++) ); + // parse directives + if ( *(pCur-1) != '.' ) + continue; + if ( !strncmp(pCur, "names", 5) || !strncmp(pCur, "table", 5) || !strncmp(pCur, "gate", 4) ) + Vec_PtrPush( p->pLatest->vNames, pCur ); + else if ( p->fBlifMv && (!strncmp(pCur, "def ", 4) || !strncmp(pCur, "default ", 8)) ) + continue; + else if ( !strncmp(pCur, "latch", 5) ) + Vec_PtrPush( p->pLatest->vLatches, pCur ); + else if ( !strncmp(pCur, "r ", 2) || !strncmp(pCur, "reset ", 6) ) + Vec_PtrPush( p->pLatest->vResets, pCur ); + else if ( !strncmp(pCur, "inputs", 6) ) + Vec_PtrPush( p->pLatest->vInputs, pCur ); + else if ( !strncmp(pCur, "outputs", 7) ) + Vec_PtrPush( p->pLatest->vOutputs, pCur ); + else if ( !strncmp(pCur, "subckt", 6) ) + Vec_PtrPush( p->pLatest->vSubckts, pCur ); + else if ( p->fBlifMv && !strncmp(pCur, "mv", 2) ) + Vec_PtrPush( p->pLatest->vMvs, pCur ); + else if ( !strncmp(pCur, "blackbox", 8) ) + p->pLatest->fBlackBox = 1; + else if ( !strncmp(pCur, "model", 5) ) + { + p->pLatest = Io_MvModAlloc(); + p->pLatest->pName = pCur; + p->pLatest->pMan = p; + } + else if ( !strncmp(pCur, "end", 3) ) + { + if ( p->pLatest ) + Vec_PtrPush( p->vModels, p->pLatest ); + p->pLatest = NULL; + } + else if ( !strncmp(pCur, "exdc", 4) ) + { + fprintf( stdout, "Line %d: Skipping EXDC network.\n", Io_MvGetLine(p, pCur) ); + break; + } + else + { + pCur--; + if ( pCur[strlen(pCur)-1] == '\r' ) + pCur[strlen(pCur)-1] = 0; + fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_MvGetLine(p, pCur), pCur ); + } + } +} + +/**Function************************************************************* + + Synopsis [Parses interfaces of the models.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvReadInterfaces( Io_MvMan_t * p ) +{ + Io_MvMod_t * pMod; + char * pLine; + int i, k; + // iterate through the models + Vec_PtrForEachEntry( p->vModels, pMod, i ) + { + // parse the model + if ( !Io_MvParseLineModel( pMod, pMod->pName ) ) + return; + // add model to the design + if ( !Abc_LibAddModel( p->pDesign, pMod->pNtk ) ) + { + sprintf( p->sError, "Line %d: Model %s is defined twice.", Io_MvGetLine(p, pMod->pName), pMod->pName ); + return; + } + // parse the inputs + Vec_PtrForEachEntry( pMod->vInputs, pLine, k ) + if ( !Io_MvParseLineInputs( pMod, pLine ) ) + return; + // parse the outputs + Vec_PtrForEachEntry( pMod->vOutputs, pLine, k ) + if ( !Io_MvParseLineOutputs( pMod, pLine ) ) + return; + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p ) +{ + Abc_Lib_t * pDesign; + Io_MvMod_t * pMod; + char * pLine; + int i, k; + // iterate through the models + Vec_PtrForEachEntry( p->vModels, pMod, i ) + { + // check if there any MV lines + if ( Vec_PtrSize(pMod->vMvs) > 0 ) + Abc_NtkStartMvVars( pMod->pNtk ); + // parse the mv lines + Vec_PtrForEachEntry( pMod->vMvs, pLine, k ) + if ( !Io_MvParseLineMv( pMod, pLine ) ) + return NULL; + // if reset lines are used there should be the same number of them as latches + if ( Vec_PtrSize(pMod->vResets) > 0 ) + { + if ( Vec_PtrSize(pMod->vLatches) != Vec_PtrSize(pMod->vResets) ) + { + sprintf( p->sError, "Line %d: Model %s has different number of latches (%d) and reset nodes (%d).", + Io_MvGetLine(p, pMod->pName), Abc_NtkName(pMod->pNtk), Vec_PtrSize(pMod->vLatches), Vec_PtrSize(pMod->vResets) ); + return NULL; + } + // create binary latch with 1-data and 0-init + if ( p->fUseReset ) + pMod->pResetLatch = Io_ReadCreateResetLatch( pMod->pNtk, p->fBlifMv ); + } + // parse the latches + Vec_PtrForEachEntry( pMod->vLatches, pLine, k ) + if ( !Io_MvParseLineLatch( pMod, pLine ) ) + return NULL; + // parse the reset lines + if ( p->fUseReset ) + Vec_PtrForEachEntry( pMod->vResets, pLine, k ) + if ( !Io_MvParseLineNamesMv( pMod, pLine, 1 ) ) + return NULL; + // parse the nodes + if ( p->fBlifMv ) + { + Vec_PtrForEachEntry( pMod->vNames, pLine, k ) + if ( !Io_MvParseLineNamesMv( pMod, pLine, 0 ) ) + return NULL; + } + else + { + Vec_PtrForEachEntry( pMod->vNames, pLine, k ) + if ( !Io_MvParseLineNamesBlif( pMod, pLine ) ) + return NULL; + } + // parse the subcircuits + Vec_PtrForEachEntry( pMod->vSubckts, pLine, k ) + if ( !Io_MvParseLineSubckt( pMod, pLine ) ) + return NULL; + // finalize the network + Abc_NtkFinalizeRead( pMod->pNtk ); + } + if ( p->nNDnodes ) +// printf( "Warning: The parser added %d PIs to replace non-deterministic nodes.\n", p->nNDnodes ); + printf( "Warning: The parser added %d constant 0 nodes to replace non-deterministic nodes.\n", p->nNDnodes ); + // return the network + pDesign = p->pDesign; + p->pDesign = NULL; + return pDesign; +} + +/**Function************************************************************* + + Synopsis [Parses the model line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + char * pToken; + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry( vTokens, 0 ); + assert( !strcmp(pToken, "model") ); + if ( Vec_PtrSize(vTokens) != 2 ) + { + sprintf( p->pMan->sError, "Line %d: Model line has %d entries while it should have 2.", Io_MvGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) ); + return 0; + } + if ( p->fBlackBox ) + p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, 1 ); + else if ( p->pMan->fBlifMv ) + p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLIFMV, 1 ); + else + p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); + p->pNtk->pName = Extra_UtilStrsav( Vec_PtrEntry(vTokens, 1) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the inputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + char * pToken; + int i; + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens, 0); + assert( !strcmp(pToken, "inputs") ); + Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 ) + Io_ReadCreatePi( p->pNtk, pToken ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the outputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + char * pToken; + int i; + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens, 0); + assert( !strcmp(pToken, "outputs") ); + Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 ) + Io_ReadCreatePo( p->pNtk, pToken ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the latches line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Abc_Obj_t * pObj, * pNet; + char * pToken; + int Init; + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens,0); + assert( !strcmp(pToken, "latch") ); + if ( Vec_PtrSize(vTokens) < 3 ) + { + sprintf( p->pMan->sError, "Line %d: Latch does not have input name and output name.", Io_MvGetLine(p->pMan, pToken) ); + return 0; + } + // create latch + if ( p->pResetLatch == NULL ) + { + pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Vec_PtrEntry(vTokens,2) ); + // get initial value + if ( p->pMan->fBlifMv ) + Abc_LatchSetInit0( pObj ); + else + { + if ( Vec_PtrSize(vTokens) > 3 ) + Init = atoi( Vec_PtrEntry(vTokens,3) ); + else + Init = 2; + if ( Init < 0 || Init > 2 ) + { + sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,3) ); + return 0; + } + if ( Init == 0 ) + Abc_LatchSetInit0( pObj ); + else if ( Init == 1 ) + Abc_LatchSetInit1( pObj ); + else // if ( Init == 2 ) + Abc_LatchSetInitDc( pObj ); + } + } + else + { + // get the net corresponding to the output of the latch + pNet = Abc_NtkFindOrCreateNet( p->pNtk, Vec_PtrEntry(vTokens,2) ); + // get the net corresponding to the latch output (feeding into reset MUX) + pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNet, "_out") ); + // create latch + pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Abc_ObjName(pNet) ); + Abc_LatchSetInit0( pObj ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the subckt line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Abc_Ntk_t * pModel; + Abc_Obj_t * pBox, * pNet, * pTerm; + char * pToken, * pName, ** ppNames; + int nEquals, i, k; + + // split the line into tokens + nEquals = Io_MvCountChars( pLine, '=' ); + Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' ); + pToken = Vec_PtrEntry(vTokens,0); + assert( !strcmp(pToken, "subckt") ); + + // get the model for this box + pName = Vec_PtrEntry(vTokens,1); + pModel = Abc_LibFindModelByName( p->pMan->pDesign, pName ); + if ( pModel == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find the model for subcircuit %s.", Io_MvGetLine(p->pMan, pToken), pName ); + return 0; + } + + // check if the number of tokens is correct + if ( nEquals != Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) ) + { + sprintf( p->pMan->sError, "Line %d: The number of ports (%d) in .subckt differs from the sum of PIs and POs of the model (%d).", + Io_MvGetLine(p->pMan, pToken), nEquals, Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) ); + return 0; + } + + // get the names + ppNames = (char **)Vec_PtrArray(vTokens) + 2 + p->pMan->fBlifMv; + + // create the box with these terminals + if ( Abc_NtkHasBlackbox(pModel) ) + pBox = Abc_NtkCreateBlackbox( p->pNtk ); + else + pBox = Abc_NtkCreateWhitebox( p->pNtk ); + pBox->pData = pModel; + if ( p->pMan->fBlifMv ) + Abc_ObjAssignName( pBox, Vec_PtrEntry(vTokens,2), NULL ); + Abc_NtkForEachPi( pModel, pTerm, i ) + { + // find this terminal among the formal inputs of the subcircuit + pName = Abc_ObjName(Abc_ObjFanout0(pTerm)); + for ( k = 0; k < nEquals; k++ ) + if ( !strcmp( ppNames[2*k], pName ) ) + break; + if ( k == nEquals ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find PI \"%s\" of the model \"%s\" as a formal input of the subcircuit.", + Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) ); + return 0; + } + // create the BI with the actual name + pNet = Abc_NtkFindOrCreateNet( p->pNtk, ppNames[2*k+1] ); + pTerm = Abc_NtkCreateBi( p->pNtk ); + Abc_ObjAddFanin( pBox, pTerm ); + Abc_ObjAddFanin( pTerm, pNet ); + } + Abc_NtkForEachPo( pModel, pTerm, i ) + { + // find this terminal among the formal outputs of the subcircuit + pName = Abc_ObjName(Abc_ObjFanin0(pTerm)); + for ( k = 0; k < nEquals; k++ ) + if ( !strcmp( ppNames[2*k], pName ) ) + break; + if ( k == nEquals ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find PO \"%s\" of the modell \"%s\" as a formal output of the subcircuit.", + Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) ); + return 0; + } + // create the BI with the actual name + pNet = Abc_NtkFindOrCreateNet( p->pNtk, ppNames[2*k+1] ); + pTerm = Abc_NtkCreateBo( p->pNtk ); + Abc_ObjAddFanin( pNet, pTerm ); + Abc_ObjAddFanin( pTerm, pBox ); + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Parses the mv line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Abc_Obj_t * pObj; + Io_MvVar_t * pVar; + Extra_MmFlex_t * pFlex; + char * pName; + int nCommas, nValues, i, k; + // count commas and get the tokens + nCommas = Io_MvCountChars( pLine, ',' ); + Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', ',' ); + pName = Vec_PtrEntry(vTokens,0); + assert( !strcmp(pName, "mv") ); + // get the number of values + if ( Vec_PtrSize(vTokens) <= nCommas + 2 ) + { + sprintf( p->pMan->sError, "Line %d: The number of values in not specified in .mv line.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } + nValues = atoi( Vec_PtrEntry(vTokens,nCommas+2) ); + if ( nValues < 2 || nValues > IO_BLIFMV_MAXVALUES ) + { + sprintf( p->pMan->sError, "Line %d: The number of values (%d) is incorrect (should be >= 2 and <= %d).", + Io_MvGetLine(p->pMan, pName), nValues, IO_BLIFMV_MAXVALUES ); + return 0; + } + // if there is no symbolic values, quit + if ( nValues == 2 && Vec_PtrSize(vTokens) == nCommas + 3 ) + return 1; + if ( Vec_PtrSize(vTokens) > nCommas + 3 && Vec_PtrSize(vTokens) - (nCommas + 3) != nValues ) + { + sprintf( p->pMan->sError, "Line %d: Wrong number (%d) of symbolic value names (should be %d).", + Io_MvGetLine(p->pMan, pName), Vec_PtrSize(vTokens) - (nCommas + 3), nValues ); + return 0; + } + // go through variables + pFlex = Abc_NtkMvVarMan( p->pNtk ); + for ( i = 0; i <= nCommas; i++ ) + { + pName = Vec_PtrEntry( vTokens, i+1 ); + pObj = Abc_NtkFindOrCreateNet( p->pNtk, pName ); + // allocate variable + pVar = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) ); + pVar->nValues = nValues; + pVar->pNames = NULL; + // create names + if ( Vec_PtrSize(vTokens) > nCommas + 3 ) + { + pVar->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * nValues ); + Vec_PtrForEachEntryStart( vTokens, pName, k, nCommas + 3 ) + { + pVar->pNames[k-(nCommas + 3)] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pName) + 1 ); + strcpy( pVar->pNames[k-(nCommas + 3)], pName ); + } + } + // save the variable + Abc_ObjSetMvVar( pObj, pVar ); + } + // make sure the names are unique + if ( pVar->pNames ) + { + for ( i = 0; i < nValues; i++ ) + for ( k = i+1; k < nValues; k++ ) + if ( !strcmp(pVar->pNames[i], pVar->pNames[k]) ) + { + pName = Vec_PtrEntry(vTokens,0); + sprintf( p->pMan->sError, "Line %d: Symbolic value name \"%s\" is repeated in .mv line.", + Io_MvGetLine(p->pMan, pName), pVar->pNames[i] ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the values into the BLIF-MV representation for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvWriteValues( Abc_Obj_t * pNode, Vec_Str_t * vFunc ) +{ + char Buffer[10]; + Abc_Obj_t * pFanin; + int i; + // add the fanin number of values + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + sprintf( Buffer, "%d", Abc_ObjMvVarNum(pFanin) ); + Vec_StrAppend( vFunc, Buffer ); + Vec_StrPush( vFunc, ' ' ); + } + // add the node number of values + sprintf( Buffer, "%d", Abc_ObjMvVarNum(Abc_ObjFanout0(pNode)) ); + Vec_StrAppend( vFunc, Buffer ); + Vec_StrPush( vFunc, '\n' ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Translated one literal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLiteralMv( Io_MvMod_t * p, Abc_Obj_t * pNode, char * pToken, Vec_Str_t * vFunc, int iLit ) +{ + char Buffer[10]; + Io_MvVar_t * pVar; + Abc_Obj_t * pFanin, * pNet; + char * pCur, * pNext; + int i; + // consider the equality literal + if ( pToken[0] == '=' ) + { + // find the fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( !strcmp( Abc_ObjName(pFanin), pToken + 1 ) ) + break; + if ( i == Abc_ObjFaninNum(pNode) ) + { + sprintf( p->pMan->sError, "Line %d: Node name in the table \"%s\" cannot be found on .names line.", + Io_MvGetLine(p->pMan, pToken), pToken + 1 ); + return 0; + } + Vec_StrPush( vFunc, '=' ); + sprintf( Buffer, "%d", i ); + Vec_StrAppend( vFunc, Buffer ); + Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); + return 1; + } + // consider regular literal + assert( iLit < Abc_ObjFaninNum(pNode) ); + pNet = iLit >= 0 ? Abc_ObjFanin(pNode, iLit) : Abc_ObjFanout0(pNode); + pVar = Abc_ObjMvVar( pNet ); + // if the var is absent or has no symbolic values quit + if ( pVar == NULL || pVar->pNames == NULL ) + { + Vec_StrAppend( vFunc, pToken ); + Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); + return 1; + } + // parse the literal using symbolic values + for ( pCur = pToken; *pCur; pCur++ ) + { + if ( Io_MvCharIsMvSymb(*pCur) ) + { + Vec_StrPush( vFunc, *pCur ); + continue; + } + // find the next MvSymb char + for ( pNext = pCur+1; *pNext; pNext++ ) + if ( Io_MvCharIsMvSymb(*pNext) ) + break; + // look for the value name + for ( i = 0; i < pVar->nValues; i++ ) + if ( !strncmp( pVar->pNames[i], pCur, pNext-pCur ) ) + break; + if ( i == pVar->nValues ) + { + *pNext = 0; + sprintf( p->pMan->sError, "Line %d: Cannot find value name \"%s\" among the value names of variable \"%s\".", + Io_MvGetLine(p->pMan, pToken), pCur, Abc_ObjName(pNet) ); + return 0; + } + // value name is found + sprintf( Buffer, "%d", i ); + Vec_StrAppend( vFunc, Buffer ); + // update the pointer + pCur = pNext - 1; + } + Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Constructs the MV-SOP cover from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_MvParseTableMv( Io_MvMod_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut ) +{ + Vec_Str_t * vFunc = p->pMan->vFunc; + char * pFirst, * pToken; + int iStart, i; + // prepare the place for the cover + Vec_StrClear( vFunc ); + // write the number of values +// Io_MvWriteValues( pNode, vFunc ); + // get the first token + pFirst = Vec_PtrEntry( vTokens2, 0 ); + if ( pFirst[0] == '.' ) + { + // write the default literal + Vec_StrPush( vFunc, 'd' ); + pToken = Vec_PtrEntry(vTokens2, 1 + iOut); + if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) ) + return NULL; + iStart = 1 + nOutputs; + } + else + iStart = 0; + // write the remaining literals + while ( iStart < Vec_PtrSize(vTokens2) ) + { + // input literals + for ( i = 0; i < nInputs; i++ ) + { + pToken = Vec_PtrEntry( vTokens2, iStart + i ); + if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, i ) ) + return NULL; + } + // output literal + pToken = Vec_PtrEntry( vTokens2, iStart + nInputs + iOut ); + if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) ) + return NULL; + // update the counter + iStart += nInputs + nOutputs; + } + Vec_StrPush( vFunc, '\0' ); + return Vec_StrArray( vFunc ); +} + +/**Function************************************************************* + + Synopsis [Adds reset circuitry corresponding to latch with pName.] + + Description [Returns the reset node's net.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Obj_t * Io_MvParseAddResetCircuit( Io_MvMod_t * p, char * pName ) +{ + char Buffer[50]; + Abc_Obj_t * pNode, * pData0Net, * pData1Net, * pResetLONet, * pOutNet; + Io_MvVar_t * pVar; + // make sure the reset latch exists + assert( p->pResetLatch != NULL ); + // get the reset net + pResetLONet = Abc_ObjFanout0(Abc_ObjFanout0(p->pResetLatch)); + // get the output net + pOutNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); + // get the data nets + pData0Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_reset") ); + pData1Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_out") ); + // duplicate MV variables + if ( Abc_NtkMvVar(p->pNtk) ) + { + pVar = Abc_ObjMvVar( pOutNet ); + Abc_ObjSetMvVar( pData0Net, Abc_NtkMvVarDup(p->pNtk, pVar) ); + Abc_ObjSetMvVar( pData1Net, Abc_NtkMvVarDup(p->pNtk, pVar) ); + } + // create the node + pNode = Abc_NtkCreateNode( p->pNtk ); + // create the output net + Abc_ObjAddFanin( pOutNet, pNode ); + // create the function + if ( p->pMan->fBlifMv ) + { +// Vec_Att_t * p = Abc_NtkMvVar( pNtk ); + int nValues = Abc_ObjMvVarNum(pOutNet); +// sprintf( Buffer, "2 %d %d %d\n1 - - =1\n0 - - =2\n", nValues, nValues, nValues ); + sprintf( Buffer, "1 - - =1\n0 - - =2\n" ); + pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, Buffer ); + } + else + pNode->pData = Abc_SopCreateMux( p->pNtk->pManFunc ); + // add nets + Abc_ObjAddFanin( pNode, pResetLONet ); + Abc_ObjAddFanin( pNode, pData1Net ); + Abc_ObjAddFanin( pNode, pData0Net ); + return pData0Net; +} + +/**Function************************************************************* + + Synopsis [Parses the nodes line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineNamesMvOne( Io_MvMod_t * p, Vec_Ptr_t * vTokens, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut, int fReset ) +{ + Abc_Obj_t * pNet, * pNode; + char * pName; + // get the output name + pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + iOut ); + // create the node + if ( fReset ) + { + pNet = Abc_NtkFindNet( p->pNtk, pName ); + if ( pNet == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Latch with output signal \"%s\" does not exist.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } +/* + if ( !Abc_ObjIsBo(Abc_ObjFanin0(pNet)) ) + { + sprintf( p->pMan->sError, "Line %d: Reset line \"%s\" defines signal that is not a latch output.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } +*/ + // construct the reset circuit and get the reset net feeding into it + pNet = Io_MvParseAddResetCircuit( p, pName ); + // create fanins + pNode = Io_ReadCreateNode( p->pNtk, Abc_ObjName(pNet), (char **)(vTokens->pArray + 1), nInputs ); + assert( nInputs == Vec_PtrSize(vTokens) - 2 ); + } + else + { + pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); + if ( Abc_ObjFaninNum(pNet) > 0 ) + { + sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } + pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), nInputs ); + } + // create the cover + pNode->pData = Io_MvParseTableMv( p, pNode, vTokens2, nInputs, nOutputs, iOut ); + if ( pNode->pData == NULL ) + return 0; + pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, pNode->pData ); +//printf( "Finished parsing node \"%s\" with table:\n%s\n", pName, pNode->pData ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the nodes line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Vec_Ptr_t * vTokens2 = p->pMan->vTokens2; + Abc_Obj_t * pNet; + char * pName, * pFirst, * pArrow; + int nInputs, nOutputs, nLiterals, nLines, i; + assert( p->pMan->fBlifMv ); + // get the arrow if it is present + pArrow = Io_MvFindArrow( pLine ); + if ( !p->pMan->fBlifMv && pArrow ) + { + sprintf( p->pMan->sError, "Line %d: Multi-output node symbol (->) in binary BLIF file.", Io_MvGetLine(p->pMan, pLine) ); + return 0; + } + // split names line into tokens + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + if ( fReset ) + assert( !strcmp(Vec_PtrEntry(vTokens,0), "r") || !strcmp(Vec_PtrEntry(vTokens,0), "reset") ); + else + assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") || !strcmp(Vec_PtrEntry(vTokens,0), "table") ); + // find the number of inputs and outputs + nInputs = Vec_PtrSize(vTokens) - 2; + nOutputs = 1; + if ( pArrow != NULL ) + { + for ( i = Vec_PtrSize(vTokens) - 2; i >= 1; i-- ) + if ( pArrow < (char*)Vec_PtrEntry(vTokens,i) ) + { + nInputs--; + nOutputs++; + } + } + // split table into tokens + pName = Vec_PtrEntryLast( vTokens ); + Io_MvSplitIntoTokensMv( vTokens2, pName + strlen(pName) ); + pFirst = Vec_PtrEntry( vTokens2, 0 ); + if ( pFirst[0] == '.' ) + { + assert( pFirst[1] == 'd' ); + nLiterals = Vec_PtrSize(vTokens2) - 1 - nOutputs; + } + else + nLiterals = Vec_PtrSize(vTokens2); + // check the number of lines + if ( nLiterals % (nInputs + nOutputs) != 0 ) + { + sprintf( p->pMan->sError, "Line %d: Wrong number of literals in the table of node \"%s\". (Spaces inside literals are not allowed.)", Io_MvGetLine(p->pMan, pFirst), pName ); + return 0; + } + // check for the ND table + nLines = nLiterals / (nInputs + nOutputs); + if ( nInputs == 0 && nLines > 1 ) + { + // add the outputs to the PIs + for ( i = 0; i < nOutputs; i++ ) + { + pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + i ); + // get the net corresponding to this node + pNet = Abc_NtkFindOrCreateNet(p->pNtk, pName); + if ( fReset ) + { + assert( p->pResetLatch != NULL ); + // construct the reset circuit and get the reset net feeding into it + pNet = Io_MvParseAddResetCircuit( p, pName ); + } + // add the new PI node +// Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(p->pNtk) ); +// fprintf( stdout, "Io_ReadBlifMv(): Adding PI for internal non-deterministic node \"%s\".\n", pName ); + p->pMan->nNDnodes++; + Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(p->pNtk) ); + } + return 1; + } + // iterate through the outputs + for ( i = 0; i < nOutputs; i++ ) + { + if ( !Io_MvParseLineNamesMvOne( p, vTokens, vTokens2, nInputs, nOutputs, i, fReset ) ) + return 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Constructs the SOP cover from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_MvParseTableBlif( Io_MvMod_t * p, char * pTable, int nFanins ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Vec_Str_t * vFunc = p->pMan->vFunc; + char * pProduct, * pOutput; + int i, Polarity = -1; + + p->pMan->nTablesRead++; + // get the tokens + Io_MvSplitIntoTokens( vTokens, pTable, '.' ); + if ( Vec_PtrSize(vTokens) == 0 ) + return Abc_SopCreateConst0( p->pNtk->pManFunc ); + if ( Vec_PtrSize(vTokens) == 1 ) + { + pOutput = Vec_PtrEntry( vTokens, 0 ); + if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) + { + sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Io_MvGetLine(p->pMan, pOutput), pOutput ); + return NULL; + } + return pOutput[0] == '0' ? Abc_SopCreateConst0(p->pNtk->pManFunc) : Abc_SopCreateConst1(p->pNtk->pManFunc); + } + pProduct = Vec_PtrEntry( vTokens, 0 ); + if ( Vec_PtrSize(vTokens) % 2 == 1 ) + { + sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Io_MvGetLine(p->pMan, pProduct), Vec_PtrSize(vTokens) ); + return NULL; + } + // parse the table + Vec_StrClear( vFunc ); + for ( i = 0; i < Vec_PtrSize(vTokens)/2; i++ ) + { + pProduct = Vec_PtrEntry( vTokens, 2*i + 0 ); + pOutput = Vec_PtrEntry( vTokens, 2*i + 1 ); + if ( strlen(pProduct) != (unsigned)nFanins ) + { + sprintf( p->pMan->sError, "Line %d: Cube \"%s\" has size different from the fanin count (%d).", Io_MvGetLine(p->pMan, pProduct), pProduct, nFanins ); + return NULL; + } + if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) + { + sprintf( p->pMan->sError, "Line %d: Output value \"%s\" is incorrect.", Io_MvGetLine(p->pMan, pProduct), pOutput ); + return NULL; + } + if ( Polarity == -1 ) + Polarity = pOutput[0] - '0'; + else if ( Polarity != pOutput[0] - '0' ) + { + sprintf( p->pMan->sError, "Line %d: Output value \"%s\" differs from the value in the first line of the table (%d).", Io_MvGetLine(p->pMan, pProduct), pOutput, Polarity ); + return NULL; + } + // parse one product + Vec_StrAppend( vFunc, pProduct ); + Vec_StrPush( vFunc, ' ' ); + Vec_StrPush( vFunc, pOutput[0] ); + Vec_StrPush( vFunc, '\n' ); + } + Vec_StrPush( vFunc, '\0' ); + return Vec_StrArray( vFunc ); +} + +/**Function************************************************************* + + Synopsis [Parses the nodes line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Abc_Obj_t * pNet, * pNode; + char * pName; + assert( !p->pMan->fBlifMv ); + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + // parse the mapped node + if ( !strcmp(Vec_PtrEntry(vTokens,0), "gate") ) + return Io_MvParseLineGateBlif( p, vTokens ); + // parse the regular name line + assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") ); + pName = Vec_PtrEntryLast( vTokens ); + pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); + if ( Abc_ObjFaninNum(pNet) > 0 ) + { + sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } + // create fanins + pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), Vec_PtrSize(vTokens) - 2 ); + // parse the table of this node + pNode->pData = Io_MvParseTableBlif( p, pName + strlen(pName), Abc_ObjFaninNum(pNode) ); + if ( pNode->pData == NULL ) + return 0; + pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, pNode->pData ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Duplicate the MV variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar ) +{ + Extra_MmFlex_t * pFlex; + Io_MvVar_t * pVarDup; + int i; + if ( pVar == NULL ) + return NULL; + pFlex = Abc_NtkMvVarMan( pNtk ); + assert( pFlex != NULL ); + pVarDup = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) ); + pVarDup->nValues = pVar->nValues; + pVarDup->pNames = NULL; + if ( pVar->pNames == NULL ) + return pVarDup; + pVarDup->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * pVar->nValues ); + for ( i = 0; i < pVar->nValues; i++ ) + { + pVarDup->pNames[i] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pVar->pNames[i]) + 1 ); + strcpy( pVarDup->pNames[i], pVar->pNames[i] ); + } + return pVarDup; +} + + +#include "mio.h" +#include "main.h" + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_ReadBlifCleanName( char * pName ) +{ + int i, Length; + Length = strlen(pName); + for ( i = 0; i < Length; i++ ) + if ( pName[i] == '=' ) + return pName + i + 1; + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens ) +{ + Mio_Library_t * pGenlib; + Mio_Gate_t * pGate; + Abc_Obj_t * pNode; + char ** ppNames, * pName; + int i, nNames; + + pName = vTokens->pArray[0]; + + // check that the library is available + pGenlib = Abc_FrameReadLibGen(); + if ( pGenlib == NULL ) + { + sprintf( p->pMan->sError, "Line %d: The current library is not available.", Io_MvGetLine(p->pMan, pName) ); + return 0; + } + + // create a new node and add it to the network + if ( vTokens->nSize < 2 ) + { + sprintf( p->pMan->sError, "Line %d: The .gate line has less than two tokens.", Io_MvGetLine(p->pMan, pName) ); + return 0; + } + + // get the gate + pGate = Mio_LibraryReadGateByName( pGenlib, vTokens->pArray[1] ); + if ( pGate == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find gate \"%s\" in the library.", Io_MvGetLine(p->pMan, pName), vTokens->pArray[1] ); + return 0; + } + + // if this is the first line with gate, update the network type + if ( Abc_NtkNodeNum(p->pNtk) == 0 ) + { + assert( p->pNtk->ntkFunc == ABC_FUNC_SOP ); + p->pNtk->ntkFunc = ABC_FUNC_MAP; + Extra_MmFlexStop( p->pNtk->pManFunc ); + p->pNtk->pManFunc = pGenlib; + } + + // remove the formal parameter names + for ( i = 2; i < vTokens->nSize; i++ ) + { + vTokens->pArray[i] = Io_ReadBlifCleanName( vTokens->pArray[i] ); + if ( vTokens->pArray[i] == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Invalid gate input assignment.", Io_MvGetLine(p->pMan, pName) ); + return 0; + } + } + + // create the node + ppNames = (char **)vTokens->pArray + 2; + nNames = vTokens->nSize - 3; + pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames ); + + // set the pointer to the functionality of the node + Abc_ObjSetData( pNode, pGate ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadDsd.c b/abc70930/src/base/io/ioReadDsd.c new file mode 100644 index 00000000..1ab726e5 --- /dev/null +++ b/abc70930/src/base/io/ioReadDsd.c @@ -0,0 +1,308 @@ +/**CFile**************************************************************** + + FileName [ioReadDsd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read network from file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Finds the end of the part.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Io_ReadDsdFindEnd( char * pCur ) +{ + char * pEnd; + int nParts = 0; + assert( *pCur == '(' ); + for ( pEnd = pCur; *pEnd; pEnd++ ) + { + if ( *pEnd == '(' ) + nParts++; + else if ( *pEnd == ')' ) + nParts--; + if ( nParts == 0 ) + return pEnd; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Splits the formula into parts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadDsdStrSplit( char * pCur, char * pParts[], int * pTypeXor ) +{ + int fAnd = 0, fXor = 0, fPri = 0, nParts = 0; + assert( *pCur ); + // process the parts + while ( 1 ) + { + // save the current part + pParts[nParts++] = pCur; + // skip the complement + if ( *pCur == '!' ) + pCur++; + // skip var + if ( *pCur >= 'a' && *pCur <= 'z' ) + pCur++; + else + { + // skip hex truth table + while ( (*pCur >= '0' && *pCur <= '9') || (*pCur >= 'A' && *pCur <= 'F') ) + pCur++; + // process parantheses + if ( *pCur != '(' ) + { + printf( "Cannot find the opening paranthesis.\n" ); + break; + } + // find the corresponding closing paranthesis + pCur = Io_ReadDsdFindEnd( pCur ); + if ( pCur == NULL ) + { + printf( "Cannot find the closing paranthesis.\n" ); + break; + } + pCur++; + } + // check the end + if ( *pCur == 0 ) + break; + // check symbol + if ( *pCur != '*' && *pCur != '+' && *pCur != ',' ) + { + printf( "Wrong separating symbol.\n" ); + break; + } + // remember the symbol + fAnd |= (*pCur == '*'); + fXor |= (*pCur == '+'); + fPri |= (*pCur == ','); + *pCur++ = 0; + } + // check separating symbols + if ( fAnd + fXor + fPri > 1 ) + { + printf( "Different types of separating symbol ennPartsed.\n" ); + return 0; + } + *pTypeXor = fXor; + return nParts; +} + +/**Function************************************************************* + + Synopsis [Recursively parses the formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadDsd_rec( Abc_Ntk_t * pNtk, char * pCur, char * pSop ) +{ + Abc_Obj_t * pObj, * pFanin; + char * pEnd, * pParts[32]; + int i, nParts, TypeExor; + + // consider complemented formula + if ( *pCur == '!' ) + { + pObj = Io_ReadDsd_rec( pNtk, pCur + 1, NULL ); + return Abc_NtkCreateNodeInv( pNtk, pObj ); + } + if ( *pCur == '(' ) + { + assert( pCur[strlen(pCur)-1] == ')' ); + pCur[strlen(pCur)-1] = 0; + nParts = Io_ReadDsdStrSplit( pCur+1, pParts, &TypeExor ); + if ( nParts == 0 ) + { + Abc_NtkDelete( pNtk ); + return NULL; + } + pObj = Abc_NtkCreateNode( pNtk ); + if ( pSop ) + { +// for ( i = nParts - 1; i >= 0; i-- ) + for ( i = 0; i < nParts; i++ ) + { + pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL ); + if ( pFanin == NULL ) + return NULL; + Abc_ObjAddFanin( pObj, pFanin ); + } + } + else + { + for ( i = 0; i < nParts; i++ ) + { + pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL ); + if ( pFanin == NULL ) + return NULL; + Abc_ObjAddFanin( pObj, pFanin ); + } + } + if ( pSop ) + pObj->pData = Abc_SopRegister( pNtk->pManFunc, pSop ); + else if ( TypeExor ) + pObj->pData = Abc_SopCreateXorSpecial( pNtk->pManFunc, nParts ); + else + pObj->pData = Abc_SopCreateAnd( pNtk->pManFunc, nParts, NULL ); + return pObj; + } + if ( *pCur >= 'a' && *pCur <= 'z' ) + { + assert( *(pCur+1) == 0 ); + return Abc_NtkPi( pNtk, *pCur - 'a' ); + } + + // skip hex truth table + pEnd = pCur; + while ( (*pEnd >= '0' && *pEnd <= '9') || (*pEnd >= 'A' && *pEnd <= 'F') ) + pEnd++; + if ( *pEnd != '(' ) + { + printf( "Cannot find the end of hexidecimal truth table.\n" ); + return NULL; + } + + // parse the truth table + *pEnd = 0; + pSop = Abc_SopFromTruthHex( pCur ); + *pEnd = '('; + pObj = Io_ReadDsd_rec( pNtk, pEnd, pSop ); + free( pSop ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Derives the DSD network of the formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadDsd( char * pForm ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj, * pTop; + Vec_Ptr_t * vNames; + char * pCur, * pFormCopy; + int i, nInputs; + + // count the number of elementary variables + nInputs = 0; + for ( pCur = pForm; *pCur; pCur++ ) + if ( *pCur >= 'a' && *pCur <= 'z' ) + nInputs = ABC_MAX( nInputs, *pCur - 'a' ); + nInputs++; + + // create the network + pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtk->pName = Extra_UtilStrsav( "dsd" ); + + // create PIs + vNames = Abc_NodeGetFakeNames( nInputs ); + for ( i = 0; i < nInputs; i++ ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), Vec_PtrEntry(vNames, i), NULL ); + Abc_NodeFreeNames( vNames ); + + // transform the formula by inserting parantheses + // this transforms strings like PRIME(a,b,cd) into (PRIME((a),(b),(cd))) + pCur = pFormCopy = ALLOC( char, 3 * strlen(pForm) + 10 ); + *pCur++ = '('; + for ( ; *pForm; pForm++ ) + if ( *pForm == '(' ) + { + *pCur++ = '('; + *pCur++ = '('; + } + else if ( *pForm == ')' ) + { + *pCur++ = ')'; + *pCur++ = ')'; + } + else if ( *pForm == ',' ) + { + *pCur++ = ')'; + *pCur++ = ','; + *pCur++ = '('; + } + else + *pCur++ = *pForm; + *pCur++ = ')'; + *pCur = 0; + + // parse the formula + pObj = Io_ReadDsd_rec( pNtk, pFormCopy, NULL ); + free( pFormCopy ); + if ( pObj == NULL ) + return NULL; + + // create output + pTop = Abc_NtkCreatePo(pNtk); + Abc_ObjAssignName( pTop, "F", NULL ); + Abc_ObjAddFanin( pTop, pObj ); + + // create the only PO + if ( !Abc_NtkCheck( pNtk ) ) + { + fprintf( stdout, "Io_ReadDsd(): Network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadEdif.c b/abc70930/src/base/io/ioReadEdif.c new file mode 100644 index 00000000..188e5b8c --- /dev/null +++ b/abc70930/src/base/io/ioReadEdif.c @@ -0,0 +1,235 @@ +/**CFile**************************************************************** + + FileName [ioReadEdif.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read ISCAS benchmarks in EDIF.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadEdif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from an EDIF file.] + + Description [Works only for the ISCAS benchmarks.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck ) +{ + Extra_FileReader_t * p; + Abc_Ntk_t * pNtk; + + printf( "Currently this parser does not work!\n" ); + return NULL; + + // start the file + p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t()" ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadEdifNetwork( p ); + Extra_FileReaderFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadEdif: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vTokens; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNet, * pObj, * pFanout; + char * pGateName, * pNetName; + int fTokensReady, iLine, i; + + // read the first line + vTokens = Extra_FileReaderGetTokens(p); + if ( strcmp( vTokens->pArray[0], "edif" ) != 0 ) + { + printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); + return NULL; + } + + // allocate the empty network + pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); + + // go through the lines of the file + fTokensReady = 0; + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); + for ( iLine = 1; fTokensReady || (vTokens = Extra_FileReaderGetTokens(p)); iLine++ ) + { + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); + + // get the type of the line + fTokensReady = 0; + if ( strcmp( vTokens->pArray[0], "instance" ) == 0 ) + { + pNetName = vTokens->pArray[1]; + pNet = Abc_NtkFindOrCreateNet( pNtk, pNetName ); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + pGateName = vTokens->pArray[1]; + if ( strncmp( pGateName, "Flip", 4 ) == 0 ) + { + pObj = Abc_NtkCreateLatch( pNtk ); + Abc_LatchSetInit0( pObj ); + } + else + { + pObj = Abc_NtkCreateNode( pNtk ); +// pObj->pData = Abc_NtkRegisterName( pNtk, pGateName ); + pObj->pData = Extra_UtilStrsav( pGateName ); // memory leak!!! + } + Abc_ObjAddFanin( pNet, pObj ); + } + else if ( strcmp( vTokens->pArray[0], "net" ) == 0 ) + { + pNetName = vTokens->pArray[1]; + if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 ) + continue; + if ( strcmp( pNetName + strlen(pNetName) - 4, "_out" ) == 0 ) + pNetName[strlen(pNetName) - 4] = 0; + pNet = Abc_NtkFindNet( pNtk, pNetName ); + assert( pNet ); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + while ( strcmp( vTokens->pArray[0], "portRef" ) == 0 ) + { + if ( strcmp( pNetName, vTokens->pArray[3] ) != 0 ) + { + pFanout = Abc_NtkFindNet( pNtk, vTokens->pArray[3] ); + Abc_ObjAddFanin( Abc_ObjFanin0(pFanout), pNet ); + } + vTokens = Extra_FileReaderGetTokens(p); + } + fTokensReady = 1; + } + else if ( strcmp( vTokens->pArray[0], "library" ) == 0 ) + { + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + while ( strcmp( vTokens->pArray[0], "port" ) == 0 ) + { + pNetName = vTokens->pArray[1]; + if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 ) + { + vTokens = Extra_FileReaderGetTokens(p); + continue; + } + if ( strcmp( pNetName + strlen(pNetName) - 3, "_PO" ) == 0 ) + pNetName[strlen(pNetName) - 3] = 0; + if ( strcmp( vTokens->pArray[3], "INPUT" ) == 0 ) + Io_ReadCreatePi( pNtk, vTokens->pArray[1] ); + else if ( strcmp( vTokens->pArray[3], "OUTPUT" ) == 0 ) + Io_ReadCreatePo( pNtk, vTokens->pArray[1] ); + else + { + printf( "%s (line %d): Wrong interface specification.\n", Extra_FileReaderGetFileName(p), iLine ); + Abc_NtkDelete( pNtk ); + return NULL; + } + vTokens = Extra_FileReaderGetTokens(p); + } + } + else if ( strcmp( vTokens->pArray[0], "design" ) == 0 ) + { + free( pNtk->pName ); + pNtk->pName = Extra_UtilStrsav( vTokens->pArray[3] ); + break; + } + } + Extra_ProgressBarStop( pProgress ); + + // assign logic functions + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( strncmp( pObj->pData, "And", 3 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateAnd(pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) ); + else if ( strncmp( pObj->pData, "Or", 2 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateOr(pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) ); + else if ( strncmp( pObj->pData, "Nand", 4 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateNand(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); + else if ( strncmp( pObj->pData, "Nor", 3 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateNor(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); + else if ( strncmp( pObj->pData, "Exor", 4 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateXor(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); + else if ( strncmp( pObj->pData, "Exnor", 5 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateNxor(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); + else if ( strncmp( pObj->pData, "Inv", 3 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateInv(pNtk->pManFunc) ); + else if ( strncmp( pObj->pData, "Buf", 3 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateBuf(pNtk->pManFunc) ); + else + { + printf( "%s: Unknown gate type \"%s\".\n", Extra_FileReaderGetFileName(p), pObj->pData ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + // check if constants have been added +// if ( pNet = Abc_NtkFindNet( pNtk, "VDD" ) ) +// Io_ReadCreateConst( pNtk, "VDD", 1 ); +// if ( pNet = Abc_NtkFindNet( pNtk, "GND" ) ) +// Io_ReadCreateConst( pNtk, "GND", 0 ); + + Abc_NtkFinalizeRead( pNtk ); + return pNtk; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadEqn.c b/abc70930/src/base/io/ioReadEqn.c new file mode 100644 index 00000000..e04f2b1a --- /dev/null +++ b/abc70930/src/base/io/ioReadEqn.c @@ -0,0 +1,239 @@ +/**CFile**************************************************************** + + FileName [ioReadEqn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read equation format files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ); +static void Io_ReadEqnStrCompact( char * pStr ); +static int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName ); +static void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from a BENCH file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck ) +{ + Extra_FileReader_t * p; + Abc_Ntk_t * pNtk; + + // start the file + p = Extra_FileReaderAlloc( pFileName, "#", ";", "=" ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadEqnNetwork( p ); + Extra_FileReaderFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadEqn: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vTokens; + Vec_Ptr_t * vVars; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + char * pNodeName, * pFormula, * pFormulaCopy, * pVarName; + int iLine, i; + + // allocate the empty network + pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_AIG, 1 ); + // set the specs + pNtk->pName = Extra_FileNameGeneric(Extra_FileReaderGetFileName(p)); + pNtk->pSpec = Extra_UtilStrsav(Extra_FileReaderGetFileName(p)); + + // go through the lines of the file + vVars = Vec_PtrAlloc( 100 ); + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); + for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) + { + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); + + // check if the first token contains anything + Io_ReadEqnStrCompact( vTokens->pArray[0] ); + if ( strlen(vTokens->pArray[0]) == 0 ) + break; + + // if the number of tokens is different from two, error + if ( vTokens->nSize != 2 ) + { + printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); + Abc_NtkDelete( pNtk ); + return NULL; + } + + // get the type of the line + if ( strncmp( vTokens->pArray[0], "INORDER", 7 ) == 0 ) + { + Io_ReadEqnStrCutAt( vTokens->pArray[1], " \n\r\t", 0, vVars ); + Vec_PtrForEachEntry( vVars, pVarName, i ) + Io_ReadCreatePi( pNtk, pVarName ); + } + else if ( strncmp( vTokens->pArray[0], "OUTORDER", 8 ) == 0 ) + { + Io_ReadEqnStrCutAt( vTokens->pArray[1], " \n\r\t", 0, vVars ); + Vec_PtrForEachEntry( vVars, pVarName, i ) + Io_ReadCreatePo( pNtk, pVarName ); + } + else + { + extern Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan ); + + // get hold of the node name and its formula + pNodeName = vTokens->pArray[0]; + pFormula = vTokens->pArray[1]; + // compact the formula + Io_ReadEqnStrCompact( pFormula ); + + // consider the case of the constant node + if ( pFormula[1] == 0 && (pFormula[0] == '0' || pFormula[0] == '1') ) + { + pFormulaCopy = NULL; + Vec_PtrClear( vVars ); + } + else + { + // make a copy of formula for names + pFormulaCopy = Extra_UtilStrsav( pFormula ); + // find the names of the fanins of this node + Io_ReadEqnStrCutAt( pFormulaCopy, "!*+()", 1, vVars ); + } + // create the node + pNode = Io_ReadCreateNode( pNtk, pNodeName, (char **)Vec_PtrArray(vVars), Vec_PtrSize(vVars) ); + // derive the function + pNode->pData = Parse_FormulaParserEqn( stdout, pFormula, vVars, pNtk->pManFunc ); + // remove the cubes + FREE( pFormulaCopy ); + } + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vVars ); + Abc_NtkFinalizeRead( pNtk ); + return pNtk; +} + + + +/**Function************************************************************* + + Synopsis [Compacts the string by throwing away space-like chars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadEqnStrCompact( char * pStr ) +{ + char * pCur, * pNew; + for ( pNew = pCur = pStr; *pCur; pCur++ ) + if ( !(*pCur == ' ' || *pCur == '\n' || *pCur == '\r' || *pCur == '\t') ) + *pNew++ = *pCur; + *pNew = 0; +} + +/**Function************************************************************* + + Synopsis [Determines unique variables in the string.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName ) +{ + char * pToken; + int i; + Vec_PtrForEachEntry( vTokens, pToken, i ) + if ( strcmp( pToken, pName ) == 0 ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Cuts the string into pieces using stop chars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens ) +{ + char * pToken; + Vec_PtrClear( vTokens ); + for ( pToken = strtok( pStr, pStop ); pToken; pToken = strtok( NULL, pStop ) ) + if ( !fUniqueOnly || Io_ReadEqnStrFind( vTokens, pToken ) == -1 ) + Vec_PtrPush( vTokens, pToken ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadPla.c b/abc70930/src/base/io/ioReadPla.c new file mode 100644 index 00000000..fdfdb4f6 --- /dev/null +++ b/abc70930/src/base/io/ioReadPla.c @@ -0,0 +1,250 @@ +/**CFile**************************************************************** + + FileName [ioReadPla.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read network from file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadPla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from a PLA file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadPla( char * pFileName, int fCheck ) +{ + Extra_FileReader_t * p; + Abc_Ntk_t * pNtk; + + // start the file + p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t|" ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadPlaNetwork( p ); + Extra_FileReaderFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadPla: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vTokens; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pTermPi, * pTermPo, * pNode; + Vec_Str_t ** ppSops; + char Buffer[100]; + int nInputs = -1, nOutputs = -1, nProducts = -1; + char * pCubeIn, * pCubeOut; + int i, k, iLine, nDigits, nCubes; + + // allocate the empty network + pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); + + // go through the lines of the file + nCubes = 0; + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); + for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) + { + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); + + // if it is the end of file, quit the loop + if ( strcmp( vTokens->pArray[0], ".e" ) == 0 ) + break; + + if ( vTokens->nSize == 1 ) + { + printf( "%s (line %d): Wrong number of token.\n", + Extra_FileReaderGetFileName(p), iLine+1 ); + Abc_NtkDelete( pNtk ); + return NULL; + } + + if ( strcmp( vTokens->pArray[0], ".i" ) == 0 ) + nInputs = atoi(vTokens->pArray[1]); + else if ( strcmp( vTokens->pArray[0], ".o" ) == 0 ) + nOutputs = atoi(vTokens->pArray[1]); + else if ( strcmp( vTokens->pArray[0], ".p" ) == 0 ) + nProducts = atoi(vTokens->pArray[1]); + else if ( strcmp( vTokens->pArray[0], ".ilb" ) == 0 ) + { + if ( vTokens->nSize - 1 != nInputs ) + printf( "Warning: Mismatch between the number of PIs on the .i line (%d) and the number of PIs on the .ilb line (%d).\n", nInputs, vTokens->nSize - 1 ); + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreatePi( pNtk, vTokens->pArray[i] ); + } + else if ( strcmp( vTokens->pArray[0], ".ob" ) == 0 ) + { + if ( vTokens->nSize - 1 != nOutputs ) + printf( "Warning: Mismatch between the number of POs on the .o line (%d) and the number of POs on the .ob line (%d).\n", nOutputs, vTokens->nSize - 1 ); + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreatePo( pNtk, vTokens->pArray[i] ); + } + else + { + // check if the input/output names are given + if ( Abc_NtkPiNum(pNtk) == 0 ) + { + if ( nInputs == -1 ) + { + printf( "%s: The number of inputs is not specified.\n", Extra_FileReaderGetFileName(p) ); + Abc_NtkDelete( pNtk ); + return NULL; + } + nDigits = Extra_Base10Log( nInputs ); + for ( i = 0; i < nInputs; i++ ) + { + sprintf( Buffer, "x%0*d", nDigits, i ); + Io_ReadCreatePi( pNtk, Buffer ); + } + } + if ( Abc_NtkPoNum(pNtk) == 0 ) + { + if ( nOutputs == -1 ) + { + printf( "%s: The number of outputs is not specified.\n", Extra_FileReaderGetFileName(p) ); + Abc_NtkDelete( pNtk ); + return NULL; + } + nDigits = Extra_Base10Log( nOutputs ); + for ( i = 0; i < nOutputs; i++ ) + { + sprintf( Buffer, "z%0*d", nDigits, i ); + Io_ReadCreatePo( pNtk, Buffer ); + } + } + if ( Abc_NtkNodeNum(pNtk) == 0 ) + { // first time here + // create the PO drivers and add them + // start the SOP covers + ppSops = ALLOC( Vec_Str_t *, nOutputs ); + Abc_NtkForEachPo( pNtk, pTermPo, i ) + { + ppSops[i] = Vec_StrAlloc( 100 ); + // create the node + pNode = Abc_NtkCreateNode(pNtk); + // connect the node to the PO net + Abc_ObjAddFanin( Abc_ObjFanin0Ntk(pTermPo), pNode ); + // connect the node to the PI nets + Abc_NtkForEachPi( pNtk, pTermPi, k ) + Abc_ObjAddFanin( pNode, Abc_ObjFanout0Ntk(pTermPi) ); + } + } + // read the cubes + if ( vTokens->nSize != 2 ) + { + printf( "%s (line %d): Input and output cubes are not specified.\n", + Extra_FileReaderGetFileName(p), iLine+1 ); + Abc_NtkDelete( pNtk ); + return NULL; + } + pCubeIn = vTokens->pArray[0]; + pCubeOut = vTokens->pArray[1]; + if ( strlen(pCubeIn) != (unsigned)nInputs ) + { + printf( "%s (line %d): Input cube length (%d) differs from the number of inputs (%d).\n", + Extra_FileReaderGetFileName(p), iLine+1, strlen(pCubeIn), nInputs ); + Abc_NtkDelete( pNtk ); + return NULL; + } + if ( strlen(pCubeOut) != (unsigned)nOutputs ) + { + printf( "%s (line %d): Output cube length (%d) differs from the number of outputs (%d).\n", + Extra_FileReaderGetFileName(p), iLine+1, strlen(pCubeOut), nOutputs ); + Abc_NtkDelete( pNtk ); + return NULL; + } + for ( i = 0; i < nOutputs; i++ ) + { + if ( pCubeOut[i] == '1' ) + { + Vec_StrAppend( ppSops[i], pCubeIn ); + Vec_StrAppend( ppSops[i], " 1\n" ); + } + } + nCubes++; + } + } + Extra_ProgressBarStop( pProgress ); + if ( nProducts != -1 && nCubes != nProducts ) + printf( "Warning: Mismatch between the number of cubes (%d) and the number on .p line (%d).\n", + nCubes, nProducts ); + + // add the SOP covers + Abc_NtkForEachPo( pNtk, pTermPo, i ) + { + pNode = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pTermPo) ); + if ( ppSops[i]->nSize == 0 ) + { + Abc_ObjRemoveFanins(pNode); + pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\n" ); + Vec_StrFree( ppSops[i] ); + continue; + } + Vec_StrPush( ppSops[i], 0 ); + pNode->pData = Abc_SopRegister( pNtk->pManFunc, ppSops[i]->pArray ); + Vec_StrFree( ppSops[i] ); + } + free( ppSops ); + Abc_NtkFinalizeRead( pNtk ); + return pNtk; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadVerilog.c b/abc70930/src/base/io/ioReadVerilog.c new file mode 100644 index 00000000..c64e330c --- /dev/null +++ b/abc70930/src/base/io/ioReadVerilog.c @@ -0,0 +1,90 @@ +/**CFile**************************************************************** + + FileName [ioReadVerilog.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read network from file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads hierarchical design from the Verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck ) +{ + Abc_Ntk_t * pNtk; + Abc_Lib_t * pDesign; + int RetValue; + + // parse the verilog file + pDesign = Ver_ParseFile( pFileName, NULL, fCheck, 1 ); + if ( pDesign == NULL ) + return NULL; + + // detect top-level model + RetValue = Abc_LibFindTopLevelModels( pDesign ); + pNtk = Vec_PtrEntry( pDesign->vTops, 0 ); + if ( RetValue > 1 ) + printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n", + Vec_PtrSize(pDesign->vTops), pNtk->pName ); + + // extract the master network + pNtk->pDesign = pDesign; + pDesign->pManFunc = NULL; + + // verify the design for cyclic dependence + assert( Vec_PtrSize(pDesign->vModules) > 0 ); + if ( Vec_PtrSize(pDesign->vModules) == 1 ) + { +// printf( "Warning: The design is not hierarchical.\n" ); + Abc_LibFree( pDesign, pNtk ); + pNtk->pDesign = NULL; + pNtk->pSpec = Extra_UtilStrsav( pFileName ); + } + else + { + // check that there is no cyclic dependency + Abc_NtkIsAcyclicHierarchy( pNtk ); + } + +//Io_WriteVerilog( pNtk, "_temp.v" ); + return pNtk; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioUtil.c b/abc70930/src/base/io/ioUtil.c new file mode 100644 index 00000000..94ec4316 --- /dev/null +++ b/abc70930/src/base/io/ioUtil.c @@ -0,0 +1,752 @@ +/**CFile**************************************************************** + + FileName [ioUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the network in BENCH format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the file type.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Io_FileType_t Io_ReadFileType( char * pFileName ) +{ + char * pExt; + if ( pFileName == NULL ) + return IO_FILE_NONE; + pExt = Extra_FileNameExtension( pFileName ); + if ( pExt == NULL ) + return IO_FILE_NONE; + if ( !strcmp( pExt, "aig" ) ) + return IO_FILE_AIGER; + if ( !strcmp( pExt, "baf" ) ) + return IO_FILE_BAF; + if ( !strcmp( pExt, "blif" ) ) + return IO_FILE_BLIF; + if ( !strcmp( pExt, "bench" ) ) + return IO_FILE_BENCH; + if ( !strcmp( pExt, "cnf" ) ) + return IO_FILE_CNF; + if ( !strcmp( pExt, "dot" ) ) + return IO_FILE_DOT; + if ( !strcmp( pExt, "edif" ) ) + return IO_FILE_EDIF; + if ( !strcmp( pExt, "eqn" ) ) + return IO_FILE_EQN; + if ( !strcmp( pExt, "gml" ) ) + return IO_FILE_GML; + if ( !strcmp( pExt, "list" ) ) + return IO_FILE_LIST; + if ( !strcmp( pExt, "mv" ) ) + return IO_FILE_BLIFMV; + if ( !strcmp( pExt, "pla" ) ) + return IO_FILE_PLA; + if ( !strcmp( pExt, "v" ) ) + return IO_FILE_VERILOG; + return IO_FILE_UNKNOWN; +} + +/**Function************************************************************* + + Synopsis [Read the network from a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck ) +{ + FILE * pFile; + Abc_Ntk_t * pNtk; + if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN ) + { + fprintf( stdout, "The generic file reader requires a known file extension.\n" ); + return NULL; + } + // check if the file exists + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Cannot open input file \"%s\". ", pFileName ); + if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) ) + fprintf( stdout, "Did you mean \"%s\"?", pFileName ); + fprintf( stdout, "\n" ); + return NULL; + } + fclose( pFile ); + // read the AIG + if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF ) + { + if ( FileType == IO_FILE_AIGER ) + pNtk = Io_ReadAiger( pFileName, fCheck ); + else // if ( FileType == IO_FILE_BAF ) + pNtk = Io_ReadBaf( pFileName, fCheck ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Reading AIG from file has failed.\n" ); + return NULL; + } + return pNtk; + } + // read the new netlist + if ( FileType == IO_FILE_BLIF ) +// pNtk = Io_ReadBlif( pFileName, fCheck ); + pNtk = Io_ReadBlifMv( pFileName, 0, fCheck ); + else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) + pNtk = Io_ReadBlifMv( pFileName, 1, fCheck ); + else if ( FileType == IO_FILE_BENCH ) + pNtk = Io_ReadBench( pFileName, fCheck ); + else if ( FileType == IO_FILE_EDIF ) + pNtk = Io_ReadEdif( pFileName, fCheck ); + else if ( FileType == IO_FILE_EQN ) + pNtk = Io_ReadEqn( pFileName, fCheck ); + else if ( FileType == IO_FILE_PLA ) + pNtk = Io_ReadPla( pFileName, fCheck ); + else if ( FileType == IO_FILE_VERILOG ) + pNtk = Io_ReadVerilog( pFileName, fCheck ); + else + { + fprintf( stderr, "Unknown file format.\n" ); + return NULL; + } + if ( pNtk == NULL ) + { + fprintf( stdout, "Reading network from file has failed.\n" ); + return NULL; + } + if ( Abc_NtkBlackboxNum(pNtk) || Abc_NtkWhiteboxNum(pNtk) ) + fprintf( stdout, "Warning: The network contains hierarchy.\n" ); + return pNtk; +} + + +/**Function************************************************************* + + Synopsis [Read the network from a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck ) +{ + Abc_Ntk_t * pNtk, * pTemp; + // get the netlist + pNtk = Io_ReadNetlist( pFileName, FileType, fCheck ); + if ( pNtk == NULL ) + return NULL; + if ( !Abc_NtkIsNetlist(pNtk) ) + return pNtk; + // flatten logic hierarchy + assert( Abc_NtkIsNetlist(pNtk) ); + if ( Abc_NtkWhiteboxNum(pNtk) > 0 ) + { + pNtk = Abc_NtkFlattenLogicHierarchy( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Flattening logic hierarchy has failed.\n" ); + return NULL; + } + } + // convert blackboxes + if ( Abc_NtkBlackboxNum(pNtk) > 0 ) + { + printf( "Hierarchy reader converted %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtk) ); + pNtk = Abc_NtkConvertBlackboxes( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Converting blackboxes has failed.\n" ); + return NULL; + } + } + // consider the case of BLIF-MV + if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) + { +//Abc_NtkPrintStats( stdout, pNtk, 0 ); +// Io_WriteBlifMv( pNtk, "_temp_.mv" ); + pNtk = Abc_NtkStrashBlifMv( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Converting BLIF-MV to AIG has failed.\n" ); + return NULL; + } + return pNtk; + } + // convert the netlist into the logic network + pNtk = Abc_NtkToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Converting netlist to logic network after reading has failed.\n" ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Write the network into file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType ) +{ + Abc_Ntk_t * pNtkTemp, * pNtkCopy; + // check if the current network is available + if ( pNtk == NULL ) + { + fprintf( stdout, "Empty network.\n" ); + return; + } + // check if the file extension if given + if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN ) + { + fprintf( stdout, "The generic file writer requires a known file extension.\n" ); + return; + } + // write the AIG formats + if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF ) + { + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" ); + return; + } + if ( FileType == IO_FILE_AIGER ) + Io_WriteAiger( pNtk, pFileName, 1 ); + else // if ( FileType == IO_FILE_BAF ) + Io_WriteBaf( pNtk, pFileName ); + return; + } + // write non-netlist types + if ( FileType == IO_FILE_CNF ) + { + Io_WriteCnf( pNtk, pFileName, 0 ); + return; + } + if ( FileType == IO_FILE_DOT ) + { + Io_WriteDot( pNtk, pFileName ); + return; + } + if ( FileType == IO_FILE_GML ) + { + Io_WriteGml( pNtk, pFileName ); + return; + } +/* + if ( FileType == IO_FILE_BLIFMV ) + { + Io_WriteBlifMv( pNtk, pFileName ); + return; + } +*/ + // convert logic network into netlist + if ( FileType == IO_FILE_PLA ) + { + if ( Abc_NtkLevel(pNtk) > 1 ) + { + fprintf( stdout, "PLA writing is available for collapsed networks.\n" ); + return; + } + if ( Abc_NtkIsComb(pNtk) ) + pNtkTemp = Abc_NtkToNetlist( pNtk ); + else + { + fprintf( stdout, "Latches are writen into the PLA file at PI/PO pairs.\n" ); + pNtkCopy = Abc_NtkDup( pNtk ); + Abc_NtkMakeComb( pNtkCopy ); + pNtkTemp = Abc_NtkToNetlist( pNtk ); + Abc_NtkDelete( pNtkCopy ); + } + if ( !Abc_NtkToSop( pNtk, 1 ) ) + return; + } + else if ( FileType == IO_FILE_BENCH ) + { + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Writing traditional BENCH is available for AIGs only (use \"write_bench\").\n" ); + return; + } + pNtkTemp = Abc_NtkToNetlistBench( pNtk ); + } + else + pNtkTemp = Abc_NtkToNetlist( pNtk ); + + if ( pNtkTemp == NULL ) + { + fprintf( stdout, "Converting to netlist has failed.\n" ); + return; + } + + if ( FileType == IO_FILE_BLIF ) + { + if ( !Abc_NtkHasSop(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) + Abc_NtkToSop( pNtkTemp, 0 ); + Io_WriteBlif( pNtkTemp, pFileName, 1 ); + } + else if ( FileType == IO_FILE_BLIFMV ) + { + if ( !Abc_NtkConvertToBlifMv( pNtkTemp ) ) + return; + Io_WriteBlifMv( pNtkTemp, pFileName ); + } + else if ( FileType == IO_FILE_BENCH ) + Io_WriteBench( pNtkTemp, pFileName ); + else if ( FileType == IO_FILE_PLA ) + Io_WritePla( pNtkTemp, pFileName ); + else if ( FileType == IO_FILE_EQN ) + { + if ( !Abc_NtkHasAig(pNtkTemp) ) + Abc_NtkToAig( pNtkTemp ); + Io_WriteEqn( pNtkTemp, pFileName ); + } + else if ( FileType == IO_FILE_VERILOG ) + { + if ( !Abc_NtkHasAig(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) + Abc_NtkToAig( pNtkTemp ); + Io_WriteVerilog( pNtkTemp, pFileName ); + } + else + fprintf( stderr, "Unknown file format.\n" ); + Abc_NtkDelete( pNtkTemp ); +} + +/**Function************************************************************* + + Synopsis [Write the network into file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName ) +{ + Abc_Ntk_t * pNtkTemp, * pNtkResult, * pNtkBase = NULL; + // check if the current network is available + if ( pNtk == NULL ) + { + fprintf( stdout, "Empty network.\n" ); + return; + } + + // read the base network + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIF ) + pNtkBase = Io_ReadBlifMv( pBaseName, 0, 1 ); + else if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV ) + pNtkBase = Io_ReadBlifMv( pBaseName, 1, 1 ); + else if ( Io_ReadFileType(pBaseName) == IO_FILE_VERILOG ) + pNtkBase = Io_ReadVerilog( pBaseName, 1 ); + else + fprintf( stderr, "Unknown input file format.\n" ); + if ( pNtkBase == NULL ) + return; + + // flatten logic hierarchy if present + if ( Abc_NtkWhiteboxNum(pNtkBase) > 0 ) + { + pNtkBase = Abc_NtkFlattenLogicHierarchy( pNtkTemp = pNtkBase ); + if ( pNtkBase == NULL ) + return; + Abc_NtkDelete( pNtkTemp ); + } + + // reintroduce the boxes into the netlist + if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV ) + { + if ( Abc_NtkBlackboxNum(pNtkBase) > 0 ) + { + printf( "Hierarchy writer does not support BLIF-MV with blackboxes.\n" ); + Abc_NtkDelete( pNtkBase ); + return; + } + // convert the current network to BLIF-MV + assert( !Abc_NtkIsNetlist(pNtk) ); + pNtkResult = Abc_NtkToNetlist( pNtk ); + if ( !Abc_NtkConvertToBlifMv( pNtkResult ) ) + return; + // reintroduce the network + pNtkResult = Abc_NtkInsertBlifMv( pNtkBase, pNtkTemp = pNtkResult ); + Abc_NtkDelete( pNtkTemp ); + } + else if ( Abc_NtkBlackboxNum(pNtkBase) > 0 ) + { + // derive the netlist + pNtkResult = Abc_NtkToNetlist( pNtk ); + pNtkResult = Abc_NtkInsertNewLogic( pNtkBase, pNtkTemp = pNtkResult ); + Abc_NtkDelete( pNtkTemp ); + if ( pNtkResult ) + printf( "Hierarchy writer reintroduced %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtkBase) ); + } + else + { + printf( "Warning: The output network does not contain blackboxes.\n" ); + pNtkResult = Abc_NtkToNetlist( pNtk ); + } + Abc_NtkDelete( pNtkBase ); + if ( pNtkResult == NULL ) + return; + + // write the resulting network + if ( Io_ReadFileType(pFileName) == IO_FILE_BLIF ) + { + if ( !Abc_NtkHasSop(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) ) + Abc_NtkToSop( pNtkResult, 0 ); + Io_WriteBlif( pNtkResult, pFileName, 1 ); + } + else if ( Io_ReadFileType(pFileName) == IO_FILE_VERILOG ) + { + if ( !Abc_NtkHasAig(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) ) + Abc_NtkToAig( pNtkResult ); + Io_WriteVerilog( pNtkResult, pFileName ); + } + else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) + { + Io_WriteBlifMv( pNtkResult, pFileName ); + } + else + fprintf( stderr, "Unknown output file format.\n" ); + + Abc_NtkDelete( pNtkResult ); +} + +/**Function************************************************************* + + Synopsis [Creates PI terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PI net + pNet = Abc_NtkFindNet( pNtk, pName ); + if ( pNet ) + printf( "Warning: PI \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PI node + pTerm = Abc_NtkCreatePi( pNtk ); + Abc_ObjAddFanin( pNet, pTerm ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Creates PO terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PO net + pNet = Abc_NtkFindNet( pNtk, pName ); + if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) + printf( "Warning: PO \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PO node + pTerm = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pTerm, pNet ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Creates PO terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateAssert( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PO net + pNet = Abc_NtkFindNet( pNtk, pName ); + if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) + printf( "Warning: Assert \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PO node + pTerm = Abc_NtkCreateAssert( pNtk ); + Abc_ObjAddFanin( pTerm, pNet ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Create a latch with the given input/output.] + + Description [By default, the latch value is unknown (ABC_INIT_NONE).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ) +{ + Abc_Obj_t * pLatch, * pTerm, * pNet; + // get the LI net + pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLI ); + // add the BO terminal + pTerm = Abc_NtkCreateBi( pNtk ); + Abc_ObjAddFanin( pTerm, pNet ); + // add the latch box + pLatch = Abc_NtkCreateLatch( pNtk ); + Abc_ObjAddFanin( pLatch, pTerm ); + // add the BI terminal + pTerm = Abc_NtkCreateBo( pNtk ); + Abc_ObjAddFanin( pTerm, pLatch ); + // get the LO net + pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLO ); + Abc_ObjAddFanin( pNet, pTerm ); + // set latch name + Abc_ObjAssignName( pLatch, pNetLO, "L" ); + return pLatch; +} + +/**Function************************************************************* + + Synopsis [Create the reset latch with data=1 and init=0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv ) +{ + Abc_Obj_t * pLatch, * pNode; + Abc_Obj_t * pNetLI, * pNetLO; + // create latch with 0 init value +// pLatch = Io_ReadCreateLatch( pNtk, "_resetLI_", "_resetLO_" ); + pNetLI = Abc_NtkCreateNet( pNtk ); + pNetLO = Abc_NtkCreateNet( pNtk ); + Abc_ObjAssignName( pNetLI, Abc_ObjName(pNetLI), NULL ); + Abc_ObjAssignName( pNetLO, Abc_ObjName(pNetLO), NULL ); + pLatch = Io_ReadCreateLatch( pNtk, Abc_ObjName(pNetLI), Abc_ObjName(pNetLO) ); + // set the initial value + Abc_LatchSetInit0( pLatch ); + // feed the latch with constant1- node +// pNode = Abc_NtkCreateNode( pNtk ); +// pNode->pData = Abc_SopRegister( pNtk->pManFunc, "2\n1\n" ); + pNode = Abc_NtkCreateNodeConst1( pNtk ); + Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pNode ); + return pLatch; +} + +/**Function************************************************************* + + Synopsis [Create node and the net driven by it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs ) +{ + Abc_Obj_t * pNet, * pNode; + int i; + // create a new node + pNode = Abc_NtkCreateNode( pNtk ); + // add the fanin nets + for ( i = 0; i < nInputs; i++ ) + { + pNet = Abc_NtkFindOrCreateNet( pNtk, pNamesIn[i] ); + Abc_ObjAddFanin( pNode, pNet ); + } + // add the fanout net + pNet = Abc_NtkFindOrCreateNet( pNtk, pNameOut ); + Abc_ObjAddFanin( pNet, pNode ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Create a constant 0 node driving the net with this name.] + + Description [Assumes that the net already exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, bool fConst1 ) +{ + Abc_Obj_t * pNet, * pTerm; + pTerm = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); + pNet = Abc_NtkFindNet(pNtk, pName); assert( pNet ); + Abc_ObjAddFanin( pNet, pTerm ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Create an inverter or buffer for the given net.] + + Description [Assumes that the nets already exist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ) +{ + Abc_Obj_t * pNet, * pNode; + pNet = Abc_NtkFindNet(pNtk, pNameIn); assert( pNet ); + pNode = Abc_NtkCreateNodeInv(pNtk, pNet); + pNet = Abc_NtkFindNet(pNtk, pNameOut); assert( pNet ); + Abc_ObjAddFanin( pNet, pNode ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Create an inverter or buffer for the given net.] + + Description [Assumes that the nets already exist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ) +{ + Abc_Obj_t * pNet, * pNode; + pNet = Abc_NtkFindNet(pNtk, pNameIn); assert( pNet ); + pNode = Abc_NtkCreateNodeBuf(pNtk, pNet); + pNet = Abc_NtkFindNet(pNtk, pNameOut); assert( pNet ); + Abc_ObjAddFanin( pNet, pNode ); + return pNet; +} + + +/**Function************************************************************* + + Synopsis [Provide an fopen replacement with path lookup] + + Description [Provide an fopen replacement where the path stored + in pathvar MVSIS variable is used to look up the path + for name. Returns NULL if file cannot be opened.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose ) +{ + char * t = 0, * c = 0, * i; + extern char * Abc_FrameReadFlag( char * pFlag ); + + if ( PathVar == 0 ) + { + return fopen( FileName, Mode ); + } + else + { + if ( c = Abc_FrameReadFlag( (char*)PathVar ) ) + { + char ActualFileName[4096]; + FILE * fp = 0; + t = Extra_UtilStrsav( c ); + for (i = strtok( t, ":" ); i != 0; i = strtok( 0, ":") ) + { +#ifdef WIN32 + _snprintf ( ActualFileName, 4096, "%s/%s", i, FileName ); +#else + snprintf ( ActualFileName, 4096, "%s/%s", i, FileName ); +#endif + if ( ( fp = fopen ( ActualFileName, Mode ) ) ) + { + if ( fVerbose ) + fprintf ( stdout, "Using file %s\n", ActualFileName ); + free( t ); + return fp; + } + } + free( t ); + return 0; + } + else + { + return fopen( FileName, Mode ); + } + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteAiger.c b/abc70930/src/base/io/ioWriteAiger.c new file mode 100644 index 00000000..ff34b177 --- /dev/null +++ b/abc70930/src/base/io/ioWriteAiger.c @@ -0,0 +1,291 @@ +/**CFile**************************************************************** + + FileName [ioWriteAiger.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write binary AIGER format developed by + Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 16, 2006.] + + Revision [$Id: ioWriteAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + The following is taken from the AIGER format description, + which can be found at http://fmv.jku.at/aiger +*/ + + +/* + The AIGER And-Inverter Graph (AIG) Format Version 20061129 + ---------------------------------------------------------- + Armin Biere, Johannes Kepler University, 2006 + + This report describes the AIG file format as used by the AIGER library. + The purpose of this report is not only to motivate and document the + format, but also to allow independent implementations of writers and + readers by giving precise and unambiguous definitions. + + ... + +Introduction + + The name AIGER contains as one part the acronym AIG of And-Inverter + Graphs and also if pronounced in German sounds like the name of the + 'Eiger', a mountain in the Swiss alps. This choice should emphasize the + origin of this format. It was first openly discussed at the Alpine + Verification Meeting 2006 in Ascona as a way to provide a simple, compact + file format for a model checking competition affiliated to CAV 2007. + + ... + +Binary Format Definition + + The binary format is semantically a subset of the ASCII format with a + slightly different syntax. The binary format may need to reencode + literals, but translating a file in binary format into ASCII format and + then back in to binary format will result in the same file. + + The main differences of the binary format to the ASCII format are as + follows. After the header the list of input literals and all the + current state literals of a latch can be omitted. Furthermore the + definitions of the AND gates are binary encoded. However, the symbol + table and the comment section are as in the ASCII format. + + The header of an AIGER file in binary format has 'aig' as format + identifier, but otherwise is identical to the ASCII header. The standard + file extension for the binary format is therefore '.aig'. + + A header for the binary format is still in ASCII encoding: + + aig M I L O A + + Constants, variables and literals are handled in the same way as in the + ASCII format. The first simplifying restriction is on the variable + indices of inputs and latches. The variable indices of inputs come first, + followed by the pseudo-primary inputs of the latches and then the variable + indices of all LHS of AND gates: + + input variable indices 1, 2, ... , I + latch variable indices I+1, I+2, ... , (I+L) + AND variable indices I+L+1, I+L+2, ... , (I+L+A) == M + + The corresponding unsigned literals are + + input literals 2, 4, ... , 2*I + latch literals 2*I+2, 2*I+4, ... , 2*(I+L) + AND literals 2*(I+L)+2, 2*(I+L)+4, ... , 2*(I+L+A) == 2*M + + All literals have to be defined, and therefore 'M = I + L + A'. With this + restriction it becomes possible that the inputs and the current state + literals of the latches do not have to be listed explicitly. Therefore, + after the header only the list of 'L' next state literals follows, one per + latch on a single line, and then the 'O' outputs, again one per line. + + In the binary format we assume that the AND gates are ordered and respect + the child parent relation. AND gates with smaller literals on the LHS + come first. Therefore we can assume that the literals on the right-hand + side of a definition of an AND gate are smaller than the LHS literal. + Furthermore we can sort the literals on the RHS, such that the larger + literal comes first. A definition thus consists of three literals + + lhs rhs0 rhs1 + + with 'lhs' even and 'lhs > rhs0 >= rhs1'. Also the variable indices are + pairwise different to avoid combinational self loops. Since the LHS + indices of the definitions are all consecutive (as even integers), + the binary format does not have to keep 'lhs'. In addition, we can use + the order restriction and only write the differences 'delta0' and 'delta1' + instead of 'rhs0' and 'rhs1', with + + delta0 = lhs - rhs0, delta1 = rhs0 - rhs1 + + The differences will all be strictly positive, and in practice often very + small. We can take advantage of this fact by the simple little-endian + encoding of unsigned integers of the next section. After the binary delta + encoding of the RHSs of all AND gates, the optional symbol table and + optional comment section start in the same format as in the ASCII case. + + ... + +*/ + +static unsigned Io_ObjMakeLit( int Var, int fCompl ) { return (Var << 1) | fCompl; } +static unsigned Io_ObjAigerNum( Abc_Obj_t * pObj ) { return (unsigned)pObj->pCopy; } +static void Io_ObjSetAigerNum( Abc_Obj_t * pObj, unsigned Num ) { pObj->pCopy = (void *)Num; } + +int Io_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols ) +{ + ProgressBar * pProgress; + FILE * pFile; + Abc_Obj_t * pObj, * pDriver; + int i, nNodes, Pos, nBufferSize; + unsigned char * pBuffer; + unsigned uLit0, uLit1, uLit; + + assert( Abc_NtkIsStrash(pNtk) ); + // start the output stream + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + Abc_NtkForEachLatch( pNtk, pObj, i ) + if ( !Abc_LatchIsInit0(pObj) ) + { + fprintf( stdout, "Io_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" ); + return; + } + + // set the node numbers to be used in the output file + nNodes = 0; + Io_ObjSetAigerNum( Abc_AigConst1(pNtk), nNodes++ ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Io_ObjSetAigerNum( pObj, nNodes++ ); + Abc_AigForEachAnd( pNtk, pObj, i ) + Io_ObjSetAigerNum( pObj, nNodes++ ); + + // write the header "M I L O A" where M = I + L + A + fprintf( pFile, "aig %u %u %u %u %u\n", + Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) + Abc_NtkNodeNum(pNtk), + Abc_NtkPiNum(pNtk), + Abc_NtkLatchNum(pNtk), + Abc_NtkPoNum(pNtk), + Abc_NtkNodeNum(pNtk) ); + + // if the driver node is a constant, we need to complement the literal below + // because, in the AIGER format, literal 0/1 is represented as number 0/1 + // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0 + + // write latch drivers + Abc_NtkForEachLatchInput( pNtk, pObj, i ) + { + pDriver = Abc_ObjFanin0(pObj); + fprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); + } + + // write PO drivers + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pDriver = Abc_ObjFanin0(pObj); + fprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); + } + + // write the nodes into the buffer + Pos = 0; + nBufferSize = 6 * Abc_NtkNodeNum(pNtk) + 100; // skeptically assuming 3 chars per one AIG edge + pBuffer = ALLOC( char, nBufferSize ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + uLit = Io_ObjMakeLit( Io_ObjAigerNum(pObj), 0 ); + uLit0 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin0(pObj)), Abc_ObjFaninC0(pObj) ); + uLit1 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin1(pObj)), Abc_ObjFaninC1(pObj) ); + assert( uLit0 < uLit1 ); + Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); + Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); + if ( Pos > nBufferSize - 10 ) + { + printf( "Io_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" ); + fclose( pFile ); + return; + } + } + assert( Pos < nBufferSize ); + Extra_ProgressBarStop( pProgress ); + + // write the buffer + fwrite( pBuffer, 1, Pos, pFile ); + free( pBuffer ); + + // write the symbol table + if ( fWriteSymbols ) + { + // write PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "i%d %s\n", i, Abc_ObjName(pObj) ); + // write latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + fprintf( pFile, "l%d %s\n", i, Abc_ObjName(Abc_ObjFanout0(pObj)) ); + // write POs + Abc_NtkForEachPo( pNtk, pObj, i ) + fprintf( pFile, "o%d %s\n", i, Abc_ObjName(pObj) ); + } + + // write the comment + fprintf( pFile, "c\n" ); + if ( pNtk->pName && strlen(pNtk->pName) > 0 ) + fprintf( pFile, ".model %s\n", pNtk->pName ); + fprintf( pFile, "This file was produced by ABC on %s\n", Extra_TimeStamp() ); + fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Adds one unsigned AIG edge to the output buffer.] + + Description [This procedure is a slightly modified version of Armin Biere's + procedure "void encode (FILE * file, unsigned x)" ] + + SideEffects [Returns the current writing position.] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; +// putc (ch, file); + pBuffer[Pos++] = ch; + x >>= 7; + } + ch = x; +// putc (ch, file); + pBuffer[Pos++] = ch; + return Pos; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteBaf.c b/abc70930/src/base/io/ioWriteBaf.c new file mode 100644 index 00000000..fc0229a4 --- /dev/null +++ b/abc70930/src/base/io/ioWriteBaf.c @@ -0,0 +1,168 @@ +/**CFile**************************************************************** + + FileName [ioWriteBaf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write AIG in the binary format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + Binary Aig Format + + The motivation for this format is to have + - compact binary representation of large AIGs (~10x more compact than BLIF) + - consequently, fast reading/writing of large AIGs (~10x faster than BLIF) + - representation for all tech-ind info related to an AIG + - human-readable file header + + The header: + (1) May contain several lines of human-readable comments. + Each comment line begins with symbol '#' and ends with symbol '\n'. + (2) Always contains the following data. + - benchmark name + - number of primary inputs + - number of primary outputs + - number of latches + - number of AIG nodes (excluding the constant 1 node) + Each entry is followed by 0-byte (character '\0'): + (3) Next follow the names of the PIs, POs, and latches in this order. + Each name is followed by 0-byte (character '\0'). + Inside each set of names (PIs, POs, latches) there should be no + identical names but the PO names may coincide with PI/latch names. + + The body: + (1) First part of the body contains binary information about the internal AIG nodes. + Each internal AIG node is represented using two edges (each edge is a 4-byte integer). + Each integer is the fanin ID followed by 1-bit representation of the complemented attribute. + (For example, complemented edge to node 10 will be represented as 2*10 + 1 = 21.) + The IDs of the nodes are created as follows: Constant 1 node has ID=0. + CIs (PIs and latch outputs) have 1-based IDs assigned in that order. + Each node in the array of the internal AIG nodes has the ID assigned in that order. + The constant 1 node is not written into the file. + (2) Second part of the body contains binary information about the edges connecting + the COs (POs and latch inputs) to the internal AIG nodes. + Each edge is a 4-byte integer the same way as a node fanin. + The latch initial value (2 bits) is stored in this integer. +*/ + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName ) +{ + ProgressBar * pProgress; + FILE * pFile; + Abc_Obj_t * pObj; + int i, nNodes, nAnds, nBufferSize; + unsigned * pBufferNode; + assert( Abc_NtkIsStrash(pNtk) ); + // start the output stream + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBaf(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + // write the comment + fprintf( pFile, "# BAF (Binary Aig Format) for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + + // write the network name + fprintf( pFile, "%s%c", pNtk->pName, 0 ); + // write the number of PIs + fprintf( pFile, "%d%c", Abc_NtkPiNum(pNtk), 0 ); + // write the number of POs + fprintf( pFile, "%d%c", Abc_NtkPoNum(pNtk), 0 ); + // write the number of latches + fprintf( pFile, "%d%c", Abc_NtkLatchNum(pNtk), 0 ); + // write the number of internal nodes + fprintf( pFile, "%d%c", Abc_NtkNodeNum(pNtk), 0 ); + + // write PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); + // write POs + Abc_NtkForEachPo( pNtk, pObj, i ) + fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); + // write latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); + fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanin0(pObj)), 0 ); + fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanout0(pObj)), 0 ); + } + + // set the node numbers to be used in the output file + Abc_NtkCleanCopy( pNtk ); + nNodes = 1; + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = (void *)nNodes++; + Abc_AigForEachAnd( pNtk, pObj, i ) + pObj->pCopy = (void *)nNodes++; + + // write the nodes into the buffer + nAnds = 0; + nBufferSize = Abc_NtkNodeNum(pNtk) * 2 + Abc_NtkCoNum(pNtk); + pBufferNode = ALLOC( int, nBufferSize ); + pProgress = Extra_ProgressBarStart( stdout, nBufferSize ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + Extra_ProgressBarUpdate( pProgress, nAnds, NULL ); + pBufferNode[nAnds++] = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj); + pBufferNode[nAnds++] = (((int)Abc_ObjFanin1(pObj)->pCopy) << 1) | Abc_ObjFaninC1(pObj); + } + + // write the COs into the buffer + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Extra_ProgressBarUpdate( pProgress, nAnds, NULL ); + pBufferNode[nAnds] = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj); + if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) + pBufferNode[nAnds] = (pBufferNode[nAnds] << 2) | ((unsigned)Abc_ObjData(Abc_ObjFanout0(pObj)) & 3); + nAnds++; + } + Extra_ProgressBarStop( pProgress ); + assert( nBufferSize == nAnds ); + + // write the buffer + fwrite( pBufferNode, 1, sizeof(int) * nBufferSize, pFile ); + fclose( pFile ); + free( pBufferNode ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteBench.c b/abc70930/src/base/io/ioWriteBench.c new file mode 100644 index 00000000..4b766a47 --- /dev/null +++ b/abc70930/src/base/io/ioWriteBench.c @@ -0,0 +1,335 @@ +/**CFile**************************************************************** + + FileName [ioWriteBench.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the network in BENCH format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteBench.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk ); + +static int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode ); + +static int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBench( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Abc_Ntk_t * pExdc; + FILE * pFile; + assert( Abc_NtkIsSopNetlist(pNtk) ); + if ( !Io_WriteBenchCheckNames(pNtk) ) + { + fprintf( stdout, "Io_WriteBench(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" ); + return 0; + } + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBench(): Cannot open the output file.\n" ); + return 0; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the network + Io_WriteBenchOne( pFile, pNtk ); + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + printf( "Io_WriteBench: EXDC is not written (warning).\n" ); + // finalize the file + fclose( pFile ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode; + int i; + + // write the PIs/POs/latches + Abc_NtkForEachPi( pNtk, pNode, i ) + fprintf( pFile, "INPUT(%s)\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Abc_NtkForEachPo( pNtk, pNode, i ) + fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + Abc_NtkForEachLatch( pNtk, pNode, i ) + fprintf( pFile, "%-11s = DFF(%s)\n", + Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) ); + + // write internal nodes + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_WriteBenchOneNode( pFile, pNode ); + } + Extra_ProgressBarStop( pProgress ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode ) +{ + int nFanins; + + assert( Abc_ObjIsNode(pNode) ); + nFanins = Abc_ObjFaninNum(pNode); + if ( nFanins == 0 ) + { // write the constant 1 node + assert( Abc_NodeIsConst1(pNode) ); + fprintf( pFile, "%-11s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, " = vdd\n" ); + } + else if ( nFanins == 1 ) + { // write the interver/buffer + if ( Abc_NodeIsBuf(pNode) ) + { + fprintf( pFile, "%-11s = BUFF(", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + } + else + { + fprintf( pFile, "%-11s = NOT(", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + } + } + else + { // write the AND gate + fprintf( pFile, "%-11s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, " = AND(%s, ", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin1(pNode)) ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format with LUTs and DFFRSE.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Abc_Ntk_t * pExdc; + FILE * pFile; + assert( Abc_NtkIsAigNetlist(pNtk) ); + if ( !Io_WriteBenchCheckNames(pNtk) ) + { + fprintf( stdout, "Io_WriteBenchLut(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" ); + return 0; + } + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBench(): Cannot open the output file.\n" ); + return 0; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the network + Io_WriteBenchLutOne( pFile, pNtk ); + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + printf( "Io_WriteBench: EXDC is not written (warning).\n" ); + // finalize the file + fclose( pFile ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode; + Vec_Int_t * vMemory; + int i; + + // write the PIs/POs/latches + Abc_NtkForEachPi( pNtk, pNode, i ) + fprintf( pFile, "INPUT(%s)\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Abc_NtkForEachPo( pNtk, pNode, i ) + fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + Abc_NtkForEachLatch( pNtk, pNode, i ) + fprintf( pFile, "%-11s = DFFRSE( %s, gnd, gnd, gnd, gnd )\n", + Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) ); +//Abc_NtkLevel(pNtk); + // write internal nodes + vMemory = Vec_IntAlloc( 10000 ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_WriteBenchLutOneNode( pFile, pNode, vMemory ); + } + Extra_ProgressBarStop( pProgress ); + Vec_IntFree( vMemory ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth ) +{ + Abc_Obj_t * pFanin; + unsigned * pTruth; + int i, nFanins; + assert( Abc_ObjIsNode(pNode) ); + nFanins = Abc_ObjFaninNum(pNode); + assert( nFanins <= 8 ); + // compute the truth table + pTruth = Abc_ConvertAigToTruth( pNode->pNtk->pManFunc, Hop_Regular(pNode->pData), nFanins, vTruth, 0 ); + if ( Hop_IsComplement(pNode->pData) ) + Extra_TruthNot( pTruth, pTruth, nFanins ); + // consider simple cases + if ( Extra_TruthIsConst0(pTruth, nFanins) ) + { + fprintf( pFile, "%-11s = gnd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return 1; + } + if ( Extra_TruthIsConst1(pTruth, nFanins) ) + { + fprintf( pFile, "%-11s = vdd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return 1; + } + if ( nFanins == 1 ) + { + fprintf( pFile, "%-11s = LUT 0x%d ( %s )\n", + Abc_ObjName(Abc_ObjFanout0(pNode)), + Abc_NodeIsBuf(pNode)? 2 : 1, + Abc_ObjName(Abc_ObjFanin0(pNode)) ); + return 1; + } + // write it in the hexadecimal form + fprintf( pFile, "%-11s = LUT 0x", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Extra_PrintHexadecimal( pFile, pTruth, nFanins ); +/* + { +extern void Kit_DsdTest( unsigned * pTruth, int nVars ); +Abc_ObjForEachFanin( pNode, pFanin, i ) +printf( "%c%d ", 'a'+i, Abc_ObjFanin0(pFanin)->Level ); +printf( "\n" ); +Kit_DsdTest( pTruth, nFanins ); + } + if ( pNode->Id % 1000 == 0 ) + { + int x = 0; + } +*/ + // write the fanins + fprintf( pFile, " (" ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + fprintf( pFile, " %s%s", Abc_ObjName(pFanin), ((i==nFanins-1)? "" : ",") ); + fprintf( pFile, " )\n" ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the names cannot be written into the bench file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + char * pName; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + for ( pName = Nm_ManFindNameById(pNtk->pManName, i); pName && *pName; pName++ ) + if ( *pName == '(' || *pName == ')' ) + return 0; + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteBlif.c b/abc70930/src/base/io/ioWriteBlif.c new file mode 100644 index 00000000..c0c29d65 --- /dev/null +++ b/abc70930/src/base/io/ioWriteBlif.c @@ -0,0 +1,591 @@ +/**CFile**************************************************************** + + FileName [ioWriteBlif.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write BLIF files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteAsserts( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ); +static void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length ); +static void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) +{ + Abc_Ntk_t * pNtkTemp; + // derive the netlist + pNtkTemp = Abc_NtkToNetlist(pNtk); + if ( pNtkTemp == NULL ) + { + fprintf( stdout, "Writing BLIF has failed.\n" ); + return; + } + Io_WriteBlif( pNtkTemp, FileName, fWriteLatches ); + Abc_NtkDelete( pNtkTemp ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) +{ + FILE * pFile; + Abc_Ntk_t * pNtkTemp; + int i; + assert( Abc_NtkIsNetlist(pNtk) ); + // start writing the file + pFile = fopen( FileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBlif(): Cannot open the output file.\n" ); + return; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the master network + Io_NtkWrite( pFile, pNtk, fWriteLatches ); + // make sure there is no logic hierarchy + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + // write the hierarchy if present + if ( Abc_NtkBlackboxNum(pNtk) > 0 ) + { + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i ) + { + if ( pNtkTemp == pNtk ) + continue; + fprintf( pFile, "\n\n" ); + Io_NtkWrite( pFile, pNtkTemp, fWriteLatches ); + } + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + Abc_Ntk_t * pExdc; + assert( Abc_NtkIsNetlist(pNtk) ); + // write the model name + fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); + // write the network + Io_NtkWriteOne( pFile, pNtk, fWriteLatches ); + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + { + fprintf( pFile, "\n" ); + fprintf( pFile, ".exdc\n" ); + Io_NtkWriteOne( pFile, pExdc, fWriteLatches ); + } + // finalize the file + fprintf( pFile, ".end\n" ); +} + +/**Function************************************************************* + + Synopsis [Write one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pLatch; + int i, Length; + + // write the PIs + fprintf( pFile, ".inputs" ); + Io_NtkWritePis( pFile, pNtk, fWriteLatches ); + fprintf( pFile, "\n" ); + + // write the POs + fprintf( pFile, ".outputs" ); + Io_NtkWritePos( pFile, pNtk, fWriteLatches ); + fprintf( pFile, "\n" ); + + // write the assertions + if ( Abc_NtkAssertNum(pNtk) ) + { + fprintf( pFile, ".asserts" ); + Io_NtkWriteAsserts( pFile, pNtk ); + fprintf( pFile, "\n" ); + } + + // write the blackbox + if ( Abc_NtkHasBlackbox( pNtk ) ) + { + fprintf( pFile, ".blackbox\n" ); + return; + } + + // write the timing info + Io_WriteTimingInfo( pFile, pNtk ); + + // write the latches + if ( fWriteLatches && !Abc_NtkIsComb(pNtk) ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Io_NtkWriteLatch( pFile, pLatch ); + fprintf( pFile, "\n" ); + } + + // write the subcircuits + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + if ( Abc_NtkBlackboxNum(pNtk) > 0 ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachBlackbox( pNtk, pNode, i ) + Io_NtkWriteSubckt( pFile, pNode ); + fprintf( pFile, "\n" ); + } + + // write each internal node + Length = Abc_NtkHasMapping(pNtk)? Mio_LibraryReadGateNameMax(pNtk->pManFunc) : 0; + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_NtkWriteNode( pFile, pNode, Length ); + } + Extra_ProgressBarStop( pProgress ); +} + + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 7; + NameCounter = 0; + + if ( fWriteLatches ) + { + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } + else + { + Abc_NtkForEachCi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 8; + NameCounter = 0; + + if ( fWriteLatches ) + { + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } + else + { + Abc_NtkForEachCo( pNtk, pTerm, i ) + { + if ( Abc_ObjIsAssert(pTerm) ) + continue; + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } +} + +/**Function************************************************************* + + Synopsis [Writes the assertion list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteAsserts( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 8; + NameCounter = 0; + + Abc_NtkForEachAssert( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pModel = pNode->pData; + Abc_Obj_t * pTerm; + int i; + // write the subcircuit +// fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) ); + fprintf( pFile, ".subckt %s", Abc_NtkName(pModel) ); + // write pairs of the formal=actual names + Abc_NtkForEachPi( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + pTerm = Abc_ObjFanin( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + } + Abc_NtkForEachPo( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + pTerm = Abc_ObjFanout( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + } + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch ) +{ + Abc_Obj_t * pNetLi, * pNetLo; + int Reset; + pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) ); + pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) ); + Reset = (int)Abc_ObjData( pLatch ); + // write the latch line + fprintf( pFile, ".latch" ); + fprintf( pFile, " %10s", Abc_ObjName(pNetLi) ); + fprintf( pFile, " %10s", Abc_ObjName(pNetLo) ); + fprintf( pFile, " %d\n", Reset-1 ); +} + + +/**Function************************************************************* + + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length ) +{ + if ( Abc_NtkHasMapping(pNode->pNtk) ) + { + // write the .gate line + fprintf( pFile, ".gate" ); + Io_NtkWriteNodeGate( pFile, pNode, Length ); + fprintf( pFile, "\n" ); + } + else + { + // write the .names line + fprintf( pFile, ".names" ); + Io_NtkWriteNodeFanins( pFile, pNode ); + fprintf( pFile, "\n" ); + // write the cubes + fprintf( pFile, "%s", Abc_ObjData(pNode) ); + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ) +{ + Mio_Gate_t * pGate = pNode->pData; + Mio_Pin_t * pGatePin; + int i; + // write the node + fprintf( pFile, " %-*s ", Length, Mio_GateReadName(pGate) ); + for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) + fprintf( pFile, "%s=%s ", Mio_PinReadName(pGatePin), Abc_ObjName( Abc_ObjFanin(pNode,i) ) ); + assert ( i == Abc_ObjFaninNum(pNode) ); + fprintf( pFile, "%s=%s", Mio_GateReadOutName(pGate), Abc_ObjName( Abc_ObjFanout0(pNode) ) ); +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNet; + int LineLength; + int AddedLength; + int NameCounter; + char * pName; + int i; + + LineLength = 6; + NameCounter = 0; + Abc_ObjForEachFanin( pNode, pNet, i ) + { + // get the fanin name + pName = Abc_ObjName(pNet); + // get the line length after the fanin name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", pName ); + LineLength += AddedLength; + NameCounter++; + } + + // get the output name + pName = Abc_ObjName(Abc_ObjFanout0(pNode)); + // get the line length after the output name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength > 75 ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", pName ); +} + +/**Function************************************************************* + + Synopsis [Writes the timing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + Abc_Time_t * pTime, * pTimeDef; + int i; + + if ( pNtk->pManTime == NULL ) + return; + + pTimeDef = Abc_NtkReadDefaultArrival( pNtk ); + fprintf( pFile, ".default_input_arrival %g %g\n", pTimeDef->Rise, pTimeDef->Fall ); + Abc_NtkForEachPi( pNtk, pNode, i ) + { + pTime = Abc_NodeReadArrival(pNode); + if ( pTime->Rise == pTimeDef->Rise && pTime->Fall == pTimeDef->Fall ) + continue; + fprintf( pFile, ".input_arrival %s %g %g\n", Abc_ObjName(pNode), pTime->Rise, pTime->Fall ); + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteBlifMv.c b/abc70930/src/base/io/ioWriteBlifMv.c new file mode 100644 index 00000000..775a2e07 --- /dev/null +++ b/abc70930/src/base/io/ioWriteBlifMv.c @@ -0,0 +1,519 @@ +/**CFile**************************************************************** + + FileName [ioWriteBlifMv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write BLIF-MV files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvAsserts( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch ); +static void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteBlifMvValues( FILE * pFile, Abc_Obj_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName ) +{ + FILE * pFile; + Abc_Ntk_t * pNtkTemp; + int i; + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkHasBlifMv(pNtk) ); + // start writing the file + pFile = fopen( FileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBlifMv(): Cannot open the output file.\n" ); + return; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the master network + Io_NtkWriteBlifMv( pFile, pNtk ); + // write the remaining networks + if ( pNtk->pDesign ) + { + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i ) + { + if ( pNtkTemp == pNtk ) + continue; + fprintf( pFile, "\n\n" ); + Io_NtkWriteBlifMv( pFile, pNtkTemp ); + } + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + assert( Abc_NtkIsNetlist(pNtk) ); + // write the model name + fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); + // write the network + Io_NtkWriteBlifMvOne( pFile, pNtk ); + // write EXDC network if it exists + if ( Abc_NtkExdc(pNtk) ) + printf( "Io_NtkWriteBlifMv(): EXDC is not written.\n" ); + // finalize the file + fprintf( pFile, ".end\n\n\n" ); +} + +/**Function************************************************************* + + Synopsis [Write one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pTerm, * pLatch; + int i; + + // write the PIs + fprintf( pFile, ".inputs" ); + Io_NtkWriteBlifMvPis( pFile, pNtk ); + fprintf( pFile, "\n" ); + + // write the POs + fprintf( pFile, ".outputs" ); + Io_NtkWriteBlifMvPos( pFile, pNtk ); + fprintf( pFile, "\n" ); + + // write the assertions + if ( Abc_NtkAssertNum(pNtk) ) + { + fprintf( pFile, ".asserts" ); + Io_NtkWriteBlifMvAsserts( pFile, pNtk ); + fprintf( pFile, "\n" ); + } + + // write the MV directives + fprintf( pFile, "\n" ); + Abc_NtkForEachCi( pNtk, pTerm, i ) + if ( Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) ); + Abc_NtkForEachCo( pNtk, pTerm, i ) + if ( Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanin0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) ); + + // write the blackbox + if ( Abc_NtkHasBlackbox( pNtk ) ) + { + fprintf( pFile, ".blackbox\n" ); + return; + } + + // write the timing info +// Io_WriteTimingInfo( pFile, pNtk ); + + // write the latches + if ( !Abc_NtkIsComb(pNtk) ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Io_NtkWriteBlifMvLatch( pFile, pLatch ); + fprintf( pFile, "\n" ); + } +/* + // write the subcircuits + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + if ( Abc_NtkBlackboxNum(pNtk) > 0 ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachBlackbox( pNtk, pNode, i ) + Io_NtkWriteBlifMvSubckt( pFile, pNode ); + fprintf( pFile, "\n" ); + } +*/ + if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachBox( pNtk, pNode, i ) + { + if ( Abc_ObjIsLatch(pNode) ) + continue; + Io_NtkWriteBlifMvSubckt( pFile, pNode ); + } + fprintf( pFile, "\n" ); + } + + // write each internal node + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_NtkWriteBlifMvNode( pFile, pNode ); + } + Extra_ProgressBarStop( pProgress ); +} + + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 7; + NameCounter = 0; + + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 8; + NameCounter = 0; + + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the assertion list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvAsserts( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 8; + NameCounter = 0; + + Abc_NtkForEachAssert( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch ) +{ + Abc_Obj_t * pNetLi, * pNetLo; + int Reset; + pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) ); + pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) ); + Reset = (int)Abc_ObjData( pLatch ); + // write the latch line + fprintf( pFile, ".latch" ); + fprintf( pFile, " %10s", Abc_ObjName(pNetLi) ); + fprintf( pFile, " %10s", Abc_ObjName(pNetLo) ); + fprintf( pFile, "\n" ); + // write the reset node + fprintf( pFile, ".reset %s\n", Abc_ObjName(pNetLo) ); + fprintf( pFile, "%d\n", Reset-1 ); +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pModel = pNode->pData; + Abc_Obj_t * pTerm; + int i; + // write the MV directives + fprintf( pFile, "\n" ); + Abc_ObjForEachFanin( pNode, pTerm, i ) + if ( Abc_ObjMvVarNum(pTerm) > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) ); + Abc_ObjForEachFanout( pNode, pTerm, i ) + if ( Abc_ObjMvVarNum(pTerm) > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) ); + // write the subcircuit + fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) ); + // write pairs of the formal=actual names + Abc_NtkForEachPi( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + pTerm = Abc_ObjFanin( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + } + Abc_NtkForEachPo( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + pTerm = Abc_ObjFanout( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + } + fprintf( pFile, "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + char * pCur; + int nValues, iFanin, i; + + // write .mv directives for the fanins + fprintf( pFile, "\n" ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { +// nValues = atoi(pCur); + nValues = Abc_ObjMvVarNum( pFanin ); + if ( nValues > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pFanin), nValues ); +// while ( *pCur++ != ' ' ); + } + + // write .mv directives for the node +// nValues = atoi(pCur); + nValues = Abc_ObjMvVarNum( Abc_ObjFanout0(pNode) ); + if ( nValues > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), nValues ); +// while ( *pCur++ != '\n' ); + + // write the .names line + fprintf( pFile, ".table" ); + Io_NtkWriteBlifMvNodeFanins( pFile, pNode ); + fprintf( pFile, "\n" ); + + // write the cubes + pCur = Abc_ObjData(pNode); + if ( *pCur == 'd' ) + { + fprintf( pFile, ".default " ); + pCur++; + } + // write the literals + for ( ; *pCur; pCur++ ) + { + fprintf( pFile, "%c", *pCur ); + if ( *pCur != '=' ) + continue; + // get the number + iFanin = atoi( pCur+1 ); + fprintf( pFile, "%s", Abc_ObjName(Abc_ObjFanin(pNode,iFanin)) ); + // scroll on to the next symbol + while ( *pCur != ' ' && *pCur != '\n' ) + pCur++; + pCur--; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNet; + int LineLength; + int AddedLength; + int NameCounter; + char * pName; + int i; + + LineLength = 6; + NameCounter = 0; + Abc_ObjForEachFanin( pNode, pNet, i ) + { + // get the fanin name + pName = Abc_ObjName(pNet); + // get the line length after the fanin name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", pName ); + LineLength += AddedLength; + NameCounter++; + } + + // get the output name + pName = Abc_ObjName(Abc_ObjFanout0(pNode)); + // get the line length after the output name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength > 75 ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", pName ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteCnf.c b/abc70930/src/base/io/ioWriteCnf.c new file mode 100644 index 00000000..e1b2d956 --- /dev/null +++ b/abc70930/src/base/io/ioWriteCnf.c @@ -0,0 +1,115 @@ +/**CFile**************************************************************** + + FileName [ioWriteCnf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to output CNF of the miter cone.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteCnf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "satSolver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * s_pNtk = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write the miter cone into a CNF file for the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteCnf( Abc_Ntk_t * pNtk, char * pFileName, int fAllPrimes ) +{ + sat_solver * pSat; + if ( Abc_NtkIsStrash(pNtk) ) + printf( "Io_WriteCnf() warning: Generating CNF by applying heuristic AIG to CNF conversion.\n" ); + else + printf( "Io_WriteCnf() warning: Generating CNF by convering logic nodes into CNF clauses.\n" ); + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter (the network with one PO).\n" ); + return 0; + } + if ( Abc_NtkLatchNum(pNtk) != 0 ) + { + fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter for combinational circuits.\n" ); + return 0; + } + if ( Abc_NtkNodeNum(pNtk) == 0 ) + { + fprintf( stdout, "The network has no logic nodes. No CNF file is generaled.\n" ); + return 0; + } + // convert to logic BDD network + if ( Abc_NtkIsLogic(pNtk) ) + Abc_NtkToBdd( pNtk ); + // create solver with clauses + pSat = Abc_NtkMiterSatCreate( pNtk, fAllPrimes ); + if ( pSat == NULL ) + { + fprintf( stdout, "The problem is trivially UNSAT. No CNF file is generated.\n" ); + return 1; + } + // write the clauses + s_pNtk = pNtk; + Sat_SolverWriteDimacs( pSat, pFileName, 0, 0, 1 ); + s_pNtk = NULL; + // free the solver + sat_solver_delete( pSat ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Output the mapping of PIs into variable numbers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteCnfOutputPiMapping( FILE * pFile, int incrementVars ) +{ + extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); + Abc_Ntk_t * pNtk = s_pNtk; + Vec_Int_t * vCiIds; + Abc_Obj_t * pObj; + int i; + vCiIds = Abc_NtkGetCiSatVarNums( pNtk ); + fprintf( pFile, "c PI variable numbers: <PI_name> <SAT_var_number>\n" ); + Abc_NtkForEachCi( pNtk, pObj, i ) + fprintf( pFile, "c %s %d\n", Abc_ObjName(pObj), Vec_IntEntry(vCiIds, i) + (int)(incrementVars > 0) ); + Vec_IntFree( vCiIds ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteDot.c b/abc70930/src/base/io/ioWriteDot.c new file mode 100644 index 00000000..8ae3cc42 --- /dev/null +++ b/abc70930/src/base/io/ioWriteDot.c @@ -0,0 +1,809 @@ +/**CFile**************************************************************** + + FileName [ioWriteDot.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the graph structure of AIG in DOT.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteDot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static char * Abc_NtkPrintSop( char * pSop ); +static int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the graph structure of network for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName ) +{ + Vec_Ptr_t * vNodes; + vNodes = Abc_NtkCollectObjects( pNtk ); + Io_WriteDotNtk( pNtk, vNodes, NULL, FileName, 0, 0 ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Writes the graph structure of network for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) +{ + FILE * pFile; + Abc_Obj_t * pNode, * pFanin; + char * pSopString; + int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl; + int Limit = 300; + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + + if ( vNodes->nSize < 1 ) + { + printf( "The set has no nodes. DOT file is not written.\n" ); + return; + } + + if ( vNodes->nSize > Limit ) + { + printf( "The set has more than %d nodes. DOT file is not written.\n", Limit ); + return; + } + + // start the stream + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // transform logic functions from BDD to SOP + if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); + return; + } + } + + // mark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 1; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 1; + + // get the levels of nodes + LevelMax = Abc_NtkLevel( pNtk ); + if ( fUseReverse ) + { + LevelMin = Abc_NtkLevelReverse( pNtk ); + assert( LevelMax == LevelMin ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + if ( Abc_ObjIsNode(pNode) ) + pNode->Level = LevelMax - pNode->Level + 1; + } + + // find the largest and the smallest levels + LevelMin = 10000; + LevelMax = -1; + fHasCos = 0; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + { + fHasCos = 1; + continue; + } + if ( LevelMin > (int)pNode->Level ) + LevelMin = pNode->Level; + if ( LevelMax < (int)pNode->Level ) + LevelMax = pNode->Level; + } + + // set the level of the CO nodes + if ( fHasCos ) + { + LevelMax++; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + pNode->Level = LevelMax; + } + } + + // write the DOT header + fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph network {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "size = \"10,8.5\";\n" ); +// fprintf( pFile, "size = \"14,11\";\n" ); +// fprintf( pFile, "page = \"8,11\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != LevelMin ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "Network structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); + fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) + fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); + else + fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the POs + if ( fHasCos ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsCo(pNode) ) + continue; + fprintf( pFile, " Node%d [label = \"%s%s\"", + pNode->Id, + (Abc_ObjIsBi(pNode)? Abc_ObjName(Abc_ObjFanout0(pNode)):Abc_ObjName(pNode)), + (Abc_ObjIsBi(pNode)? "_in":"") ); + fprintf( pFile, ", shape = %s", (Abc_ObjIsBi(pNode)? "box":"invtriangle") ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate nodes of each rank + for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( (int)pNode->Level != Level ) + continue; + if ( Abc_ObjFaninNum(pNode) == 0 ) + continue; +// fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + if ( Abc_NtkIsStrash(pNtk) ) + pSopString = ""; + else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) + pSopString = Mio_GateReadName(pNode->pData); + else if ( Abc_NtkHasMapping(pNtk) ) + pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData)); + else + pSopString = Abc_NtkPrintSop(pNode->pData); + fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); + + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the PI nodes if any + if ( LevelMin == 0 ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMin ); + // generate the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsCi(pNode) ) + { + // check if the costant node is present + if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 ) + { + fprintf( pFile, " Node%d [label = \"Const%d\"", pNode->Id, Abc_NtkIsStrash(pNode->pNtk) || Abc_NodeIsConst1(pNode) ); + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + continue; + } + fprintf( pFile, " Node%d [label = \"%s\"", + pNode->Id, + (Abc_ObjIsBo(pNode)? Abc_ObjName(Abc_ObjFanin0(pNode)):Abc_ObjName(pNode)) ); + fprintf( pFile, ", shape = %s", (Abc_ObjIsBo(pNode)? "box":"triangle") ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( (int)pNode->Level != LevelMax ) + continue; + fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); + } + + // generate edges + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsLatch(pNode) ) + continue; + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + if ( Abc_ObjIsLatch(pFanin) ) + continue; + fCompl = 0; + if ( Abc_NtkIsStrash(pNtk) ) + fCompl = Abc_ObjFaninC(pNode, k); + // generate the edge from this node to the next + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pFanin->Id ); + fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" ); +// fprintf( pFile, ", label = \"%c\"", 'a' + k ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + } + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 0; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 0; + + // convert the network back into BDDs if this is how it was + if ( fHasBdds ) + Abc_NtkSopToBdd(pNtk); +} + + +/**Function************************************************************* + + Synopsis [Writes the graph structure of network for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) +{ + FILE * pFile; + Abc_Obj_t * pNode, * pFanin; + char * pSopString; + int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl; + int Limit = 300; + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + + if ( vNodes->nSize < 1 ) + { + printf( "The set has no nodes. DOT file is not written.\n" ); + return; + } + + if ( vNodes->nSize > Limit ) + { + printf( "The set has more than %d nodes. DOT file is not written.\n", Limit ); + return; + } + + // start the stream + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // transform logic functions from BDD to SOP + if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); + return; + } + } + + // mark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 1; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 1; + + // get the levels of nodes + LevelMax = Abc_NtkLevel( pNtk ); + if ( fUseReverse ) + { + LevelMin = Abc_NtkLevelReverse( pNtk ); + assert( LevelMax == LevelMin ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + if ( Abc_ObjIsNode(pNode) ) + pNode->Level = LevelMax - pNode->Level + 1; + } + + // find the largest and the smallest levels + LevelMin = 10000; + LevelMax = -1; + fHasCos = 0; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + { + fHasCos = 1; + continue; + } + if ( LevelMin > (int)pNode->Level ) + LevelMin = pNode->Level; + if ( LevelMax < (int)pNode->Level ) + LevelMax = pNode->Level; + } + + // set the level of the CO nodes + if ( fHasCos ) + { + LevelMax++; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + pNode->Level = LevelMax; + } + } + + // write the DOT header + fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph network {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "size = \"10,8.5\";\n" ); +// fprintf( pFile, "size = \"14,11\";\n" ); +// fprintf( pFile, "page = \"8,11\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != LevelMin ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "Network structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); + fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) + fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); + else + fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the POs + if ( fHasCos ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsPo(pNode) ) + continue; + fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = %s", "invtriangle" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate nodes of each rank + for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( (int)pNode->Level != Level ) + continue; +// fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + if ( Abc_NtkIsStrash(pNtk) ) + pSopString = ""; + else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) + pSopString = Mio_GateReadName(pNode->pData); + else if ( Abc_NtkHasMapping(pNtk) ) + pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData)); + else + pSopString = Abc_NtkPrintSop(pNode->pData); + fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); + + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the PI nodes if any + if ( LevelMin == 0 ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMin ); + // generate the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( pNode->Level > 0 ) + continue; + if ( !Abc_ObjIsPi(pNode) ) + { + // check if the costant node is present + if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 ) + { + fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + continue; + } + fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = %s", "triangle" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + +// fprintf( pFile, "{\n" ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsLatch(pNode) ) + continue; + fprintf( pFile, "Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = box" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } +// fprintf( pFile, "}" ); +// fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( (int)pNode->Level != LevelMax ) + continue; + if ( !Abc_ObjIsPo(pNode) ) + continue; + fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); + } + + // generate edges + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsBi(pNode) || Abc_ObjIsBo(pNode) ) + continue; + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + fCompl = 0; + if ( Abc_NtkIsStrash(pNtk) ) + { + if ( Abc_ObjIsBi(pFanin) ) + fCompl = Abc_ObjFaninC(pFanin, k); + else + fCompl = Abc_ObjFaninC(pNode, k); + } + if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) ) + pFanin = Abc_ObjFanin0(pFanin); + if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) ) + pFanin = Abc_ObjFanin0(pFanin); + if ( !pFanin->fMarkC ) + continue; + + // generate the edge from this node to the next + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pFanin->Id ); + fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" ); +// fprintf( pFile, ", label = \"%c\"", 'a' + k ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + } + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 0; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 0; + + // convert the network back into BDDs if this is how it was + if ( fHasBdds ) + Abc_NtkSopToBdd(pNtk); +} + + +/**Function************************************************************* + + Synopsis [Computes the printable SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_NtkPrintSop( char * pSop ) +{ + static char Buffer[1000]; + char * pGet, * pSet; + pSet = Buffer; + for ( pGet = pSop; *pGet; pGet++ ) + { + if ( *pGet == '\n' ) + { + *pSet++ = '\\'; + *pSet++ = 'n'; + } + else + *pSet++ = *pGet; + } + *(pSet-2) = 0; + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Computes the printable SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + if ( !Abc_ObjIsNode(pObj) ) + continue; + if ( Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 ) + continue; + Counter ++; + } + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteEqn.c b/abc70930/src/base/io/ioWriteEqn.c new file mode 100644 index 00000000..95c54577 --- /dev/null +++ b/abc70930/src/base/io/ioWriteEqn.c @@ -0,0 +1,252 @@ +/**CFile**************************************************************** + + FileName [ioWriteEqn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write equation representation of the network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the logic network in the equation format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ) +{ + FILE * pFile; + + assert( Abc_NtkIsAigNetlist(pNtk) ); + if ( Abc_NtkLatchNum(pNtk) > 0 ) + printf( "Warning: only combinational portion is being written.\n" ); + + // check that the names are fine for the EQN format + if ( !Io_NtkWriteEqnCheck(pNtk) ) + return; + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteEqn(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "# Equations for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + + // write the equations for the network + Io_NtkWriteEqnOne( pFile, pNtk ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Write one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Vec_Vec_t * vLevels; + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pFanin; + int i, k; + + // write the PIs + fprintf( pFile, "INORDER =" ); + Io_NtkWriteEqnCis( pFile, pNtk ); + fprintf( pFile, ";\n" ); + + // write the POs + fprintf( pFile, "OUTORDER =" ); + Io_NtkWriteEqnCos( pFile, pNtk ); + fprintf( pFile, ";\n" ); + + // write each internal node + vLevels = Vec_VecAlloc( 10 ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + fprintf( pFile, "%s = ", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + // set the input names + Abc_ObjForEachFanin( pNode, pFanin, k ) + Hop_IthVar(pNtk->pManFunc, k)->pData = Abc_ObjName(pFanin); + // write the formula + Hop_ObjPrintEqn( pFile, pNode->pData, vLevels, 0 ); + fprintf( pFile, ";\n" ); + } + Extra_ProgressBarStop( pProgress ); + Vec_VecFree( vLevels ); +} + + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 9; + NameCounter = 0; + + Abc_NtkForEachCi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 10; + NameCounter = 0; + + Abc_NtkForEachCo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Make sure the network does not have offending names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + char * pName; + int i, k, Length; + int RetValue = 1; + + // make sure the network does not have proper names, such as "0" or "1" or containing parantheses + Abc_NtkForEachObj( pNtk, pObj, i ) + { + pName = Nm_ManFindNameById(pNtk->pManName, i); + if ( pName == NULL ) + continue; + Length = strlen(pName); + if ( pName[0] == '0' || pName[0] == '1' ) + { + RetValue = 0; + break; + } + for ( k = 0; k < Length; k++ ) + if ( pName[k] == '(' || pName[k] == ')' || pName[k] == '!' || pName[k] == '*' || pName[k] == '+' ) + { + RetValue = 0; + break; + } + if ( k < Length ) + break; + } + if ( RetValue == 0 ) + { + printf( "The network cannot be written in the EQN format because object %d has name \"%s\".\n", i, pName ); + printf( "Consider renaming the objects using command \"short_names\" and trying again.\n" ); + } + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteGml.c b/abc70930/src/base/io/ioWriteGml.c new file mode 100644 index 00000000..dc897300 --- /dev/null +++ b/abc70930/src/base/io/ioWriteGml.c @@ -0,0 +1,116 @@ +/**CFile**************************************************************** + + FileName [ioWriteGml.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the graph structure of AIG in GML.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteGml.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the graph structure of AIG in GML.] + + Description [Useful for graph visualization using tools such as yEd: + http://www.yworks.com/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ) +{ + FILE * pFile; + Abc_Obj_t * pObj, * pFanin; + int i, k; + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteGml(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "# GML for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + fprintf( pFile, "graph [\n" ); + + // output the POs + fprintf( pFile, "\n" ); + Abc_NtkForEachPo( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"triangle\" fill \"#00FFFF\" ]\n" ); // blue + fprintf( pFile, " ]\n" ); + } + // output the PIs + fprintf( pFile, "\n" ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"triangle\" fill \"#00FF00\" ]\n" ); // green + fprintf( pFile, " ]\n" ); + } + // output the latches + fprintf( pFile, "\n" ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"rectangle\" fill \"#FF0000\" ]\n" ); // red + fprintf( pFile, " ]\n" ); + } + // output the nodes + fprintf( pFile, "\n" ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"ellipse\" fill \"#CCCCFF\" ]\n" ); // grey + fprintf( pFile, " ]\n" ); + } + + // output the edges + fprintf( pFile, "\n" ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + fprintf( pFile, " edge [ source %5d target %5d\n", pObj->Id, pFanin->Id ); + fprintf( pFile, " graphics [ type \"line\" arrow \"first\" ]\n" ); + fprintf( pFile, " ]\n" ); + } + } + + fprintf( pFile, "]\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteList.c b/abc70930/src/base/io/ioWriteList.c new file mode 100644 index 00000000..71af7c53 --- /dev/null +++ b/abc70930/src/base/io/ioWriteList.c @@ -0,0 +1,288 @@ +/**CFile**************************************************************** + + FileName [ioWriteList.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the graph structure of sequential AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteList.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +/* +-------- Original Message -------- +Subject: Re: abc release and retiming +Date: Sun, 13 Nov 2005 20:31:18 -0500 (EST) +From: Luca Carloni <luca@cs.columbia.edu> +To: Alan Mishchenko <alanmi@eecs.berkeley.edu> + +Alan, + +My graph-representation file format is based on an adjacency list +representation and is indeed quite simple, in fact maybe too simple... I +used it in order to reason on relatively small weighed direct graphs. I +simply list all vertices, one per line and for each vertex "V_source" I +list all vertices that are "sinks" with respect to it, i.e. such that +there is a distinct arc between "V_source" and each of them (in +paranthesis I list the name of the edge and its weight (number of latency +on that path). For instance, if you look at the following graph, you have +that vertex "v_5" is connected to vertex "v_6" through a directed arc +called "v_5_to_v_6" whose latency is equal to 3, i.e. there are three +flip-flops on this arc. Still, notice that I sometime interpret the graph +also as the representation of a LIS where each node corresponds to a +shell encapsulating a sequential core module (i.e. a module which does not +contain any combinational path between its inputs and its outputs). With +this representation an arc of latency 3 is interpreted as a wire where two +relay stations have been inserted in addition to the flip-flop terminating +the output of the core module. + +Finally, notice that the name of the arc does not necessarily have to be +"v_5_to_v_6", but it could have been something like "arc_222" or "xyz" as +long as it is a unique name in the graph. + +Thanks, +Luca + +Example of graph representation +----------------------------------------------------------------------------- +v_5 > v_6 ([v_5_to_v_6] = 3), v_12 ([v_5_to_v_12] = 2). +v_2 > v_4 ([v_2_to_v_4] = 1), v_10_s0 ([v_2_to_v_10_s0] = 6), v_12 ([v_2_to_v_12] = 3). +v_9 > v_10_s0 ([v_9_to_v_10_s0] = 5), v_12 ([v_9_to_v_12] = 2). +v_12 > v_13 ([v_12_to_v_13] = 5). +v_13 > v_14 ([v_13_to_v_14] = 1). +v_6 > v_7 ([v_6_to_v_7] = 2). +v_4 > v_5 ([v_4_to_v_5] = 2). +v_1 > v_2 ([v_1_to_v_2] = 1). +v_7 > v_8 ([v_7_to_v_8] = 2). +t > . +v_14 > t ([v_14_to_t] = 1), v_5 ([v_14_to_v_5] = 1). +v_8 > v_9 ([v_8_to_v_9] = 2). +s > v_1 ([s_to_v_1] = 1). +v_10_s0 > v_10_s1 ([v_10_s0_to_v_10_s1] = 1). +v_10_s1 > v_4 ([v_10_s1__v_4] = 1), v_8 ([v_10_s1__v_8] = 1). +----------------------------------------------------------------------------- +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj ); +static void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the adjacency list for a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ) +{ + FILE * pFile; + Abc_Obj_t * pObj; + int i; + +// assert( Abc_NtkIsSeq(pNtk) ); + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteList(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + fprintf( pFile, "# Adjacency list for sequential AIG \"%s\"\n", pNtk->pName ); + fprintf( pFile, "# written by ABC on %s\n", Extra_TimeStamp() ); + + // write the constant node + if ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk) ) > 0 ) + Io_WriteListEdge( pFile, Abc_AigConst1(pNtk) ); + + // write the PI edges + Abc_NtkForEachPi( pNtk, pObj, i ) + Io_WriteListEdge( pFile, pObj ); + + // write the internal nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + Io_WriteListEdge( pFile, pObj ); + + // write the host node + if ( fUseHost ) + Io_WriteListHost( pFile, pNtk ); + else + Abc_NtkForEachPo( pNtk, pObj, i ) + Io_WriteListEdge( pFile, pObj ); + + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Writes the adjacency list for one edge in a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i; + fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) ); + Abc_ObjForEachFanout( pObj, pFanout, i ) + { + fprintf( pFile, " %s", Abc_ObjName(pFanout) ); + fprintf( pFile, " ([%s_to_", Abc_ObjName(pObj) ); +// fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), Seq_ObjFanoutL(pObj, pFanout) ); + fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), 0 ); + if ( i != Abc_ObjFanoutNum(pObj) - 1 ) + fprintf( pFile, "," ); + } + fprintf( pFile, "." ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the adjacency list for one edge in a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + Abc_NtkForEachPo( pNtk, pObj, i ) + { + fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) ); + fprintf( pFile, " %s ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), "HOST", 0 ); + fprintf( pFile, "." ); + fprintf( pFile, "\n" ); + } + + fprintf( pFile, "%-10s > ", "HOST" ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + fprintf( pFile, " %s", Abc_ObjName(pObj) ); + fprintf( pFile, " ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), 0 ); + if ( i != Abc_NtkPiNum(pNtk) - 1 ) + fprintf( pFile, "," ); + } + fprintf( pFile, "." ); + fprintf( pFile, "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Writes the adjacency list for a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName ) +{ + FILE * pFile; + Abc_Obj_t * pObj, * pFanout; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) ); + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteCellNet(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + fprintf( pFile, "# CellNet file for network \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + + // the only tricky part with writing is handling latches: + // each latch comes with (a) single-input latch-input node, (b) latch proper, (c) single-input latch-output node + // we arbitrarily decide to use the interger ID of the latch-input node to represent the latch in the file + // (this ID is used for both the cell and the net driven by that cell) + + // write the PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "cell %d is 0\n", pObj->Id ); + // write the POs + Abc_NtkForEachPo( pNtk, pObj, i ) + fprintf( pFile, "cell %d is 1\n", pObj->Id ); + // write the latches (use the ID of latch input) + Abc_NtkForEachLatch( pNtk, pObj, i ) + fprintf( pFile, "cell %d is 2\n", Abc_ObjFanin0(pObj)->Id ); + // write the logic nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + fprintf( pFile, "cell %d is %d\n", pObj->Id, 3+Abc_ObjFaninNum(pObj) ); + + // write the nets driven by PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + { + fprintf( pFile, "net %d %d 0", pObj->Id, pObj->Id ); + Abc_ObjForEachFanout( pObj, pFanout, k ) + fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); + fprintf( pFile, "\n" ); + } + // write the nets driven by latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + fprintf( pFile, "net %d %d 0", Abc_ObjFanin0(pObj)->Id, Abc_ObjFanin0(pObj)->Id ); + pObj = Abc_ObjFanout0(pObj); + Abc_ObjForEachFanout( pObj, pFanout, k ) + fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); + fprintf( pFile, "\n" ); + } + // write the nets driven by nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + { + fprintf( pFile, "net %d %d 0", pObj->Id, pObj->Id ); + Abc_ObjForEachFanout( pObj, pFanout, k ) + fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); + fprintf( pFile, "\n" ); + } + + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWritePla.c b/abc70930/src/base/io/ioWritePla.c new file mode 100644 index 00000000..b119751c --- /dev/null +++ b/abc70930/src/base/io/ioWritePla.c @@ -0,0 +1,197 @@ +/**CFile**************************************************************** + + FileName [ioWritePla.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the network in BENCH format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWritePla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the network in PLA format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WritePla( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Abc_Ntk_t * pExdc; + FILE * pFile; + + assert( Abc_NtkIsSopNetlist(pNtk) ); + assert( Abc_NtkLevel(pNtk) == 1 ); + + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WritePla(): Cannot open the output file.\n" ); + return 0; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the network + Io_WritePlaOne( pFile, pNtk ); + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + printf( "Io_WritePla: EXDC is not written (warning).\n" ); + // finalize the file + fclose( pFile ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the network in PLA format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pFanin, * pDriver; + char * pCubeIn, * pCubeOut, * pCube; + int i, k, nProducts, nInputs, nOutputs, nFanins; + + nProducts = 0; + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); + if ( !Abc_ObjIsNode(pDriver) ) + { + nProducts++; + continue; + } + if ( Abc_NodeIsConst(pDriver) ) + { + if ( Abc_NodeIsConst1(pDriver) ) + nProducts++; + continue; + } + nProducts += Abc_SopGetCubeNum(pDriver->pData); + } + + // collect the parameters + nInputs = Abc_NtkCiNum(pNtk); + nOutputs = Abc_NtkCoNum(pNtk); + pCubeIn = ALLOC( char, nInputs + 1 ); + pCubeOut = ALLOC( char, nOutputs + 1 ); + memset( pCubeIn, '-', nInputs ); pCubeIn[nInputs] = 0; + memset( pCubeOut, '0', nOutputs ); pCubeOut[nOutputs] = 0; + + // write the header + fprintf( pFile, ".i %d\n", nInputs ); + fprintf( pFile, ".o %d\n", nOutputs ); + fprintf( pFile, ".ilb" ); + Abc_NtkForEachCi( pNtk, pNode, i ) + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".ob" ); + Abc_NtkForEachCo( pNtk, pNode, i ) + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".p %d\n", nProducts ); + + // mark the CI nodes + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = (Abc_Obj_t *)i; + + // write the cubes + pProgress = Extra_ProgressBarStart( stdout, nOutputs ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + // prepare the output cube + if ( i - 1 >= 0 ) + pCubeOut[i-1] = '0'; + pCubeOut[i] = '1'; + + // consider special cases of nodes + pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); + if ( !Abc_ObjIsNode(pDriver) ) + { + assert( Abc_ObjIsCi(pDriver) ); + pCubeIn[(int)pDriver->pCopy] = '1' - Abc_ObjFaninC0(pNode); + fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); + pCubeIn[(int)pDriver->pCopy] = '-'; + continue; + } + if ( Abc_NodeIsConst(pDriver) ) + { + if ( Abc_NodeIsConst1(pDriver) ) + fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); + continue; + } + + // make sure the cover is not complemented + assert( !Abc_SopIsComplement( pDriver->pData ) ); + + // write the cubes + nFanins = Abc_ObjFaninNum(pDriver); + Abc_SopForEachCube( pDriver->pData, nFanins, pCube ) + { + Abc_ObjForEachFanin( pDriver, pFanin, k ) + { + pFanin = Abc_ObjFanin0Ntk(pFanin); + assert( (int)pFanin->pCopy < nInputs ); + pCubeIn[(int)pFanin->pCopy] = pCube[k]; + } + fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); + } + // clean the cube for future writing + Abc_ObjForEachFanin( pDriver, pFanin, k ) + { + pFanin = Abc_ObjFanin0Ntk(pFanin); + assert( Abc_ObjIsCi(pFanin) ); + pCubeIn[(int)pFanin->pCopy] = '-'; + } + Extra_ProgressBarUpdate( pProgress, i, NULL ); + } + Extra_ProgressBarStop( pProgress ); + fprintf( pFile, ".e\n" ); + + // clean the CI nodes + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = NULL; + free( pCubeIn ); + free( pCubeOut ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteVerilog.c b/abc70930/src/base/io/ioWriteVerilog.c new file mode 100644 index 00000000..9e71e3e4 --- /dev/null +++ b/abc70930/src/base/io/ioWriteVerilog.c @@ -0,0 +1,639 @@ +/**CFile**************************************************************** + + FileName [ioWriteVerilog.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to output a special subset of Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ); +static char * Io_WriteVerilogGetName( char * pName ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write verilog.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Abc_Ntk_t * pNetlist; + FILE * pFile; + int i; + // can only write nodes represented using local AIGs + if ( !Abc_NtkIsAigNetlist(pNtk) && !Abc_NtkIsMappedNetlist(pNtk) ) + { + printf( "Io_WriteVerilog(): Can produce Verilog for mapped or AIG netlists only.\n" ); + return; + } + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteVerilog(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + // write the equations for the network + fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + fprintf( pFile, "\n" ); + + // write modules + if ( pNtk->pDesign ) + { + // write the network first + Io_WriteVerilogInt( pFile, pNtk ); + // write other things + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNetlist, i ) + { + assert( Abc_NtkIsNetlist(pNetlist) ); + if ( pNetlist == pNtk ) + continue; + fprintf( pFile, "\n" ); + Io_WriteVerilogInt( pFile, pNetlist ); + } + } + else + { + Io_WriteVerilogInt( pFile, pNtk ); + } + + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Writes verilog.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + // write inputs and outputs +// fprintf( pFile, "module %s ( gclk,\n ", Abc_NtkName(pNtk) ); + fprintf( pFile, "module %s ( ", Abc_NtkName(pNtk) ); + // add the clock signal if it does not exist + if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 ) + fprintf( pFile, "clock, " ); + // write other primary inputs + fprintf( pFile, "\n " ); + if ( Abc_NtkPiNum(pNtk) > 0 ) + { + Io_WriteVerilogPis( pFile, pNtk, 3 ); + fprintf( pFile, ",\n " ); + } + if ( Abc_NtkPoNum(pNtk) > 0 ) + Io_WriteVerilogPos( pFile, pNtk, 3 ); + fprintf( pFile, " );\n" ); + // add the clock signal if it does not exist + if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 ) + fprintf( pFile, " input clock;\n" ); + // write inputs, outputs, registers, and wires + if ( Abc_NtkPiNum(pNtk) > 0 ) + { +// fprintf( pFile, " input gclk," ); + fprintf( pFile, " input " ); + Io_WriteVerilogPis( pFile, pNtk, 10 ); + fprintf( pFile, ";\n" ); + } + if ( Abc_NtkPoNum(pNtk) > 0 ) + { + fprintf( pFile, " output" ); + Io_WriteVerilogPos( pFile, pNtk, 5 ); + fprintf( pFile, ";\n" ); + } + // if this is not a blackbox, write internal signals + if ( !Abc_NtkHasBlackbox(pNtk) ) + { + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( pFile, " reg" ); + Io_WriteVerilogRegs( pFile, pNtk, 4 ); + fprintf( pFile, ";\n" ); + } + if ( Io_WriteVerilogWiresCount(pNtk) > 0 ) + { + fprintf( pFile, " wire" ); + Io_WriteVerilogWires( pFile, pNtk, 4 ); + fprintf( pFile, ";\n" ); + } + // write nodes + Io_WriteVerilogObjects( pFile, pNtk ); + // write registers + if ( Abc_NtkLatchNum(pNtk) > 0 ) + Io_WriteVerilogLatches( pFile, pNtk ); + } + // finalize the file + fprintf( pFile, "endmodule\n\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPiNum(pNtk)-1)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pTerm, * pNet, * pSkip; + int LineLength; + int AddedLength; + int NameCounter; + int i; + int nskip; + + pSkip = 0; + nskip = 0; + + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + + if ( Abc_ObjIsPi(Abc_ObjFanin0(pNet)) ) + { + // Skip this output since it is a feedthrough -- the same + // name will appear as an input and an output which other + // tools reading verilog do not like. + + nskip++; + pSkip = pNet; // save an example of skipped net + continue; + } + + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPoNum(pNtk)-1)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + + if (nskip != 0) + { + assert (pSkip); + printf( "Io_WriteVerilogPos(): Omitted %d feedthrough nets from output list of module (e.g. %s).\n", nskip, Abc_ObjName(pSkip) ); + return; + } + +} + +/**Function************************************************************* + + Synopsis [Writes the wires.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pObj, * pNet, * pBox, * pTerm; + int LineLength; + int AddedLength; + int NameCounter; + int i, k, Counter, nNodes; + + // count the number of wires + nNodes = Io_WriteVerilogWiresCount( pNtk ); + + // write the wires + Counter = 0; + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) + continue; + pNet = Abc_ObjFanout0(pObj); + if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + Abc_NtkForEachBox( pNtk, pBox, i ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + Abc_ObjForEachFanin( pBox, pTerm, k ) + { + pNet = Abc_ObjFanin0(pTerm); + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + Abc_ObjForEachFanout( pBox, pTerm, k ) + { + pNet = Abc_ObjFanout0(pTerm); + if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + } + assert( Counter == nNodes ); +} + +/**Function************************************************************* + + Synopsis [Writes the regs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pLatch, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i, Counter, nNodes; + + // count the number of latches + nNodes = Abc_NtkLatchNum(pNtk); + + // write the wires + Counter = 0; + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + pNet = Abc_ObjFanout0(Abc_ObjFanout0(pLatch)); + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pLatch; + int i; + if ( Abc_NtkLatchNum(pNtk) == 0 ) + return; + // write the latches +// fprintf( pFile, " always @(posedge %s) begin\n", Io_WriteVerilogGetName(Abc_ObjFanout0(Abc_NtkPi(pNtk,0))) ); +// fprintf( pFile, " always begin\n" ); + fprintf( pFile, " always @ (posedge clock) begin\n" ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + fprintf( pFile, " %s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); + fprintf( pFile, " <= %s;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pLatch)))) ); + } + fprintf( pFile, " end\n" ); + // check if there are initial values + Abc_NtkForEachLatch( pNtk, pLatch, i ) + if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO || Abc_LatchInit(pLatch) == ABC_INIT_ONE ) + break; + if ( i == Abc_NtkLatchNum(pNtk) ) + return; + // write the initial values + fprintf( pFile, " initial begin\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_NtkPi(pNtk,0)))) ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO ) + fprintf( pFile, " %s <= 1\'b0;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); + else if ( Abc_LatchInit(pLatch) == ABC_INIT_ONE ) + fprintf( pFile, " %s <= 1\'b1;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); + } + fprintf( pFile, " end\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the nodes and boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Vec_Vec_t * vLevels; + Abc_Ntk_t * pNtkBox; + Abc_Obj_t * pObj, * pTerm, * pFanin; + Hop_Obj_t * pFunc; + int i, k, Counter, nDigits, Length; + + // write boxes + nDigits = Extra_Base10Log( Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) ); + Counter = 0; + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + pNtkBox = pObj->pData; + fprintf( pFile, " %s box%0*d", pNtkBox->pName, nDigits, Counter++ ); + fprintf( pFile, "(" ); + Abc_NtkForEachPi( pNtkBox, pTerm, k ) + { + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pTerm))) ); + fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin(pObj,k)))) ); + } + Abc_NtkForEachPo( pNtkBox, pTerm, k ) + { + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(pTerm))) ); + fprintf( pFile, "(%s)%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout(pObj,k)))), k==Abc_NtkPoNum(pNtkBox)-1? "":", " ); + } + fprintf( pFile, ");\n" ); + } + // write nodes + if ( Abc_NtkHasMapping(pNtk) ) + { + Length = Mio_LibraryReadGateNameMax(pNtk->pManFunc); + nDigits = Extra_Base10Log( Abc_NtkNodeNum(pNtk) ); + Counter = 0; + Abc_NtkForEachNode( pNtk, pObj, k ) + { + Mio_Gate_t * pGate = pObj->pData; + Mio_Pin_t * pGatePin; + // write the node + fprintf( pFile, " %-*s g%0*d", Length, Mio_GateReadName(pGate), nDigits, Counter++ ); + fprintf( pFile, "(" ); + for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) + { + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_PinReadName(pGatePin)) ); + fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanin(pObj,i) )) ); + } + assert ( i == Abc_ObjFaninNum(pObj) ); + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_GateReadOutName(pGate)) ); + fprintf( pFile, "(%s)", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )) ); + fprintf( pFile, ");\n" ); + } + } + else + { + vLevels = Vec_VecAlloc( 10 ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + pFunc = pObj->pData; + fprintf( pFile, " assign %s = ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); + // set the input names + Abc_ObjForEachFanin( pObj, pFanin, k ) + Hop_IthVar(pNtk->pManFunc, k)->pData = Extra_UtilStrsav(Io_WriteVerilogGetName(Abc_ObjName(pFanin))); + // write the formula + Hop_ObjPrintVerilog( pFile, pFunc, vLevels, 0 ); + fprintf( pFile, ";\n" ); + // clear the input names + Abc_ObjForEachFanin( pObj, pFanin, k ) + free( Hop_IthVar(pNtk->pManFunc, k)->pData ); + } + Vec_VecFree( vLevels ); + } +} + +/**Function************************************************************* + + Synopsis [Counts the number of wires.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pNet, * pBox; + int i, k, nWires; + nWires = Abc_NtkLatchNum(pNtk); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) + continue; + pNet = Abc_ObjFanout0(pObj); + if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + nWires++; + } + Abc_NtkForEachBox( pNtk, pBox, i ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + nWires += Abc_ObjFaninNum(pBox); + Abc_ObjForEachFanout( pBox, pObj, k ) + { + pNet = Abc_ObjFanout0(pObj); + if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + nWires++; + } + } + return nWires; +} + +/**Function************************************************************* + + Synopsis [Prepares the name for writing the Verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Io_WriteVerilogGetName( char * pName ) +{ + static char Buffer[500]; + int Length, i; + Length = strlen(pName); + // consider the case of a signal having name "0" or "1" + if ( !(Length == 1 && (pName[0] == '0' || pName[0] == '1')) ) + { + for ( i = 0; i < Length; i++ ) + if ( !((pName[i] >= 'a' && pName[i] <= 'z') || + (pName[i] >= 'A' && pName[i] <= 'Z') || + (pName[i] >= '0' && pName[i] <= '9') || pName[i] == '_') ) + break; + if ( i == Length ) + return pName; + } + // create Verilog style name + Buffer[0] = '\\'; + for ( i = 0; i < Length; i++ ) + Buffer[i+1] = pName[i]; + Buffer[Length+1] = ' '; + Buffer[Length+2] = 0; + return Buffer; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/io_.c b/abc70930/src/base/io/io_.c new file mode 100644 index 00000000..62dd60e5 --- /dev/null +++ b/abc70930/src/base/io/io_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [io_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read network from file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: io_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/module.make b/abc70930/src/base/io/module.make new file mode 100644 index 00000000..bb35a7fc --- /dev/null +++ b/abc70930/src/base/io/module.make @@ -0,0 +1,25 @@ +SRC += src/base/io/io.c \ + src/base/io/ioReadAiger.c \ + src/base/io/ioReadBaf.c \ + src/base/io/ioReadBench.c \ + src/base/io/ioReadBlif.c \ + src/base/io/ioReadBlifAig.c \ + src/base/io/ioReadBlifMv.c \ + src/base/io/ioReadDsd.c \ + src/base/io/ioReadEdif.c \ + src/base/io/ioReadEqn.c \ + src/base/io/ioReadPla.c \ + src/base/io/ioReadVerilog.c \ + src/base/io/ioUtil.c \ + src/base/io/ioWriteAiger.c \ + src/base/io/ioWriteBaf.c \ + src/base/io/ioWriteBench.c \ + src/base/io/ioWriteBlif.c \ + src/base/io/ioWriteBlifMv.c \ + src/base/io/ioWriteCnf.c \ + src/base/io/ioWriteDot.c \ + src/base/io/ioWriteEqn.c \ + src/base/io/ioWriteGml.c \ + src/base/io/ioWriteList.c \ + src/base/io/ioWritePla.c \ + src/base/io/ioWriteVerilog.c diff --git a/abc70930/src/base/main/libSupport.c b/abc70930/src/base/main/libSupport.c new file mode 100644 index 00000000..471ea09e --- /dev/null +++ b/abc70930/src/base/main/libSupport.c @@ -0,0 +1,193 @@ +/**CFile**************************************************************** + + FileName [libSupport.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [Support for external libaries.] + + Author [Mike Case] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: libSupport.c,v 1.1 2005/09/06 19:59:51 casem Exp $] + +***********************************************************************/ + +#include "mainInt.h" +#include <stdio.h> +#include <string.h> + +#ifndef WIN32 +# include <sys/types.h> +# include <dirent.h> +# include <dlfcn.h> +#endif + +#define MAX_LIBS 256 +static void* libHandles[MAX_LIBS+1]; // will be null terminated + +typedef void (*lib_init_end_func) (Abc_Frame_t * pAbc); + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// This will find all the ABC library extensions in the current directory and load them all. +//////////////////////////////////////////////////////////////////////////////////////////////////// +void open_libs() { + int curr_lib = 0; + +#ifdef WIN32 +// printf("Warning: open_libs WIN32 not implemented.\n"); +#else + DIR* dirp; + struct dirent* dp; + char *env, *init_p, *p; + int done; + + env = getenv ("ABC_LIB_PATH"); + if (env == NULL) { +// printf("Warning: ABC_LIB_PATH not defined. Looking into the current directory.\n"); + init_p = malloc (2*sizeof(char)); + init_p[0]='.'; init_p[1] = 0; + } else { + init_p = malloc ((strlen(env)+1)*sizeof(char)); + strcpy (init_p, env); + } + + // Extract directories and read libraries + done = 0; + p = init_p; + while (!done) { + char *endp = strchr (p,':'); + if (endp == NULL) done = 1; // last directory in the list + else *endp = 0; // end of string + + dirp = opendir(p); + if (dirp == NULL) { +// printf("Warning: directory in ABC_LIB_PATH does not exist (%s).\n", p); + continue; + } + + while ((dp = readdir(dirp)) != NULL) { + if ((strncmp("libabc_", dp->d_name, 7) == 0) && + (strcmp(".so", dp->d_name + strlen(dp->d_name) - 3) == 0)) { + + // make sure we don't overflow the handle array + if (curr_lib >= MAX_LIBS) { + printf("Warning: maximum number of ABC libraries (%d) exceeded. Not loading %s.\n", + MAX_LIBS, + dp->d_name); + } + + // attempt to load it + else { + char* szPrefixed = malloc((strlen(dp->d_name) + strlen(p) + 2) * + sizeof(char)); + sprintf(szPrefixed, "%s/", p); + strcat(szPrefixed, dp->d_name); + libHandles[curr_lib] = dlopen(szPrefixed, RTLD_NOW | RTLD_LOCAL); + + // did the load succeed? + if (libHandles[curr_lib] != 0) { + printf("Loaded ABC library: %s (Abc library extension #%d)\n", szPrefixed, curr_lib); + curr_lib++; + } else { + printf("Warning: failed to load ABC library %s:\n\t%s\n", szPrefixed, dlerror()); + } + + free(szPrefixed); + } + } + } + closedir(dirp); + p = endp+1; + } + + free(init_p); +#endif + + // null terminate the list of handles + libHandles[curr_lib] = 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// This will close all open ABC library extensions +//////////////////////////////////////////////////////////////////////////////////////////////////// +void close_libs() { +#ifdef WIN32 + printf("Warning: close_libs WIN32 not implemented.\n"); +#else + int i; + for (i = 0; libHandles[i] != 0; i++) { + if (dlclose(libHandles[i]) != 0) { + printf("Warning: failed to close library %d\n", i); + } + libHandles[i] = 0; + } +#endif +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// This will get a pointer to a function inside of an open library +//////////////////////////////////////////////////////////////////////////////////////////////////// +void* get_fnct_ptr(int lib_num, char* sym_name) { +#ifdef WIN32 + printf("Warning: get_fnct_ptr WIN32 not implemented.\n"); + return 0; +#else + return dlsym(libHandles[lib_num], sym_name); +#endif +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// This will call an initialization function in every open library. +//////////////////////////////////////////////////////////////////////////////////////////////////// +void call_inits(Abc_Frame_t* pAbc) { + int i; + lib_init_end_func init_func; + for (i = 0; libHandles[i] != 0; i++) { + init_func = (lib_init_end_func) get_fnct_ptr(i, "abc_init"); + if (init_func == 0) { + printf("Warning: Failed to initialize library %d.\n", i); + } else { + (*init_func)(pAbc); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// This will call a shutdown function in every open library. +//////////////////////////////////////////////////////////////////////////////////////////////////// +void call_ends(Abc_Frame_t* pAbc) { + int i; + lib_init_end_func end_func; + for (i = 0; libHandles[i] != 0; i++) { + end_func = (lib_init_end_func) get_fnct_ptr(i, "abc_end"); + if (end_func == 0) { + printf("Warning: Failed to end library %d.\n", i); + } else { + (*end_func)(pAbc); + } + } +} + +void Libs_Init(Abc_Frame_t * pAbc) +{ + open_libs(); + call_inits(pAbc); +} + +void Libs_End(Abc_Frame_t * pAbc) +{ + call_ends(pAbc); + + // It's good practice to close our libraries at this point, but this can mess up any backtrace printed by Valgind. + // close_libs(); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/base/main/main.c b/abc70930/src/base/main/main.c new file mode 100644 index 00000000..8f43c605 --- /dev/null +++ b/abc70930/src/base/main/main.c @@ -0,0 +1,317 @@ +/**CFile**************************************************************** + + FileName [main.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [Here everything starts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: main.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" + +// this line should be included in the library project +//#define _LIB + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int TypeCheck( Abc_Frame_t * pAbc, char * s); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifndef _LIB + +/**Function************************************************************* + + Synopsis [The main() procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int main( int argc, char * argv[] ) +{ + Abc_Frame_t * pAbc; + char sCommandUsr[500], sCommandTmp[100], sReadCmd[20], sWriteCmd[20], c; + char * sCommand, * sOutFile, * sInFile; + int fStatus = 0; + bool fBatch, fInitSource, fInitRead, fFinalWrite; + + // added to detect memory leaks: +#ifdef _DEBUG + _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); +#endif + +// Npn_Experiment(); +// Npn_Generate(); + + // get global frame (singleton pattern) + // will be initialized on first call + pAbc = Abc_FrameGetGlobalFrame(); + + // default options + fBatch = 0; + fInitSource = 1; + fInitRead = 0; + fFinalWrite = 0; + sInFile = sOutFile = NULL; + sprintf( sReadCmd, "read" ); + sprintf( sWriteCmd, "write" ); + + Extra_UtilGetoptReset(); + while ((c = Extra_UtilGetopt(argc, argv, "c:hf:F:o:st:T:x")) != EOF) { + switch(c) { + case 'c': + strcpy( sCommandUsr, globalUtilOptarg ); + fBatch = 1; + break; + + case 'f': + sprintf(sCommandUsr, "source %s", globalUtilOptarg); + fBatch = 1; + break; + + case 'F': + sprintf(sCommandUsr, "source -x %s", globalUtilOptarg); + fBatch = 1; + break; + + case 'h': + goto usage; + break; + + case 'o': + sOutFile = globalUtilOptarg; + fFinalWrite = 1; + break; + + case 's': + fInitSource = 0; + break; + + case 't': + if ( TypeCheck( pAbc, globalUtilOptarg ) ) + { + if ( !strcmp(globalUtilOptarg, "none") == 0 ) + { + fInitRead = 1; + sprintf( sReadCmd, "read_%s", globalUtilOptarg ); + } + } + else { + goto usage; + } + fBatch = 1; + break; + + case 'T': + if ( TypeCheck( pAbc, globalUtilOptarg ) ) + { + if (!strcmp(globalUtilOptarg, "none") == 0) + { + fFinalWrite = 1; + sprintf( sWriteCmd, "write_%s", globalUtilOptarg); + } + } + else { + goto usage; + } + fBatch = 1; + break; + + case 'x': + fFinalWrite = 0; + fInitRead = 0; + fBatch = 1; + break; + + default: + goto usage; + } + } + + if ( fBatch ) + { + pAbc->fBatchMode = 1; + + if (argc - globalUtilOptind == 0) + { + sInFile = NULL; + } + else if (argc - globalUtilOptind == 1) + { + fInitRead = 1; + sInFile = argv[globalUtilOptind]; + } + else + { + Abc_UtilsPrintUsage( pAbc, argv[0] ); + } + + // source the resource file + if ( fInitSource ) + { + Abc_UtilsSource( pAbc ); + } + + fStatus = 0; + if ( fInitRead && sInFile ) + { + sprintf( sCommandTmp, "%s %s", sReadCmd, sInFile ); + fStatus = Cmd_CommandExecute( pAbc, sCommandTmp ); + } + + if ( fStatus == 0 ) + { + /* cmd line contains `source <file>' */ + fStatus = Cmd_CommandExecute( pAbc, sCommandUsr ); + if ( (fStatus == 0 || fStatus == -1) && fFinalWrite && sOutFile ) + { + sprintf( sCommandTmp, "%s %s", sWriteCmd, sOutFile ); + fStatus = Cmd_CommandExecute( pAbc, sCommandTmp ); + } + } + + } + else + { + // start interactive mode + // print the hello line + Abc_UtilsPrintHello( pAbc ); + + // source the resource file + if ( fInitSource ) + { + Abc_UtilsSource( pAbc ); + } + + // execute commands given by the user + while ( !feof(stdin) ) + { + // print command line prompt and + // get the command from the user + sCommand = Abc_UtilsGetUsersInput( pAbc ); + + // execute the user's command + fStatus = Cmd_CommandExecute( pAbc, sCommand ); + + // stop if the user quitted or an error occurred + if ( fStatus == -1 || fStatus == -2 ) + break; + } + } + + // if the memory should be freed, quit packages + if ( fStatus < 0 ) + { + Abc_Stop(); + } + return 0; + +usage: + Abc_UtilsPrintHello( pAbc ); + Abc_UtilsPrintUsage( pAbc, argv[0] ); + return 1; +} + +#endif + +/**Function************************************************************* + + Synopsis [Initialization procedure for the library project.] + + Description [Note that when Abc_Start() is run in a static library + project, it does not load the resource file by default. As a result, + ABC is not set up the same way, as when it is run on a command line. + For example, some error messages while parsing files will not be + produced, and intermediate networks will not be checked for consistancy. + One possibility is to load the resource file after Abc_Start() as follows: + Abc_UtilsSource( Abc_FrameGetGlobalFrame() );] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Start() +{ + Abc_Frame_t * pAbc; + // added to detect memory leaks: +#ifdef _DEBUG + _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); +#endif + // start the glocal frame + pAbc = Abc_FrameGetGlobalFrame(); + // source the resource file +// Abc_UtilsSource( pAbc ); +} + +/**Function************************************************************* + + Synopsis [Deallocation procedure for the library project.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Stop() +{ + Abc_Frame_t * pAbc; + pAbc = Abc_FrameGetGlobalFrame(); + // perform uninitializations + Abc_FrameEnd( pAbc ); + // stop the framework + Abc_FrameDeallocate( pAbc ); +} + +/**Function******************************************************************** + + Synopsis [Returns 1 if s is a file type recognized, else returns 0.] + + Description [Returns 1 if s is a file type recognized by ABC, else returns 0. + Recognized types are "blif", "bench", "pla", and "none".] + + SideEffects [] + +******************************************************************************/ +static int TypeCheck( Abc_Frame_t * pAbc, char * s ) +{ + if (strcmp(s, "blif") == 0) + return 1; + else if (strcmp(s, "bench") == 0) + return 1; + else if (strcmp(s, "pla") == 0) + return 1; + else if (strcmp(s, "none") == 0) + return 1; + else { + fprintf( pAbc->Err, "unknown type %s\n", s ); + return 0; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/main/main.h b/abc70930/src/base/main/main.h new file mode 100644 index 00000000..4433a8b4 --- /dev/null +++ b/abc70930/src/base/main/main.h @@ -0,0 +1,122 @@ +/**CFile**************************************************************** + + FileName [main.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [External declarations of the main package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: main.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __MAIN_H__ +#define __MAIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// TYPEDEFS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// the framework containing all data +typedef struct Abc_Frame_t_ Abc_Frame_t; + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +// this include should be the first one in the list +// it is used to catch memory leaks on Windows +#include "leaks.h" + +// data structure packages +#include "extra.h" +#include "vec.h" +#include "st.h" + +// core packages +#include "abc.h" +#include "cmd.h" +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== main.c ===========================================================*/ +extern void Abc_Start(); +extern void Abc_Stop(); + +/*=== mainFrame.c ===========================================================*/ +extern Abc_Ntk_t * Abc_FrameReadNtk( Abc_Frame_t * p ); +extern FILE * Abc_FrameReadOut( Abc_Frame_t * p ); +extern FILE * Abc_FrameReadErr( Abc_Frame_t * p ); +extern bool Abc_FrameReadMode( Abc_Frame_t * p ); +extern bool Abc_FrameSetMode( Abc_Frame_t * p, bool fNameMode ); +extern void Abc_FrameRestart( Abc_Frame_t * p ); +extern bool Abc_FrameShowProgress( Abc_Frame_t * p ); + +extern void Abc_FrameSetCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNet ); +extern void Abc_FrameSwapCurrentAndBackup( Abc_Frame_t * p ); +extern void Abc_FrameReplaceCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNet ); +extern void Abc_FrameUnmapAllNetworks( Abc_Frame_t * p ); +extern void Abc_FrameDeleteAllNetworks( Abc_Frame_t * p ); + +extern void Abc_FrameSetGlobalFrame( Abc_Frame_t * p ); +extern Abc_Frame_t * Abc_FrameGetGlobalFrame(); + +extern Vec_Ptr_t * Abc_FrameReadStore(); +extern int Abc_FrameReadStoreSize(); +extern void * Abc_FrameReadLibLut(); +extern void * Abc_FrameReadLibGen(); +extern void * Abc_FrameReadLibSuper(); +extern void * Abc_FrameReadLibVer(); +extern void * Abc_FrameReadManDd(); +extern void * Abc_FrameReadManDec(); +extern char * Abc_FrameReadFlag( char * pFlag ); +extern bool Abc_FrameIsFlagEnabled( char * pFlag ); + +extern void Abc_FrameSetNtkStore( Abc_Ntk_t * pNtk ); +extern void Abc_FrameSetNtkStoreSize( int nStored ); +extern void Abc_FrameSetLibLut( void * pLib ); +extern void Abc_FrameSetLibGen( void * pLib ); +extern void Abc_FrameSetLibSuper( void * pLib ); +extern void Abc_FrameSetLibVer( void * pLib ); +extern void Abc_FrameSetFlag( char * pFlag, char * pValue ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/base/main/mainFrame.c b/abc70930/src/base/main/mainFrame.c new file mode 100644 index 00000000..eae8b7a6 --- /dev/null +++ b/abc70930/src/base/main/mainFrame.c @@ -0,0 +1,503 @@ +/**CFile**************************************************************** + + FileName [mainFrame.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [The global framework resides in this file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mainFrame.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" +#include "abc.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Frame_t * s_GlobalFrame = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [APIs to access parameters in the flobal frame.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_FrameReadStore() { return s_GlobalFrame->vStore; } +int Abc_FrameReadStoreSize() { return Vec_PtrSize(s_GlobalFrame->vStore); } +void * Abc_FrameReadLibLut() { return s_GlobalFrame->pLibLut; } +void * Abc_FrameReadLibGen() { return s_GlobalFrame->pLibGen; } +void * Abc_FrameReadLibSuper() { return s_GlobalFrame->pLibSuper; } +void * Abc_FrameReadLibVer() { return s_GlobalFrame->pLibVer; } +void * Abc_FrameReadManDd() { if ( s_GlobalFrame->dd == NULL ) s_GlobalFrame->dd = Cudd_Init( 0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); return s_GlobalFrame->dd; } +void * Abc_FrameReadManDec() { if ( s_GlobalFrame->pManDec == NULL ) s_GlobalFrame->pManDec = Dec_ManStart(); return s_GlobalFrame->pManDec; } +char * Abc_FrameReadFlag( char * pFlag ) { return Cmd_FlagReadByName( s_GlobalFrame, pFlag ); } + +void Abc_FrameSetLibLut( void * pLib ) { s_GlobalFrame->pLibLut = pLib; } +void Abc_FrameSetLibGen( void * pLib ) { s_GlobalFrame->pLibGen = pLib; } +void Abc_FrameSetLibSuper( void * pLib ) { s_GlobalFrame->pLibSuper = pLib; } +void Abc_FrameSetLibVer( void * pLib ) { s_GlobalFrame->pLibVer = pLib; } +void Abc_FrameSetFlag( char * pFlag, char * pValue ) { Cmd_FlagUpdateValue( s_GlobalFrame, pFlag, pValue ); } + +/**Function************************************************************* + + Synopsis [Returns 1 if the flag is enabled without value or with value 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_FrameIsFlagEnabled( char * pFlag ) +{ + char * pValue; + // if flag is not defined, it is not enabled + pValue = Abc_FrameReadFlag( pFlag ); + if ( pValue == NULL ) + return 0; + // if flag is defined but value is not empty (no parameter) or "1", it is not enabled + if ( strcmp(pValue, "") && strcmp(pValue, "1") ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Frame_t * Abc_FrameAllocate() +{ + Abc_Frame_t * p; + extern void define_cube_size( int n ); + extern void set_espresso_flags(); + // allocate and clean + p = ALLOC( Abc_Frame_t, 1 ); + memset( p, 0, sizeof(Abc_Frame_t) ); + // get version + p->sVersion = Abc_UtilsGetVersion( p ); + // set streams + p->Err = stderr; + p->Out = stdout; + p->Hst = NULL; + // set the starting step + p->nSteps = 1; + p->fBatchMode = 0; + // networks to be used by choice + p->vStore = Vec_PtrAlloc( 16 ); + // initialize decomposition manager + define_cube_size(20); + set_espresso_flags(); + // initialize the trace manager +// Abc_HManStart(); + return p; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameDeallocate( Abc_Frame_t * p ) +{ + extern void Rwt_ManGlobalStop(); + extern void undefine_cube_size(); +// extern void Ivy_TruthManStop(); +// Abc_HManStop(); + undefine_cube_size(); + Rwt_ManGlobalStop(); +// Ivy_TruthManStop(); + if ( p->pLibVer ) Abc_LibFree( p->pLibVer, NULL ); + if ( p->pManDec ) Dec_ManStop( p->pManDec ); + if ( p->dd ) Extra_StopManager( p->dd ); + if ( p->vStore ) Vec_PtrFree( p->vStore ); + Abc_FrameDeleteAllNetworks( p ); + free( p ); + s_GlobalFrame = NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameRestart( Abc_Frame_t * p ) +{ +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_FrameShowProgress( Abc_Frame_t * p ) +{ + return Abc_FrameIsFlagEnabled( "progressbar" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_FrameReadNtk( Abc_Frame_t * p ) +{ + return p->pNtkCur; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +FILE * Abc_FrameReadOut( Abc_Frame_t * p ) +{ + return p->Out; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +FILE * Abc_FrameReadErr( Abc_Frame_t * p ) +{ + return p->Err; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_FrameReadMode( Abc_Frame_t * p ) +{ + int fShortNames; + char * pValue; + pValue = Cmd_FlagReadByName( p, "namemode" ); + if ( pValue == NULL ) + fShortNames = 0; + else + fShortNames = atoi(pValue); + return fShortNames; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_FrameSetMode( Abc_Frame_t * p, bool fNameMode ) +{ + char Buffer[2]; + bool fNameModeOld; + fNameModeOld = Abc_FrameReadMode( p ); + Buffer[0] = '0' + fNameMode; + Buffer[1] = 0; + Cmd_FlagUpdateValue( p, "namemode", (char *)Buffer ); + return fNameModeOld; +} + + +/**Function************************************************************* + + Synopsis [Sets the given network to be the current one.] + + Description [Takes the network and makes it the current network. + The previous current network is attached to the given network as + a backup copy. In the stack of backup networks contains too many + networks (defined by the paramater "savesteps"), the bottom + most network is deleted.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameSetCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNtkNew ) +{ + Abc_Ntk_t * pNtk, * pNtk2, * pNtk3; + int nNetsPresent; + int nNetsToSave; + char * pValue; + + // link it to the previous network + Abc_NtkSetBackup( pNtkNew, p->pNtkCur ); + // set the step of this network + Abc_NtkSetStep( pNtkNew, ++p->nSteps ); + // set this network to be the current network + p->pNtkCur = pNtkNew; + + // remove any extra network that may happen to be in the stack + pValue = Cmd_FlagReadByName( p, "savesteps" ); + // if the value of steps to save is not set, assume 1-level undo + if ( pValue == NULL ) + nNetsToSave = 1; + else + nNetsToSave = atoi(pValue); + + // count the network, remember the last one, and the one before the last one + nNetsPresent = 0; + pNtk2 = pNtk3 = NULL; + for ( pNtk = p->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk2) ) + { + nNetsPresent++; + pNtk3 = pNtk2; + pNtk2 = pNtk; + } + + // remove the earliest backup network if it is more steps away than we store + if ( nNetsPresent - 1 > nNetsToSave ) + { // delete the last network + Abc_NtkDelete( pNtk2 ); + // clean the pointer of the network before the last one + Abc_NtkSetBackup( pNtk3, NULL ); + } +} + +/**Function************************************************************* + + Synopsis [This procedure swaps the current and the backup network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameSwapCurrentAndBackup( Abc_Frame_t * p ) +{ + Abc_Ntk_t * pNtkCur, * pNtkBack, * pNtkBack2; + int iStepCur, iStepBack; + + pNtkCur = p->pNtkCur; + pNtkBack = Abc_NtkBackup( pNtkCur ); + iStepCur = Abc_NtkStep ( pNtkCur ); + + // if there is no backup nothing to reset + if ( pNtkBack == NULL ) + return; + + // remember the backup of the backup + pNtkBack2 = Abc_NtkBackup( pNtkBack ); + iStepBack = Abc_NtkStep ( pNtkBack ); + + // set pNtkCur to be the next after the backup's backup + Abc_NtkSetBackup( pNtkCur, pNtkBack2 ); + Abc_NtkSetStep ( pNtkCur, iStepBack ); + + // set pNtkCur to be the next after the backup + Abc_NtkSetBackup( pNtkBack, pNtkCur ); + Abc_NtkSetStep ( pNtkBack, iStepCur ); + + // set the current network + p->pNtkCur = pNtkBack; +} + + +/**Function************************************************************* + + Synopsis [Replaces the current network by the given one.] + + Description [This procedure does not modify the stack of saved + networks.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameReplaceCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNtk ) +{ + if ( pNtk == NULL ) + return; + + // transfer the parameters to the new network + if ( p->pNtkCur && Abc_FrameIsFlagEnabled( "backup" ) ) + { + Abc_NtkSetBackup( pNtk, Abc_NtkBackup(p->pNtkCur) ); + Abc_NtkSetStep( pNtk, Abc_NtkStep(p->pNtkCur) ); + // delete the current network + Abc_NtkDelete( p->pNtkCur ); + } + else + { + Abc_NtkSetBackup( pNtk, NULL ); + Abc_NtkSetStep( pNtk, ++p->nSteps ); + // delete the current network if present but backup is disabled + if ( p->pNtkCur ) + Abc_NtkDelete( p->pNtkCur ); + } + // set the new current network + p->pNtkCur = pNtk; +} + +/**Function************************************************************* + + Synopsis [Removes library binding of all currently stored networks.] + + Description [This procedure is called when the library is freed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameUnmapAllNetworks( Abc_Frame_t * p ) +{ + Abc_Ntk_t * pNtk; + for ( pNtk = p->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk) ) + if ( Abc_NtkHasMapping(pNtk) ) + Abc_NtkMapToSop( pNtk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameDeleteAllNetworks( Abc_Frame_t * p ) +{ + Abc_Ntk_t * pNtk, * pNtk2; + // delete all the currently saved networks + for ( pNtk = p->pNtkCur, + pNtk2 = pNtk? Abc_NtkBackup(pNtk): NULL; + pNtk; + pNtk = pNtk2, + pNtk2 = pNtk? Abc_NtkBackup(pNtk): NULL ) + Abc_NtkDelete( pNtk ); + // set the current network empty + p->pNtkCur = NULL; +// fprintf( p->Out, "All networks have been deleted.\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameSetGlobalFrame( Abc_Frame_t * p ) +{ + s_GlobalFrame = p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Frame_t * Abc_FrameGetGlobalFrame() +{ + if ( s_GlobalFrame == 0 ) + { + // start the framework + s_GlobalFrame = Abc_FrameAllocate(); + // perform initializations + Abc_FrameInit( s_GlobalFrame ); + } + return s_GlobalFrame; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/main/mainInit.c b/abc70930/src/base/main/mainInit.c new file mode 100644 index 00000000..03953e5b --- /dev/null +++ b/abc70930/src/base/main/mainInit.c @@ -0,0 +1,100 @@ +/**CFile**************************************************************** + + FileName [mainInit.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [Initialization procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mainInit.c,v 1.3 2005/09/14 22:53:37 casem Exp $] + +***********************************************************************/ + +#include "mainInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Abc_Init( Abc_Frame_t * pAbc ); +extern void Abc_End ( Abc_Frame_t * pAbc ); +extern void Io_Init( Abc_Frame_t * pAbc ); +extern void Io_End ( Abc_Frame_t * pAbc ); +extern void Cmd_Init( Abc_Frame_t * pAbc ); +extern void Cmd_End ( Abc_Frame_t * pAbc ); +extern void Fpga_Init( Abc_Frame_t * pAbc ); +extern void Fpga_End ( Abc_Frame_t * pAbc ); +extern void Map_Init( Abc_Frame_t * pAbc ); +extern void Map_End ( Abc_Frame_t * pAbc ); +extern void Mio_Init( Abc_Frame_t * pAbc ); +extern void Mio_End ( Abc_Frame_t * pAbc ); +extern void Super_Init( Abc_Frame_t * pAbc ); +extern void Super_End ( Abc_Frame_t * pAbc ); +extern void Libs_Init(Abc_Frame_t * pAbc); +extern void Libs_End(Abc_Frame_t * pAbc); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts all the packages.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameInit( Abc_Frame_t * pAbc ) +{ + Cmd_Init( pAbc ); + Io_Init( pAbc ); + Abc_Init( pAbc ); + Fpga_Init( pAbc ); + Map_Init( pAbc ); + Mio_Init( pAbc ); + Super_Init( pAbc ); + Libs_Init( pAbc ); +} + + +/**Function************************************************************* + + Synopsis [Stops all the packages.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameEnd( Abc_Frame_t * pAbc ) +{ + Abc_End( pAbc ); + Io_End( pAbc ); + Cmd_End( pAbc ); + Fpga_End( pAbc ); + Map_End( pAbc ); + Mio_End( pAbc ); + Super_End( pAbc ); + Libs_End( pAbc ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/main/mainInt.h b/abc70930/src/base/main/mainInt.h new file mode 100644 index 00000000..09ad96f3 --- /dev/null +++ b/abc70930/src/base/main/mainInt.h @@ -0,0 +1,109 @@ +/**CFile**************************************************************** + + FileName [mainInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [Internal declarations of the main package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mainInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __MAIN_INT_H__ +#define __MAIN_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "main.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// the current version +#define ABC_VERSION "UC Berkeley, ABC 1.01" + +// the maximum length of an input line +#define MAX_STR 32768 + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Abc_Frame_t_ +{ + // general info + char * sVersion; // the name of the current version + // commands, aliases, etc + st_table * tCommands; // the command table + st_table * tAliases; // the alias table + st_table * tFlags; // the flag table + Vec_Ptr_t * aHistory; // the command history + // the functionality + Abc_Ntk_t * pNtkCur; // the current network + int nSteps; // the counter of different network processed + int fAutoexac; // marks the autoexec mode + int fBatchMode; // are we invoked in batch mode? + // output streams + FILE * Out; + FILE * Err; + FILE * Hst; + // used for runtime measurement + int TimeCommand; // the runtime of the last command + int TimeTotal; // the total runtime of all commands + // temporary storage for structural choices + Vec_Ptr_t * vStore; // networks to be used by choice + // decomposition package + void * pManDec; // decomposition manager + DdManager * dd; // temporary BDD package + // libraries for mapping + void * pLibLut; // the current LUT library + void * pLibGen; // the current genlib + void * pLibSuper; // the current supergate library + void * pLibVer; // the current Verilog library +}; + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== mvMain.c ===========================================================*/ +extern int main( int argc, char * argv[] ); +/*=== mvInit.c ===================================================*/ +extern void Abc_FrameInit( Abc_Frame_t * pAbc ); +extern void Abc_FrameEnd( Abc_Frame_t * pAbc ); +/*=== mvFrame.c =====================================================*/ +extern Abc_Frame_t * Abc_FrameAllocate(); +extern void Abc_FrameDeallocate( Abc_Frame_t * p ); +/*=== mvUtils.c =====================================================*/ +extern char * Abc_UtilsGetVersion( Abc_Frame_t * pAbc ); +extern char * Abc_UtilsGetUsersInput( Abc_Frame_t * pAbc ); +extern void Abc_UtilsPrintHello( Abc_Frame_t * pAbc ); +extern void Abc_UtilsPrintUsage( Abc_Frame_t * pAbc, char * ProgName ); +extern void Abc_UtilsSource( Abc_Frame_t * pAbc ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/base/main/mainUtils.c b/abc70930/src/base/main/mainUtils.c new file mode 100644 index 00000000..58cc33ec --- /dev/null +++ b/abc70930/src/base/main/mainUtils.c @@ -0,0 +1,277 @@ +/**CFile**************************************************************** + + FileName [mainUtils.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [Miscellaneous utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mainUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" + +#ifndef _WIN32 +#include "readline/readline.h" +#endif + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// +static char * DateReadFromDateString(char * datestr); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_UtilsGetVersion( Abc_Frame_t * pAbc ) +{ + static char Version[1000]; + sprintf(Version, "%s (compiled %s %s)", ABC_VERSION, __DATE__, __TIME__); + return Version; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_UtilsGetUsersInput( Abc_Frame_t * pAbc ) +{ + static char Buffer[1000], Prompt[1000]; + sprintf( Prompt, "abc %02d> ", pAbc->nSteps ); +#ifdef _WIN32 + fprintf( pAbc->Out, "%s", Prompt ); + fgets( Buffer, 999, stdin ); + return Buffer; +#else + static char* line = NULL; + if (line != NULL) free(line); + line = readline(Prompt); + if (line == NULL){ printf("***EOF***\n"); exit(0); } + add_history(line); + return line; +#endif +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_UtilsPrintHello( Abc_Frame_t * pAbc ) +{ + fprintf( pAbc->Out, "%s\n", pAbc->sVersion ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_UtilsPrintUsage( Abc_Frame_t * pAbc, char * ProgName ) +{ + fprintf( pAbc->Err, "\n" ); + fprintf( pAbc->Err, + "usage: %s [-c cmd] [-f script] [-h] [-o file] [-s] [-t type] [-T type] [-x] [file]\n", + ProgName); + fprintf( pAbc->Err, " -c cmd\texecute commands `cmd'\n"); + fprintf( pAbc->Err, " -F script\texecute commands from a script file and echo commands\n"); + fprintf( pAbc->Err, " -f script\texecute commands from a script file\n"); + fprintf( pAbc->Err, " -h\t\tprint the command usage\n"); + fprintf( pAbc->Err, " -o file\tspecify output filename to store the result\n"); + fprintf( pAbc->Err, " -s\t\tdo not read any initialization file\n"); + fprintf( pAbc->Err, " -t type\tspecify input type (blif_mv (default), blif_mvs, blif, or none)\n"); + fprintf( pAbc->Err, " -T type\tspecify output type (blif_mv (default), blif_mvs, blif, or none)\n"); + fprintf( pAbc->Err, " -x\t\tequivalent to '-t none -T none'\n"); + fprintf( pAbc->Err, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_UtilsSource( Abc_Frame_t * pAbc ) +{ +#ifdef WIN32 + if ( Cmd_CommandExecute(pAbc, "source abc.rc") ) + { + if ( Cmd_CommandExecute(pAbc, "source ..\\abc.rc") == 0 ) + printf( "Loaded \"abc.rc\" from the parent directory.\n" ); + else if ( Cmd_CommandExecute(pAbc, "source ..\\..\\abc.rc") == 0 ) + printf( "Loaded \"abc.rc\" from the grandparent directory.\n" ); + } +#else + +#if 0 + { + char * sPath1, * sPath2; + + // If .rc is present in both the home and current directories, then read + // it from the home directory. Otherwise, read it from wherever it's located. + sPath1 = Extra_UtilFileSearch(".rc", "~/", "r"); + sPath2 = Extra_UtilFileSearch(".rc", ".", "r"); + + if ( sPath1 && sPath2 ) { + /* ~/.rc == .rc : Source the file only once */ + (void) Cmd_CommandExecute(pAbc, "source -s ~/.rc"); + } + else { + if (sPath1) { + (void) Cmd_CommandExecute(pAbc, "source -s ~/.rc"); + } + if (sPath2) { + (void) Cmd_CommandExecute(pAbc, "source -s .rc"); + } + } + if ( sPath1 ) FREE(sPath1); + if ( sPath2 ) FREE(sPath2); + + /* execute the abc script which can be open with the "open_path" */ + Cmd_CommandExecute( pAbc, "source -s abc.rc" ); + } +#endif + + { + char * sPath1, * sPath2; + char * home; + + // If .rc is present in both the home and current directories, then read + // it from the home directory. Otherwise, read it from wherever it's located. + home = getenv("HOME"); + if (home){ + char * sPath3 = ALLOC(char, strlen(home) + 2); + (void) sprintf(sPath3, "%s/", home); + sPath1 = Extra_UtilFileSearch(".abc.rc", sPath3, "r"); + FREE(sPath3); + }else + sPath1 = NULL; + + sPath2 = Extra_UtilFileSearch(".abc.rc", ".", "r"); + + if ( sPath1 && sPath2 ) { + /* ~/.rc == .rc : Source the file only once */ + (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc"); + } + else { + if (sPath1) { + (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc"); + } + if (sPath2) { + (void) Cmd_CommandExecute(pAbc, "source -s .abc.rc"); + } + } + if ( sPath1 ) FREE(sPath1); + if ( sPath2 ) FREE(sPath2); + + /* execute the abc script which can be open with the "open_path" */ + Cmd_CommandExecute( pAbc, "source -s abc.rc" ); + } + +#endif //WIN32 + { + // reset command history + char * pName; + int i; + Vec_PtrForEachEntry( pAbc->aHistory, pName, i ) + free( pName ); + pAbc->aHistory->nSize = 0; + } +} + +/**Function******************************************************************** + + Synopsis [Returns the date in a brief format assuming its coming from + the program `date'.] + + Description [optional] + + SideEffects [] + +******************************************************************************/ +char * +DateReadFromDateString( + char * datestr) +{ + static char result[25]; + char day[10]; + char month[10]; + char zone[10]; + char *at; + int date; + int hour; + int minute; + int second; + int year; + + if (sscanf(datestr, "%s %s %2d %2d:%2d:%2d %s %4d", + day, month, &date, &hour, &minute, &second, zone, &year) == 8) { + if (hour >= 12) { + if (hour >= 13) hour -= 12; + at = "PM"; + } + else { + if (hour == 0) hour = 12; + at = "AM"; + } + (void) sprintf(result, "%d-%3s-%02d at %d:%02d %s", + date, month, year % 100, hour, minute, at); + return result; + } + else { + return datestr; + } +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/main/module.make b/abc70930/src/base/main/module.make new file mode 100644 index 00000000..367f89f6 --- /dev/null +++ b/abc70930/src/base/main/module.make @@ -0,0 +1,5 @@ +SRC += src/base/main/main.c \ + src/base/main/mainFrame.c \ + src/base/main/mainInit.c \ + src/base/main/libSupport.c \ + src/base/main/mainUtils.c diff --git a/abc70930/src/base/temp.c b/abc70930/src/base/temp.c new file mode 100644 index 00000000..55709247 --- /dev/null +++ b/abc70930/src/base/temp.c @@ -0,0 +1,83 @@ + +/**Function************************************************************* + + Synopsis [Command procedure to allow for static BDD variable ordering.] + + Description [This procedure should be integrated in "abc\src\base\abci\abc.c" + similar to how procedure Abc_CommandReorder() is currently integrated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandOrder( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr, * pFile; + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + int fReverse; + int fVerbose; + extern void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose ); + extern void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fReverse = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) + { + switch ( c ) + { + case 'r': + fReverse ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // if the var order file is given, implement this order + pFileName = NULL; + if ( argc == globalUtilOptind + 1 ) + { + pFileName = argv[globalUtilOptind]; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + fprintf( pErr, "Cannot open file \"%s\" with the BDD variable order.\n", pFileName ); + return 1; + } + fclose( pFile ); + } + if ( pFileName ) + Abc_NtkImplementCiOrder( pNtk, pFileName, fReverse, fVerbose ); + else + Abc_NtkFindCiOrder( pNtk, fReverse, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: order [-rvh] <file>\n" ); + fprintf( pErr, "\t computes a good static CI variable order\n" ); + fprintf( pErr, "\t-r : toggle reverse ordering [default = %s]\n", fReverse? "yes": "no" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t<file> : (optional) file with the given variable order\n" ); + return 1; +} diff --git a/abc70930/src/base/ver/module.make b/abc70930/src/base/ver/module.make new file mode 100644 index 00000000..2cc37803 --- /dev/null +++ b/abc70930/src/base/ver/module.make @@ -0,0 +1,4 @@ +SRC += src/base/ver/verCore.c \ + src/base/ver/verFormula.c \ + src/base/ver/verParse.c \ + src/base/ver/verStream.c diff --git a/abc70930/src/base/ver/ver.h b/abc70930/src/base/ver/ver.h new file mode 100644 index 00000000..9c538ac4 --- /dev/null +++ b/abc70930/src/base/ver/ver.h @@ -0,0 +1,118 @@ +/**CFile**************************************************************** + + FileName [ver.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: ver.h,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __VER_H__ +#define __VER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include <stdio.h> +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ver_Man_t_ Ver_Man_t; +typedef struct Ver_Stream_t_ Ver_Stream_t; + +struct Ver_Man_t_ +{ + // internal parameters + int fMapped; // mapped verilog + int fUseMemMan; // allocate memory manager in the networks + int fCheck; // checks network for currectness + // input file stream + char * pFileName; + Ver_Stream_t * pReader; + int fNameLast; + ProgressBar * pProgress; + // current design + Abc_Lib_t * pDesign; + st_table * tName2Suffix; + // error handling + FILE * Output; + int fTopLevel; + int fError; + char sError[2000]; + // intermediate structures + Vec_Ptr_t * vNames; + Vec_Ptr_t * vStackFn; + Vec_Int_t * vStackOp; + Vec_Int_t * vPerm; +}; + + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== verCore.c ========================================================*/ +extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); +extern void Ver_ParsePrintErrorMessage( Ver_Man_t * p ); +/*=== verFormula.c ========================================================*/ +extern void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage ); +extern void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage ); +/*=== verParse.c ========================================================*/ +extern int Ver_ParseSkipComments( Ver_Man_t * p ); +extern char * Ver_ParseGetName( Ver_Man_t * p ); +/*=== verStream.c ========================================================*/ +extern Ver_Stream_t * Ver_StreamAlloc( char * pFileName ); +extern void Ver_StreamFree( Ver_Stream_t * p ); +extern char * Ver_StreamGetFileName( Ver_Stream_t * p ); +extern int Ver_StreamGetFileSize( Ver_Stream_t * p ); +extern int Ver_StreamGetCurPosition( Ver_Stream_t * p ); +extern int Ver_StreamGetLineNumber( Ver_Stream_t * p ); + +extern int Ver_StreamIsOkey( Ver_Stream_t * p ); +extern char Ver_StreamScanChar( Ver_Stream_t * p ); +extern char Ver_StreamPopChar( Ver_Stream_t * p ); +extern void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip ); +extern void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop ); +extern char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/base/ver/verCore.c b/abc70930/src/base/ver/verCore.c new file mode 100644 index 00000000..7a217fd7 --- /dev/null +++ b/abc70930/src/base/ver/verCore.c @@ -0,0 +1,2840 @@ +/**CFile**************************************************************** + + FileName [verCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Parses several flavors of structural Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verCore.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" +#include "mio.h" +#include "main.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// types of verilog signals +typedef enum { + VER_SIG_NONE = 0, + VER_SIG_INPUT, + VER_SIG_OUTPUT, + VER_SIG_INOUT, + VER_SIG_REG, + VER_SIG_WIRE +} Ver_SignalType_t; + +// types of verilog gates +typedef enum { + VER_GATE_AND = 0, + VER_GATE_OR, + VER_GATE_XOR, + VER_GATE_BUF, + VER_GATE_NAND, + VER_GATE_NOR, + VER_GATE_XNOR, + VER_GATE_NOT +} Ver_GateType_t; + +static Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib ); +static void Ver_ParseStop( Ver_Man_t * p ); +static void Ver_ParseFreeData( Ver_Man_t * p ); +static void Ver_ParseInternal( Ver_Man_t * p ); +static int Ver_ParseModule( Ver_Man_t * p ); +static int Ver_ParseSignal( Ver_Man_t * p, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType ); +static int Ver_ParseAlways( Ver_Man_t * p, Abc_Ntk_t * pNtk ); +static int Ver_ParseInitial( Ver_Man_t * p, Abc_Ntk_t * pNtk ); +static int Ver_ParseAssign( Ver_Man_t * p, Abc_Ntk_t * pNtk ); +static int Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateType_t GateType ); +static int Ver_ParseGate( Ver_Man_t * p, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate ); +static int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox ); +static int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox ); +static int Ver_ParseAttachBoxes( Ver_Man_t * pMan ); + +static Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName ); +static Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName ); +static Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO ); +static Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ); + +static void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan ); + +static inline int Ver_NtkIsDefined( Abc_Ntk_t * pNtkBox ) { assert( pNtkBox->pName ); return Abc_NtkPiNum(pNtkBox) || Abc_NtkPoNum(pNtkBox); } +static inline int Ver_ObjIsConnected( Abc_Obj_t * pObj ) { assert( Abc_ObjIsBox(pObj) ); return Abc_ObjFaninNum(pObj) || Abc_ObjFanoutNum(pObj); } + +int glo_fMapped = 0; // this is bad! + +typedef struct Ver_Bundle_t_ Ver_Bundle_t; +struct Ver_Bundle_t_ +{ + char * pNameFormal; // the name of the formal net + Vec_Ptr_t * vNetsActual; // the vector of actual nets (MSB to LSB) +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib ) +{ + Ver_Man_t * p; + p = ALLOC( Ver_Man_t, 1 ); + memset( p, 0, sizeof(Ver_Man_t) ); + p->pFileName = pFileName; + p->pReader = Ver_StreamAlloc( pFileName ); + if ( p->pReader == NULL ) + return NULL; + p->Output = stdout; + p->vNames = Vec_PtrAlloc( 100 ); + p->vStackFn = Vec_PtrAlloc( 100 ); + p->vStackOp = Vec_IntAlloc( 100 ); + p->vPerm = Vec_IntAlloc( 100 ); + // create the design library and assign the technology library + p->pDesign = Abc_LibCreate( pFileName ); + p->pDesign->pLibrary = pGateLib; + p->pDesign->pGenlib = Abc_FrameReadLibGen(); + return p; +} + +/**Function************************************************************* + + Synopsis [Stop parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseStop( Ver_Man_t * p ) +{ + if ( p->pProgress ) + Extra_ProgressBarStop( p->pProgress ); + Ver_StreamFree( p->pReader ); + Vec_PtrFree( p->vNames ); + Vec_PtrFree( p->vStackFn ); + Vec_IntFree( p->vStackOp ); + Vec_IntFree( p->vPerm ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [File parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ) +{ + Ver_Man_t * p; + Abc_Lib_t * pDesign; + // start the parser + p = Ver_ParseStart( pFileName, pGateLib ); + p->fMapped = glo_fMapped; + p->fCheck = fCheck; + p->fUseMemMan = fUseMemMan; + if ( glo_fMapped ) + { + Hop_ManStop(p->pDesign->pManFunc); + p->pDesign->pManFunc = NULL; + } + // parse the file + Ver_ParseInternal( p ); + // save the result + pDesign = p->pDesign; + p->pDesign = NULL; + // stop the parser + Ver_ParseStop( p ); + return pDesign; +} + +/**Function************************************************************* + + Synopsis [File parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseInternal( Ver_Man_t * pMan ) +{ + Abc_Ntk_t * pNtk; + char * pToken; + int i; + + // preparse the modeles + pMan->pProgress = Extra_ProgressBarStart( stdout, Ver_StreamGetFileSize(pMan->pReader) ); + while ( 1 ) + { + // get the next token + pToken = Ver_ParseGetName( pMan ); + if ( pToken == NULL ) + break; + if ( strcmp( pToken, "module" ) ) + { + sprintf( pMan->sError, "Cannot read \"module\" directive." ); + Ver_ParsePrintErrorMessage( pMan ); + return; + } + // parse the module + if ( !Ver_ParseModule(pMan) ) + return; + } + Extra_ProgressBarStop( pMan->pProgress ); + pMan->pProgress = NULL; + + // process defined and undefined boxes + if ( !Ver_ParseAttachBoxes( pMan ) ) + return; + + // connect the boxes and check + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + // fix the dangling nets + Abc_NtkFinalizeRead( pNtk ); + // check the network for correctness + if ( pMan->fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + pMan->fTopLevel = 1; + sprintf( pMan->sError, "The network check has failed for network %s.", pNtk->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return; + } + } +} + +/**Function************************************************************* + + Synopsis [File parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseFreeData( Ver_Man_t * p ) +{ + if ( p->pDesign ) + { + Abc_LibFree( p->pDesign, NULL ); + p->pDesign = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Prints the error message including the file name and line number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParsePrintErrorMessage( Ver_Man_t * p ) +{ + p->fError = 1; + if ( p->fTopLevel ) // the line number is not given + fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); + else // print the error message with the line number + fprintf( p->Output, "%s (line %d): %s\n", + p->pFileName, Ver_StreamGetLineNumber(p->pReader), p->sError ); + // free the data + Ver_ParseFreeData( p ); +} + +/**Function************************************************************* + + Synopsis [Finds the network by name or create a new blackbox network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Ver_ParseFindOrCreateNetwork( Ver_Man_t * pMan, char * pName ) +{ + Abc_Ntk_t * pNtkNew; + // check if the network exists + if ( pNtkNew = Abc_LibFindModelByName( pMan->pDesign, pName ) ) + return pNtkNew; +//printf( "Creating network %s.\n", pName ); + // create new network + pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, pMan->fUseMemMan ); + pNtkNew->pName = Extra_UtilStrsav( pName ); + pNtkNew->pSpec = NULL; + // add module to the design + Abc_LibAddModel( pMan->pDesign, pNtkNew ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Finds the network by name or create a new blackbox network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ver_ParseFindNet( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pObj; + if ( pObj = Abc_NtkFindNet(pNtk, pName) ) + return pObj; + if ( !strcmp( pName, "1\'b0" ) || !strcmp( pName, "1\'bx" ) ) + return Abc_NtkFindOrCreateNet( pNtk, "1\'b0" ); + if ( !strcmp( pName, "1\'b1" ) ) + return Abc_NtkFindOrCreateNet( pNtk, "1\'b1" ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the blackbox type into a different one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseConvertNetwork( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, int fMapped ) +{ + if ( fMapped ) + { + // convert from the blackbox into the network with local functions representated by AIGs + if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) + { + // change network type + assert( pNtk->pManFunc == NULL ); + pNtk->ntkFunc = ABC_FUNC_MAP; + pNtk->pManFunc = pMan->pDesign->pGenlib; + } + else if ( pNtk->ntkFunc != ABC_FUNC_MAP ) + { + sprintf( pMan->sError, "The network %s appears to have both gates and assign statements. Currently such network are not allowed. One way to fix this problem might be to replace assigns by buffers from the library.", pNtk->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + else + { + // convert from the blackbox into the network with local functions representated by AIGs + if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) + { + // change network type + assert( pNtk->pManFunc == NULL ); + pNtk->ntkFunc = ABC_FUNC_AIG; + pNtk->pManFunc = pMan->pDesign->pManFunc; + } + else if ( pNtk->ntkFunc != ABC_FUNC_AIG ) + { + sprintf( pMan->sError, "The network %s appears to have both gates and assign statements. Currently such network are not allowed. One way to fix this problem might be to replace assigns by buffers from the library.", pNtk->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one Verilog module.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseModule( Ver_Man_t * pMan ) +{ + Mio_Gate_t * pGate; + Ver_Stream_t * p = pMan->pReader; + Abc_Ntk_t * pNtk, * pNtkTemp; + char * pWord, Symbol; + int RetValue; + + // get the network name + pWord = Ver_ParseGetName( pMan ); + + // get the network with this name + pNtk = Ver_ParseFindOrCreateNetwork( pMan, pWord ); + + // make sure we stopped at the opening paranthesis + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot find \"(\" after \"module\" in network %s.", pNtk->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // skip to the end of parantheses + do { + if ( Ver_ParseGetName( pMan ) == NULL ) + return 0; + Symbol = Ver_StreamPopChar(p); + } while ( Symbol == ',' ); + assert( Symbol == ')' ); + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + Symbol = Ver_StreamPopChar(p); + if ( Symbol != ';' ) + { + sprintf( pMan->sError, "Expected closing paranthesis after \"module\"." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // parse the inputs/outputs/registers/wires/inouts + while ( 1 ) + { + Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL ); + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + if ( !strcmp( pWord, "input" ) ) + RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_INPUT ); + else if ( !strcmp( pWord, "output" ) ) + RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_OUTPUT ); + else if ( !strcmp( pWord, "reg" ) ) + RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_REG ); + else if ( !strcmp( pWord, "wire" ) ) + RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_WIRE ); + else if ( !strcmp( pWord, "inout" ) ) + RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_INOUT ); + else + break; + if ( RetValue == 0 ) + return 0; + } + + // parse the remaining statements + while ( 1 ) + { + Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL ); + + if ( !strcmp( pWord, "and" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_AND ); + else if ( !strcmp( pWord, "or" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_OR ); + else if ( !strcmp( pWord, "xor" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_XOR ); + else if ( !strcmp( pWord, "buf" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_BUF ); + else if ( !strcmp( pWord, "nand" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NAND ); + else if ( !strcmp( pWord, "nor" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NOR ); + else if ( !strcmp( pWord, "xnor" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_XNOR ); + else if ( !strcmp( pWord, "not" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NOT ); + + else if ( !strcmp( pWord, "assign" ) ) + RetValue = Ver_ParseAssign( pMan, pNtk ); + else if ( !strcmp( pWord, "always" ) ) + RetValue = Ver_ParseAlways( pMan, pNtk ); + else if ( !strcmp( pWord, "initial" ) ) + RetValue = Ver_ParseInitial( pMan, pNtk ); + else if ( !strcmp( pWord, "endmodule" ) ) + break; + else if ( pMan->pDesign->pGenlib && (pGate = Mio_LibraryReadGateByName(pMan->pDesign->pGenlib, pWord)) ) // current design + RetValue = Ver_ParseGate( pMan, pNtk, pGate ); +// else if ( pMan->pDesign->pLibrary && st_lookup(pMan->pDesign->pLibrary->tModules, pWord, (char**)&pNtkTemp) ) // gate library +// RetValue = Ver_ParseGate( pMan, pNtkTemp ); + else // assume this is the box used in the current design + { + pNtkTemp = Ver_ParseFindOrCreateNetwork( pMan, pWord ); + RetValue = Ver_ParseBox( pMan, pNtk, pNtkTemp ); + } + if ( RetValue == 0 ) + return 0; + // skip the comments + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + // get new word + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + } + + // convert from the blackbox into the network with local functions representated by AIGs + if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) + { + if ( Abc_NtkNodeNum(pNtk) > 0 || Abc_NtkBoxNum(pNtk) > 0 ) + { + if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) ) + return 0; + } + else + { + Abc_Obj_t * pObj, * pBox, * pTerm; + int i; + pBox = Abc_NtkCreateBlackbox(pNtk); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + pTerm = Abc_NtkCreateBi(pNtk); + Abc_ObjAddFanin( pTerm, Abc_ObjFanout0(pObj) ); + Abc_ObjAddFanin( pBox, pTerm ); + } + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pTerm = Abc_NtkCreateBo(pNtk); + Abc_ObjAddFanin( pTerm, pBox ); + Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pTerm ); + } + } + } + + // remove the table if needed + Ver_ParseRemoveSuffixTable( pMan ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Lookups the suffix of the signal of the form [m:n].] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseLookupSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb ) +{ + unsigned Value; + *pnMsb = *pnLsb = -1; + if ( pMan->tName2Suffix == NULL ) + return 1; + if ( !st_lookup( pMan->tName2Suffix, (char *)pWord, (char **)&Value ) ) + return 1; + *pnMsb = (Value >> 8) & 0xff; + *pnLsb = Value & 0xff; + return 1; +} + +/**Function************************************************************* + + Synopsis [Lookups the suffix of the signal of the form [m:n].] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseInsertsSuffix( Ver_Man_t * pMan, char * pWord, int nMsb, int nLsb ) +{ + unsigned Value; + if ( pMan->tName2Suffix == NULL ) + pMan->tName2Suffix = st_init_table( strcmp, st_strhash ); + if ( st_is_member( pMan->tName2Suffix, pWord ) ) + return 1; + assert( nMsb >= 0 && nMsb < 128 ); + assert( nLsb >= 0 && nLsb < 128 ); + Value = (nMsb << 8) | nLsb; + st_insert( pMan->tName2Suffix, Extra_UtilStrsav(pWord), (char *)Value ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Lookups the suffic of the signal of the form [m:n].] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan ) +{ + st_generator * gen; + char * pKey, * pValue; + if ( pMan->tName2Suffix == NULL ) + return; + st_foreach_item( pMan->tName2Suffix, gen, (char **)&pKey, (char **)&pValue ) + free( pKey ); + st_free_table( pMan->tName2Suffix ); + pMan->tName2Suffix = NULL; +} + +/**Function************************************************************* + + Synopsis [Determine signal prefix of the form [Beg:End].] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseSignalPrefix( Ver_Man_t * pMan, char ** ppWord, int * pnMsb, int * pnLsb ) +{ + char * pWord = *ppWord; + int nMsb, nLsb; + assert( pWord[0] == '[' ); + // get the beginning + nMsb = atoi( pWord + 1 ); + // find the splitter + while ( *pWord && *pWord != ':' && *pWord != ']' ) + pWord++; + if ( *pWord == 0 ) + { + sprintf( pMan->sError, "Cannot find closing bracket in this line." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + if ( *pWord == ']' ) + nLsb = nMsb; + else + { + assert( *pWord == ':' ); + nLsb = atoi( pWord + 1 ); + // find the closing paranthesis + while ( *pWord && *pWord != ']' ) + pWord++; + if ( *pWord == 0 ) + { + sprintf( pMan->sError, "Cannot find closing bracket in this line." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + assert( *pWord == ']' ); + pWord++; + } + assert( nMsb >= 0 && nLsb >= 0 ); + // return + *ppWord = pWord; + *pnMsb = nMsb; + *pnLsb = nLsb; + return 1; +} + +/**Function************************************************************* + + Synopsis [Determine signal suffix of the form [m:n].] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseSignalSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb ) +{ + char * pCur; + int Length; + Length = strlen(pWord); + assert( pWord[Length-1] == ']' ); + // walk backward + for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- ) + if ( *pCur == ':' || *pCur == '[' ) + break; + if ( pCur == pWord ) + { + sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + if ( *pCur == '[' ) + { + *pnMsb = *pnLsb = atoi(pCur+1); + *pCur = 0; + return 1; + } + assert( *pCur == ':' ); + // get the end of the interval + *pnLsb = atoi(pCur+1); + // find the beginning + for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- ) + if ( *pCur == '[' ) + break; + if ( pCur == pWord ) + { + sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + assert( *pCur == '[' ); + // get the beginning of the interval + *pnMsb = atoi(pCur+1); + // cut the word + *pCur = 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns the values of constant bits.] + + Description [The resulting bits are in MSB to LSB order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseConstant( Ver_Man_t * pMan, char * pWord ) +{ + int nBits, i; + assert( pWord[0] >= '1' && pWord[1] <= '9' ); + nBits = atoi(pWord); + // find the next symbol \' + while ( *pWord && *pWord != '\'' ) + pWord++; + if ( *pWord == 0 ) + { + sprintf( pMan->sError, "Cannot find symbol \' in the constant." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + assert( *pWord == '\'' ); + pWord++; + if ( *pWord != 'b' ) + { + sprintf( pMan->sError, "Currently can only handle binary constants." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + pWord++; + // scan the bits + Vec_PtrClear( pMan->vNames ); + for ( i = 0; i < nBits; i++ ) + { + if ( pWord[i] != '0' && pWord[i] != '1' && pWord[i] != 'x' ) + { + sprintf( pMan->sError, "Having problem parsing the binary constant." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + if ( pWord[i] == 'x' ) + Vec_PtrPush( pMan->vNames, (void *)0 ); + else + Vec_PtrPush( pMan->vNames, (void *)(pWord[i]-'0') ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [The signals are added in the order from LSB to MSB.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType ) +{ + Ver_Stream_t * p = pMan->pReader; + char Buffer[1000], Symbol, * pWord; + int nMsb, nLsb, Bit, Limit, i; + nMsb = nLsb = -1; + while ( 1 ) + { + // get the next word + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + + // check if the range is specified + if ( pWord[0] == '[' && !pMan->fNameLast ) + { + assert( nMsb == -1 && nLsb == -1 ); + Ver_ParseSignalPrefix( pMan, &pWord, &nMsb, &nLsb ); + // check the case when there is space between bracket and the next word + if ( *pWord == 0 ) + { + // get the signal name + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + } + } + + // create signals + if ( nMsb == -1 && nLsb == -1 ) + { + if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT ) + Ver_ParseCreatePi( pNtk, pWord ); + if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT ) + Ver_ParseCreatePo( pNtk, pWord ); + if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG ) + Abc_NtkFindOrCreateNet( pNtk, pWord ); + } + else + { + assert( nMsb >= 0 && nLsb >= 0 ); + // add to the hash table + Ver_ParseInsertsSuffix( pMan, pWord, nMsb, nLsb ); + // add signals from Lsb to Msb + Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1; + for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1 ) + { + sprintf( Buffer, "%s[%d]", pWord, Bit ); + if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT ) + Ver_ParseCreatePi( pNtk, Buffer ); + if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT ) + Ver_ParseCreatePo( pNtk, Buffer ); + if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG ) + Abc_NtkFindOrCreateNet( pNtk, Buffer ); + } + } + + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ',' ) + continue; + if ( Symbol == ';' ) + return 1; + break; + } + sprintf( pMan->sError, "Cannot parse signal line (expected , or ;)." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseAlways( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Obj_t * pNet, * pNet2; + int fStopAfterOne; + char * pWord, * pWord2; + char Symbol; + // parse the directive + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + if ( pWord[0] == '@' ) + { + Ver_StreamSkipToChars( p, ")" ); + Ver_StreamPopChar(p); + // parse the directive + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + } + // decide how many statements to parse + fStopAfterOne = 0; + if ( strcmp( pWord, "begin" ) ) + fStopAfterOne = 1; + // iterate over the initial states + while ( 1 ) + { + if ( !fStopAfterOne ) + { + // get the name of the output signal + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // look for the end of directive + if ( !strcmp( pWord, "end" ) ) + break; + } + // get the fanout net + pNet = Ver_ParseFindNet( pNtk, pWord ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the always statement for %s (output wire is not defined).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // get the equality sign + Symbol = Ver_StreamPopChar(p); + if ( Symbol != '<' && Symbol != '=' ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + if ( Symbol == '<' ) + Ver_StreamPopChar(p); + // skip the comments + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + // get the second name + pWord2 = Ver_ParseGetName( pMan ); + if ( pWord2 == NULL ) + return 0; + // check if the name is complemented + if ( pWord2[0] == '~' ) + { + pNet2 = Ver_ParseFindNet( pNtk, pWord2+1 ); + pNet2 = Ver_ParseCreateInv( pNtk, pNet2 ); + } + else + pNet2 = Ver_ParseFindNet( pNtk, pWord2 ); + if ( pNet2 == NULL ) + { + sprintf( pMan->sError, "Cannot read the always statement for %s (input wire is not defined).", pWord2 ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // create the latch + Ver_ParseCreateLatch( pNtk, pNet2, pNet ); + // remove the last symbol + Symbol = Ver_StreamPopChar(p); + assert( Symbol == ';' ); + // quit if only one directive + if ( fStopAfterOne ) + break; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseInitial( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Obj_t * pNode, * pNet; + int fStopAfterOne; + char * pWord, * pEquation; + char Symbol; + // parse the directive + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // decide how many statements to parse + fStopAfterOne = 0; + if ( strcmp( pWord, "begin" ) ) + fStopAfterOne = 1; + // iterate over the initial states + while ( 1 ) + { + if ( !fStopAfterOne ) + { + // get the name of the output signal + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // look for the end of directive + if ( !strcmp( pWord, "end" ) ) + break; + } + // get the fanout net + pNet = Ver_ParseFindNet( pNtk, pWord ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the initial statement for %s (output wire is not defined).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // get the equality sign + Symbol = Ver_StreamPopChar(p); + if ( Symbol != '<' && Symbol != '=' ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + if ( Symbol == '<' ) + Ver_StreamPopChar(p); + // skip the comments + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + // get the second name + pEquation = Ver_StreamGetWord( p, ";" ); + if ( pEquation == NULL ) + return 0; + // find the corresponding latch + if ( Abc_ObjFaninNum(pNet) == 0 ) + { + sprintf( pMan->sError, "Cannot find the latch to assign the initial value." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + pNode = Abc_ObjFanin0(Abc_ObjFanin0(pNet)); + assert( Abc_ObjIsLatch(pNode) ); + // set the initial state + if ( !strcmp(pEquation, "0") || !strcmp(pEquation, "1\'b0") ) + Abc_LatchSetInit0( pNode ); + else if ( !strcmp(pEquation, "1") || !strcmp(pEquation, "1\'b1") ) + Abc_LatchSetInit1( pNode ); +// else if ( !strcmp(pEquation, "2") ) +// Abc_LatchSetInitDc( pNode ); + else + { + sprintf( pMan->sError, "Incorrect initial value of the latch %s.", Abc_ObjName(pNet) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // remove the last symbol + Symbol = Ver_StreamPopChar(p); + assert( Symbol == ';' ); + // quit if only one directive + if ( fStopAfterOne ) + break; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseAssign( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + char Buffer[1000], Buffer2[1000]; + Ver_Stream_t * p = pMan->pReader; + Abc_Obj_t * pNode, * pNet; + char * pWord, * pName, * pEquation; + Hop_Obj_t * pFunc; + char Symbol; + int i, Bit, Limit, Length, fReduction; + int nMsb, nLsb; + +// if ( Ver_StreamGetLineNumber(p) == 2756 ) +// { +// int x = 0; +// } + + // convert from the blackbox into the network with local functions representated by AIGs + if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) ) + return 0; + + while ( 1 ) + { + // get the name of the output signal + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // check for vector-inputs + if ( !Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ) ) + return 0; + // handle special case of constant assignment + if ( nMsb >= 0 && nLsb >= 0 ) + { + // save the fanout name + strcpy( Buffer, pWord ); + // get the equality sign + if ( Ver_StreamPopChar(p) != '=' ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // get the constant + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // check if it is indeed a constant + if ( !(pWord[0] >= '0' && pWord[0] <= '9') ) + { + sprintf( pMan->sError, "Currently can only assign vector-signal \"%s\" to be a constant.", Buffer ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // get individual bits of the constant + if ( !Ver_ParseConstant( pMan, pWord ) ) + return 0; + // check that the constant has the same size + Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1; + if ( Limit != Vec_PtrSize(pMan->vNames) ) + { + sprintf( pMan->sError, "The constant size (%d) is different from the signal\"%s\" size (%d).", + Vec_PtrSize(pMan->vNames), Buffer, Limit ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // iterate through the bits + for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1 ) + { + // get the fanin net + if ( Vec_PtrEntry( pMan->vNames, Limit-1-i ) ) + pNet = Ver_ParseFindNet( pNtk, "1\'b1" ); + else + pNet = Ver_ParseFindNet( pNtk, "1\'b0" ); + assert( pNet != NULL ); + + // create the buffer + pNode = Abc_NtkCreateNodeBuf( pNtk, pNet ); + + // get the fanout net + sprintf( Buffer2, "%s[%d]", Buffer, Bit ); + pNet = Ver_ParseFindNet( pNtk, Buffer2 ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Abc_ObjAddFanin( pNet, pNode ); + } + // go to the end of the line + Ver_ParseSkipComments( pMan ); + } + else + { + // consider the case of reduction operations + fReduction = 0; + if ( pWord[0] == '{' && !pMan->fNameLast ) + fReduction = 1; + if ( fReduction ) + { + pWord++; + pWord[strlen(pWord)-1] = 0; + assert( pWord[0] != '\\' ); + } + // get the fanout net + pNet = Ver_ParseFindNet( pNtk, pWord ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // get the equality sign + if ( Ver_StreamPopChar(p) != '=' ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // skip the comments + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + // get the second name + if ( fReduction ) + pEquation = Ver_StreamGetWord( p, ";" ); + else + pEquation = Ver_StreamGetWord( p, ",;" ); + if ( pEquation == NULL ) + { + sprintf( pMan->sError, "Cannot read the equation for %s.", Abc_ObjName(pNet) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // consider the case of mapped network + Vec_PtrClear( pMan->vNames ); + if ( pMan->fMapped ) + { + if ( !strcmp( pEquation, "1\'b0" ) ) + pFunc = (Hop_Obj_t *)Mio_LibraryReadConst0(Abc_FrameReadLibGen()); + else if ( !strcmp( pEquation, "1\'b1" ) ) + pFunc = (Hop_Obj_t *)Mio_LibraryReadConst1(Abc_FrameReadLibGen()); + else + { + // "assign foo = \bar ;" + if ( *pEquation == '\\' ) + { + pEquation++; + pEquation[strlen(pEquation) - 1] = 0; + } + if ( Ver_ParseFindNet(pNtk, pEquation) == NULL ) + { + sprintf( pMan->sError, "Cannot read Verilog with non-trivial assignments in the mapped netlist." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Vec_PtrPush( pMan->vNames, (void *)strlen(pEquation) ); + Vec_PtrPush( pMan->vNames, pEquation ); + // get the buffer + pFunc = (Hop_Obj_t *)Mio_LibraryReadBuf(Abc_FrameReadLibGen()); + if ( pFunc == NULL ) + { + sprintf( pMan->sError, "Reading assign statement for node %s has failed because the genlib library has no buffer.", Abc_ObjName(pNet) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + } + else + { + if ( !strcmp(pEquation, "0") || !strcmp(pEquation, "1\'b0") || !strcmp(pEquation, "1\'bx") ) + pFunc = Hop_ManConst0(pNtk->pManFunc); + else if ( !strcmp(pEquation, "1") || !strcmp(pEquation, "1\'b1") ) + pFunc = Hop_ManConst1(pNtk->pManFunc); + else if ( fReduction ) + pFunc = Ver_FormulaReduction( pEquation, pNtk->pManFunc, pMan->vNames, pMan->sError ); + else + pFunc = Ver_FormulaParser( pEquation, pNtk->pManFunc, pMan->vNames, pMan->vStackFn, pMan->vStackOp, pMan->sError ); + if ( pFunc == NULL ) + { + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + + // create the node with the given inputs + pNode = Abc_NtkCreateNode( pNtk ); + pNode->pData = pFunc; + Abc_ObjAddFanin( pNet, pNode ); + // connect to fanin nets + for ( i = 0; i < Vec_PtrSize(pMan->vNames)/2; i++ ) + { + // get the name of this signal + Length = (int)Vec_PtrEntry( pMan->vNames, 2*i ); + pName = Vec_PtrEntry( pMan->vNames, 2*i + 1 ); + pName[Length] = 0; + // find the corresponding net + pNet = Ver_ParseFindNet( pNtk, pName ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (input wire %s is not defined).", pWord, pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Abc_ObjAddFanin( pNode, pNet ); + } + } + + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ',' ) + continue; + if ( Symbol == ';' ) + return 1; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateType_t GateType ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Obj_t * pNet, * pNode; + char * pWord, Symbol; + + // convert from the blackbox into the network with local functions representated by AIGs + if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) ) + return 0; + + // this is gate name - throw it away + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot parse a standard gate (expected opening paranthesis)." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + + // create the node + pNode = Abc_NtkCreateNode( pNtk ); + + // parse pairs of formal/actural inputs + while ( 1 ) + { + // parse the output name + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // get the net corresponding to this output + pNet = Ver_ParseFindNet( pNtk, pWord ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Net is missing in gate %s.", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // if this is the first net, add it as an output + if ( Abc_ObjFanoutNum(pNode) == 0 ) + Abc_ObjAddFanin( pNet, pNode ); + else + Abc_ObjAddFanin( pNode, pNet ); + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ')' ) + break; + // skip comma + if ( Symbol != ',' ) + { + sprintf( pMan->sError, "Cannot parse a standard gate %s (expected closing paranthesis).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + } + if ( (GateType == VER_GATE_BUF || GateType == VER_GATE_NOT) && Abc_ObjFaninNum(pNode) != 1 ) + { + sprintf( pMan->sError, "Buffer or interver with multiple fanouts %s (currently not supported).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + if ( Ver_StreamPopChar(p) != ';' ) + { + sprintf( pMan->sError, "Cannot read standard gate %s (expected closing semicolumn).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // add logic function + if ( GateType == VER_GATE_AND || GateType == VER_GATE_NAND ) + pNode->pData = Hop_CreateAnd( pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); + else if ( GateType == VER_GATE_OR || GateType == VER_GATE_NOR ) + pNode->pData = Hop_CreateOr( pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); + else if ( GateType == VER_GATE_XOR || GateType == VER_GATE_XNOR ) + pNode->pData = Hop_CreateExor( pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); + else if ( GateType == VER_GATE_BUF || GateType == VER_GATE_NOT ) + pNode->pData = Hop_CreateAnd( pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); + if ( GateType == VER_GATE_NAND || GateType == VER_GATE_NOR || GateType == VER_GATE_XNOR || GateType == VER_GATE_NOT ) + pNode->pData = Hop_Not( pNode->pData ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns the index of the given pin the gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_FindGateInput( Mio_Gate_t * pGate, char * pName ) +{ + Mio_Pin_t * pGatePin; + int i; + for ( i = 0, pGatePin = Mio_GateReadPins(pGate); pGatePin != NULL; pGatePin = Mio_PinReadNext(pGatePin), i++ ) + if ( strcmp(pName, Mio_PinReadName(pGatePin)) == 0 ) + return i; + if ( strcmp(pName, Mio_GateReadOutName(pGate)) == 0 ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseGate( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Obj_t * pNetActual, * pNode; + char * pWord, Symbol; + int Input, i, nFanins = Mio_GateReadInputs(pGate); + + // convert from the blackbox into the network with local functions representated by gates + if ( 1 != pMan->fMapped ) + { + sprintf( pMan->sError, "The network appears to be mapped. Use \"r -m\" to read mapped Verilog." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // update the network type if needed + if ( !Ver_ParseConvertNetwork( pMan, pNtk, 1 ) ) + return 0; + + // parse the directive and set the pointers to the PIs/POs of the gate + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // this is gate name - throw it away + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot parse gate %s (expected opening paranthesis).", Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + + // start the node + pNode = Abc_NtkCreateNode( pNtk ); + pNode->pData = pGate; + + // parse pairs of formal/actural inputs + Vec_IntClear( pMan->vPerm ); + while ( 1 ) + { + // process one pair of formal/actual parameters + if ( Ver_StreamPopChar(p) != '.' ) + { + sprintf( pMan->sError, "Cannot parse gate %s (expected .).", Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // parse the formal name + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + + // find the corresponding pin of the gate + Input = Ver_FindGateInput( pGate, pWord ); + if ( Input == -1 ) + { + sprintf( pMan->sError, "Formal input name %s cannot be found in the gate %s.", pWord, Mio_GateReadOutName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // open the paranthesis + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected opening paranthesis).", pWord, Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // parse the actual name + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // check if the name is complemented + assert( pWord[0] != '~' ); +/* + fCompl = (pWord[0] == '~'); + if ( fCompl ) + { + fComplUsed = 1; + pWord++; + if ( pNtk->pData == NULL ) + pNtk->pData = Extra_MmFlexStart(); + } +*/ + // get the actual net + pNetActual = Ver_ParseFindNet( pNtk, pWord ); + if ( pNetActual == NULL ) + { + sprintf( pMan->sError, "Actual net %s is missing.", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // close the paranthesis + if ( Ver_StreamPopChar(p) != ')' ) + { + sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // add the fanin + if ( Input < nFanins ) + { + Vec_IntPush( pMan->vPerm, Input ); + Abc_ObjAddFanin( pNode, pNetActual ); // fanin + } + else + Abc_ObjAddFanin( pNetActual, pNode ); // fanout + + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ')' ) + break; + + // skip comma + if ( Symbol != ',' ) + { + sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + } + + // check that the gate as the same number of input + if ( !(Abc_ObjFaninNum(pNode) == nFanins && Abc_ObjFanoutNum(pNode) == 1) ) + { + sprintf( pMan->sError, "Parsing of gate %s has failed.", Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + if ( Ver_StreamPopChar(p) != ';' ) + { + sprintf( pMan->sError, "Cannot read gate %s (expected closing semicolumn).", Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // check if we need to permute the inputs + Vec_IntForEachEntry( pMan->vPerm, Input, i ) + if ( Input != i ) + break; + if ( i < Vec_IntSize(pMan->vPerm) ) + { + // add the fanin numnbers to the end of the permuation array + for ( i = 0; i < nFanins; i++ ) + Vec_IntPush( pMan->vPerm, Abc_ObjFaninId(pNode, i) ); + // write the fanin numbers into their corresponding places (according to the gate) + for ( i = 0; i < nFanins; i++ ) + Vec_IntWriteEntry( &pNode->vFanins, Vec_IntEntry(pMan->vPerm, i), Vec_IntEntry(pMan->vPerm, i+nFanins) ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox ) +{ + char Buffer[1000]; + Ver_Stream_t * p = pMan->pReader; + Ver_Bundle_t * pBundle; + Vec_Ptr_t * vBundles; + Abc_Obj_t * pNetActual; + Abc_Obj_t * pNode; + char * pWord, Symbol; + int fCompl, fFormalIsGiven; + int i, k, Bit, Limit, nMsb, nLsb, fQuit, flag; + + // gate the name of the box + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + + // create a box with this name + pNode = Abc_NtkCreateBlackbox( pNtk ); + pNode->pData = pNtkBox; + Abc_ObjAssignName( pNode, pWord, NULL ); + + // continue parsing the box + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot parse box %s (expected opening paranthesis).", Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + + // parse pairs of formal/actual inputs + vBundles = Vec_PtrAlloc( 16 ); + pNode->pCopy = (Abc_Obj_t *)vBundles; + while ( 1 ) + { + // allocate the bundle (formal name + array of actual nets) + pBundle = ALLOC( Ver_Bundle_t, 1 ); + pBundle->pNameFormal = NULL; + pBundle->vNetsActual = Vec_PtrAlloc( 4 ); + Vec_PtrPush( vBundles, pBundle ); + + // process one pair of formal/actual parameters + fFormalIsGiven = 0; + if ( Ver_StreamScanChar(p) == '.' ) + { + fFormalIsGiven = 1; + if ( Ver_StreamPopChar(p) != '.' ) + { + sprintf( pMan->sError, "Cannot parse box %s (expected .).", Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // parse the formal name + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + + // save the name + pBundle->pNameFormal = Extra_UtilStrsav( pWord ); + + // open the paranthesis + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot formal parameter %s of box %s (expected opening paranthesis).", pWord, Abc_ObjName(pNode)); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + } + + // check if this is the beginning of {} expression + Symbol = Ver_StreamScanChar(p); + + // consider the case of vector-inputs + if ( Symbol == '{' ) + { + // skip this char + Ver_StreamPopChar(p); + + // read actual names + i = 0; + fQuit = 0; + while ( 1 ) + { + // parse the formal name + Ver_ParseSkipComments( pMan ); + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + + // check if the last char is a closing brace + if ( pWord[strlen(pWord)-1] == '}' ) + { + pWord[strlen(pWord)-1] = 0; + fQuit = 1; + } + if ( pWord[0] == 0 ) + break; + + // check for constant + if ( pWord[0] >= '1' && pWord[0] <= '9' ) + { + if ( !Ver_ParseConstant( pMan, pWord ) ) + return 0; + // add constant MSB to LSB + for ( k = 0; k < Vec_PtrSize(pMan->vNames); k++, i++ ) + { + // get the actual net + sprintf( Buffer, "1\'b%d", (int)(Vec_PtrEntry(pMan->vNames,k) != NULL) ); + pNetActual = Ver_ParseFindNet( pNtk, Buffer ); + if ( pNetActual == NULL ) + { + sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", Buffer, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Vec_PtrPush( pBundle->vNetsActual, pNetActual ); + } + } + else + { + // get the suffix of the form [m:n] + if ( pWord[strlen(pWord)-1] == ']' && !pMan->fNameLast ) + Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb ); + else + Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ); + + // generate signals + if ( nMsb == -1 && nLsb == -1 ) + { + // get the actual net + pNetActual = Ver_ParseFindNet( pNtk, pWord ); + if ( pNetActual == NULL ) + { + if ( !strncmp(pWord, "Open_", 5) || + !strncmp(pWord, "dct_unconnected", 15) ) + pNetActual = Abc_NtkCreateNet( pNtk ); + else + { + sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + Vec_PtrPush( pBundle->vNetsActual, pNetActual ); + i++; + } + else + { + // go from MSB to LSB + assert( nMsb >= 0 && nLsb >= 0 ); + Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1; + for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--, i++ ) + { + // get the actual net + sprintf( Buffer, "%s[%d]", pWord, Bit ); + pNetActual = Ver_ParseFindNet( pNtk, Buffer ); + if ( pNetActual == NULL ) + { + if ( !strncmp(pWord, "Open_", 5) || + !strncmp(pWord, "dct_unconnected", 15) ) + pNetActual = Abc_NtkCreateNet( pNtk ); + else + { + sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + Vec_PtrPush( pBundle->vNetsActual, pNetActual ); + } + } + } + + if ( fQuit ) + break; + + // skip comma + Ver_ParseSkipComments( pMan ); + Symbol = Ver_StreamPopChar(p); + if ( Symbol == '}' ) + break; + if ( Symbol != ',' ) + { + sprintf( pMan->sError, "Cannot parse formal parameter %s of gate %s (expected comma).", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + } + else + { + // get the next word + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // consider the case of empty name + fCompl = 0; + if ( pWord[0] == 0 ) + { + pNetActual = Abc_NtkCreateNet( pNtk ); + Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) ); + } + else + { + // get the actual net + flag=0; + pNetActual = Ver_ParseFindNet( pNtk, pWord ); + if ( pNetActual == NULL ) + { + Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ); + if ( nMsb == -1 && nLsb == -1 ) + { + Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb ); + if ( nMsb == -1 && nLsb == -1 ) + { + if ( !strncmp(pWord, "Open_", 5) || + !strncmp(pWord, "dct_unconnected", 15) ) + { + pNetActual = Abc_NtkCreateNet( pNtk ); + Vec_PtrPush( pBundle->vNetsActual, pNetActual ); + } + else + { + sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + else + { + flag=1; + } + } + else + { + flag=1; + } + if (flag) + { + Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1; + for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--) + { + // get the actual net + sprintf( Buffer, "%s[%d]", pWord, Bit ); + pNetActual = Ver_ParseFindNet( pNtk, Buffer ); + if ( pNetActual == NULL ) + { + if ( !strncmp(pWord, "Open_", 5) || + !strncmp(pWord, "dct_unconnected", 15)) + pNetActual = Abc_NtkCreateNet( pNtk ); + else + { + sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + Vec_PtrPush( pBundle->vNetsActual, pNetActual ); + } + } + } + else + { + Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) ); + } + } + } + + if ( fFormalIsGiven ) + { + // close the paranthesis + Ver_ParseSkipComments( pMan ); + if ( Ver_StreamPopChar(p) != ')' ) + { + sprintf( pMan->sError, "Cannot parse formal parameter %s of box %s (expected closing paranthesis).", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + } + + // check if it is the end of gate + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ')' ) + break; + // skip comma + if ( Symbol != ',' ) + { + sprintf( pMan->sError, "Cannot parse formal parameter %s of box %s (expected comma).", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + } + + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + if ( Ver_StreamPopChar(p) != ';' ) + { + sprintf( pMan->sError, "Cannot read box %s (expected closing semicolumn).", Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + return 1; +} + +/**Function************************************************************* + + Synopsis [Connects one box to the network] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseFreeBundle( Ver_Bundle_t * pBundle ) +{ + FREE( pBundle->pNameFormal ); + Vec_PtrFree( pBundle->vNetsActual ); + free( pBundle ); +} + +/**Function************************************************************* + + Synopsis [Connects one box to the network] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox ) +{ + Vec_Ptr_t * vBundles = (Vec_Ptr_t *)pBox->pCopy; + Abc_Ntk_t * pNtk = pBox->pNtk; + Abc_Ntk_t * pNtkBox = pBox->pData; + Abc_Obj_t * pTerm, * pTermNew, * pNetAct; + Ver_Bundle_t * pBundle; + char * pNameFormal; + int i, k, j, iBundle, Length; + + assert( !Ver_ObjIsConnected(pBox) ); + assert( Ver_NtkIsDefined(pNtkBox) ); + assert( !Abc_NtkHasBlackbox(pNtkBox) || Abc_NtkBoxNum(pNtkBox) == 1 ); +/* + // clean the PI/PO nets + Abc_NtkForEachPi( pNtkBox, pTerm, i ) + Abc_ObjFanout0(pTerm)->pCopy = NULL; + Abc_NtkForEachPo( pNtkBox, pTerm, i ) + Abc_ObjFanin0(pTerm)->pCopy = NULL; +*/ + // check if some of them do not have formal names + Vec_PtrForEachEntry( vBundles, pBundle, k ) + if ( pBundle->pNameFormal == NULL ) + break; + if ( k < Vec_PtrSize(vBundles) ) + { + printf( "Warning: The instance %s of network %s will be connected without using formal names.\n", pNtkBox->pName, Abc_ObjName(pBox) ); + // add all actual nets in the bundles + iBundle = 0; + Vec_PtrForEachEntry( vBundles, pBundle, j ) + iBundle += Vec_PtrSize(pBundle->vNetsActual); + + // check the number of actual nets is the same as the number of formal nets + if ( iBundle != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ) + { + sprintf( pMan->sError, "The number of actual IOs (%d) is different from the number of formal IOs (%d) when instantiating network %s in box %s.", + Vec_PtrSize(vBundles), Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox), pNtkBox->pName, Abc_ObjName(pBox) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // connect bundles in the natural order + iBundle = 0; + Abc_NtkForEachPi( pNtkBox, pTerm, i ) + { + pBundle = Vec_PtrEntry( vBundles, iBundle++ ); + // the bundle is found - add the connections - using order LSB to MSB + Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k ) + { + pTermNew = Abc_NtkCreateBi( pNtk ); + Abc_ObjAddFanin( pBox, pTermNew ); + Abc_ObjAddFanin( pTermNew, pNetAct ); + i++; + } + i--; + } + // create fanins of the box + Abc_NtkForEachPo( pNtkBox, pTerm, i ) + { + pBundle = Vec_PtrEntry( vBundles, iBundle++ ); + // the bundle is found - add the connections - using order LSB to MSB + Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k ) + { + pTermNew = Abc_NtkCreateBo( pNtk ); + Abc_ObjAddFanin( pTermNew, pBox ); + Abc_ObjAddFanin( pNetAct, pTermNew ); + i++; + } + i--; + } + + // free the bundling + Vec_PtrForEachEntry( vBundles, pBundle, k ) + Ver_ParseFreeBundle( pBundle ); + Vec_PtrFree( vBundles ); + pBox->pCopy = NULL; + return 1; + } + + // bundles arrive in any order - but inside each bundle the order is MSB to LSB + // make sure every formal PI has a corresponding net + Abc_NtkForEachPi( pNtkBox, pTerm, i ) + { + // get the name of this formal net + pNameFormal = Abc_ObjName( Abc_ObjFanout0(pTerm) ); + // try to find the bundle with this formal net + pBundle = NULL; + Vec_PtrForEachEntry( vBundles, pBundle, k ) + if ( !strcmp(pBundle->pNameFormal, pNameFormal) ) + break; + assert( pBundle != NULL ); + // if the bundle is not found, try without parantheses + if ( k == Vec_PtrSize(vBundles) ) + { + pBundle = NULL; + Length = strlen(pNameFormal); + if ( pNameFormal[Length-1] == ']' ) + { + // find the opening brace + for ( Length--; Length >= 0; Length-- ) + if ( pNameFormal[Length] == '[' ) + break; + // compare names before brace + if ( Length > 0 ) + { + Vec_PtrForEachEntry( vBundles, pBundle, j ) + if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) ) + break; + if ( j == Vec_PtrSize(vBundles) ) + pBundle = NULL; + } + } + if ( pBundle == NULL ) + { + sprintf( pMan->sError, "Cannot find an actual net for the formal net %s when instantiating network %s in box %s.", + pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + // the bundle is found - add the connections - using order LSB to MSB + Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k ) + { + pTermNew = Abc_NtkCreateBi( pNtk ); + Abc_ObjAddFanin( pBox, pTermNew ); + Abc_ObjAddFanin( pTermNew, pNetAct ); + i++; + } + i--; + } + + // connect those formal POs that do have nets + Abc_NtkForEachPo( pNtkBox, pTerm, i ) + { + // get the name of this PI + pNameFormal = Abc_ObjName( Abc_ObjFanin0(pTerm) ); + // try to find this formal net in the bundle + pBundle = NULL; + Vec_PtrForEachEntry( vBundles, pBundle, k ) + if ( !strcmp(pBundle->pNameFormal, pNameFormal) ) + break; + assert( pBundle != NULL ); + // if the name is not found, try without parantheses + if ( k == Vec_PtrSize(vBundles) ) + { + pBundle = NULL; + Length = strlen(pNameFormal); + if ( pNameFormal[Length-1] == ']' ) + { + // find the opening brace + for ( Length--; Length >= 0; Length-- ) + if ( pNameFormal[Length] == '[' ) + break; + // compare names before brace + if ( Length > 0 ) + { + Vec_PtrForEachEntry( vBundles, pBundle, j ) + if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) ) + break; + if ( j == Vec_PtrSize(vBundles) ) + pBundle = NULL; + } + } + if ( pBundle == NULL ) + { +// printf( "Warning: The formal output %s is not driven when instantiating network %s in box %s.", +// pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) ); + continue; + } + } + // the bundle is found - add the connections + Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k ) + { + if ( !strcmp(Abc_ObjName(pNetAct), "1\'b0") || !strcmp(Abc_ObjName(pNetAct), "1\'b1") ) + { + sprintf( pMan->sError, "It looks like formal output %s is driving a constant net (%s) when instantiating network %s in box %s.", + pBundle->pNameFormal, Abc_ObjName(pNetAct), pNtkBox->pName, Abc_ObjName(pBox) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + pTermNew = Abc_NtkCreateBo( pNtk ); + Abc_ObjAddFanin( pTermNew, pBox ); + Abc_ObjAddFanin( pNetAct, pTermNew ); + i++; + } + i--; + } + + // free the bundling + Vec_PtrForEachEntry( vBundles, pBundle, k ) + Ver_ParseFreeBundle( pBundle ); + Vec_PtrFree( vBundles ); + pBox->pCopy = NULL; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Connects the defined boxes.] + + Description [Returns 2 if there are any undef boxes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseConnectDefBoxes( Ver_Man_t * pMan ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pBox; + int i, k, RetValue = 1; + // go through all the modules + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + // go through all the boxes of this module + Abc_NtkForEachBox( pNtk, pBox, k ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + // skip internal boxes of the blackboxes + if ( pBox->pData == NULL ) + continue; + // if the network is undefined, it will be connected later + if ( !Ver_NtkIsDefined(pBox->pData) ) + { + RetValue = 2; + continue; + } + // connect the box + if ( !Ver_ParseConnectBox( pMan, pBox ) ) + return 0; + // if the network is a true blackbox, skip + if ( Abc_NtkHasBlackbox(pBox->pData) ) + continue; + // convert the box to the whitebox + Abc_ObjBlackboxToWhitebox( pBox ); + } + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Collects the undef boxes and maps them into their instances.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ver_ParseCollectUndefBoxes( Ver_Man_t * pMan ) +{ + Vec_Ptr_t * vUndefs; + Abc_Ntk_t * pNtk, * pNtkBox; + Abc_Obj_t * pBox; + int i, k; + // clear the module structures + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + pNtk->pData = NULL; + // go through all the blackboxes + vUndefs = Vec_PtrAlloc( 16 ); + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + Abc_NtkForEachBlackbox( pNtk, pBox, k ) + { + pNtkBox = pBox->pData; + if ( pNtkBox == NULL ) + continue; + if ( Ver_NtkIsDefined(pNtkBox) ) + continue; + if ( pNtkBox->pData == NULL ) + { + // save the box + Vec_PtrPush( vUndefs, pNtkBox ); + pNtkBox->pData = Vec_PtrAlloc( 16 ); + } + // save the instance + Vec_PtrPush( pNtkBox->pData, pBox ); + } + } + return vUndefs; +} + +/**Function************************************************************* + + Synopsis [Reports how many times each type of undefined box occurs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseReportUndefBoxes( Ver_Man_t * pMan ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pBox; + int i, k, nBoxes; + // clean + nBoxes = 0; + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + pNtk->fHiePath = 0; + if ( !Ver_NtkIsDefined(pNtk) ) + nBoxes++; + } + // count + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + Abc_NtkForEachBlackbox( pNtk, pBox, k ) + if ( pBox->pData && !Ver_NtkIsDefined(pBox->pData) ) + ((Abc_Ntk_t *)pBox->pData)->fHiePath++; + // print the stats + printf( "Warning: The design contains %d undefined objects interpreted as blackboxes:\n", nBoxes ); + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + if ( !Ver_NtkIsDefined(pNtk) ) + printf( "%s (%d) ", Abc_NtkName(pNtk), pNtk->fHiePath ); + printf( "\n" ); + // clean + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + pNtk->fHiePath = 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if there are non-driven nets.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseCheckNondrivenNets( Vec_Ptr_t * vUndefs ) +{ + Abc_Ntk_t * pNtk; + Ver_Bundle_t * pBundle; + Abc_Obj_t * pBox, * pNet; + int i, k, j, m; + // go through undef box types + Vec_PtrForEachEntry( vUndefs, pNtk, i ) + // go through instances of this type + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + // go through the bundles of this instance + Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) + // go through the actual nets of this bundle + if ( pBundle ) + Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m ) + { + char * pName = Abc_ObjName(pNet); + if ( Abc_ObjFaninNum(pNet) == 0 ) // non-driven + if ( strcmp(Abc_ObjName(pNet), "1\'b0") && strcmp(Abc_ObjName(pNet), "1\'b1") ) // diff from a const + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if formal nets with the given name are driven in any of the instances of undef boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseFormalNetsAreDriven( Abc_Ntk_t * pNtk, char * pNameFormal ) +{ + Ver_Bundle_t * pBundle; + Abc_Obj_t * pBox, * pNet; + int k, j, m; + // go through instances of this type + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + { + // find a bundle with the given name in this instance + Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) + if ( pBundle && !strcmp( pBundle->pNameFormal, pNameFormal ) ) + break; + // skip non-driven bundles + if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) + continue; + // check if all nets are driven in this bundle + Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m ) + if ( Abc_ObjFaninNum(pNet) > 0 ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the non-driven bundle that is given distance from the end.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ver_Bundle_t * Ver_ParseGetNondrivenBundle( Abc_Ntk_t * pNtk, int Counter ) +{ + Ver_Bundle_t * pBundle; + Abc_Obj_t * pBox, * pNet; + int k, m; + // go through instances of this type + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + { + if ( Counter >= Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) + continue; + // get the bundle given distance away + pBundle = Vec_PtrEntry( (Vec_Ptr_t *)pBox->pCopy, Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) - 1 - Counter ); + if ( pBundle == NULL ) + continue; + // go through the actual nets of this bundle + Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m ) + if ( !Abc_ObjFaninNum(pNet) && !Ver_ParseFormalNetsAreDriven(pNtk, pBundle->pNameFormal) ) // non-driven + return pBundle; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Drives the bundle in the given undef box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseDriveFormal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_Bundle_t * pBundle0 ) +{ + char Buffer[200]; + char * pName; + Ver_Bundle_t * pBundle; + Abc_Obj_t * pBox, * pTerm, * pTermNew, * pNetAct, * pNetFormal; + int k, j, m; + + // drive this net in the undef box + Vec_PtrForEachEntry( pBundle0->vNetsActual, pNetAct, m ) + { + // create the formal net + if ( Vec_PtrSize(pBundle0->vNetsActual) == 1 ) + sprintf( Buffer, "%s", pBundle0->pNameFormal ); + else + sprintf( Buffer, "%s[%d]", pBundle0->pNameFormal, m ); + assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL ); + pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer ); + // connect it to the box + pTerm = Abc_NtkCreateBo( pNtk ); + assert( Abc_NtkBoxNum(pNtk) <= 1 ); + pBox = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk); + Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pNetFormal ); + Abc_ObjAddFanin( pNetFormal, pTerm ); + Abc_ObjAddFanin( pTerm, pBox ); + } + + // go through instances of this type + pName = Extra_UtilStrsav(pBundle0->pNameFormal); + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + { + // find a bundle with the given name in this instance + Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) + if ( pBundle && !strcmp( pBundle->pNameFormal, pName ) ) + break; + // skip non-driven bundles + if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) + continue; + // check if any nets are driven in this bundle + Vec_PtrForEachEntry( pBundle->vNetsActual, pNetAct, m ) + if ( Abc_ObjFaninNum(pNetAct) > 0 ) + { + sprintf( pMan->sError, "Internal error while trying to connect undefined boxes. It is likely that the algorithm currently used has its limitations." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // drive the nets by the undef box + Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, m ) + { + pTermNew = Abc_NtkCreateBo( pNetAct->pNtk ); + Abc_ObjAddFanin( pTermNew, pBox ); + Abc_ObjAddFanin( pNetAct, pTermNew ); + } + // remove the bundle + Ver_ParseFreeBundle( pBundle ); + Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL ); + } + free( pName ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Drives the bundle in the given undef box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseDriveInputs( Ver_Man_t * pMan, Vec_Ptr_t * vUndefs ) +{ + char Buffer[200]; + Ver_Bundle_t * pBundle; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pBox, * pBox2, * pTerm, * pTermNew, * pNetFormal, * pNetAct; + int i, k, j, m, CountCur, CountTotal = -1; + // iterate through the undef boxes + Vec_PtrForEachEntry( vUndefs, pNtk, i ) + { + // count the number of unconnected bundles for instances of this type of box + CountTotal = -1; + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + { + CountCur = 0; + Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) + CountCur += (pBundle != NULL); + if ( CountTotal == -1 ) + CountTotal = CountCur; + else if ( CountTotal != CountCur ) + { + sprintf( pMan->sError, "The number of formal inputs (%d) is different from the expected one (%d) when instantiating network %s in box %s.", + CountCur, CountTotal, pNtk->pName, Abc_ObjName(pBox) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + + // create formals + pBox = Vec_PtrEntry( pNtk->pData, 0 ); + Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) + { + if ( pBundle == NULL ) + continue; + Vec_PtrForEachEntry( pBundle->vNetsActual, pNetAct, m ) + { + // find create the formal net + if ( Vec_PtrSize(pBundle->vNetsActual) == 1 ) + sprintf( Buffer, "%s", pBundle->pNameFormal ); + else + sprintf( Buffer, "%s[%d]", pBundle->pNameFormal, m ); + assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL ); + pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer ); + // connect + pTerm = Abc_NtkCreateBi( pNtk ); + assert( Abc_NtkBoxNum(pNtk) <= 1 ); + pBox2 = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk); + Abc_ObjAddFanin( pNetFormal, Abc_NtkCreatePi(pNtk) ); + Abc_ObjAddFanin( pTerm, pNetFormal ); + Abc_ObjAddFanin( pBox2, pTerm ); + } + } + + // go through all the boxes + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + { + // go through all the bundles + Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) + { + if ( pBundle == NULL ) + continue; + // drive the nets by the undef box + Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, m ) + { + pTermNew = Abc_NtkCreateBi( pNetAct->pNtk ); + Abc_ObjAddFanin( pBox, pTermNew ); + Abc_ObjAddFanin( pTermNew, pNetAct ); + } + // remove the bundle + Ver_ParseFreeBundle( pBundle ); + Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL ); + } + + // free the bundles + Vec_PtrFree( (Vec_Ptr_t *)pBox->pCopy ); + pBox->pCopy = NULL; + } + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Returns the max size of any undef box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseMaxBoxSize( Vec_Ptr_t * vUndefs ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pBox; + int i, k, nMaxSize = 0; + // go through undef box types + Vec_PtrForEachEntry( vUndefs, pNtk, i ) + // go through instances of this type + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + // check the number of bundles of this instance + if ( nMaxSize < Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) + nMaxSize = Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy); + return nMaxSize; +} + +/**Function************************************************************* + + Synopsis [Prints the comprehensive report into a log file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParsePrintLog( Ver_Man_t * pMan ) +{ + Abc_Ntk_t * pNtk, * pNtkBox; + Abc_Obj_t * pBox; + FILE * pFile; + char * pNameGeneric; + char Buffer[1000]; + int i, k; + + // open the log file + pNameGeneric = Extra_FileNameGeneric( pMan->pFileName ); + sprintf( Buffer, "%s.log", pNameGeneric ); + free( pNameGeneric ); + pFile = fopen( Buffer, "w" ); + + // count the total number of instances and how many times they occur + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + pNtk->fHieVisited = 0; + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + Abc_NtkForEachBox( pNtk, pBox, k ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + pNtkBox = pBox->pData; + if ( pNtkBox == NULL ) + continue; + pNtkBox->fHieVisited++; + } + // print each box and its stats + fprintf( pFile, "The hierarhical design %s contains %d modules:\n", pMan->pFileName, Vec_PtrSize(pMan->pDesign->vModules) ); + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + fprintf( pFile, "%-24s : ", Abc_NtkName(pNtk) ); + if ( !Ver_NtkIsDefined(pNtk) ) + fprintf( pFile, "undefbox" ); + else if ( Abc_NtkHasBlackbox(pNtk) ) + fprintf( pFile, "blackbox" ); + else + fprintf( pFile, "logicbox" ); + fprintf( pFile, " instantiated %6d times ", pNtk->fHieVisited ); +// fprintf( pFile, "\n " ); + fprintf( pFile, " pi = %4d", Abc_NtkPiNum(pNtk) ); + fprintf( pFile, " po = %4d", Abc_NtkPiNum(pNtk) ); + fprintf( pFile, " nd = %8d", Abc_NtkNodeNum(pNtk) ); + fprintf( pFile, " lat = %6d", Abc_NtkLatchNum(pNtk) ); + fprintf( pFile, " box = %6d", Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) ); + fprintf( pFile, "\n" ); + } + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + pNtk->fHieVisited = 0; + + // report instances with dangling outputs + if ( Vec_PtrSize(pMan->pDesign->vModules) > 1 ) + { + Vec_Ptr_t * vBundles; + Ver_Bundle_t * pBundle; + int j, nActNets, Counter = 0, CounterBoxes = 0; + // count the number of instances with dangling outputs + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + Abc_NtkForEachBox( pNtk, pBox, k ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + vBundles = (Vec_Ptr_t *)pBox->pCopy; + pNtkBox = pBox->pData; + if ( pNtkBox == NULL ) + continue; + if ( !Ver_NtkIsDefined(pNtkBox) ) + continue; + // count the number of actual nets + nActNets = 0; + Vec_PtrForEachEntry( vBundles, pBundle, j ) + nActNets += Vec_PtrSize(pBundle->vNetsActual); + // the box is defined and will be connected + if ( nActNets != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ) + Counter++; + } + } + if ( Counter == 0 ) + fprintf( pFile, "The outputs of all box instances are connected.\n" ); + else + { + fprintf( pFile, "\n" ); + fprintf( pFile, "The outputs of %d box instances are not connected:\n", Counter ); + // enumerate through the boxes + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + Abc_NtkForEachBox( pNtk, pBox, k ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + vBundles = (Vec_Ptr_t *)pBox->pCopy; + pNtkBox = pBox->pData; + if ( pNtkBox == NULL ) + continue; + if ( !Ver_NtkIsDefined(pNtkBox) ) + continue; + // count the number of actual nets + nActNets = 0; + Vec_PtrForEachEntry( vBundles, pBundle, j ) + nActNets += Vec_PtrSize(pBundle->vNetsActual); + // the box is defined and will be connected + if ( nActNets != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ) + fprintf( pFile, "In module \"%s\" instance \"%s\" of box \"%s\" has different numbers of actual/formal nets (%d/%d).\n", + Abc_NtkName(pNtk), Abc_ObjName(pBox), Abc_NtkName(pNtkBox), nActNets, Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ); + } + } + } + } + fclose( pFile ); + printf( "Hierarchy statistics can be found in log file \"%s\".\n", Buffer ); +} + + +/**Function************************************************************* + + Synopsis [Attaches the boxes to the network.] + + Description [This procedure is called after the design is parsed. + At that point, all the defined models have their PIs present. + They are connected first. Next undef boxes are processed (if present). + Iteratively, one bundle is selected to be driven by the undef boxes in such + a way that there is no conflict (if it is driven by an instance of the box, + no other net will be driven twice by the same formal net of some other instance + of the same box). In the end, all the remaining nets that cannot be driven + by the undef boxes are connected to the undef boxes as inputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseAttachBoxes( Ver_Man_t * pMan ) +{ + Abc_Ntk_t * pNtk; + Ver_Bundle_t * pBundle; + Vec_Ptr_t * vUndefs; + int i, RetValue, Counter, nMaxBoxSize; + + // print the log file + if ( pMan->pDesign->vModules && Vec_PtrSize(pMan->pDesign->vModules) > 1 ) + Ver_ParsePrintLog( pMan ); + + // connect defined boxes + RetValue = Ver_ParseConnectDefBoxes( pMan ); + if ( RetValue < 2 ) + return RetValue; + + // report the boxes + Ver_ParseReportUndefBoxes( pMan ); + + // collect undef box types and their actual instances + vUndefs = Ver_ParseCollectUndefBoxes( pMan ); + assert( Vec_PtrSize( vUndefs ) > 0 ); + + // go through all undef box types + Counter = 0; + nMaxBoxSize = Ver_ParseMaxBoxSize( vUndefs ); + while ( Ver_ParseCheckNondrivenNets(vUndefs) && Counter < nMaxBoxSize ) + { + // go through undef box types + pBundle = NULL; + Vec_PtrForEachEntry( vUndefs, pNtk, i ) + if ( pBundle = Ver_ParseGetNondrivenBundle( pNtk, Counter ) ) + break; + if ( pBundle == NULL ) + { + Counter++; + continue; + } + // drive this bundle by this box + if ( !Ver_ParseDriveFormal( pMan, pNtk, pBundle ) ) + return 0; + } + + // make all the remaining bundles the drivers of undefs + if ( !Ver_ParseDriveInputs( pMan, vUndefs ) ) + return 0; + + // cleanup + Vec_PtrForEachEntry( vUndefs, pNtk, i ) + { + Vec_PtrFree( pNtk->pData ); + pNtk->pData = NULL; + } + Vec_PtrFree( vUndefs ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Creates PI terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PI net +// pNet = Ver_ParseFindNet( pNtk, pName ); +// if ( pNet ) +// printf( "Warning: PI \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PI node + pTerm = Abc_NtkCreatePi( pNtk ); + Abc_ObjAddFanin( pNet, pTerm ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Creates PO terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PO net +// pNet = Ver_ParseFindNet( pNtk, pName ); +// if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) +// printf( "Warning: PO \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PO node + pTerm = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pTerm, pNet ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Create a latch with the given input/output.] + + Description [By default, the latch value is a don't-care.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO ) +{ + Abc_Obj_t * pLatch, * pTerm; + // add the BO terminal + pTerm = Abc_NtkCreateBi( pNtk ); + Abc_ObjAddFanin( pTerm, pNetLI ); + // add the latch box + pLatch = Abc_NtkCreateLatch( pNtk ); + Abc_ObjAddFanin( pLatch, pTerm ); + // add the BI terminal + pTerm = Abc_NtkCreateBo( pNtk ); + Abc_ObjAddFanin( pTerm, pLatch ); + // get the LO net + Abc_ObjAddFanin( pNetLO, pTerm ); + // set latch name + Abc_ObjAssignName( pLatch, Abc_ObjName(pNetLO), "L" ); + Abc_LatchSetInitDc( pLatch ); + return pLatch; +} + +/**Function************************************************************* + + Synopsis [Creates inverter and returns its net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ) +{ + Abc_Obj_t * pObj; + pObj = Abc_NtkCreateNodeInv( pNtk, pNet ); + pNet = Abc_NtkCreateNet( pNtk ); + Abc_ObjAddFanin( pNet, pObj ); + return pNet; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/ver/verFormula.c b/abc70930/src/base/ver/verFormula.c new file mode 100644 index 00000000..19a2c523 --- /dev/null +++ b/abc70930/src/base/ver/verFormula.c @@ -0,0 +1,474 @@ +/**CFile**************************************************************** + + FileName [verFormula.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Formula parser to read Verilog assign statements.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verFormula.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the list of operation symbols to be used in expressions +#define VER_PARSE_SYM_OPEN '(' // opening paranthesis +#define VER_PARSE_SYM_CLOSE ')' // closing paranthesis +#define VER_PARSE_SYM_CONST0 '0' // constant 0 +#define VER_PARSE_SYM_CONST1 '1' // constant 1 +#define VER_PARSE_SYM_NEGBEF1 '!' // negation before the variable +#define VER_PARSE_SYM_NEGBEF2 '~' // negation before the variable +#define VER_PARSE_SYM_AND '&' // logic AND +#define VER_PARSE_SYM_OR '|' // logic OR +#define VER_PARSE_SYM_XOR '^' // logic XOR +#define VER_PARSE_SYM_MUX1 '?' // first symbol of MUX +#define VER_PARSE_SYM_MUX2 ':' // second symbol of MUX + +// the list of opcodes (also specifying operation precedence) +#define VER_PARSE_OPER_NEG 7 // negation (highest precedence) +#define VER_PARSE_OPER_AND 6 // logic AND +#define VER_PARSE_OPER_XOR 5 // logic EXOR (a'b | ab') +#define VER_PARSE_OPER_OR 4 // logic OR +#define VER_PARSE_OPER_EQU 3 // equvalence (a'b'| ab ) +#define VER_PARSE_OPER_MUX 2 // MUX(a,b,c) (ab | a'c ) +#define VER_PARSE_OPER_MARK 1 // OpStack token standing for an opening paranthesis + +// these are values of the internal Flag +#define VER_PARSE_FLAG_START 1 // after the opening parenthesis +#define VER_PARSE_FLAG_VAR 2 // after operation is received +#define VER_PARSE_FLAG_OPER 3 // after operation symbol is received +#define VER_PARSE_FLAG_ERROR 4 // when error is detected + +static Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper ); +static int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Parser of the formula encountered in assign statements.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage ) +{ + char * pTemp; + Hop_Obj_t * bFunc, * bTemp; + int nParans, Flag; + int Oper, Oper1, Oper2; + int v; + + // clear the stacks and the names + Vec_PtrClear( vNames ); + Vec_PtrClear( vStackFn ); + Vec_IntClear( vStackOp ); + + if ( !strcmp(pFormula, "0") || !strcmp(pFormula, "1\'b0") ) + return Hop_ManConst0(pMan); + if ( !strcmp(pFormula, "1") || !strcmp(pFormula, "1\'b1") ) + return Hop_ManConst1(pMan); + + // make sure that the number of opening and closing parantheses is the same + nParans = 0; + for ( pTemp = pFormula; *pTemp; pTemp++ ) + if ( *pTemp == '(' ) + nParans++; + else if ( *pTemp == ')' ) + nParans--; + if ( nParans != 0 ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Different number of opening and closing parantheses ()." ); + return NULL; + } + + // add parantheses + pTemp = pFormula + strlen(pFormula) + 2; + *pTemp-- = 0; *pTemp = ')'; + while ( --pTemp != pFormula ) + *pTemp = *(pTemp - 1); + *pTemp = '('; + + // perform parsing + Flag = VER_PARSE_FLAG_START; + for ( pTemp = pFormula; *pTemp; pTemp++ ) + { + switch ( *pTemp ) + { + // skip all spaces, tabs, and end-of-lines + case ' ': + case '\t': + case '\r': + case '\n': + continue; +/* + // treat Constant 0 as a variable + case VER_PARSE_SYM_CONST0: + Vec_PtrPush( vStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( Hop_ManConst0(pMan) ); + if ( Flag == VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 0." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Flag = VER_PARSE_FLAG_VAR; + break; + + // the same for Constant 1 + case VER_PARSE_SYM_CONST1: + Vec_PtrPush( vStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( Hop_ManConst1(pMan) ); + if ( Flag == VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 1." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Flag = VER_PARSE_FLAG_VAR; + break; +*/ + case VER_PARSE_SYM_NEGBEF1: + case VER_PARSE_SYM_NEGBEF2: + if ( Flag == VER_PARSE_FLAG_VAR ) + {// if NEGBEF follows a variable, AND is assumed + sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before negation." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Vec_IntPush( vStackOp, VER_PARSE_OPER_NEG ); + break; + + case VER_PARSE_SYM_AND: + case VER_PARSE_SYM_OR: + case VER_PARSE_SYM_XOR: + case VER_PARSE_SYM_MUX1: + case VER_PARSE_SYM_MUX2: + if ( Flag != VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + if ( *pTemp == VER_PARSE_SYM_AND ) + Vec_IntPush( vStackOp, VER_PARSE_OPER_AND ); + else if ( *pTemp == VER_PARSE_SYM_OR ) + Vec_IntPush( vStackOp, VER_PARSE_OPER_OR ); + else if ( *pTemp == VER_PARSE_SYM_XOR ) + Vec_IntPush( vStackOp, VER_PARSE_OPER_XOR ); + else if ( *pTemp == VER_PARSE_SYM_MUX1 ) + Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); +// else if ( *pTemp == VER_PARSE_SYM_MUX2 ) +// Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); + Flag = VER_PARSE_FLAG_OPER; + break; + + case VER_PARSE_SYM_OPEN: + if ( Flag == VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before a paranthesis." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Vec_IntPush( vStackOp, VER_PARSE_OPER_MARK ); + // after an opening bracket, it feels like starting over again + Flag = VER_PARSE_FLAG_START; + break; + + case VER_PARSE_SYM_CLOSE: + if ( Vec_IntSize( vStackOp ) ) + { + while ( 1 ) + { + if ( !Vec_IntSize( vStackOp ) ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Oper = Vec_IntPop( vStackOp ); + if ( Oper == VER_PARSE_OPER_MARK ) + break; + // skip the second MUX operation +// if ( Oper == VER_PARSE_OPER_MUX2 ) +// { +// Oper = Vec_IntPop( vStackOp ); +// assert( Oper == VER_PARSE_OPER_MUX1 ); +// } + + // perform the given operation + if ( Ver_FormulaParserTopOper( pMan, vStackFn, Oper ) == NULL ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); + return NULL; + } + } + } + else + { + sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + if ( Flag != VER_PARSE_FLAG_ERROR ) + Flag = VER_PARSE_FLAG_VAR; + break; + + + default: + // scan the next name + v = Ver_FormulaParserFindVar( pTemp, vNames ); + if ( *pTemp == '\\' ) + pTemp++; + pTemp += (int)Vec_PtrEntry( vNames, 2*v ) - 1; + + // assume operation AND, if vars follow one another + if ( Flag == VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Incorrect state." ); + return NULL; + } + bTemp = Hop_IthVar( pMan, v ); + Vec_PtrPush( vStackFn, bTemp ); // Cudd_Ref( bTemp ); + Flag = VER_PARSE_FLAG_VAR; + break; + } + + if ( Flag == VER_PARSE_FLAG_ERROR ) + break; // error exit + else if ( Flag == VER_PARSE_FLAG_START ) + continue; // go on parsing + else if ( Flag == VER_PARSE_FLAG_VAR ) + while ( 1 ) + { // check if there are negations in the OpStack + if ( !Vec_IntSize(vStackOp) ) + break; + Oper = Vec_IntPop( vStackOp ); + if ( Oper != VER_PARSE_OPER_NEG ) + { + Vec_IntPush( vStackOp, Oper ); + break; + } + else + { +// Vec_PtrPush( vStackFn, Cudd_Not(Vec_PtrPop(vStackFn)) ); + Vec_PtrPush( vStackFn, Hop_Not(Vec_PtrPop(vStackFn)) ); + } + } + else // if ( Flag == VER_PARSE_FLAG_OPER ) + while ( 1 ) + { // execute all the operations in the OpStack + // with precedence higher or equal than the last one + Oper1 = Vec_IntPop( vStackOp ); // the last operation + if ( !Vec_IntSize(vStackOp) ) + { // if it is the only operation, push it back + Vec_IntPush( vStackOp, Oper1 ); + break; + } + Oper2 = Vec_IntPop( vStackOp ); // the operation before the last one + if ( Oper2 >= Oper1 && !(Oper1 == Oper2 && Oper1 == VER_PARSE_OPER_MUX) ) + { // if Oper2 precedence is higher or equal, execute it + if ( Ver_FormulaParserTopOper( pMan, vStackFn, Oper2 ) == NULL ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); + return NULL; + } + Vec_IntPush( vStackOp, Oper1 ); // push the last operation back + } + else + { // if Oper2 precedence is lower, push them back and done + Vec_IntPush( vStackOp, Oper2 ); + Vec_IntPush( vStackOp, Oper1 ); + break; + } + } + } + + if ( Flag != VER_PARSE_FLAG_ERROR ) + { + if ( Vec_PtrSize(vStackFn) ) + { + bFunc = Vec_PtrPop(vStackFn); + if ( !Vec_PtrSize(vStackFn) ) + if ( !Vec_IntSize(vStackOp) ) + { +// Cudd_Deref( bFunc ); + return bFunc; + } + else + sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the operation stack\n" ); + else + sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the function stack\n" ); + } + else + sprintf( pErrorMessage, "Parse_FormulaParser(): The input string is empty\n" ); + } +// Cudd_Ref( bFunc ); +// Cudd_RecursiveDeref( dd, bFunc ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs the operation on the top entries in the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper ) +{ + Hop_Obj_t * bArg0, * bArg1, * bArg2, * bFunc; + // perform the given operation + bArg2 = Vec_PtrPop( vStackFn ); + bArg1 = Vec_PtrPop( vStackFn ); + if ( Oper == VER_PARSE_OPER_AND ) + bFunc = Hop_And( pMan, bArg1, bArg2 ); + else if ( Oper == VER_PARSE_OPER_XOR ) + bFunc = Hop_Exor( pMan, bArg1, bArg2 ); + else if ( Oper == VER_PARSE_OPER_OR ) + bFunc = Hop_Or( pMan, bArg1, bArg2 ); + else if ( Oper == VER_PARSE_OPER_EQU ) + bFunc = Hop_Not( Hop_Exor( pMan, bArg1, bArg2 ) ); + else if ( Oper == VER_PARSE_OPER_MUX ) + { + bArg0 = Vec_PtrPop( vStackFn ); +// bFunc = Cudd_bddIte( dd, bArg0, bArg1, bArg2 ); Cudd_Ref( bFunc ); + bFunc = Hop_Mux( pMan, bArg0, bArg1, bArg2 ); +// Cudd_RecursiveDeref( dd, bArg0 ); +// Cudd_Deref( bFunc ); + } + else + return NULL; +// Cudd_Ref( bFunc ); +// Cudd_RecursiveDeref( dd, bArg1 ); +// Cudd_RecursiveDeref( dd, bArg2 ); + Vec_PtrPush( vStackFn, bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Returns the index of the new variable found.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames ) +{ + char * pTemp, * pTemp2; + int nLength, nLength2, i; + // start the string + pTemp = pString; + // find the end of the string delimited by other characters + if ( *pTemp == '\\' ) + { + pString++; + while ( *pTemp && *pTemp != ' ' ) + pTemp++; + } + else + { + while ( *pTemp && *pTemp != ' ' && *pTemp != '\t' && *pTemp != '\r' && *pTemp != '\n' && *pTemp != ',' && *pTemp != '}' && + *pTemp != VER_PARSE_SYM_OPEN && *pTemp != VER_PARSE_SYM_CLOSE && + *pTemp != VER_PARSE_SYM_NEGBEF1 && *pTemp != VER_PARSE_SYM_NEGBEF2 && + *pTemp != VER_PARSE_SYM_AND && *pTemp != VER_PARSE_SYM_OR && *pTemp != VER_PARSE_SYM_XOR && + *pTemp != VER_PARSE_SYM_MUX1 && *pTemp != VER_PARSE_SYM_MUX2 ) + pTemp++; + } + // look for this string in the array + nLength = pTemp - pString; + for ( i = 0; i < Vec_PtrSize(vNames)/2; i++ ) + { + nLength2 = (int)Vec_PtrEntry( vNames, 2*i + 0 ); + if ( nLength2 != nLength ) + continue; + pTemp2 = Vec_PtrEntry( vNames, 2*i + 1 ); + if ( strncmp( pString, pTemp2, nLength ) ) + continue; + return i; + } + // could not find - add and return the number + Vec_PtrPush( vNames, (void *)nLength ); + Vec_PtrPush( vNames, pString ); + return i; +} + +/**Function************************************************************* + + Synopsis [Returns the AIG representation of the reduction formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage ) +{ + Hop_Obj_t * pRes; + int v, fCompl; + char Symbol; + + // get the operation + Symbol = *pFormula++; + fCompl = ( Symbol == '~' ); + if ( fCompl ) + Symbol = *pFormula++; + // check the operation + if ( Symbol != '&' && Symbol != '|' && Symbol != '^' ) + { + sprintf( pErrorMessage, "Ver_FormulaReduction(): Unknown operation (%c)\n", Symbol ); + return NULL; + } + // skip the brace + while ( *pFormula++ != '{' ); + // parse the names + Vec_PtrClear( vNames ); + while ( *pFormula != '}' ) + { + v = Ver_FormulaParserFindVar( pFormula, vNames ); + pFormula += (int)Vec_PtrEntry( vNames, 2*v ); + while ( *pFormula == ' ' || *pFormula == ',' ) + pFormula++; + } + // compute the function + if ( Symbol == '&' ) + pRes = Hop_CreateAnd( pMan, Vec_PtrSize(vNames)/2 ); + else if ( Symbol == '|' ) + pRes = Hop_CreateOr( pMan, Vec_PtrSize(vNames)/2 ); + else if ( Symbol == '^' ) + pRes = Hop_CreateExor( pMan, Vec_PtrSize(vNames)/2 ); + return Hop_NotCond( pRes, fCompl ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/ver/verParse.c b/abc70930/src/base/ver/verParse.c new file mode 100644 index 00000000..9462fc8b --- /dev/null +++ b/abc70930/src/base/ver/verParse.c @@ -0,0 +1,117 @@ +/**CFile**************************************************************** + + FileName [verParse.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Performs some Verilog parsing tasks.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verParse.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Skips the comments of they are present.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseSkipComments( Ver_Man_t * pMan ) +{ + Ver_Stream_t * p = pMan->pReader; + char Symbol; + // skip spaces + Ver_StreamSkipChars( p, " \t\n\r" ); + if ( !Ver_StreamIsOkey(pMan->pReader) ) + return 1; + // read the first symbol + Symbol = Ver_StreamScanChar( p ); + if ( Symbol != '/' ) + return 1; + Ver_StreamPopChar( p ); + // read the second symbol + Symbol = Ver_StreamScanChar( p ); + if ( Symbol == '/' ) + { // skip till the end of line + Ver_StreamSkipToChars( p, "\n" ); + return Ver_ParseSkipComments( pMan ); + } + if ( Symbol == '*' ) + { // skip till the next occurance of */ + Ver_StreamPopChar( p ); + do { + Ver_StreamSkipToChars( p, "*" ); + Ver_StreamPopChar( p ); + } while ( Ver_StreamScanChar( p ) != '/' ); + Ver_StreamPopChar( p ); + return Ver_ParseSkipComments( pMan ); + } + sprintf( pMan->sError, "Cannot parse after symbol \"/\"." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Parses a Verilog name that can be being with a slash.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ver_ParseGetName( Ver_Man_t * pMan ) +{ + Ver_Stream_t * p = pMan->pReader; + char Symbol; + char * pWord; + pMan->fNameLast = 0; + if ( !Ver_StreamIsOkey(p) ) + return NULL; + if ( !Ver_ParseSkipComments( pMan ) ) + return NULL; + Symbol = Ver_StreamScanChar( p ); + if ( Symbol == '\\' ) + { + pMan->fNameLast = 1; + Ver_StreamPopChar( p ); + pWord = Ver_StreamGetWord( p, " \r\n" ); + } + else + pWord = Ver_StreamGetWord( p, " \t\n\r(),;" ); + if ( !Ver_ParseSkipComments( pMan ) ) + return NULL; + return pWord; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/ver/verStream.c b/abc70930/src/base/ver/verStream.c new file mode 100644 index 00000000..9b56bb3f --- /dev/null +++ b/abc70930/src/base/ver/verStream.c @@ -0,0 +1,443 @@ +/**CFile**************************************************************** + + FileName [verStream.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Input file stream, which knows nothing about Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verStream.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define VER_BUFFER_SIZE 1048576 // 1M - size of the data chunk stored in memory +#define VER_OFFSET_SIZE 65536 // 64K - load new data when less than this is left +#define VER_WORD_SIZE 65536 // 64K - the largest token that can be returned + +#define VER_MINIMUM(a,b) (((a) < (b))? (a) : (b)) + +struct Ver_Stream_t_ +{ + // the input file + char * pFileName; // the input file name + FILE * pFile; // the input file pointer + int nFileSize; // the total number of bytes in the file + int nFileRead; // the number of bytes currently read from file + int nLineCounter; // the counter of lines processed + // temporary storage for data + char * pBuffer; // the buffer + int nBufferSize; // the size of the buffer + char * pBufferCur; // the current reading position + char * pBufferEnd; // the first position not used by currently loaded data + char * pBufferStop; // the position where loading new data will be done + // tokens given to the user + char pChars[VER_WORD_SIZE+5]; // temporary storage for a word (plus end-of-string and two parantheses) + int nChars; // the total number of characters in the word + // status of the parser + int fStop; // this flag goes high when the end of file is reached +}; + +static void Ver_StreamReload( Ver_Stream_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the file reader for the given file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ver_Stream_t * Ver_StreamAlloc( char * pFileName ) +{ + Ver_Stream_t * p; + FILE * pFile; + int nCharsToRead; + // check if the file can be opened + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Ver_StreamAlloc(): Cannot open input file \"%s\".\n", pFileName ); + return NULL; + } + // start the file reader + p = ALLOC( Ver_Stream_t, 1 ); + memset( p, 0, sizeof(Ver_Stream_t) ); + p->pFileName = pFileName; + p->pFile = pFile; + // get the file size, in bytes + fseek( pFile, 0, SEEK_END ); + p->nFileSize = ftell( pFile ); + rewind( pFile ); + // allocate the buffer + p->pBuffer = ALLOC( char, VER_BUFFER_SIZE+1 ); + p->nBufferSize = VER_BUFFER_SIZE; + p->pBufferCur = p->pBuffer; + // determine how many chars to read + nCharsToRead = VER_MINIMUM(p->nFileSize, VER_BUFFER_SIZE); + // load the first part into the buffer + fread( p->pBuffer, nCharsToRead, 1, p->pFile ); + p->nFileRead = nCharsToRead; + // set the ponters to the end and the stopping point + p->pBufferEnd = p->pBuffer + nCharsToRead; + p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE; + // start the arrays + p->nLineCounter = 1; // 1-based line counting + return p; +} + +/**Function************************************************************* + + Synopsis [Loads new data into the file reader.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_StreamReload( Ver_Stream_t * p ) +{ + int nCharsUsed, nCharsToRead; + assert( !p->fStop ); + assert( p->pBufferCur > p->pBufferStop ); + assert( p->pBufferCur < p->pBufferEnd ); + // figure out how many chars are still not processed + nCharsUsed = p->pBufferEnd - p->pBufferCur; + // move the remaining data to the beginning of the buffer + memmove( p->pBuffer, p->pBufferCur, nCharsUsed ); + p->pBufferCur = p->pBuffer; + // determine how many chars we will read + nCharsToRead = VER_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead ); + // read the chars + fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile ); + p->nFileRead += nCharsToRead; + // set the ponters to the end and the stopping point + p->pBufferEnd = p->pBuffer + nCharsUsed + nCharsToRead; + p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE; +} + +/**Function************************************************************* + + Synopsis [Stops the file reader.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_StreamFree( Ver_Stream_t * p ) +{ + if ( p->pFile ) + fclose( p->pFile ); + FREE( p->pBuffer ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the file size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ver_StreamGetFileName( Ver_Stream_t * p ) +{ + return p->pFileName; +} + +/**Function************************************************************* + + Synopsis [Returns the file size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_StreamGetFileSize( Ver_Stream_t * p ) +{ + return p->nFileSize; +} + +/**Function************************************************************* + + Synopsis [Returns the current reading position.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_StreamGetCurPosition( Ver_Stream_t * p ) +{ + return p->nFileRead - (p->pBufferEnd - p->pBufferCur); +} + +/**Function************************************************************* + + Synopsis [Returns the line number for the given token.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_StreamGetLineNumber( Ver_Stream_t * p ) +{ + return p->nLineCounter; +} + + + +/**Function************************************************************* + + Synopsis [Returns current symbol.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_StreamIsOkey( Ver_Stream_t * p ) +{ + return !p->fStop; +} + +/**Function************************************************************* + + Synopsis [Returns current symbol.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char Ver_StreamScanChar( Ver_Stream_t * p ) +{ + assert( !p->fStop ); + return *p->pBufferCur; +} + +/**Function************************************************************* + + Synopsis [Returns current symbol and moves to the next.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char Ver_StreamPopChar( Ver_Stream_t * p ) +{ + assert( !p->fStop ); + // check if the new data should to be loaded + if ( p->pBufferCur > p->pBufferStop ) + Ver_StreamReload( p ); + // check if there are symbols left + if ( p->pBufferCur == p->pBufferEnd ) // end of file + { + p->fStop = 1; + return -1; + } + // count the lines + if ( *p->pBufferCur == '\n' ) + p->nLineCounter++; + return *p->pBufferCur++; +} + +/**Function************************************************************* + + Synopsis [Skips the current symbol and all symbols from the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip ) +{ + char * pChar, * pTemp; + assert( !p->fStop ); + assert( pCharsToSkip != NULL ); + // check if the new data should to be loaded + if ( p->pBufferCur > p->pBufferStop ) + Ver_StreamReload( p ); + // skip the symbols + for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) + { + // skip symbols as long as they are in the list + for ( pTemp = pCharsToSkip; *pTemp; pTemp++ ) + if ( *pChar == *pTemp ) + break; + if ( *pTemp == 0 ) // pChar is not found in the list + { + p->pBufferCur = pChar; + return; + } + // count the lines + if ( *pChar == '\n' ) + p->nLineCounter++; + } + // the file is finished or the last part continued + // through VER_OFFSET_SIZE chars till the end of the buffer + if ( p->pBufferStop == p->pBufferEnd ) // end of file + { + p->fStop = 1; + return; + } + printf( "Ver_StreamSkipSymbol() failed to parse the file \"%s\".\n", p->pFileName ); +} + +/**Function************************************************************* + + Synopsis [Skips all symbols until encountering one from the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop ) +{ + char * pChar, * pTemp; + assert( !p->fStop ); + assert( pCharsToStop != NULL ); + // check if the new data should to be loaded + if ( p->pBufferCur > p->pBufferStop ) + Ver_StreamReload( p ); + // skip the symbols + for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) + { + // skip symbols as long as they are NOT in the list + for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) + if ( *pChar == *pTemp ) + break; + if ( *pTemp == 0 ) // pChar is not found in the list + { + // count the lines + if ( *pChar == '\n' ) + p->nLineCounter++; + continue; + } + // the symbol is found - move position and return + p->pBufferCur = pChar; + return; + } + // the file is finished or the last part continued + // through VER_OFFSET_SIZE chars till the end of the buffer + if ( p->pBufferStop == p->pBufferEnd ) // end of file + { + p->fStop = 1; + return; + } + printf( "Ver_StreamSkipToSymbol() failed to parse the file \"%s\".\n", p->pFileName ); +} + +/**Function************************************************************* + + Synopsis [Returns current word delimited by the set of symbols.] + + Description [Modifies the stream by inserting 0 at the first encounter + of one of the symbols in the list.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop ) +{ + char * pChar, * pTemp; + if ( p->fStop ) + return NULL; + assert( pCharsToStop != NULL ); + // check if the new data should to be loaded + if ( p->pBufferCur > p->pBufferStop ) + Ver_StreamReload( p ); + // skip the symbols + p->nChars = 0; + for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) + { + // skip symbols as long as they are NOT in the list + for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) + if ( *pChar == *pTemp ) + break; + if ( *pTemp == 0 ) // pChar is not found in the list + { + p->pChars[p->nChars++] = *pChar; + if ( p->nChars == VER_WORD_SIZE ) + { + printf( "Ver_StreamGetWord(): The buffer size is exceeded.\n" ); + return NULL; + } + // count the lines + if ( *pChar == '\n' ) + p->nLineCounter++; + continue; + } + // the symbol is found - move the position, set the word end, return the word + p->pBufferCur = pChar; + p->pChars[p->nChars] = 0; + return p->pChars; + } + // the file is finished or the last part continued + // through VER_OFFSET_SIZE chars till the end of the buffer + if ( p->pBufferStop == p->pBufferEnd ) // end of file + { + p->fStop = 1; + p->pChars[p->nChars] = 0; + return p->pChars; + } + printf( "Ver_StreamGetWord() failed to parse the file \"%s\".\n", p->pFileName ); + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/ver/verWords.c b/abc70930/src/base/ver/verWords.c new file mode 100644 index 00000000..f9d27010 --- /dev/null +++ b/abc70930/src/base/ver/verWords.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [verWords.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Handles keywords that are currently supported.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verWords.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/ver/ver_.c b/abc70930/src/base/ver/ver_.c new file mode 100644 index 00000000..76599dac --- /dev/null +++ b/abc70930/src/base/ver/ver_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [ver_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Parses several flavors of structural Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: ver_.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + |